{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "password-input",
  "title": "Password Input",
  "author": "AniBT <https://anibt.net>",
  "description": "AniBT password field: an input with a named show / hide key that reports its state.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@anibt/theme",
    "@anibt/input"
  ],
  "files": [
    {
      "path": "registry/anibt/ui/password-input.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { EyeIcon, EyeOffIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Input } from \"@/registry/anibt/ui/input\"\n\n/**\n * PasswordInput — an AniBT 「贴纸手账」 `Input` with the one visibility key.\n *\n * The key at the right end is a quiet 24px square (the pink wash under the\n * pointer) that is always named — `showLabel` / `hideLabel` — and reports\n * its state with `aria-pressed`, so a keyboard and a screen reader can tell\n * show from hide. Whether the characters are on screen is this component's\n * own state: nothing outside a password field needs to know.\n *\n * `toggleWhenEmpty={false}` hides the key until something is typed (a\n * controlled field only). `className` sizes the wrapper (the key sits at its\n * end); `inputClassName` reaches the `<input>`, and so does every other\n * prop, `ref` included — pass `autoComplete=\"current-password\"` or\n * `\"new-password\"`.\n */\ntype PasswordInputProps = Omit<React.ComponentProps<\"input\">, \"type\"> & {\n  /** Show the key on an empty field too (default). */\n  toggleWhenEmpty?: boolean\n  /** Classes for the `<input>`; `className` sizes the wrapper. */\n  inputClassName?: string\n  showLabel?: string\n  hideLabel?: string\n}\n\nfunction PasswordInput({\n  className,\n  inputClassName,\n  toggleWhenEmpty = true,\n  showLabel = \"显示密码\",\n  hideLabel = \"隐藏密码\",\n  value,\n  disabled,\n  ...props\n}: PasswordInputProps) {\n  const [visible, setVisible] = React.useState(false)\n  const hasValue = typeof value === \"string\" ? value.length > 0 : value !== undefined\n  const showToggle = toggleWhenEmpty || hasValue\n  const label = visible ? hideLabel : showLabel\n\n  return (\n    <div data-slot=\"password-input\" className={cn(\"relative w-full min-w-0\", className)}>\n      <Input\n        type={visible ? \"text\" : \"password\"}\n        value={value}\n        disabled={disabled}\n        autoCapitalize=\"none\"\n        autoCorrect=\"off\"\n        spellCheck={false}\n        className={cn(showToggle && \"pr-9\", inputClassName)}\n        {...props}\n      />\n      {showToggle ? (\n        <button\n          type=\"button\"\n          onClick={() => setVisible((current) => !current)}\n          disabled={disabled}\n          aria-label={label}\n          aria-pressed={visible}\n          title={label}\n          className=\"absolute top-1/2 right-1.5 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[6px] text-muted-foreground transition-colors duration-150 hover:bg-accent hover:text-accent-foreground focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-solid disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-muted-foreground\"\n        >\n          {visible ? <EyeOffIcon className=\"size-4\" aria-hidden=\"true\" /> : <EyeIcon className=\"size-4\" aria-hidden=\"true\" />}\n        </button>\n      ) : null}\n    </div>\n  )\n}\n\nexport { PasswordInput }\nexport type { PasswordInputProps }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}