import { useEffect, useRef, useState } from "react"; import { useIsomorphicLayoutEffect } from "../use-isomorphic-layout-effect"; export type OverflowDirection = "vertical" | "horizontal" | "any"; // eslint-disable-next-line max-lines-per-function export const useIsOverflow = ({ ref, direction = "vertical", trigger, }: { ref: React.MutableRefObject; direction?: OverflowDirection; trigger?: unknown; }) => { const [isOverflow, setIsOverflow] = useState(false); const [width, setWidth] = useState(0); const observer = useRef( typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver((entries) => { const firstEntry = entries[0]; const firstEntryContentRect = firstEntry?.contentRect; setWidth(firstEntryContentRect?.width); }) ); useEffect(() => { const { current } = ref; const observerCurrent = observer.current; if (current) { observer.current?.observe(current); } return () => { current && observerCurrent?.unobserve(current); }; }, [ref]); useIsomorphicLayoutEffect(() => { const { current } = ref; if (current) { const currentOverflow = current.style.overflow; if (!currentOverflow || currentOverflow !== "hidden") { current.style.overflow = "hidden"; } const hasOverflow = direction === "vertical" ? current.scrollHeight > current.clientHeight : direction === "horizontal" ? current.scrollWidth > current.clientWidth : current.scrollHeight > current.clientHeight || current.scrollWidth > current.clientWidth; setIsOverflow(hasOverflow); current.style.overflow = currentOverflow; } }, [ref, direction, width, ...(Array.isArray(trigger) ? trigger : [trigger])]); return isOverflow; };