import { FC, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import styled, { useTheme } from "styled-components"; import Box from "../Styled/Box"; import Button from "../Styled/Button"; import Icon, { StyledIcon } from "../Styled/Icon"; import Input from "../Styled/Input"; import Spacing from "../Styled/Spacing"; import { TextSpan } from "../Styled/Text"; enum CopyStatus { Success, Error, Default } interface ClipboardProps { text?: string; inputTheme?: "light" | "dark"; inputPlaceholder?: string; // needed for testing timeout?: number; onCopy?: (contents: string) => void; createdMessage?: string; } const Clipboard: FC = (props) => { const { text, inputTheme, inputPlaceholder, onCopy, createdMessage } = props; const { t } = useTranslation(); const styledTheme = useTheme(); const [status, setStatus] = useState(CopyStatus.Default); const [showCreatedMessage, setShowCreatedMessage] = useState(false); const prevTextRef = useRef(text); useEffect(() => { if (createdMessage && !prevTextRef.current && text) { setShowCreatedMessage(true); } prevTextRef.current = text; }, [text, createdMessage]); const handleCopy = async () => { setShowCreatedMessage(false); try { if (text) { await navigator.clipboard.writeText(text); setStatus(CopyStatus.Success); if (onCopy) onCopy(text); } else { setStatus(CopyStatus.Error); } } catch { setStatus(CopyStatus.Error); } }; useEffect(() => { if (status === CopyStatus.Success || status === CopyStatus.Error) { const timer = setTimeout(() => { setStatus(CopyStatus.Default); }, props.timeout ?? 3000); return () => clearTimeout(timer); } }, [status, props.timeout]); const canCopy = !!navigator.clipboard; const statusMessage = status === CopyStatus.Error ? t("clipboard.unsuccessful") : status === CopyStatus.Success ? t("clipboard.success") : createdMessage; return ( e.currentTarget.select()} /> {canCopy && ( )} {(canCopy && status !== CopyStatus.Default) || showCreatedMessage ? ( <> {statusMessage} ) : null} ); }; export default Clipboard; const ClipboardDiv = styled.div` position: relative; `;