{"version":3,"sources":["../src/hooks/useIntersectionObserver.ts"],"names":["useIntersectionObserver","elementRef","threshold","root","rootMargin","freezeOnceVisible","entry","setEntry","useState","useEffect","element","observer"],"mappings":"uCA6CO,SAASA,CAAAA,CACdC,EACA,CAAE,SAAA,CAAAC,EAAY,CAAG,CAAA,IAAA,CAAAC,EAAO,IAAM,CAAA,UAAA,CAAAC,EAAa,IAAM,CAAA,iBAAA,CAAAC,CAAoB,CAAA,CAAA,CAAM,CAAyB,CAAA,GAClE,CAClC,GAAM,CAACC,CAAOC,CAAAA,CAAQ,EAAIC,QAA2C,CAAA,IAAI,CAEzE,CAAA,OAAAC,SAAU,CAAA,IAAM,CACd,IAAMC,CAAAA,CAAUT,GAAA,IAAAA,CAAAA,KAAAA,CAAAA,CAAAA,CAAAA,CAAY,QAI5B,GAHI,CAACS,CAGDL,EAAAA,CAAAA,GAAqBC,CAAA,EAAA,IAAA,EAAAA,EAAO,cAAgB,CAAA,CAAA,OAEhD,IAAMK,CAAW,CAAA,IAAI,qBACnB,CAAC,CAACL,CAAK,CAAM,GAAA,CACXC,EAASD,CAAK,EAChB,EACA,CAAE,SAAA,CAAAJ,EAAW,IAAAC,CAAAA,CAAAA,CAAM,UAAAC,CAAAA,CAAW,CAChC,CAAA,CAEA,OAAAO,CAAS,CAAA,OAAA,CAAQD,CAAO,CAEjB,CAAA,IAAM,CACXC,CAAS,CAAA,UAAA,GACX,CACF,CAAG,CAAA,CAACV,EAAYC,CAAWC,CAAAA,CAAAA,CAAMC,EAAYC,CAAmBC,CAAAA,CAAAA,EAAA,YAAAA,CAAO,CAAA,cAAc,CAAC,CAAA,CAE/EA,CACT","file":"useIntersectionObserver.mjs","sourcesContent":["import { useState, useEffect, RefObject } from \"react\";\n\ninterface IntersectionOptions extends IntersectionObserverInit {\n  freezeOnceVisible?: boolean;\n}\n\n/**\n * Hook that tracks when an element enters or leaves the viewport using the Intersection Observer API.\n *\n * Useful for implementing lazy loading, infinite scrolling, animations on scroll,\n * or tracking visibility of elements for analytics purposes.\n *\n * @param elementRef - React ref object pointing to the target element to observe\n * @param options - Configuration options for the intersection observer:\n *   - `threshold`: Number or array defining at what percentage of visibility the callback should trigger (0-1)\n *   - `root`: Element used as viewport for checking visibility (defaults to browser viewport)\n *   - `rootMargin`: Margin around the root element (CSS-like syntax, e.g., \"10px 20px\")\n *   - `freezeOnceVisible`: If true, stops observing once element becomes visible (useful for one-time animations)\n *\n * @returns IntersectionObserverEntry object containing visibility information, or null if element not found\n *\n * @example\n * ```tsx\n * function LazyImage({ src, alt }: { src: string; alt: string }) {\n *   const imgRef = useRef<HTMLImageElement>(null);\n *   const entry = useIntersectionObserver(imgRef, {\n *     threshold: 0.1,\n *     freezeOnceVisible: true\n *   });\n *\n *   const isVisible = entry?.isIntersecting;\n *\n *   return (\n *     <img\n *       ref={imgRef}\n *       src={isVisible ? src : undefined}\n *       alt={alt}\n *       style={{ opacity: isVisible ? 1 : 0 }}\n *     />\n *   );\n * }\n * ```\n *\n * @see https://thibault.sh/hooks/use-intersection-observer\n */\nexport function useIntersectionObserver<T extends HTMLElement>(\n  elementRef: RefObject<T | null> | null,\n  { threshold = 0, root = null, rootMargin = \"0%\", freezeOnceVisible = false }: IntersectionOptions = {}\n): IntersectionObserverEntry | null {\n  const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);\n\n  useEffect(() => {\n    const element = elementRef?.current;\n    if (!element) return;\n\n    // Don't observe if element is already visible and freeze is enabled\n    if (freezeOnceVisible && entry?.isIntersecting) return;\n\n    const observer = new IntersectionObserver(\n      ([entry]) => {\n        setEntry(entry);\n      },\n      { threshold, root, rootMargin }\n    );\n\n    observer.observe(element);\n\n    return () => {\n      observer.disconnect();\n    };\n  }, [elementRef, threshold, root, rootMargin, freezeOnceVisible, entry?.isIntersecting]);\n\n  return entry;\n}\n"]}