react-bottom-scroll-listener
Version:
A simple React component that lets you listen for when you have scrolled to the bottom.
100 lines (85 loc) • 4.06 kB
JavaScript
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var react = require('react');
var lodashDebounce = _interopDefault(require('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 = react.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 = react.useMemo(function () {
return createCallback(debounce, onBottom, debounceOptions);
}, [debounce, onBottom]);
var containerRef = react.useRef(null);
var handleOnScroll = react.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]);
react.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;
};
exports.BottomScrollListener = BottomScrollListener;
exports.useBottomScrollListener = useBottomScrollListener;
//# sourceMappingURL=index.js.map