import React, { useCallback, useEffect, useRef, useState } from 'react' import Mdash from '../Mdash/Mdash' import Tooltip, { type TooltipProps } from '../Tooltip/Tooltip' import { trimText } from '../../services/HelperServiceTyped' import { cn } from '../../services/cn' export type TrimTextProps = { /** The text that you need truncated */ text: string /** The number of characters before the text is truncated */ limit?: number /** Position the tooltip will open */ position?: TooltipProps['position'] /** Optional class to add to the text */ customClass?: string /** Optional prop to add a test id to the TrimText for QA testing */ qaTestId?: string } const TrimText = ({ text, limit, position, customClass = '', qaTestId = 'trim-text', }: TrimTextProps): React.JSX.Element => { const divRef = useRef(null) const spanRef = useRef(null) const [isTruncated, setIsTruncated] = useState(false) // Memoized function that checks if text is truncated by comparing scroll width (total content width) vs visible width const checkTruncation = useCallback(() => { if (divRef.current && spanRef.current) { const isTextTruncated = divRef.current?.scrollWidth > divRef.current.clientWidth || spanRef.current?.scrollWidth > spanRef.current.clientWidth setIsTruncated(isTextTruncated) } }, []) // Defer the execution of checkTruncation to the next event loop iteration // to ensure the DOM is fully rendered before checking truncation setTimeout(() => { checkTruncation() }, 0) useEffect(() => { const handleResize = () => { checkTruncation() } window.addEventListener('resize', handleResize) // Create observer to watch for size changes const resizeObserver = new ResizeObserver(checkTruncation) if (divRef.current) { resizeObserver.observe(divRef.current) if (spanRef.current) { resizeObserver.observe(spanRef.current) } } return () => { window.removeEventListener('resize', handleResize) resizeObserver.disconnect() } }, [checkTruncation, text, divRef, spanRef]) if (!text) return const trimmedText = trimText(text, limit ? limit : text.length) return limit ? ( trimmedText.length <= (limit ? limit : text?.length) ? ( {text} ) : ( {trimmedText} ) ) : (
{isTruncated ? ( {text} ) : ( {text} )}
) } export default TrimText