import { useCallback, useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; interface CopyTextProps { text: string; /** What to display. Defaults to `text`. */ children?: React.ReactNode; containerClassName?: string; className?: string; ariaLabel?: string; title?: string; /** Tooltip message shown after copying. Default: "Copied!" */ copiedLabel?: string; } export function CopyText({ text, children, containerClassName, className, ariaLabel, title, copiedLabel = "Copied!", }: CopyTextProps) { const [visible, setVisible] = useState(false); const [label, setLabel] = useState(copiedLabel); const timerRef = useRef>(undefined); const triggerRef = useRef(null); useEffect(() => () => clearTimeout(timerRef.current), []); 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} ); }