{"version":3,"file":"CopyButton.cjs","names":[],"sources":["../../../src/components/CopyButton/CopyButton.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./CopyButton.module.css\";\n\nexport interface CopyButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n    /** Text written to the clipboard when the button is clicked. */\n    value: string;\n    /** How long (ms) the \"copied\" state stays active before resetting. Defaults to 2000. */\n    timeout?: number;\n    /** Optional label. Falls back to \"Copy\" / \"Copied\" based on state. */\n    children?: ReactNode;\n    /** Called after a successful clipboard write. */\n    onCopied?: () => void;\n}\n\n/**\n * Button that copies a string to the clipboard and shows a transient \"copied\"\n * state for `timeout` milliseconds.\n *\n * When `children` are provided they are rendered in both states; otherwise the\n * label toggles between \"Copy\" and \"Copied\". The reset timer is cleared on\n * unmount to avoid setting state on an unmounted component.\n *\n * @tempest-limits empty-catch — `navigator.clipboard.writeText` rejects when the\n * page is not a secure context, when the document is not focused, or when the user\n * denied the permission. None of those are recoverable here and none deserve an\n * error surface: the button simply never enters the \"copied\" state, which is the\n * feedback the user needs.\n *\n * @example\n * <CopyButton value=\"npm i tempest-react-sdk\" />\n */\nexport function CopyButton({\n    value,\n    timeout = 2000,\n    children,\n    onCopied,\n    className,\n    onClick,\n    ...props\n}: CopyButtonProps) {\n    const [copied, setCopied] = useState(false);\n    const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n    useEffect(() => {\n        return () => {\n            if (timerRef.current !== null) clearTimeout(timerRef.current);\n        };\n    }, []);\n\n    const handleClick = useCallback(\n        async (event: React.MouseEvent<HTMLButtonElement>) => {\n            onClick?.(event);\n            try {\n                await navigator.clipboard.writeText(value);\n                setCopied(true);\n                onCopied?.();\n                if (timerRef.current !== null) clearTimeout(timerRef.current);\n                timerRef.current = setTimeout(() => setCopied(false), timeout);\n            } catch {\n                /* empty */\n            }\n        },\n        [value, timeout, onCopied, onClick],\n    );\n\n    return (\n        <button\n            type=\"button\"\n            className={cn(styles.button, copied && styles.copied, className)}\n            data-copied={copied || undefined}\n            onClick={handleClick}\n            {...props}\n        >\n            {children ?? (copied ? \"Copied\" : \"Copy\")}\n        </button>\n    );\n}\n"],"mappings":"iIAiCA,SAAgB,EAAW,CACvB,QACA,UAAU,IACV,WACA,WACA,YACA,UACA,GAAG,GACa,CAChB,GAAM,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAAS,EAAK,EACpC,GAAA,EAAW,EAAA,OAAA,CAA6C,IAAI,GAElE,EAAA,EAAA,UAAA,SACiB,CACL,EAAS,UAAY,MAAM,aAAa,EAAS,OAAO,CAChE,EACD,CAAC,CAAC,EAEL,IAAM,GAAA,EAAc,EAAA,YAAA,CAChB,KAAO,IAA+C,CAClD,IAAU,CAAK,EACf,GAAI,CACA,MAAM,UAAU,UAAU,UAAU,CAAK,EACzC,EAAU,EAAI,EACd,IAAW,EACP,EAAS,UAAY,MAAM,aAAa,EAAS,OAAO,EAC5D,EAAS,QAAU,eAAiB,EAAU,EAAK,EAAG,CAAO,CACjE,MAAQ,CAER,CACJ,EACA,CAAC,EAAO,EAAS,EAAU,CAAO,CACtC,EAEA,OACI,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,QAAO,OAAQ,GAAU,EAAA,QAAO,OAAQ,CAAS,EAC/D,cAAa,GAAU,IAAA,GACvB,QAAS,EACT,GAAI,EAEH,SAAA,IAAa,EAAS,SAAW,OAC9B,CAAA,CAEhB"}