2023-01-02 16:36:24 +03:00
|
|
|
import { useEffect, useState } from 'preact/hooks';
|
|
|
|
|
|
|
|
export default function useScroll({
|
|
|
|
scrollableElement = window,
|
|
|
|
distanceFromTop = 0,
|
|
|
|
distanceFromBottom = 0,
|
2023-01-02 18:16:49 +03:00
|
|
|
scrollThreshold = 10,
|
2023-01-02 16:36:24 +03:00
|
|
|
} = {}) {
|
|
|
|
const [scrollDirection, setScrollDirection] = useState(null);
|
|
|
|
const [reachTop, setReachTop] = useState(false);
|
|
|
|
const [nearReachTop, setNearReachTop] = useState(false);
|
|
|
|
const [nearReachBottom, setNearReachBottom] = useState(false);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
let previousScrollTop = scrollableElement.scrollTop;
|
|
|
|
|
|
|
|
function onScroll() {
|
|
|
|
const { scrollTop, scrollHeight, clientHeight } = scrollableElement;
|
2023-01-02 18:16:49 +03:00
|
|
|
const scrollDistance = Math.abs(scrollTop - previousScrollTop);
|
2023-01-02 16:36:24 +03:00
|
|
|
|
2023-01-02 18:16:49 +03:00
|
|
|
if (scrollDistance >= scrollThreshold) {
|
|
|
|
setScrollDirection(previousScrollTop < scrollTop ? 'down' : 'up');
|
|
|
|
previousScrollTop = scrollTop;
|
|
|
|
}
|
2023-01-02 16:36:24 +03:00
|
|
|
|
|
|
|
setReachTop(scrollTop === 0);
|
|
|
|
setNearReachTop(scrollTop <= distanceFromTop);
|
|
|
|
setNearReachBottom(
|
|
|
|
scrollTop + clientHeight >= scrollHeight - distanceFromBottom,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
scrollableElement.addEventListener('scroll', onScroll, { passive: true });
|
|
|
|
|
|
|
|
return () => scrollableElement.removeEventListener('scroll', onScroll);
|
2023-01-02 18:16:49 +03:00
|
|
|
}, [scrollableElement, distanceFromTop, distanceFromBottom, scrollThreshold]);
|
2023-01-02 16:36:24 +03:00
|
|
|
|
|
|
|
return { scrollDirection, reachTop, nearReachTop, nearReachBottom };
|
|
|
|
}
|