import { useCallback, useRef, useState } from "react"; import { cn } from "@/lib/utils"; interface CopyTextProps { text: string; /** What to display. Defaults to `text`. */ children?: React.ReactNode; className?: string; /** Tooltip message shown after copying. Default: "Copied!" */ copiedLabel?: string; } export function CopyText({ text, children, className, copiedLabel = "Copied!" }: CopyTextProps) { const [visible, setVisible] = useState(false); const [label, setLabel] = useState(copiedLabel); const timerRef = useRef>(undefined); const triggerRef = useRef(null); const handleClick = useCallback(async () => { try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(text); } else { // Fallback for non-secure contexts (e.g. HTTP on non-localhost) const textarea = document.createElement("textarea"); textarea.value = text; textarea.style.position = "fixed"; textarea.style.left = "-9999px"; document.body.appendChild(textarea); try { textarea.select(); const success = document.execCommand("copy"); if (!success) throw new Error("execCommand copy failed"); } finally { document.body.removeChild(textarea); } } setLabel(copiedLabel); } catch { setLabel("Copy failed"); } clearTimeout(timerRef.current); setVisible(true); timerRef.current = setTimeout(() => setVisible(false), 1500); }, [copiedLabel, text]); return ( {label} ); }