Skip to content

Instantly share code, notes, and snippets.

@manix84
Last active July 24, 2024 08:26
Show Gist options
  • Select an option

  • Save manix84/2bf3d984ee115eadfc3e5e3385213480 to your computer and use it in GitHub Desktop.

Select an option

Save manix84/2bf3d984ee115eadfc3e5e3385213480 to your computer and use it in GitHub Desktop.
A React+Typescript hook for copying different mime types to the clipboard at once.
/**
This code is licensed under the terms of the MIT license
*/
/**
Usage:
const { copyToClipboard } = useClipboard();
copyToClipboard([
{ type: "text/plain", data: "Some String" },
{ type: "text/html", data: "<h1>Some Header</h1>" }
])?.then(() => {
console.log("SUCCESS")
}).catch(() => {
console.error("OH NOS!")
});
*/
import { useCallback } from 'react';
type ClipboardItemData = {
type: string;
data: string;
};
const useClipboard = () => {
const copyToClipboard = useCallback(async (items: ClipboardItemData[]): Promise<void> => {
if (navigator.clipboard && navigator.clipboard.write) {
try {
if (typeof ClipboardItem !== 'undefined' && navigator.clipboard.write) {
const clipboardItems = new ClipboardItem(
items.reduce((acc, item) => {
acc[item.type] = new Blob([item.data], { type: item.type });
return acc;
}, {} as Record<string, string | Blob | PromiseLike<string | Blob>>));
await navigator.clipboard.write([clipboardItems]);
} else {
const plainText = (items.filter((item) => item.type === "text/plain")[0] || items[0]).data;
// Fallback for browsers that do not support ClipboardItem (e.g., Firefox)
await navigator.clipboard.writeText(plainText);
}
} catch (error) {
console.error('Error copying to clipboard: ', error);
throw error;
}
} else {
// Fallback to document.execCommand for older browsers
const plainText = (items.filter((item) => item.type === "text/plain")[0] || items[0]).data;
const textarea = document.createElement('textarea');
textarea.value = plainText;
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} catch (error) {
console.error('Error copying to clipboard: ', error);
throw error;
} finally {
document.body.removeChild(textarea);
}
}
}, []);
return { copyToClipboard };
};
export default useClipboard;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment