{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "password-input",
  "title": "Password Input",
  "description": "A password field with a visibility toggle and a four-step strength guide that explains how to improve the entry.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/tealmac/password-input.tsx",
      "content": "// Adapted from Ballmac UI (https://github.com/vamsiy78/ballmac-ui), MIT License, Copyright (c) 2026 Ballmac.\n\"use client\"\n\nimport * as React from \"react\"\nimport { Eye, EyeOff } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype PasswordInputProps = Omit<\n  React.ComponentProps<\"input\">,\n  \"type\" | \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n  /** Controlled password value. */\n  value?: string\n  /** Initial password when uncontrolled. */\n  defaultValue?: string\n  /** Called with the new password. */\n  onValueChange?: (value: string) => void\n  /** Show a four-step strength guide. */\n  showStrength?: boolean\n  /** Accessible name of the password field. */\n  label?: string\n}\nfunction PasswordInput({\n  value,\n  defaultValue = \"\",\n  onValueChange,\n  showStrength = true,\n  label,\n  className,\n  disabled,\n  ...props\n}: PasswordInputProps) {\n  label ??= \"Password\"\n  const [internal, setInternal] = React.useState(defaultValue)\n  const [visible, setVisible] = React.useState(false)\n  const current = value ?? internal\n  const score =\n    Number(current.length >= 8) +\n    Number(/[a-z]/.test(current) && /[A-Z]/.test(current)) +\n    Number(/\\d/.test(current)) +\n    Number(/[^a-zA-Z\\d]/.test(current))\n  const strength = [\"Too short\", \"Needs work\", \"Fair\", \"Good\", \"Strong\"][score]\n  function commit(next: string) {\n    if (value === undefined) setInternal(next)\n    onValueChange?.(next)\n  }\n  return (\n    <div data-slot=\"password-input\" className={cn(\"w-full min-w-0\", className)}>\n      <div className=\"border-input bg-background focus-within:border-ring focus-within:ring-ring/50 flex h-9 items-center rounded-md border shadow-xs transition-[border-color,box-shadow] duration-150 focus-within:ring-[3px] motion-reduce:transition-none\">\n        <input\n          data-slot=\"password-input-field\"\n          type={visible ? \"text\" : \"password\"}\n          autoComplete=\"new-password\"\n          aria-label={label}\n          disabled={disabled}\n          value={current}\n          onChange={(event) => commit(event.currentTarget.value)}\n          className=\"text-foreground placeholder:text-muted-foreground h-full min-w-0 flex-1 bg-transparent px-3 text-sm outline-none disabled:opacity-50\"\n          {...props}\n        />\n        <button\n          type=\"button\"\n          aria-label={visible ? \"Hide password\" : \"Show password\"}\n          aria-pressed={visible}\n          disabled={disabled}\n          onClick={() => setVisible(!visible)}\n          className=\"text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring/50 me-1 flex size-8 shrink-0 items-center justify-center rounded-md outline-none focus-visible:ring-[3px] disabled:opacity-50\"\n        >\n          {visible ? (\n            <EyeOff aria-hidden=\"true\" className=\"size-4\" />\n          ) : (\n            <Eye aria-hidden=\"true\" className=\"size-4\" />\n          )}\n        </button>\n      </div>\n      {showStrength && current.length > 0 && (\n        <div data-slot=\"password-strength\" className=\"mt-2\" aria-live=\"polite\">\n          <div aria-hidden=\"true\" className=\"grid grid-cols-4 gap-1\">\n            {[1, 2, 3, 4].map((level) => (\n              <span\n                key={level}\n                className={cn(\n                  \"bg-muted h-1 rounded-full\",\n                  score >= level &&\n                    (score < 3 ? \"bg-destructive\" : \"bg-chart-2\")\n                )}\n              />\n            ))}\n          </div>\n          <p className=\"text-muted-foreground mt-1.5 text-xs\">\n            {`Strength: ${strength}. Use 8+ characters, mixed case, a number, and a symbol.`}\n          </p>\n        </div>\n      )}\n    </div>\n  )\n}\nexport { PasswordInput, type PasswordInputProps }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}