import * as React from 'react'; import classnames from 'classnames'; import ILocalContainerProps from '../../../common/structures/ILocalContainerProps'; import { Container } from '../../modules/Container/Container'; import { CopyButtonIcon, CopiedStateIconVariants, UncopiedStateIconVariants } from './_private/CopyButtonIcon'; import styles from './CopyButton.scss'; /** * This lib is only exported as a CommonJS module, so the require syntax must be used * unless the EsModuleInterop flag is turned on for this project */ const copy = require('clipboard-copy'); const { useState } = React; export enum CopiedStateBGStyleVariants { green = 'green', transparent = 'transparent', transparentGrayText = 'transparentGrayText', } export enum UncopiedStateBGStyleVariants { gray = 'gray', transparent = 'transparent', } export enum PaddingAmount { small = 'small', medium = 'medium', } export interface ICopyButtonProps extends ILocalContainerProps { tag?: string; /* Timeout for how long to show "copied" state after a click */ copiedTimeout: number; /* Text to show in uncopied state */ uncopiedStateText?: string; /* Text to show in copied state */ copiedStateText?: string; /* Icon to show in uncopied state */ uncopiedStateIconVariant?: keyof typeof UncopiedStateIconVariants | null; /* Icon to show in copied state */ copiedStateIconVariant?: keyof typeof CopiedStateIconVariants | null; /* Background styling for uncopied state */ uncopiedStateBGStyleVariant?: keyof typeof UncopiedStateBGStyleVariants; /* Background styling for copied state */ copiedStateBGStyleVariant?: keyof typeof CopiedStateBGStyleVariants; /* Padding amount to apply */ padding?: PaddingAmount | keyof typeof PaddingAmount; /* Text to copy to the clipboard */ textToCopy: string; }; export const CopyButton = (props: ICopyButtonProps) => { const { className, copiedStateBGStyleVariant, uncopiedStateBGStyleVariant, copiedStateIconVariant, copiedStateText, copiedTimeout, id, padding, style, tag, textToCopy, uncopiedStateText, uncopiedStateIconVariant, } = props; const Tag: any = tag; const [isCopied, setIsCopied] = useState(false); const [popin, setPopin] = useState(false); const animationDuration: number = 500; const setIsCopiedAndTriggerPopin = (newIsCopied: boolean) => { setIsCopied(newIsCopied); setPopin(true); setTimeout(() => setPopin(false), animationDuration) } const handleClick = () => { copy(textToCopy); if (isCopied) return; const newTimeout: number = copiedTimeout + animationDuration * 2; setIsCopiedAndTriggerPopin(true); setTimeout(() => setIsCopiedAndTriggerPopin(false), newTimeout); } const isTransparentUncopiedStateBG = uncopiedStateBGStyleVariant === UncopiedStateBGStyleVariants.transparent; const isGrayUncopiedStateBG = uncopiedStateBGStyleVariant === UncopiedStateBGStyleVariants.gray; const isGrayCopiedStateText = copiedStateBGStyleVariant === CopiedStateBGStyleVariants.transparentGrayText; const isTransparentCopiedStateBG = copiedStateBGStyleVariant === CopiedStateBGStyleVariants.transparent || isGrayCopiedStateText; const isGreenCopiedStateBG = copiedStateBGStyleVariant === CopiedStateBGStyleVariants.green; const smallPadding = padding === PaddingAmount.small; const mediumPadding = padding === PaddingAmount.medium; return ( {(isCopied && copiedStateText || !isCopied && uncopiedStateText) && {isCopied ? copiedStateText : uncopiedStateText} } ) }; CopyButton.defaultProps = { tag: 'button', copiedTimeout: 1000, uncopiedStateText: 'Copy', copiedStateText: 'Copied', uncopiedStateIconVariant: null, copiedStateIconVariant: CopiedStateIconVariants.checkmark, copiedStateBGStyleVariant: CopiedStateBGStyleVariants.green, uncopiedStateBGStyleVariant: UncopiedStateBGStyleVariants.gray, padding: PaddingAmount.small, /** * Though this prop is optional, it is included here so that any falsy JS values (null & undefined in particular) * are passed into the user's clipboard as an empty string */ textToCopy: '', };