useCopyToClipboard
zyeon/use-copy-to-clipboardFreeHook
A clipboard-copy hook with a timed copied state and a non-throwing error channel.
Install it
npx shadcn@latest add https://ui.zyeon.ai/r/use-copy-to-clipboard.jsonSource
1"use client"23import * as React from "react"45export interface UseCopyToClipboardOptions {6 /** How long `copied` stays true before falling back to false, in ms. Defaults to 2000. */7 resetDelay?: number8}910export interface UseCopyToClipboardResult {11 copied: boolean12 copy: (text: string) => Promise<boolean>13 error: Error | null14}1516function toError(reason: unknown): Error {17 if (reason instanceof Error) return reason18 if (reason && typeof reason === "object" && "message" in reason) {19 return new Error(String((reason as { message: unknown }).message))20 }21 return new Error("Clipboard write failed")22}2324/**25 * Clipboard copy plus an auto-resetting state machine. A successful `copy` sets26 * `copied` to true and it falls back to false after `resetDelay`; calling `copy`27 * again restarts the timer, and unmounting clears it. A failure (permission denied /28 * insecure context / no API) only sets `error` and returns false — it never throws.29 * The hook itself never touches `navigator` during render, only inside `copy`, so it30 * is safe in a server-rendered component.31 */32export function useCopyToClipboard(33 options: UseCopyToClipboardOptions = {},34): UseCopyToClipboardResult {35 const { resetDelay = 2000 } = options36 const [copied, setCopied] = React.useState(false)37 const [error, setError] = React.useState<Error | null>(null)38 const timeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)3940 const clearResetTimer = () => {41 if (timeoutRef.current !== null) {42 clearTimeout(timeoutRef.current)43 timeoutRef.current = null44 }45 }4647 // Clean up on unmount, so a late timer can't setState on a gone component.48 React.useEffect(() => clearResetTimer, [])4950 const copy = React.useCallback(51 (text: string) => {52 if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {53 setError(new Error("Clipboard API unavailable (insecure context or unsupported browser)"))54 return Promise.resolve(false)55 }5657 return navigator.clipboard.writeText(text).then(58 () => {59 setError(null)60 setCopied(true)61 clearResetTimer()62 timeoutRef.current = setTimeout(() => {63 setCopied(false)64 timeoutRef.current = null65 }, resetDelay)66 return true67 },68 reason => {69 setError(toError(reason))70 return false71 },72 )73 },74 [resetDelay],75 )7677 return { copied, copy, error }78}7980// … truncated
Files it writes
More from zyeon
All 893 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useAsyncuse-async | zyeon | Hooks | Free | no deps | |
| useBatteryuse-battery | zyeon | Hooks | Free | no deps | |
| useBroadcastChanneluse-broadcast-channel | zyeon | Hooks | Free | no deps | |
| useClickOutsideuse-click-outside | zyeon | Hooks | Free | no deps | |
| useClipboardPasteuse-clipboard-paste | zyeon | Hooks | Free | no deps | |
| useControllableStateuse-controllable-state | zyeon | Hooks | Free | no deps | |
| useCookieuse-cookie | zyeon | Hooks | Free | no deps | |
| useCountdownuse-countdown | zyeon | Hooks | Free | no deps |
