/* eslint-disable react/jsx-no-bind */ import { withStyles } from '@material-ui/styles'; import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import Icon from '../icons/components/Icon'; import { IconCheck, IconCopy } from '../icons/svg'; import { withPixelLineHeight } from '../styles/functions.web'; import { Theme } from '../ui/types'; import { copyText } from '../util/helpers'; const styles = (theme: Theme) => { return { copyButton: { ...withPixelLineHeight(theme.typography.bodyLongRegular), borderRadius: theme.shape.borderRadius, display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 8px 8px 16px', marginTop: 5, width: 'calc(100% - 24px)', height: 24, background: theme.palette.action01, cursor: 'pointer', '&:hover': { backgroundColor: theme.palette.action01Hover, fontWeight: 600 }, '&.clicked': { background: theme.palette.success02 }, '& > div > svg > path': { fill: theme.palette.text01 } }, content: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 292, marginRight: theme.spacing(3), '&.selected': { fontWeight: 600 } } }; }; let mounted: boolean; type Props = { /** * Css class to apply on container. */ className: string, /** * An object containing the CSS classes. */ classes: any, /** * The displayed text. */ displayedText: string, /** * The id of the button. */ id?: string, /** * The text displayed on copy success. */ textOnCopySuccess: string, /** * The text displayed on mouse hover. */ textOnHover: string, /** * The text that needs to be copied (might differ from the displayedText). */ textToCopy: string }; /** * Component meant to enable users to copy the conference URL. * * @returns {React$Element} */ function CopyButton({ classes, className, displayedText, textToCopy, textOnHover, textOnCopySuccess, id }: Props) { const [ isClicked, setIsClicked ] = useState(false); const [ isHovered, setIsHovered ] = useState(false); useEffect(() => { mounted = true; return () => { mounted = false; }; }, []); /** * Click handler for the element. * * @returns {void} */ async function onClick() { setIsHovered(false); const isCopied = await copyText(textToCopy); if (isCopied) { setIsClicked(true); setTimeout(() => { // avoid: Can't perform a React state update on an unmounted component if (mounted) { setIsClicked(false); } }, 2500); } } /** * Hover handler for the element. * * @returns {void} */ function onHoverIn() { if (!isClicked) { setIsHovered(true); } } /** * Hover handler for the element. * * @returns {void} */ function onHoverOut() { setIsHovered(false); } /** * KeyPress handler for accessibility. * * @param {React.KeyboardEventHandler} e - The key event to handle. * * @returns {void} */ function onKeyPress(e: React.KeyboardEvent) { if (onClick && (e.key === ' ' || e.key === 'Enter')) { e.preventDefault(); onClick(); } } /** * Renders the content of the link based on the state. * * @returns {React$Element} */ function renderContent() { if (isClicked) { return ( <>
{ textOnCopySuccess }
); } return ( <>
{ isHovered ? textOnHover : displayedText }
); } return (
{ renderContent() }
); } CopyButton.defaultProps = { className: '' }; // @ts-ignore export default withStyles(styles)(CopyButton);