UNPKG

@barguide/react-hooks

Version:
82 lines (66 loc) 2.13 kB
import { useEffect, useState } from 'react'; import throttle from 'lodash/throttle'; /** * @name useCheckoutLoader * @description We use the "effect" hook to add/remove an "emitter" instance * to our Modal component. By passing the "setter" from our React State we * can get a live subscription to the state */ const useScrollDirection = () => { const threshhold = 30; const triggerBottom = 100; const triggerTop = 100; const triggerDistance = 150; const [bottom, setBottom] = useState(false); const [direction, setDirection] = useState(false); const [position, setPosition] = useState(0); const [top, setTop] = useState(false); const onScroll = (_event: any) => { const root = document.documentElement; const { clientHeight, scrollTop, scrollHeight } = root; const remainder = scrollHeight - clientHeight - scrollTop; const isBottom = remainder <= triggerBottom; const isTop = scrollTop <= threshhold; const isSignificant = Math.abs(scrollTop - position) > triggerDistance; const nearBottom = remainder <= triggerBottom; const nearTop = scrollTop <= triggerTop; const isException = nearBottom || nearTop; if (isException) { if (nearTop && !top) { setBottom(false); setTop(true); } else if (nearBottom && !bottom) { setBottom(true); setTop(false); } return; } // Required travel distance if (isSignificant) { const isDownward = scrollTop > position; // Edge-cases if (top !== isTop) setTop(isTop); else if (bottom !== isBottom) setBottom(isBottom); // Account for negative scrolling (mobile) setPosition(scrollTop <= 0 ? 0 : scrollTop); setDirection(isDownward); } }; const throttledResize = throttle(onScroll, 100, { leading: true, trailing: true }); useEffect(() => { window.addEventListener('scroll', throttledResize); return () => { window.removeEventListener('scroll', throttledResize); }; }); return { bottom, direction, position, top }; }; export { useScrollDirection };