From 65b4bdcf774cef6e554f5f0fb543d56385a46087 Mon Sep 17 00:00:00 2001 From: Phil Buchanan Date: Mon, 4 Oct 2021 15:22:45 -0400 Subject: [PATCH] Initial work on adding copy to clipboard support --- .../copy-to-clipboard-button/index.js | 47 +++++++++++++++++++ .../copy-to-clipboard-button/index.scss | 7 +++ src/components/display/index.js | 9 +++- src/components/display/index.scss | 7 ++- src/components/index.js | 1 + src/hooks/index.js | 1 + src/hooks/use-copy-to-clipboard/index.js | 28 +++++++++++ 7 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/components/copy-to-clipboard-button/index.js create mode 100644 src/components/copy-to-clipboard-button/index.scss create mode 100644 src/hooks/use-copy-to-clipboard/index.js diff --git a/src/components/copy-to-clipboard-button/index.js b/src/components/copy-to-clipboard-button/index.js new file mode 100644 index 0000000..d583aa0 --- /dev/null +++ b/src/components/copy-to-clipboard-button/index.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { useEffect, useState } from 'react'; + +import { useCopyToClipboard } from '../../hooks'; +import { classnames } from '../../utils'; +import './index.scss'; + +export default ({ + value, + className, +}) => { + const [isCopied, setIsCopied] = useState(false); + const [copiedText, copyToClipboard] = useCopyToClipboard(); + + useEffect(() => { + if (!!isCopied) { + const timer = setTimeout(() => { + setIsCopied(false); + }, 2000); + + return () => { + clearTimeout(timer); + }; + } + }, [isCopied]); + + return ( + + ); +}; diff --git a/src/components/copy-to-clipboard-button/index.scss b/src/components/copy-to-clipboard-button/index.scss new file mode 100644 index 0000000..b50e389 --- /dev/null +++ b/src/components/copy-to-clipboard-button/index.scss @@ -0,0 +1,7 @@ +.c-copy-to-clipboard-button { + display: flex; + justify-content: center; + align-items: center; + width: 24px; + height: 24px; +} diff --git a/src/components/display/index.js b/src/components/display/index.js index 42aaa66..7f2bafb 100644 --- a/src/components/display/index.js +++ b/src/components/display/index.js @@ -1,7 +1,7 @@ import React, { useEffect, useLayoutEffect, useState } from 'react'; -import { Button, Equation } from '../../components'; -import { addCommas } from '../../utils'; +import { Button, CopyToClipboardButton, Equation } from '../../components'; +import { addCommas, classnames } from '../../utils'; import './index.scss'; const operators = { @@ -91,6 +91,11 @@ export default ({ ) }
+ { computedResult !== undefined && ( + + ) }
{ addCommas(resultDisplay) }
diff --git a/src/components/display/index.scss b/src/components/display/index.scss index 3ec6e95..8ab8c1f 100644 --- a/src/components/display/index.scss +++ b/src/components/display/index.scss @@ -21,8 +21,8 @@ .c-display__previous-wrapper, .c-display__result-wrapper, .c-display__equation-body { - padding-left: 12px; - padding-right: 12px; + padding-left: 20px; + padding-right: 24px; } .c-display__previous-wrapper { @@ -47,6 +47,9 @@ } .c-display__result-wrapper { + display: flex; + justify-content: space-between; + align-items: center; flex: 1 1 auto; font-size: 3rem; font-weight: var(--font--weight--light); diff --git a/src/components/index.js b/src/components/index.js index 5375a98..97d2ba9 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,5 +1,6 @@ export { default as BaseControl } from './base-control'; export { default as Button } from './button'; +export { default as CopyToClipboardButton } from './copy-to-clipboard-button'; export { default as Display } from './display'; export { default as Equation } from './equation'; export { default as History } from './history'; diff --git a/src/hooks/index.js b/src/hooks/index.js index c833d96..1d851fc 100644 --- a/src/hooks/index.js +++ b/src/hooks/index.js @@ -1,3 +1,4 @@ +export { default as useCopyToClipboard } from './use-copy-to-clipboard'; export { default as useDebounceEffect } from './use-debounce-effect'; export { default as useKeyPress } from './use-key-press'; export { default as useLocalStorage } from './use-local-storage'; diff --git a/src/hooks/use-copy-to-clipboard/index.js b/src/hooks/use-copy-to-clipboard/index.js new file mode 100644 index 0000000..e7996c1 --- /dev/null +++ b/src/hooks/use-copy-to-clipboard/index.js @@ -0,0 +1,28 @@ +import { useState } from 'react'; + +export default function useCopyToClipboard() { + const [copiedText, setCopiedText] = useState(null); + + const copy = (text) => { + if (!navigator?.clipboard) { + console.warn('Clipboard not supported'); + + return false; + } + + // Try to save to clipboard then save it in the state if worked + try { + navigator.clipboard.writeText(text); + setCopiedText(text); + + return true; + } catch (error) { + console.warn('Copy failed', error); + setCopiedText(null); + + return false; + } + } + + return [copiedText, copy]; +}