/** * useCopyToClipboard Hook * * Wrapper for Clipboard API with success/error handling and toast notifications. * * Features: * - Copy text to clipboard * - Success/error state tracking * - Automatic toast notifications * - Fallback for older browsers */ import { useState } from 'react'; import { toast } from 'sonner'; interface CopyToClipboardResult { copy: (text: string, successMessage?: string) => Promise; isCopied: boolean; error: Error | null; } export function useCopyToClipboard(): CopyToClipboardResult { const [isCopied, setIsCopied] = useState(false); const [error, setError] = useState(null); const copy = async (text: string, successMessage: string = 'Copied to clipboard') => { // Reset state setIsCopied(false); setError(null); try { // Modern Clipboard API if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(text); } else { // Fallback for older browsers or non-secure contexts const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; textArea.style.top = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); const successful = document.execCommand('copy'); textArea.remove(); if (!successful) { throw new Error('Copy command failed'); } } setIsCopied(true); toast.success(successMessage); // Reset isCopied after 2 seconds setTimeout(() => { setIsCopied(false); }, 2000); } catch (err) { const copyError = err instanceof Error ? err : new Error('Failed to copy'); setError(copyError); toast.error('Failed to copy to clipboard'); console.error('Copy error:', copyError); } }; return { copy, isCopied, error }; }