import { RefObject, useEffect, useState } from 'react'; /** * Returns true once the observed element has come within `margin` pixels of * the viewport. Disconnects the observer after the first intersection so there * is no ongoing overhead. */ export function useNearViewport(ref: RefObject, margin = 200): boolean { const [triggered, setTriggered] = useState(false); useEffect(() => { const el = ref.current; if (!el || triggered) return undefined; const observer = new IntersectionObserver( (entries) => { if (entries[0]?.isIntersecting) { setTriggered(true); observer.disconnect(); } }, { rootMargin: `${margin}px` }, ); observer.observe(el); return () => observer.disconnect(); }, [ref, margin, triggered]); return triggered; }