mirror of
https://github.com/hanzo-apps/dataroom.git
synced 2026-10-30 14:47:36 +00:00
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
|
export const useCopyToClipboard = (
|
|
timeout: number = 3000,
|
|
): [
|
|
boolean,
|
|
(
|
|
value: string | ClipboardItem,
|
|
options?: { onSuccess?: () => void; throwOnError?: boolean },
|
|
) => Promise<void>,
|
|
] => {
|
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
const clearTimer = () => {
|
|
if (timer.current) {
|
|
clearTimeout(timer.current);
|
|
timer.current = null;
|
|
}
|
|
};
|
|
|
|
const copyToClipboard = useCallback(
|
|
async (
|
|
value: string | ClipboardItem,
|
|
{
|
|
onSuccess,
|
|
throwOnError,
|
|
}: { onSuccess?: () => void; throwOnError?: boolean } = {},
|
|
) => {
|
|
clearTimer();
|
|
try {
|
|
if (typeof value === "string") {
|
|
await navigator.clipboard.writeText(value);
|
|
} else if (value instanceof ClipboardItem) {
|
|
await navigator.clipboard.write([value]);
|
|
}
|
|
setCopied(true);
|
|
onSuccess?.();
|
|
|
|
// Ensure timeout is a non-negative finite number
|
|
if (Number.isFinite(timeout) && timeout >= 0) {
|
|
timer.current = setTimeout(() => setCopied(false), timeout);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to copy: ", error);
|
|
if (throwOnError) throw error;
|
|
}
|
|
},
|
|
[timeout],
|
|
);
|
|
|
|
// Cleanup the timer when the component unmounts
|
|
useEffect(() => {
|
|
return () => clearTimer();
|
|
}, []);
|
|
|
|
return [copied, copyToClipboard];
|
|
};
|