UNPKG

@modern-kit/react

Version:
121 lines (117 loc) 3.37 kB
import { useRef, useState, useCallback, useEffect } from 'react'; import { throttle } from '@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 = useRef(null); const prevScrollY = useRef(0); const prevScrollX = useRef(0); const [scrollState, setScrollState] = useState({ scrollX: 0, scrollY: 0, scrollWidth: 0, scrollHeight: 0, direction: { y: "none", x: "none" }, progress: { y: 0, x: 0 } }); const updateScrollPosition = 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 = 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 = useCallback(() => { updateScrollPosition({ scrollX: window.scrollX, scrollY: window.scrollY, scrollWidth: document.documentElement.scrollWidth, scrollHeight: document.documentElement.scrollHeight, clientWidth: window.innerWidth, clientHeight: window.innerHeight }); }, [updateScrollPosition]); useEffect(() => { if (!enabled) return; const targetElement = ref.current ?? window; const scrollHandler = ref.current ? handleScrollByRef : handleScrollByWindow; const throttledScrollHandler = 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 }; } export { useScrollEvent }; //# sourceMappingURL=index.mjs.map