(
ref: RefObject<T | null>,
{ debounceTime = 300, onScroll }: UseScrollOptions = {}
)
| 16 | |
| 17 | // Custom hook to handle scroll events with optional debouncing |
| 18 | const useScroll = <T extends HTMLElement>( |
| 19 | ref: RefObject<T | null>, |
| 20 | { debounceTime = 300, onScroll }: UseScrollOptions = {} |
| 21 | ) => { |
| 22 | const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined); |
| 23 | |
| 24 | useEffect(() => { |
| 25 | // Get the current element |
| 26 | const element = ref.current; |
| 27 | |
| 28 | // Return early if no element or onScroll callback is provided |
| 29 | if (!element || !onScroll) { |
| 30 | return; |
| 31 | } |
| 32 | |
| 33 | // Debounced scroll handler |
| 34 | const handleScroll = () => { |
| 35 | // Clear existing timeout |
| 36 | if (timeoutRef.current) { |
| 37 | clearTimeout(timeoutRef.current); |
| 38 | } |
| 39 | |
| 40 | // Set new timeout to call onScroll after debounceTime |
| 41 | timeoutRef.current = setTimeout(() => { |
| 42 | if (element) { |
| 43 | onScroll({ |
| 44 | x: element.scrollLeft, |
| 45 | y: element.scrollTop, |
| 46 | }); |
| 47 | } |
| 48 | }, debounceTime); |
| 49 | }; |
| 50 | |
| 51 | element.addEventListener('scroll', handleScroll, { passive: true }); |
| 52 | |
| 53 | return () => { |
| 54 | element.removeEventListener('scroll', handleScroll); |
| 55 | // Clear any pending debounced calls |
| 56 | if (timeoutRef.current) { |
| 57 | clearTimeout(timeoutRef.current); |
| 58 | } |
| 59 | }; |
| 60 | }, [ref, onScroll, debounceTime]); |
| 61 | }; |
| 62 | |
| 63 | export default useScroll; |
no outgoing calls
no test coverage detected