{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "password-input",
  "title": "Password Input",
  "description": "The text comes into focus out of a blur when revealed, and requirements tick as they are met.",
  "dependencies": [
    "@ui-sdk/core@0.1.0-beta.2",
    "@ui-sdk/react@0.1.0-beta.2"
  ],
  "registryDependencies": [
    "@keyframery/motion"
  ],
  "files": [
    {
      "path": "registry/components/keyframery/primitives/password-input.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/password-input`: same parts, same props. Swap the import and keep\n   your code. This file adds motion only. Colours, radii, shadows and spacing stay yours. */\n\nimport {\n  PasswordInput as PasswordInputRoot,\n  PasswordInputControl as PasswordInputControlPart,\n  PasswordInputToggle as PasswordInputTogglePart,\n} from \"@ui-sdk/react/password-input\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/password-input\"\n\nconst keyframes =\n  \"@keyframes kf-password-reveal{from{filter:blur(5px);opacity:.35;letter-spacing:.12em}to{filter:none;opacity:1;letter-spacing:normal}}\"\n\n/* The root is usually the field's box: its focus ring is the outline, which closes in from\n   10px out on a spring, easing from its resting colour to its focus colour. Give it width and colour with `has-[input:focus-visible]:outline-…`. */\nfunction PasswordInput({ className, ...props }: React.ComponentProps<typeof PasswordInputRoot>) {\n  return (\n    <PasswordInputRoot\n      className={cn(\n        \"outline-offset-[10px] has-[input:focus-visible]:outline-offset-0\",\n        \"[transition:outline-offset_calc(160ms*var(--kf-speed,1))_var(--ease-house),outline-width_calc(160ms*var(--kf-speed,1))_var(--ease-house),outline-color_0s_linear_calc(160ms*var(--kf-speed,1)),box-shadow_calc(150ms*var(--kf-speed,1))_var(--ease-house),background-color_calc(150ms*var(--kf-speed,1))_var(--ease-house)] has-[input:focus-visible]:[transition:outline-offset_calc(900ms*var(--kf-speed,1))_var(--ease-spring),outline-width_calc(900ms*var(--kf-speed,1))_var(--ease-spring),outline-color_calc(700ms*var(--kf-speed,1))_var(--ease-house),box-shadow_calc(150ms*var(--kf-speed,1))_var(--ease-house),background-color_calc(150ms*var(--kf-speed,1))_var(--ease-house)]\",\n        \"motion-reduce:[transition:none]!\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* When the password is revealed, the text comes into focus: a short blur-to-clear. */\nfunction PasswordInputControl({\n  className,\n  ...props\n}: React.ComponentProps<typeof PasswordInputControlPart>) {\n  return (\n    <>\n      <style href=\"kf-password-reveal\" precedence=\"default\">\n        {keyframes}\n      </style>\n      <PasswordInputControlPart\n        className={cn(\n          \"data-visible:animate-[kf-password-reveal_calc(420ms*var(--kf-speed,1))_var(--ease-house)] motion-reduce:animate-none!\",\n          className,\n        )}\n        {...props}\n      />\n    </>\n  )\n}\n\n/* The toggle presses with a pop release. Whatever icon it shows pops in when it changes\n   (render a different icon for each state, as the UI SDK examples do): it grows from 40%\n   with a quarter turn on `ease-pop`. */\nfunction PasswordInputToggle({\n  className,\n  ...props\n}: React.ComponentProps<typeof PasswordInputTogglePart>) {\n  return (\n    <PasswordInputTogglePart\n      className={cn(\n        \"[transition:scale_calc(260ms*var(--kf-speed,1))_var(--ease-pop),color_calc(150ms*var(--kf-speed,1)),background-color_calc(150ms*var(--kf-speed,1))] active:scale-[0.86]\",\n        \"[&_svg]:[transition:scale_calc(440ms*var(--kf-speed,1))_var(--ease-pop),rotate_calc(440ms*var(--kf-speed,1))_var(--ease-pop),opacity_calc(200ms*var(--kf-speed,1))_var(--ease-house)]\",\n        \"[&_svg]:starting:scale-[0.4] [&_svg]:starting:-rotate-90 [&_svg]:starting:opacity-0\",\n        \"motion-reduce:[transition:none]! motion-reduce:[&_svg]:[transition:none]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { PasswordInput, PasswordInputControl, PasswordInputToggle }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/password-input.tsx"
    },
    {
      "path": "registry/components/keyframery/password-input.tsx",
      "content": "\"use client\"\n\n/* Styled password input: the animated primitive plus the Keyframery look. */\n\nimport * as React from \"react\"\n\nimport {\n  PasswordInput as PasswordInputPrimitive,\n  PasswordInputControl as PasswordInputControlPrimitive,\n  PasswordInputToggle as PasswordInputTogglePrimitive,\n  createPasswordInputController,\n} from \"@/components/keyframery/primitives/password-input\"\nimport { cn } from \"@/lib/utils\"\n\n/* The root is the field: the native input, a Caps Lock mark and the toggle sit inside one box.\n   The hairline's colour is one variable, so hover, focus and invalid each change a single value. */\nfunction PasswordInput({ className, ...props }: React.ComponentProps<typeof PasswordInputPrimitive>) {\n  return (\n    <PasswordInputPrimitive\n      className={cn(\n        \"group/password flex h-9 w-full min-w-0 cursor-text items-center gap-1 rounded-[10px] bg-background ps-3 pe-1 text-[13px] text-muted-foreground\",\n        \"outline-0 outline-ring\",\n        \"[--field-line:rgb(0_0_0/0.09)] dark:[--field-line:rgb(255_255_255/0.1)]\",\n        \"shadow-[0_0_0_1px_var(--field-line),0_1px_2px_rgb(0_0_0/0.05)] dark:shadow-[0_0_0_1px_var(--field-line)]\",\n        \"hover:[--field-line:rgb(0_0_0/0.16)] dark:hover:[--field-line:rgb(255_255_255/0.18)]\",\n        \"has-[input:focus-visible]:outline-[3px] has-[input:focus-visible]:outline-ring/30 has-[input:focus-visible]:[--field-line:var(--ring)] dark:has-[input:focus-visible]:[--field-line:var(--ring)]\",\n        \"has-aria-invalid:outline-destructive has-aria-invalid:has-[input:focus-visible]:outline-destructive/30 has-aria-invalid:[--field-line:var(--destructive)] dark:has-aria-invalid:[--field-line:var(--destructive)]\",\n        \"data-readonly:bg-muted/50\",\n        \"data-disabled:cursor-not-allowed data-disabled:bg-muted data-disabled:[--field-line:rgb(0_0_0/0.06)] dark:data-disabled:[--field-line:rgb(255_255_255/0.06)]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction PasswordInputControl({\n  className,\n  ...props\n}: React.ComponentProps<typeof PasswordInputControlPrimitive>) {\n  return (\n    <PasswordInputControlPrimitive\n      className={cn(\n        \"h-full min-w-0 flex-1 bg-transparent text-[13px] text-foreground outline-none select-text placeholder:text-muted-foreground/70\",\n        \"data-disabled:cursor-not-allowed data-disabled:text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nconst icon = {\n  viewBox: \"0 0 16 16\",\n  fill: \"none\",\n  stroke: \"currentColor\",\n  strokeWidth: \"1.5\",\n  strokeLinecap: \"round\",\n  strokeLinejoin: \"round\",\n  \"aria-hidden\": true,\n} as const\n\nfunction EyeIcon() {\n  return (\n    <svg {...icon} className=\"size-4\">\n      <path d=\"M1.75 8S4 3.75 8 3.75 14.25 8 14.25 8 12 12.25 8 12.25 1.75 8 1.75 8Z\" />\n      <circle cx=\"8\" cy=\"8\" r=\"2\" />\n    </svg>\n  )\n}\n\nfunction EyeOffIcon() {\n  return (\n    <svg {...icon} className=\"size-4\">\n      <path d=\"M6.6 3.9A6 6 0 0 1 8 3.75C12 3.75 14.25 8 14.25 8a11 11 0 0 1-1.7 2.3M4.3 4.9C2.6 6 1.75 8 1.75 8S4 12.25 8 12.25a6 6 0 0 0 2.9-.75\" />\n      <path d=\"M6.6 6.6a2 2 0 0 0 2.8 2.8\" />\n      <path d=\"m2.5 2.5 11 11\" />\n    </svg>\n  )\n}\n\n/* One icon per state, so the primitive pops each one in as it changes. */\nfunction PasswordInputToggle({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof PasswordInputTogglePrimitive>) {\n  return (\n    <PasswordInputTogglePrimitive\n      className={cn(\n        \"grid size-7 shrink-0 cursor-pointer place-items-center rounded-[7px] text-muted-foreground outline-none\",\n        \"hover:bg-foreground/[0.06] hover:text-foreground aria-pressed:text-foreground\",\n        \"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n        \"[&_svg]:shrink-0\",\n        className,\n      )}\n      {...props}\n    >\n      {children ?? ((state) => (state.visible ? <EyeOffIcon /> : <EyeIcon />))}\n    </PasswordInputTogglePrimitive>\n  )\n}\n\n/* Place inside PasswordInput, before the toggle. It is out of the page until Caps Lock\n   is on while the field has focus, then it pops in from its starting style. */\nfunction PasswordInputCapsLock({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"password-input-caps-lock\"\n      title=\"Caps Lock is on\"\n      className={cn(\n        \"hidden size-5 shrink-0 place-items-center rounded-[6px] bg-muted text-foreground\",\n        \"group-data-capslock/password:grid\",\n        \"[transition:opacity_calc(200ms*var(--kf-speed,1))_var(--ease-house),scale_calc(380ms*var(--kf-speed,1))_var(--ease-pop),display_calc(380ms*var(--kf-speed,1))] transition-discrete\",\n        \"starting:scale-50 starting:opacity-0 motion-reduce:transition-none!\",\n        className,\n      )}\n      {...props}\n    >\n      <svg {...icon} className=\"size-3.5\">\n        <path d=\"M8 2.75 3.25 8h2.5v2.25h4.5V8h2.5L8 2.75Z\" />\n        <path d=\"M5.75 13h4.5\" />\n      </svg>\n      <span className=\"sr-only\">Caps Lock is on</span>\n    </span>\n  )\n}\n\nexport {\n  PasswordInput,\n  PasswordInputCapsLock,\n  PasswordInputControl,\n  PasswordInputToggle,\n  createPasswordInputController,\n}\n",
      "type": "registry:component",
      "target": "components/keyframery/password-input.tsx"
    }
  ],
  "type": "registry:component"
}