{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "clipboard",
  "title": "Clipboard",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/clipboard/Clipboard.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { Check, Copy } from 'lucide-react'\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'\nimport { cn } from '@/lib/utils'\n\nexport type ClipboardState = 'idle' | 'success' | 'error'\n\nexport interface ClipboardProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n  /** Text to copy to the clipboard. */\n  text?: string\n  /** Optional visible label next to the icon. */\n  label?: string\n  /** Disable the button (no copy, no tooltip). */\n  disabled?: boolean\n  /** Hide the copy icon (useful when a label is shown). */\n  hideIcon?: boolean\n  /** Tooltip text shown on hover before copying. */\n  tooltip?: string\n  /** Feedback text shown after a successful copy. */\n  successText?: string\n  /** Feedback text shown after a failed copy. */\n  errorText?: string\n  /** How long (ms) the success/error feedback stays before resetting. */\n  timeout?: number\n  /** Show the feedback as a tooltip rather than swapping the icon. */\n  feedbackTooltip?: boolean\n  /** Fired before the copy attempt with the text being copied. */\n  onCopy?: (text: string) => void\n  /** Fired after a successful copy. */\n  onSuccess?: (text: string) => void\n  /** Fired after a failed copy. */\n  onError?: (error: Error) => void\n  /** Render-prop children receiving the current state, or static nodes. */\n  children?: React.ReactNode | ((state: ClipboardState) => React.ReactNode)\n}\n\nconst Clipboard = React.forwardRef<HTMLButtonElement, ClipboardProps>(\n  (\n    {\n      text = '',\n      label = '',\n      disabled = false,\n      hideIcon = false,\n      tooltip = 'Copy',\n      successText = 'Copied!',\n      errorText = 'Failed',\n      timeout = 2000,\n      feedbackTooltip = true,\n      onCopy,\n      onSuccess,\n      onError,\n      className,\n      children,\n      onClick,\n      ...props\n    },\n    ref,\n  ) => {\n    const [state, setState] = React.useState<ClipboardState>('idle')\n    const resetTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n    const setFeedback = React.useCallback(\n      (nextState: ClipboardState) => {\n        setState(nextState)\n        if (resetTimer.current) clearTimeout(resetTimer.current)\n        resetTimer.current = setTimeout(() => {\n          setState('idle')\n        }, timeout)\n      },\n      [timeout],\n    )\n\n    // Match the Vue onBeforeUnmount fix: clear any pending reset timer on unmount.\n    React.useEffect(() => {\n      return () => {\n        if (resetTimer.current) clearTimeout(resetTimer.current)\n      }\n    }, [])\n\n    const copy = React.useCallback(\n      async (e: React.MouseEvent<HTMLButtonElement>) => {\n        if (disabled) return\n        onClick?.(e)\n        const value = text\n        onCopy?.(value)\n        try {\n          if (navigator.clipboard?.writeText) {\n            const write = navigator.clipboard.writeText(value)\n            setFeedback('success')\n            await write\n          } else {\n            // Legacy fallback for non-secure contexts.\n            const ta = document.createElement('textarea')\n            ta.value = value\n            ta.style.position = 'fixed'\n            ta.style.opacity = '0'\n            document.body.appendChild(ta)\n            ta.select()\n            document.execCommand('copy')\n            document.body.removeChild(ta)\n            setFeedback('success')\n          }\n          onSuccess?.(value)\n        } catch (err) {\n          setFeedback('error')\n          onError?.(err as Error)\n        }\n      },\n      [disabled, text, onCopy, onSuccess, onError, onClick, setFeedback],\n    )\n\n    const currentTooltip = state === 'success' ? successText : state === 'error' ? errorText : tooltip\n\n    return (\n      <TooltipProvider delayDuration={300}>\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <button\n              type=\"button\"\n              ref={ref}\n              data-uipkge=\"\"\n              data-slot=\"clipboard\"\n              data-feedback-state={state}\n              disabled={disabled}\n              aria-label={currentTooltip}\n              onClick={copy}\n              className={cn(\n                'inline-flex items-center gap-1.5 rounded-md text-sm transition-colors',\n                'text-muted-foreground hover:text-foreground',\n                'focus-visible:ring-ring/50 outline-none focus-visible:ring-[3px]',\n                'disabled:cursor-not-allowed disabled:opacity-50',\n                className,\n              )}\n              {...props}\n            >\n              {!hideIcon && (\n                <span data-slot=\"clipboard-icon\" className=\"inline-flex\">\n                  {state === 'success' ? <Check className=\"size-4 text-emerald-500\" /> : <Copy className=\"size-4\" />}\n                </span>\n              )}\n              {label && <span data-slot=\"clipboard-label\">{label}</span>}\n              {typeof children === 'function' ? children(state) : children}\n            </button>\n          </TooltipTrigger>\n          {(feedbackTooltip || state === 'idle') && <TooltipContent>{currentTooltip}</TooltipContent>}\n        </Tooltip>\n      </TooltipProvider>\n    )\n  },\n)\nClipboard.displayName = 'Clipboard'\n\nexport { Clipboard }\n",
      "type": "registry:ui",
      "target": "~/components/ui/clipboard/Clipboard.tsx"
    },
    {
      "path": "packages/registry-react/components/clipboard/index.ts",
      "content": "export { Clipboard, type ClipboardProps, type ClipboardState } from './Clipboard'\n",
      "type": "registry:ui",
      "target": "~/components/ui/clipboard/index.ts"
    }
  ],
  "dependencies": [
    "lucide-react",
    "@radix-ui/react-tooltip"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/tooltip.json"
  ],
  "description": "Copy-to-clipboard button with success/error feedback. Swaps the icon to a check on success, shows a tooltip with configurable feedback text, supports a visible label, disabled state, a custom timeout for feedback reset, and copy/success/error events. Includes a legacy execCommand fallback for non-secure contexts. Composes the tooltip primitive.",
  "categories": [
    "utility",
    "control"
  ]
}