diff --git a/src/components/hooks/useCopyToClipboard/index.ts b/src/components/hooks/useCopyToClipboard/index.ts index 587004c6..a87219e6 100644 --- a/src/components/hooks/useCopyToClipboard/index.ts +++ b/src/components/hooks/useCopyToClipboard/index.ts @@ -1,90 +1,7 @@ -import { useState } from 'react' +import useCopyToClipboard from './use-copy-clipboard' -const useCopyToClipboard = () => { - const [result, setResult] = useState(null) +import useCopy from './use-copy' - const copy = async (text: string) => { - try { - await navigator.clipboard.writeText(text) - setResult({ state: 'success' }) - } catch (e: any) { - setResult({ state: 'error', message: e.message }) - throw e - } finally { - // 👇 Show the result feedback for 2 seconds - setTimeout(() => { - setResult(null) - }, 2000) - } - } +export default useCopy - // 👇 We want the result as a tuple - return [copy, result] as const -} -export default useCopyToClipboard - -// export function Example() { -// const [inputText, setInputText] = useState(''); -// const [copyToClipboard, copyResult] = useCopyToClipboard(); - -// const handleChangeInput = (e: React.ChangeEvent) => { -// setInputText(e.target.value); -// }; - -// const handleClickCopy = () => { -// copyToClipboard(inputText); -// }; - -// return ( -//
-// -// -//
-// {copyResult?.state === 'success' && 'Copied successfully!'} -// {copyResult?.state === 'error' && `Error: ${copyResult.message}`} -//
-//
-// ); -// } - -// import toast from 'react-hot-toast'; - -// type Props = React.HTMLAttributes & { -// text: string; -// }; - -// function CopyToClipboard({ text, children = 'Copy', ...rest }: Props) { -// const handleClickCopy = async () => { -// try { -// await navigator.clipboard.writeText(text); -// // 👇 Using react-hot-toast to provide feedback -// toast.success('Copied!'); -// } catch (e) { -// toast.error(`Error: ${e.message}`); -// throw e; -// } -// }; - -// return ( -// -// ); -// } - -// export function Example() { -// const [inputText, setInputText] = React.useState(''); - -// const handleChangeInput = (e: React.ChangeEvent) => { -// setInputText(e.target.value); -// }; - -// return ( -//
-// {/* 👇 Don't forget to add this */} -// -// -// -//
-// ); -// } +export { useCopyToClipboard } diff --git a/src/components/hooks/useCopyToClipboard/use-copy-clipboard.ts b/src/components/hooks/useCopyToClipboard/use-copy-clipboard.ts new file mode 100644 index 00000000..587004c6 --- /dev/null +++ b/src/components/hooks/useCopyToClipboard/use-copy-clipboard.ts @@ -0,0 +1,90 @@ +import { useState } from 'react' + +const useCopyToClipboard = () => { + const [result, setResult] = useState(null) + + const copy = async (text: string) => { + try { + await navigator.clipboard.writeText(text) + setResult({ state: 'success' }) + } catch (e: any) { + setResult({ state: 'error', message: e.message }) + throw e + } finally { + // 👇 Show the result feedback for 2 seconds + setTimeout(() => { + setResult(null) + }, 2000) + } + } + + // 👇 We want the result as a tuple + return [copy, result] as const +} +export default useCopyToClipboard + +// export function Example() { +// const [inputText, setInputText] = useState(''); +// const [copyToClipboard, copyResult] = useCopyToClipboard(); + +// const handleChangeInput = (e: React.ChangeEvent) => { +// setInputText(e.target.value); +// }; + +// const handleClickCopy = () => { +// copyToClipboard(inputText); +// }; + +// return ( +//
+// +// +//
+// {copyResult?.state === 'success' && 'Copied successfully!'} +// {copyResult?.state === 'error' && `Error: ${copyResult.message}`} +//
+//
+// ); +// } + +// import toast from 'react-hot-toast'; + +// type Props = React.HTMLAttributes & { +// text: string; +// }; + +// function CopyToClipboard({ text, children = 'Copy', ...rest }: Props) { +// const handleClickCopy = async () => { +// try { +// await navigator.clipboard.writeText(text); +// // 👇 Using react-hot-toast to provide feedback +// toast.success('Copied!'); +// } catch (e) { +// toast.error(`Error: ${e.message}`); +// throw e; +// } +// }; + +// return ( +// +// ); +// } + +// export function Example() { +// const [inputText, setInputText] = React.useState(''); + +// const handleChangeInput = (e: React.ChangeEvent) => { +// setInputText(e.target.value); +// }; + +// return ( +//
+// {/* 👇 Don't forget to add this */} +// +// +// +//
+// ); +// } diff --git a/src/components/hooks/useCopyToClipboard/use-copy.ts b/src/components/hooks/useCopyToClipboard/use-copy.ts new file mode 100644 index 00000000..e7309222 --- /dev/null +++ b/src/components/hooks/useCopyToClipboard/use-copy.ts @@ -0,0 +1,41 @@ +'use client' +import { useCallback, useEffect, useState } from 'react' + +type CopiedValue = string | null + +type CopyFn = (text: string) => Promise + +const useCopy = ({ isCopiedDelay = 2000 }: { isCopiedDelay?: number } = {}): [CopiedValue, CopyFn, boolean] => { + const [copiedText, setCopiedText] = useState(null) + const [isCopied, setIsCopied] = useState(false) + + useEffect(() => { + if (!isCopied) { + return + } + setTimeout(() => { + setIsCopied(false) + }, isCopiedDelay) + }, [isCopied, isCopiedDelay]) + + const copy: CopyFn = useCallback(async (text) => { + if (!navigator?.clipboard) { + return false + } + + // Try to save to clipboard then save it in the state if worked + try { + await navigator.clipboard.writeText(text) + setCopiedText(text) + setIsCopied(true) + return true + } catch (_error) { + setCopiedText(null) + return false + } + }, []) + + return [copiedText, copy, isCopied] +} + +export default useCopy diff --git a/src/components/stateless/ReactSignature/index.jsx b/src/components/stateless/ReactSignature/index.jsx new file mode 100644 index 00000000..e69de29b