UNPKG

next

Version:

The React Framework

120 lines (118 loc) 3.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useIntersection = useIntersection; var _react = require("react"); var _requestIdleCallback = require("./request-idle-callback"); const hasIntersectionObserver = typeof IntersectionObserver !== 'undefined'; function useIntersection({ rootRef , rootMargin , disabled }) { const isDisabled = disabled || !hasIntersectionObserver; const unobserve = (0, _react).useRef(); const [visible, setVisible] = (0, _react).useState(false); const [root, setRoot] = (0, _react).useState(rootRef ? rootRef.current : null); const setRef = (0, _react).useCallback((el)=>{ if (unobserve.current) { unobserve.current(); unobserve.current = undefined; } if (isDisabled || visible) return; if (el && el.tagName) { unobserve.current = observe(el, (isVisible)=>isVisible && setVisible(isVisible) , { root, rootMargin }); } }, [ isDisabled, root, rootMargin, visible ]); const resetVisible = (0, _react).useCallback(()=>{ setVisible(false); }, []); (0, _react).useEffect(()=>{ if (!hasIntersectionObserver) { if (!visible) { const idleCallback = (0, _requestIdleCallback).requestIdleCallback(()=>setVisible(true) ); return ()=>(0, _requestIdleCallback).cancelIdleCallback(idleCallback) ; } } }, [ visible ]); (0, _react).useEffect(()=>{ if (rootRef) setRoot(rootRef.current); }, [ rootRef ]); return [ setRef, visible, resetVisible ]; } function observe(element, callback, options) { const { id , observer , elements } = createObserver(options); elements.set(element, callback); observer.observe(element); return function unobserve() { elements.delete(element); observer.unobserve(element); // Destroy observer when there's nothing left to watch: if (elements.size === 0) { observer.disconnect(); observers.delete(id); let index = idList.findIndex((obj)=>obj.root === id.root && obj.margin === id.margin ); if (index > -1) { idList.splice(index, 1); } } }; } const observers = new Map(); const idList = []; function createObserver(options) { const id = { root: options.root || null, margin: options.rootMargin || '' }; let existing = idList.find((obj)=>obj.root === id.root && obj.margin === id.margin ); let instance; if (existing) { instance = observers.get(existing); } else { instance = observers.get(id); idList.push(id); } if (instance) { return instance; } const elements = new Map(); const observer = new IntersectionObserver((entries)=>{ entries.forEach((entry)=>{ const callback = elements.get(entry.target); const isVisible = entry.isIntersecting || entry.intersectionRatio > 0; if (callback && isVisible) { callback(isVisible); } }); }, options); observers.set(id, instance = { id, observer, elements }); return instance; } if (typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) { Object.assign(exports.default, exports); module.exports = exports.default; } //# sourceMappingURL=use-intersection.js.map