import { useEffect, useRef } from 'react'; /** * Props for useIntersectionObserver hook */ interface IUseIntersectionObserverProps { behavior?: 'enter' | 'leave'; /** Callback function triggered when target element intersects with root */ onIntersect: (() => void) | undefined; /** The element that is used as the viewport for checking visibility of the target */ root?: Element | null; /** Margin around the root element */ rootMargin?: string; /** A number or array of numbers between 0.0 and 1.0 indicating visibility threshold */ threshold?: number | number[]; /** Whether the observer should be active */ enabled?: boolean; } const useIntersectionObserver = ( props: IUseIntersectionObserverProps, ): React.RefObject => { const { behavior = 'enter', onIntersect, root = null, rootMargin = '0px', threshold = 0, enabled = true, } = props; const targetRef = useRef(null); useEffect(() => { if (!enabled || !onIntersect) { return; } const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { if (behavior === 'enter') { onIntersect(); } } else if (behavior === 'leave') { onIntersect(); } }); }, { root, rootMargin, threshold, }, ); const element = targetRef.current; if (element) { observer.observe(element); } // eslint-disable-next-line consistent-return return () => { if (element) { observer.unobserve(element); } }; }, [enabled, onIntersect, root, rootMargin, threshold, behavior]); return targetRef; }; export { useIntersectionObserver, }; export default useIntersectionObserver;