{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sensitive-input",
  "title": "Sensitive Input",
  "description": "A password or token field: masked by default, with a button that reveals it and an optional one that copies it.",
  "registryDependencies": [
    "https://sproutboat.com/ikada/r/theme.json",
    "https://sproutboat.com/ikada/r/cn.json",
    "https://sproutboat.com/ikada/r/icon-button.json",
    "https://sproutboat.com/ikada/r/icons.json",
    "https://sproutboat.com/ikada/r/inline-confirm.json",
    "https://sproutboat.com/ikada/r/input.json"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/sensitive-input.tsx",
      "content": "\"use client\";\n\nimport { useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@/components/ikada/lib/cn\";\nimport { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from \"@/components/ikada/lib/icons\";\nimport { IconButton } from \"@/components/ikada/icon-button\";\nimport { InlineConfirm } from \"@/components/ikada/inline-confirm\";\nimport { Input } from \"@/components/ikada/input\";\nimport type { InputProps } from \"@/components/ikada/input\";\n\nexport interface SensitiveInputProps extends Omit<InputProps, \"type\"> {\n  /** Shows a copy button. It copies the real value even while it is masked. */\n  copyable?: boolean;\n  /** Starts revealed. */\n  defaultRevealed?: boolean;\n  /** Accessible names of the two buttons. */\n  revealLabel?: string;\n  /** Accessible name of the hide button. Default \"Hide value\". */\n  hideLabel?: string;\n  /** Accessible name of the copy button. Default \"Copy value\". */\n  copyLabel?: string;\n  /** Extra buttons or text after the built-in ones. */\n  trailing?: ReactNode;\n}\n\n/**\n * A password or token field: masked by default, with a button that reveals it and an\n * optional one that copies it. Works inside a Field (id, label and errors are wired by Base UI);\n * `autoComplete` stays under the caller's control, so a sign-in form can keep `current-password`.\n */\nexport function SensitiveInput({\n  copyable = false,\n  defaultRevealed = false,\n  revealLabel = \"Show value\",\n  hideLabel = \"Hide value\",\n  copyLabel = \"Copy value\",\n  trailing,\n  className,\n  ...props\n}: SensitiveInputProps) {\n  const [revealed, setRevealed] = useState(defaultRevealed);\n  const box = useRef<HTMLDivElement>(null);\n\n  async function copy(confirm: () => void) {\n    try {\n      await navigator.clipboard.writeText(box.current?.querySelector(\"input\")?.value ?? \"\");\n    } catch {\n      return;\n    }\n    confirm();\n  }\n\n  return (\n    <div data-slot=\"sensitive-input\" ref={box} className=\"relative flex w-full min-w-0 items-center\">\n      <Input\n        {...props}\n        type={revealed ? \"text\" : \"password\"}\n        className={cn(copyable ? \"pe-[4.5rem] pointer-coarse:pe-24\" : \"pe-10 pointer-coarse:pe-14\", className)}\n      />\n      <span className=\"absolute inset-y-0 end-1 flex items-center gap-0.5\">\n        <IconButton\n          label={revealed ? hideLabel : revealLabel}\n          size=\"sm\"\n          aria-pressed={revealed}\n          onClick={() => setRevealed((open) => !open)}\n          className=\"rounded-xs text-fg-muted hover:text-fg\"\n        >\n          {revealed ? <EyeOffIcon /> : <EyeIcon />}\n        </IconButton>\n        {copyable ? (\n          <InlineConfirm message=\"Copied\" announce=\"Copied to clipboard\" className=\"shrink-0\">\n            {({ confirm, active }) => (\n              <IconButton\n                label={active ? \"Copied\" : copyLabel}\n                size=\"sm\"\n                onClick={() => copy(confirm)}\n                className=\"rounded-xs text-fg-muted hover:text-fg\"\n              >\n                {active ? <CheckIcon className=\"text-brand-fg\" /> : <CopyIcon />}\n              </IconButton>\n            )}\n          </InlineConfirm>\n        ) : null}\n        {trailing}\n      </span>\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/sensitive-input.tsx"
    }
  ],
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}