{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ds-password-strength-meter",
  "title": "PasswordStrengthMeter",
  "description": "Indicador dinâmico de segurança de senha com 4 níveis semânticos e checklist de requisitos em tempo real.",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "@lema-ds/ui-i18n",
    "@lema-ds/ds-locale-provider",
    "@lema-ds/tokens"
  ],
  "files": [
    {
      "path": "components/ds/ds-password-strength-meter.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { CheckIcon, XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { UI_I18N, type UILocale } from \"@/lib/ui-i18n\"\nimport { useUILocale } from \"@/components/ui/ds-locale-provider\"\n\n// ── Types ──\n\nexport interface PasswordCriterion {\n  id: string\n  label: string\n  met: boolean\n}\n\nexport interface PasswordStrengthMeterProps\n  extends\n    React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof passwordStrengthMeterVariants> {\n  password?: string\n  showChecklist?: boolean\n  minLength?: number\n  locale?: UILocale\n}\n\n// ── Variants ──\n\nexport const passwordStrengthMeterVariants = cva(\"flex w-full flex-col gap-2\", {\n  variants: {\n    size: {\n      sm: \"text-xs\",\n      md: \"text-sm\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n  },\n})\n\n// ── Helpers ──\n\nexport function evaluatePassword(password: string, minLength = 8) {\n  const hasLength = password.length >= minLength\n  const hasUpper = /[A-Z]/.test(password)\n  const hasNumber = /[0-9]/.test(password)\n  const hasSpecial = /[^A-Za-z0-9]/.test(password)\n\n  let score = 0\n  if (hasLength) score += 1\n  if (hasUpper) score += 1\n  if (hasNumber) score += 1\n  if (hasSpecial) score += 1\n\n  return {\n    score, // 0 to 4\n    criteria: [\n      { id: \"length\", met: hasLength },\n      { id: \"upper\", met: hasUpper },\n      { id: \"number\", met: hasNumber },\n      { id: \"special\", met: hasSpecial },\n    ],\n  }\n}\n\n// ── Component ──\n\nexport const PasswordStrengthMeter = React.forwardRef<\n  HTMLDivElement,\n  PasswordStrengthMeterProps\n>(\n  (\n    {\n      className,\n      password = \"\",\n      showChecklist = true,\n      minLength = 8,\n      size = \"md\",\n      locale: localeProp,\n      ...props\n    },\n    ref\n  ) => {\n    const locale = useUILocale(localeProp)\n    const t = UI_I18N[locale]?.auth ?? UI_I18N[\"en-US\"].auth\n    const { score, criteria } = evaluatePassword(password, minLength)\n\n    const levelConfig = [\n      { label: \"\", color: \"bg-muted\" },\n      { label: t.passwordStrengthWeak, color: \"bg-destructive\" },\n      { label: t.passwordStrengthMedium, color: \"bg-warning\" },\n      { label: t.passwordStrengthStrong, color: \"bg-primary\" },\n      { label: t.passwordStrengthVeryStrong, color: \"bg-success\" },\n    ][score]\n\n    const criteriaLabels: Record<string, string> = {\n      length: `${t.ruleLength} (${minLength})`,\n      upper: t.ruleUppercase,\n      number: t.ruleNumber,\n      special: t.ruleSpecial,\n    }\n\n    return (\n      <div\n        ref={ref}\n        role=\"status\"\n        aria-live=\"polite\"\n        className={cn(passwordStrengthMeterVariants({ size }), className)}\n        {...props}\n      >\n        {/* Progress Bars */}\n        <div className=\"flex flex-col gap-1.5\">\n          <div className=\"flex items-center justify-between text-xs\">\n            <span className=\"font-medium text-muted-foreground\">\n              {t.password}\n            </span>\n            {password.length > 0 && (\n              <span className=\"font-semibold text-foreground\">\n                {levelConfig.label}\n              </span>\n            )}\n          </div>\n\n          <div className=\"grid grid-cols-4 gap-1.5\" aria-hidden=\"true\">\n            {[1, 2, 3, 4].map((step) => {\n              const isActive = score >= step\n              return (\n                <div\n                  key={step}\n                  className={cn(\n                    \"h-1.5 rounded-full transition-all duration-300\",\n                    isActive ? levelConfig.color : \"bg-muted\"\n                  )}\n                />\n              )\n            })}\n          </div>\n        </div>\n\n        {/* Requirements Checklist */}\n        {showChecklist && (\n          <ul className=\"flex flex-col gap-1 pt-1\" role=\"list\">\n            {criteria.map((item) => {\n              const label = criteriaLabels[item.id] || item.id\n              return (\n                <li\n                  key={item.id}\n                  className={cn(\n                    \"flex items-center gap-2 text-xs transition-colors\",\n                    item.met ? \"text-success\" : \"text-muted-foreground\"\n                  )}\n                >\n                  {item.met ? (\n                    <CheckIcon\n                      className=\"size-3.5 shrink-0\"\n                      aria-hidden=\"true\"\n                    />\n                  ) : (\n                    <XIcon\n                      className=\"size-3.5 shrink-0 opacity-40\"\n                      aria-hidden=\"true\"\n                    />\n                  )}\n                  <span>{label}</span>\n                </li>\n              )\n            })}\n          </ul>\n        )}\n      </div>\n    )\n  }\n)\nPasswordStrengthMeter.displayName = \"PasswordStrengthMeter\"\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
