useClipboard
A hook that allows you to copy a value to the clipboard, the value initialized can be overridden by passing a value to the copy
function. This hook also takes care of the state change required to display a UI change when the user copies a value.
Parameters
Name | Type | Description |
---|---|---|
copyString | string, number | The value to be copied to the clipboard, this can be overridden at any time by passing a value to the |
config.delay | number | The delay in milliseconds after which the |
Return Values
Name | Type | Description |
---|---|---|
clipboard.copied | boolean | A boolean value that indicates whether the user has copied the value to the clipboard, the value is reset to false after the |
clipboard.copy | number | A function to copy a value to the clipboard, the value initialized can be overridden by passing a value to the |
Source Code
const copyMethods = [ async (str) => { await navigator.clipboard.writeText(str); }, async (str) => { const textarea = document.createElement('textarea'); textarea.value = str; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.focus(); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); }, ]; const useClipboard = (copyString, config = {}) => { const { delay = 1000 } = config; let lastCopied = $state(null); let copied = $derived(lastCopied !== null); const copyToClipboard = async (overwriteCopyStr) => { const strToCopy = String(overwriteCopyStr === undefined ? copyString : overwriteCopyStr); for (const method of copyMethods) { try { await method(strToCopy); return; } catch (error) { console.error('Copy method failed:', error); } } throw new Error('Copy failed, browser not supported.'); }; const copy = async (newCopyString) => { if (!['string', 'number'].includes(typeof newCopyString)) { throw new Error('Invalid copy type: Only string and number are supported.'); } const time = Date.now(); lastCopied = time; await copyToClipboard(newCopyString); await new Promise((res) => setTimeout(res, delay)); if (time !== lastCopied) return; lastCopied = null; }; return { get copied() { return copied; }, copy, }; }; export default useClipboard;
<script> import useClipboard from './useClipboard.svelte'; const intiialValue = 'Rich Harris'; const clipboard = useClipboard(intiialValue); let value = $state(intiialValue); </script> <div class="container"> <input bind:value placeholder="Enter text to copy..." /> <button type="button" on:click={() => clipboard.copy(value)}>{clipboard.copied ? 'Copied' : 'Copy'}</button> </div> <style lang="scss"> .container { display: flex; justify-content: center; gap: 15px; } button { width: 80px; } </style>