import { Fragment, useEffect, useRef, useState } from 'react'; import Box from '../Box'; import Flex from '../Flex'; import Icon from '../Icon'; import IconCompact from '../IconCompact'; import Text from '../Text'; import { MaxLength } from '../TextField'; import useExperimentalTheme from '../utils/useExperimentalTheme'; type Props = { maxLength: MaxLength; currentLength?: number; disabled?: boolean; }; export default function FormHelperTextCounter({ disabled, currentLength, maxLength }: Props) { const ref = useRef(null); const [width, setWidth] = useState(undefined); const theme = useExperimentalTheme(); useEffect(() => { const containerWidth = ref?.current?.getBoundingClientRect().width; setWidth(containerWidth ? Math.ceil(containerWidth) : undefined); }, [ref]); const maxLengthChars = maxLength?.characterCount.toString() ?? ''; const maxLengthReached = (currentLength ?? 0) >= (maxLength.characterCount ?? 0); let icon: 'workflow-status-warning' | 'workflow-status-problem' = 'workflow-status-warning'; let iconVR: 'compact-workflow-status-warning' | 'compact-workflow-status-problem' = 'compact-workflow-status-warning'; let textColor: 'warning' | 'error' | 'disabled' = 'warning'; if ( typeof currentLength === 'number' && typeof maxLength?.characterCount === 'number' && currentLength > maxLength?.characterCount ) { icon = 'workflow-status-problem'; iconVR = 'compact-workflow-status-problem'; textColor = 'error'; } if (disabled) { textColor = 'disabled'; } return ( {/* This hidden container is used to calculate the width of the character tracker and prevent spacing changes on each input value changes */} {`${maxLengthChars}/${maxLengthChars}`} {maxLengthReached ? ( {/* This visually hidden error message is accessible by screenreaders. It alerts the user right after the maximum length is reached. */} {maxLength?.errorAccessibilityLabel} {theme.MAIN ? ( ) : ( )} ) : ( )} , {`${currentLength?.toString() ?? ''}/${maxLengthChars}`} ); }