UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

56 lines 3.19 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { useState, useEffect } from 'react'; /** * Custom hook to track whether an element is visible in the viewport or a scrollable ancestor. * Uses the IntersectionObserver API. * * @template T - The type of the element being observed. * @param {RefObject<T>} elementRef - A ref attached to the element to observe. * @param {UseVisibilityOptions} [options] - Configuration options for the IntersectionObserver. * @param {Element | null} [options.root=null] - The element that is used as the viewport for checking visibility. Defaults to the browser viewport. * @param {string} [options.rootMargin='0px'] - Margin around the root. Can have values similar to the CSS margin property. * @param {number | number[]} [options.threshold=0] - A single number or an array of numbers indicating the percentage of the target's visibility the observer triggers at. * @param {boolean} [options.initialIsVisible=false] - Initial state before the observer runs. * @param {boolean} [options.disconnectOnVisible=false] - If true, the observer disconnects after the element first becomes visible. * @returns {boolean} True if the element is currently intersecting/visible based on the options, false otherwise. */ export const useVisibility = (elementRef, _a = {}) => { var { initialIsVisible = false, disconnectOnVisible = false } = _a, observerOptions = __rest(_a, ["initialIsVisible", "disconnectOnVisible"]); const [isVisible, setIsVisible] = useState(initialIsVisible); useEffect(() => { const element = elementRef.current; if (!element || typeof IntersectionObserver === 'undefined') { // Ensure element exists and IntersectionObserver is supported return; } const observer = new IntersectionObserver(([entry]) => { // Update state based on intersection const currentlyVisible = entry.isIntersecting; setIsVisible(currentlyVisible); // Disconnect if option is set and element is now visible if (disconnectOnVisible && currentlyVisible) { observer.disconnect(); } }, observerOptions); observer.observe(element); // Cleanup: disconnect the observer when the component unmounts or ref changes return () => { observer.disconnect(); }; // Re-run effect if elementRef or observer options change // Note: observerOptions are stringified for reliable comparison in deps array, // as object identity changes on every render otherwise. }, [elementRef, JSON.stringify(observerOptions), disconnectOnVisible]); return isVisible; }; //# sourceMappingURL=useVisibility.js.map