@sky-mavis/tanto-widget
Version:
Tanto Widget
82 lines • 2.38 kB
JavaScript
import {jsx,jsxs}from'@emotion/react/jsx-runtime';import {useTheme}from'@emotion/react';import {AnimatePresence}from'motion/react';import*as m from'motion/react-m';import {useState,useCallback,useEffect}from'react';import {CheckCircleFillIcon}from'../../assets/CheckCircleFillIcon.mjs';import {CopyIcon}from'../../assets/CopyIcon.mjs';import {Box}from'../box/Box.mjs';import {Button}from'../button/Button.mjs';const DEFAULT_ANIMATION_DURATION = 1_500;
function useClipboard(value, duration = DEFAULT_ANIMATION_DURATION) {
const [copied, setCopied] = useState(false);
const handleCopy = useCallback(async () => {
if (copied || !value) return;
try {
await navigator.clipboard.writeText(value.trim());
setCopied(true);
} catch {}
}, [value, copied]);
useEffect(() => {
if (!copied) return;
const timer = setTimeout(() => setCopied(false), duration);
return () => clearTimeout(timer);
}, [copied, duration]);
return {
copied,
handleCopy
};
}
function CopyButton({
intent = 'secondary',
size = 'xsmall',
value,
children,
...rest
}) {
const theme = useTheme();
const {
copied,
handleCopy
} = useClipboard(value);
const containerStyles = {
align: 'center',
gap: children ? 4 : 0,
mx: children ? 0 : -2
};
return jsx(Button, {
intent: intent,
size: size,
onClick: handleCopy,
disabled: !value,
...rest,
children: jsxs(Box, {
...containerStyles,
children: [jsx(AnimatePresence, {
mode: "popLayout",
initial: false,
children: jsx(m.div, {
initial: {
opacity: 0,
scale: 0.5,
rotate: copied ? -180 : 180
},
animate: {
opacity: 1,
scale: 1,
rotate: 0
},
exit: {
opacity: 0,
scale: 0.5,
rotate: copied ? 180 : -180
},
transition: {
type: 'spring',
stiffness: 300,
damping: copied ? 20 : 30
},
children: copied ? jsx(CheckCircleFillIcon, {
color: theme.successColor,
size: 18
}) : jsx(CopyIcon, {
size: 18
})
}, copied.toString())
}), children && jsx("div", {
children: children
})]
})
});
}export{CopyButton};