import classNames from 'classnames'; import copy from 'copy-to-clipboard'; import type { MouseEvent, ReactNode } from 'react'; import { Children, cloneElement, isValidElement, useEffect, useState } from 'react'; import Portal from '@/components/elements/Portal'; import FadeTransition from '@/components/elements/transitions/FadeTransition'; interface CopyOnClickProps { text: string | number | null | undefined; showInNotification?: boolean; children: ReactNode; } const CopyOnClick = ({ text, showInNotification = true, children }: CopyOnClickProps) => { const [copied, setCopied] = useState(false); useEffect(() => { if (!copied) return; const timeout = setTimeout(() => { setCopied(false); }, 2500); return () => { clearTimeout(timeout); }; }, [copied]); if (!isValidElement(children)) { throw new Error('Component passed to must be a valid React element.'); } const child = !text ? Children.only(children) : cloneElement(Children.only(children), { // @ts-expect-error I don't know className: classNames(children.props.className || '', 'cursor-pointer'), onClick: (e: MouseEvent) => { copy(String(text)); setCopied(true); if (typeof children.props.onClick === 'function') { children.props.onClick(e); } }, }); return ( <> {copied && ( {showInNotification ? `Copied "${String(text)}" to clipboard.` : 'Copied text to clipboard.'} )} {child} > ); }; export default CopyOnClick;
{showInNotification ? `Copied "${String(text)}" to clipboard.` : 'Copied text to clipboard.'}