import type { TooltipProps } from '@mui/material' import { useLayoutEffect, useRef, useState, type JSX, type Ref } from 'react' import { Tooltip } from '../tooltip/tooltip' const EMPTY_DEPENDENCIES: unknown[] = [] /** * An intelligent tooltip wrapper that automatically detects text overflow and displays a tooltip only when content is truncated. * * @remarks * Uses a render prop pattern. The child function receives a `ref` that must be attached to the element being monitored for overflow. Use the `dependencies` array to trigger re-evaluation when content or container size changes. * * @example * ```tsx * * {({ ref }) => ( * * This is a long text that might get truncated * * )} * * ``` */ export function SmartTooltip({ title, dependencies = EMPTY_DEPENDENCIES, timeout = 500, TooltipProps, children, }: { title: string | undefined dependencies?: unknown[] timeout?: number children: (props: { ref: Ref }) => JSX.Element TooltipProps?: Partial }) { const ref = useRef(null) const [isOverflowing, setIsOverflowing] = useState(false) // Call sites pass a fresh `dependencies={[…]}` literal each render; key by // value so the effect does not churn ResizeObserver on referential churn. const dependenciesKey = JSON.stringify(dependencies) useLayoutEffect(() => { const checkOverflow = () => { const el = ref.current if (!el) return setIsOverflowing( el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight, ) } // Initial measure after layout settles (fonts, flex collapse, …). const timerId = setTimeout(checkOverflow, timeout) // Re-measure when the element is resized (e.g. legend title reflows as // hover-faded actions collapse/expand). const el = ref.current const resizeObserver = el && typeof ResizeObserver !== 'undefined' ? new ResizeObserver(checkOverflow) : null if (el) resizeObserver?.observe(el) return () => { clearTimeout(timerId) resizeObserver?.disconnect() } }, [dependenciesKey, timeout]) return ( {children({ ref })} ) }