{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "copy-id",
  "title": "Copy Id",
  "description": "An ID or token in a mono well with a copy button; \"Copied\" confirms in place, never as a toast.",
  "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"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/copy-id.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@/components/ikada/lib/cn\";\nimport { CheckIcon, CopyIcon } from \"@/components/ikada/lib/icons\";\nimport { IconButton } from \"@/components/ikada/icon-button\";\nimport { InlineConfirm } from \"@/components/ikada/inline-confirm\";\n\nexport interface CopyIdProps extends Omit<ComponentProps<\"span\">, \"children\"> {\n  /** The full value written to the clipboard. */\n  value: string;\n  /** What is shown; defaults to the value. Use it to shorten hashes. */\n  display?: string;\n  /** Accessible name of the button, e.g. \"Copy deployment ID\". */\n  label?: string;\n  /** Called after a successful copy. */\n  onCopied?: (value: string) => void;\n}\n\n/** Both icons stay mounted; the idle one scales to 0.25, blurs and fades. Reduced motion keeps the fade. */\nconst swap = (on: boolean): string =>\n  on ? \"scale-100 opacity-100 blur-none\" : \"scale-(--sb-scale-icon) opacity-0 blur-xs motion-reduce:blur-none\";\n\n/** An ID or token in a mono well with a copy button; \"Copied\" confirms in place, never as a toast. */\nexport function CopyId({ value, display, label = \"Copy ID\", onCopied, className, ref, ...props }: CopyIdProps) {\n  async function copy(confirm: () => void) {\n    try {\n      await navigator.clipboard.writeText(value);\n    } catch {\n      return;\n    }\n    confirm();\n    onCopied?.(value);\n  }\n\n  return (\n    <span\n      data-slot=\"copy-id\"\n      ref={ref}\n      className={cn(\n        \"inline-flex h-8 min-w-0 max-w-full items-center gap-1 rounded-md bg-well ps-2.5 pe-1 shadow-field pointer-coarse:h-11\",\n        className,\n      )}\n      {...props}\n    >\n      <code className=\"min-w-0 truncate font-mono text-sb-sm font-medium text-fg\" title={value}>\n        {display ?? value}\n      </code>\n      <InlineConfirm message=\"Copied\" announce=\"Copied to clipboard\" className=\"shrink-0\">\n        {({ confirm, active }) => (\n          <IconButton\n            label={active ? \"Copied\" : label}\n            size=\"sm\"\n            onClick={() => copy(confirm)}\n            className=\"size-6 shrink-0 rounded-xs text-fg-muted hover:text-fg\"\n          >\n            <span className=\"inline-grid size-4 *:col-start-1 *:row-start-1 *:transition-[opacity,scale,filter] *:duration-300 *:ease-out\">\n              <CopyIcon className={swap(!active)} />\n              <CheckIcon className={cn(swap(active), \"text-brand-fg\")} />\n            </span>\n          </IconButton>\n        )}\n      </InlineConfirm>\n    </span>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/copy-id.tsx"
    }
  ],
  "categories": [
    "data-display"
  ],
  "type": "registry:ui"
}