import { useCallback, useLayoutEffect, useMemo } from 'react' export function useScrollSwipe( callback: (direction: 'up' | 'down' | 'left' | 'right') => void, ref?: React.RefObject, offset = 50 ) { const prevScrollPos = useMemo( () => ({ x: -1, y: -1 }), [] ) const scrollHandler = useCallback( ({ target }) => { const isSwipe = (pre: number, cur: number) => { const sub = cur - pre if (Math.abs(sub) >= offset) { return sub >= 0 ? 1 : -1 } return 0 } const el = target.scrollingElement || target const currentScrollPos = { x: el.scrollLeft, y: el.scrollTop } if (prevScrollPos.x < 0) { prevScrollPos.x = currentScrollPos.x prevScrollPos.y = currentScrollPos.y } const resX = isSwipe(prevScrollPos.x, currentScrollPos.x) const resY = isSwipe(prevScrollPos.y, currentScrollPos.y) if (resX !== 0) { callback(resX > 0 ? 'left' : 'right') } if (resY !== 0) { callback(resY > 0 ? 'down' : 'up') prevScrollPos.y = currentScrollPos.y } }, [callback, offset, prevScrollPos] ) useLayoutEffect(() => { const el = ref?.current || window if (el) { el.addEventListener('scroll', scrollHandler, { passive: true }) } return () => { el.removeEventListener('scroll', scrollHandler) } }) }