import React, { useMemo, useRef } from 'react' import useTheme from '../use-theme' import withDefaults from '../utils/with-defaults' import { SnippetTypes, CopyTypes, NormalTypes } from '../utils/prop-types' import { getStyles } from './styles' import SnippetIcon from './snippet-icon' import useClipboard from '../utils/use-clipboard' import useToasts from '../use-toasts' interface Props { text?: string | string[] symbol?: string toastText?: string toastType?: NormalTypes filled?: boolean width?: string copy?: CopyTypes type?: SnippetTypes className?: string } const defaultProps = { filled: false, symbol: '$', toastText: 'Copied to clipboard!', toastType: 'success' as NormalTypes, width: 'initial', copy: 'default' as CopyTypes, type: 'default' as SnippetTypes, className: '' } type NativeAttrs = Omit, keyof Props> export type SnippetProps = Props & typeof defaultProps & NativeAttrs const textArrayToString = (text: string[]): string => { return text.reduce((pre, current) => { if (!current) return pre return pre ? `${pre}\n${current}` : current }, '') } const Snippet: React.FC> = ({ type, filled, children, symbol, toastText, toastType, text, width, copy: copyType, className, ...props }) => { const theme = useTheme() const { copy } = useClipboard() const { setToast } = useToasts() const ref = useRef(null) const isMultiLine = text && Array.isArray(text) const style = useMemo(() => getStyles(type, theme.palette, filled), [type, theme.palette, filled]) const showCopyIcon = useMemo(() => copyType !== 'prevent', [copyType]) const childText = useMemo(() => { if (isMultiLine) return textArrayToString(text as string[]) if (!children) return text as string if (!ref.current) return '' return ref.current.textContent }, [ref.current, children, text]) const symbolBefore = useMemo(() => { const str = symbol.trim() return str ? `${str} ` : '' }, [symbol]) const clickHandler = () => { if (!childText || !showCopyIcon) return copy(childText) if (copyType === 'slient') return setToast({ text: toastText, type: toastType }) } return (
{isMultiLine ? ( (text as string[]).map((t, index) =>
{t}
) ) : (
{children || text}
)} {showCopyIcon && (
)}
) } const MemoSnippet = React.memo(Snippet) export default withDefaults(MemoSnippet, defaultProps)