All files / web/src/hooks useClipboard.ts

100% Statements 64/64
100% Branches 6/6
100% Functions 1/1
100% Lines 64/64

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 651x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 65x 65x 65x 65x 65x 13x 13x 12x 12x 2x 12x 13x 1x 1x 13x 65x 65x 65x 65x 8x 65x 65x 65x 65x  
import { useCallback, useState } from 'react'
 
export interface UseClipboardOptions {
  /**
   * Timeout in milliseconds to reset the copied state
   * @default 1500
   */
  timeout?: number
}
 
export interface UseClipboardReturn {
  /**
   * Whether the text was recently copied
   */
  copied: boolean
 
  /**
   * Copy text to clipboard
   */
  copy: (text: string) => Promise<void>
 
  /**
   * Reset the copied state manually
   */
  reset: () => void
}
 
/**
 * Hook for copying text to clipboard with visual feedback
 *
 * @example
 * ```tsx
 * const { copied, copy } = useClipboard()
 *
 * <button onClick={() => copy('Hello!')}>
 *   {copied ? 'Copied!' : 'Copy'}
 * </button>
 * ```
 */
export function useClipboard(options: UseClipboardOptions = {}): UseClipboardReturn {
  const { timeout = 1500 } = options
  const [copied, setCopied] = useState(false)
 
  const copy = useCallback(
    async (text: string) => {
      try {
        await navigator.clipboard.writeText(text)
        setCopied(true)
        setTimeout(() => {
          setCopied(false)
        }, timeout)
      } catch (error) {
        console.error('[useClipboard] Failed to copy to clipboard:', error)
      }
    },
    [timeout]
  )
 
  const reset = useCallback(() => {
    setCopied(false)
  }, [])
 
  return { copied, copy, reset }
}