@modern-kit/react
Version:
123 lines (118 loc) • 3.42 kB
JavaScript
'use strict';
var React = require('react');
var utils = require('@modern-kit/utils');
const getScrollProgress = (current, total, clientSize) => {
const maxScroll = total - clientSize;
if (maxScroll <= 0) return 0;
return Math.min(Math.round(current / maxScroll * 100), 100);
};
const getScrollDirection = (currentScrollX, currentScrollY, prevScrollY, prevScrollX) => {
return {
y: currentScrollY === prevScrollY ? "none" : currentScrollY > prevScrollY ? "down" : "up",
x: currentScrollX === prevScrollX ? "none" : currentScrollX > prevScrollX ? "right" : "left"
};
};
function useScrollEvent({
throttleDelay = 0,
throttleLeading = true,
throttleTrailing = true,
enabled = true
} = {}) {
const ref = React.useRef(null);
const prevScrollY = React.useRef(0);
const prevScrollX = React.useRef(0);
const [scrollState, setScrollState] = React.useState({
scrollX: 0,
scrollY: 0,
scrollWidth: 0,
scrollHeight: 0,
direction: {
y: "none",
x: "none"
},
progress: {
y: 0,
x: 0
}
});
const updateScrollPosition = React.useCallback(
({
scrollX,
scrollY,
scrollWidth,
scrollHeight,
clientWidth,
clientHeight
}) => {
setScrollState({
scrollX,
scrollY,
scrollWidth,
scrollHeight,
direction: getScrollDirection(
scrollX,
scrollY,
prevScrollY.current,
prevScrollX.current
),
progress: {
y: getScrollProgress(scrollY, scrollHeight, clientHeight),
x: getScrollProgress(scrollX, scrollWidth, clientWidth)
}
});
prevScrollY.current = scrollY;
prevScrollX.current = scrollX;
},
[]
);
const handleScrollByRef = React.useCallback(() => {
if (!ref.current) return;
const targetElement = ref.current;
updateScrollPosition({
scrollX: targetElement.scrollLeft,
scrollY: targetElement.scrollTop,
scrollWidth: targetElement.scrollWidth,
scrollHeight: targetElement.scrollHeight,
clientWidth: targetElement.clientWidth,
clientHeight: targetElement.clientHeight
});
}, [updateScrollPosition]);
const handleScrollByWindow = React.useCallback(() => {
updateScrollPosition({
scrollX: window.scrollX,
scrollY: window.scrollY,
scrollWidth: document.documentElement.scrollWidth,
scrollHeight: document.documentElement.scrollHeight,
clientWidth: window.innerWidth,
clientHeight: window.innerHeight
});
}, [updateScrollPosition]);
React.useEffect(() => {
if (!enabled) return;
const targetElement = ref.current ?? window;
const scrollHandler = ref.current ? handleScrollByRef : handleScrollByWindow;
const throttledScrollHandler = utils.throttle(scrollHandler, throttleDelay, {
leading: throttleLeading,
trailing: throttleTrailing
});
scrollHandler();
targetElement.addEventListener("scroll", throttledScrollHandler);
return () => {
targetElement.removeEventListener("scroll", throttledScrollHandler);
throttledScrollHandler.cancel();
};
}, [
handleScrollByRef,
handleScrollByWindow,
enabled,
throttleDelay,
throttleLeading,
throttleTrailing
]);
return {
ref,
scrollState
};
}
exports.useScrollEvent = useScrollEvent;
//# sourceMappingURL=index.cjs.map