import { useEffect, useState } from "react"; import 'intersection-observer'; import { BasicTarget, getTargetElement } from '../utils/dom'; type InViewport = boolean | undefined; function isInViewPort(el: HTMLElement): boolean { if (!el) return false; const viewPortWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; const rect = el.getBoundingClientRect(); if (rect) { const { top, bottom, left, right } = rect; return bottom > 0 && top <= viewPortHeight && left <= viewPortWidth && right > 0; } return false; } function useInViewport(target: BasicTarget): InViewport { const [inViewPort, setInViewPort] = useState(() => { const el = getTargetElement(target); return isInViewPort(el as HTMLElement); }); useEffect(() => { const el = getTargetElement(target); if (!el) return () => { }; const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { setInViewPort(true); } else { setInViewPort(false); } } }); observer.observe(el as HTMLElement); return () => { observer.disconnect(); } }, [typeof target === "function" ? undefined : target]); return inViewPort; } export default useInViewport;