{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "clipboard",
  "title": "Clipboard",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/clipboard/Clipboard.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n  import type { HTMLButtonAttributes } from 'svelte/elements'\n\n  export type ClipboardState = 'idle' | 'success' | 'error'\n\n  // `oncopy` / `onerror` intentionally shadow the DOM clipboard/error event\n  // handlers: this button fires copy-lifecycle callbacks, not DOM events.\n  export interface ClipboardProps extends Omit<HTMLButtonAttributes, 'oncopy' | 'onerror' | 'children'> {\n    /** Text to copy to the clipboard. */\n    text?: string\n    /** Optional visible label next to the icon. */\n    label?: string\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    /** The rendered button, via `bind:ref`. */\n    ref?: HTMLButtonElement | null\n    /** Custom copy UI. Receives `{ state }`. */\n    children?: Snippet<[{ state: ClipboardState }]>\n    /** Fires when a copy is attempted. */\n    oncopy?: (text: string) => void\n    /** Fires after a successful copy. */\n    onsuccess?: (text: string) => void\n    /** Fires after a failed copy. */\n    onerror?: (error: Error) => void\n  }\n</script>\n\n<script lang=\"ts\">\n  import { onDestroy } from 'svelte'\n  import { Check, Copy } from '@lucide/svelte'\n  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '$lib/components/ui/tooltip'\n  import { cn } from '$lib/utils'\n\n  let {\n    class: className,\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    ref = $bindable(null),\n    children,\n    oncopy,\n    onsuccess,\n    onerror,\n    ...restProps\n  }: ClipboardProps = $props()\n\n  let state = $state<ClipboardState>('idle')\n  let resetTimer: ReturnType<typeof setTimeout> | null = null\n\n  function setFeedback(nextState: ClipboardState) {\n    state = nextState\n    if (resetTimer) clearTimeout(resetTimer)\n    resetTimer = setTimeout(() => {\n      state = 'idle'\n    }, timeout)\n  }\n\n  async function copy() {\n    if (disabled) return\n    const value = text\n    oncopy?.(value)\n    try {\n      if (navigator.clipboard?.writeText) {\n        await navigator.clipboard.writeText(value)\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        const ok = document.execCommand('copy')\n        document.body.removeChild(ta)\n        if (!ok) throw new Error('execCommand copy failed')\n      }\n      setFeedback('success')\n      onsuccess?.(value)\n    } catch (err) {\n      setFeedback('error')\n      onerror?.(err as Error)\n    }\n  }\n\n  const currentTooltip = $derived(state === 'success' ? successText : state === 'error' ? errorText : tooltip)\n\n  onDestroy(() => {\n    if (resetTimer) clearTimeout(resetTimer)\n  })\n</script>\n\n<TooltipProvider delayDuration={300}>\n  <Tooltip>\n    <TooltipTrigger>\n      {#snippet child({ props }: { props: Record<string, unknown> })}\n        <button\n          bind:this={ref}\n          type=\"button\"\n          {...props}\n          data-uipkge\n          data-slot=\"clipboard\"\n          data-feedback-state={state}\n          {disabled}\n          class={cn(\n            'inline-flex items-center gap-2 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          aria-label={currentTooltip}\n          onclick={(e) => {\n            // Preserve a trigger-provided click handler (e.g. click-to-open\n            // tooltips) alongside the copy action.\n            const triggerClick = props.onclick as ((e: MouseEvent) => void) | undefined\n            triggerClick?.(e)\n            copy()\n          }}\n          {...restProps}\n        >\n          {#if !hideIcon}\n            <span data-slot=\"clipboard-icon\" class=\"inline-flex\">\n              {#if state === 'success'}\n                <Check class=\"size-4 text-emerald-500\" />\n              {:else}\n                <Copy class=\"size-4\" />\n              {/if}\n            </span>\n          {/if}\n          {#if label}\n            <span data-slot=\"clipboard-label\">{label}</span>\n          {/if}\n          {@render children?.({ state })}\n        </button>\n      {/snippet}\n    </TooltipTrigger>\n    {#if feedbackTooltip || state === 'idle'}\n      <TooltipContent>\n        {currentTooltip}\n      </TooltipContent>\n    {/if}\n  </Tooltip>\n</TooltipProvider>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/clipboard/Clipboard.svelte"
    },
    {
      "path": "packages/registry-svelte/components/clipboard/index.ts",
      "content": "export { default as Clipboard, type ClipboardProps, type ClipboardState } from './Clipboard.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/clipboard/index.ts"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/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 callbacks. Includes a legacy execCommand fallback for non-secure contexts. Composes the tooltip primitive.",
  "categories": [
    "utility",
    "control"
  ]
}