UNPKG

react-bottom-scroll-listener

Version:

A simple React component that lets you listen for when you have scrolled to the bottom.

97 lines (83 loc) 3.89 kB
import { useMemo, useRef, useCallback, useEffect } from 'react'; import lodashDebounce from 'lodash.debounce'; var createCallback = function createCallback(debounce, handleOnScroll, options) { if (debounce) { return lodashDebounce(handleOnScroll, debounce, options); } else { return handleOnScroll; } }; function useBottomScrollListener(onBottom, options) { var _useMemo = useMemo(function () { var _options$offset, _options$debounce, _options$debounceOpti, _options$triggerOnNoS; return { offset: (_options$offset = options === null || options === void 0 ? void 0 : options.offset) != null ? _options$offset : 0, debounce: (_options$debounce = options === null || options === void 0 ? void 0 : options.debounce) != null ? _options$debounce : 200, debounceOptions: (_options$debounceOpti = options === null || options === void 0 ? void 0 : options.debounceOptions) != null ? _options$debounceOpti : { leading: true }, triggerOnNoScroll: (_options$triggerOnNoS = options === null || options === void 0 ? void 0 : options.triggerOnNoScroll) != null ? _options$triggerOnNoS : false }; }, [options === null || options === void 0 ? void 0 : options.offset, options === null || options === void 0 ? void 0 : options.debounce, options === null || options === void 0 ? void 0 : options.debounceOptions, options === null || options === void 0 ? void 0 : options.triggerOnNoScroll]), offset = _useMemo.offset, triggerOnNoScroll = _useMemo.triggerOnNoScroll, debounce = _useMemo.debounce, debounceOptions = _useMemo.debounceOptions; var debouncedOnBottom = useMemo(function () { return createCallback(debounce, onBottom, debounceOptions); }, [debounce, onBottom]); var containerRef = useRef(null); var handleOnScroll = useCallback(function () { if (containerRef.current != null) { var scrollNode = containerRef.current; var scrollContainerBottomPosition = Math.round(scrollNode.scrollTop + scrollNode.clientHeight); var scrollPosition = Math.round(scrollNode.scrollHeight - offset); if (scrollPosition <= scrollContainerBottomPosition) { debouncedOnBottom(); } } else { var _scrollNode = document.scrollingElement || document.documentElement; var _scrollContainerBottomPosition = Math.round(_scrollNode.scrollTop + window.innerHeight); var _scrollPosition = Math.round(_scrollNode.scrollHeight - offset); if (_scrollPosition <= _scrollContainerBottomPosition) { debouncedOnBottom(); } } }, [offset, onBottom, containerRef.current]); useEffect(function () { var ref = containerRef.current; if (ref != null) { ref.addEventListener('scroll', handleOnScroll); } else { window.addEventListener('scroll', handleOnScroll); } if (triggerOnNoScroll) { handleOnScroll(); } return function () { if (ref != null) { ref.removeEventListener('scroll', handleOnScroll); } else { window.removeEventListener('scroll', handleOnScroll); } }; }, [handleOnScroll, debounce]); return containerRef; } var BottomScrollListener = function BottomScrollListener(_ref) { var children = _ref.children, onBottom = _ref.onBottom, offset = _ref.offset, debounce = _ref.debounce, debounceOptions = _ref.debounceOptions, triggerOnNoScroll = _ref.triggerOnNoScroll; var optionalScrollContainerRef = useBottomScrollListener(onBottom, { offset: offset, debounce: debounce, debounceOptions: debounceOptions, triggerOnNoScroll: triggerOnNoScroll }); if (!children) return null;else if (typeof children === 'function') return children(optionalScrollContainerRef);else return children; }; export { BottomScrollListener, useBottomScrollListener }; //# sourceMappingURL=index.modern.js.map