Files
zeekayandHanzo Dev 32a732ba95 fix(lib): say what the clipboard hook checks, as it has always checked it
`Boolean(typeof ClipboardItem && navigator.clipboard.write)` looks like a
check for ClipboardItem, but `typeof` always yields a non-empty string, so
the expression was always navigator.clipboard.write — ESLint 10's
no-constant-binary-expression says so. The check now says only that, which
is what it has always evaluated to, and a comment records why that is
enough: without ClipboardItem, handleClipboardApiCopy throws inside its own
try and falls back to writeText. The ternary used as a statement becomes an
if, as typescript-eslint 8's no-unused-expressions asks.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-19 05:07:02 -07:00

65 lines
1.8 KiB
TypeScript

import { useState } from 'react';
export type CopiedValue = string | null;
export type CopyFn = (_text: CopyValue, _blobType?: string) => Promise<boolean>;
type CopyValue = Promise<string> | string;
export function useCopyToClipboard(): [CopiedValue, CopyFn] {
const [copiedText, setCopiedText] = useState<CopiedValue>(null);
const copy: CopyFn = async (text, blobType = 'text/plain') => {
if (!navigator?.clipboard) {
console.warn('Clipboard not supported');
return false;
}
// A browser without ClipboardItem throws inside handleClipboardApiCopy, which falls
// back to writeText.
const isClipboardApiSupported = Boolean(navigator.clipboard.write);
// Try to save to clipboard then save it in the state if worked
try {
if (isClipboardApiSupported) {
await handleClipboardApiCopy(text, blobType);
} else {
await handleWriteTextCopy(text);
}
setCopiedText(await text);
return true;
} catch (error) {
console.warn('Copy failed', error);
setCopiedText(null);
return false;
}
};
/**
* Handle copying values to the clipboard using the ClipboardItem API.
*
* Works in all browsers except FireFox.
*
* https://caniuse.com/mdn-api_clipboarditem
*/
const handleClipboardApiCopy = async (value: CopyValue, blobType = 'text/plain') => {
try {
await navigator.clipboard.write([new ClipboardItem({ [blobType]: value })]);
} catch (e) {
// Fallback attempt.
await handleWriteTextCopy(value);
}
};
/**
* Handle copying values to the clipboard using `writeText`.
*
* Works in all browsers except Safari for async values.
*/
const handleWriteTextCopy = async (value: CopyValue) => {
await navigator.clipboard.writeText(await value);
};
return [copiedText, copy];
}