11import { useState , useEffect , useCallback , useRef } from 'react' ;
2-
3- /** Enumeration for axis values */
4- export enum Axis {
5- /**
6- * The x-axis represents the horizontal direction.
7- */
8- X = 'x' ,
9- /**
10- * The y-axis represents the vertical direction.
11- */
12- Y = 'y'
13- }
14-
15- /** Enumeration for direction values */
16- export enum Direction {
17- /**
18- * The up direction represents the scroll direction moving towards the top.
19- */
20- Up = 'up' ,
21- /**
22- * The down direction represents the scroll direction moving towards the bottom.
23- */
24- Down = 'down' ,
25- /**
26- * The left direction represents the scroll direction moving towards the left.
27- */
28- Left = 'left' ,
29- /**
30- * The right direction represents the scroll direction moving towards the right.
31- */
32- Right = 'right' ,
33- /**
34- * The still direction represents the scroll direction when the user is not scrolling.
35- */
36- Still = 'still'
37- }
38-
39- type ScrollPosition = {
40- /**
41- * The top position represents the distance from the top edge of the page.
42- */
43- top : number ;
44- /**
45- * The bottom position represents the distance from the bottom edge of the page.
46- */
47- bottom : number ;
48- /**
49- * The left position represents the distance from the left edge of the page.
50- */
51- left : number ;
52- /**
53- * The right position represents the distance from the right edge of the page.
54- */
55- right : number ;
56- } ;
57-
58- /** Type declaration for the returned scroll information */
59- type ScrollInfo = {
60- /**
61- * The scrollDir represents the current scroll direction.
62- */
63- scrollDir : Direction ;
64- /**
65- * The scrollPosition represents the current scroll position.
66- */
67- scrollPosition : ScrollPosition ;
68- } ;
69-
70- /** Type declaration for scroll properties */
71- type ScrollProps = {
72- /**
73- * The target represents the scrollable element to check for scroll detection.
74- */
75- target ?: HTMLDivElement | Window ;
76- /**
77- * The thr represents the threshold value for scroll detection.
78- */
79- thr ?: number ;
80- /**
81- * The axis represents the scroll axis (x or y).
82- */
83- axis ?: Axis ;
84- /**
85- * The scrollUp represents the scroll direction when moving up.
86- */
87- scrollUp ?: Direction ;
88- /**
89- * The scrollDown represents the scroll direction when moving down.
90- */
91- scrollDown ?: Direction ;
92- /**
93- * The still represents the scroll direction when the user is not scrolling.
94- */
95- still ?: Direction ;
96- } ;
2+ import {
3+ Axis ,
4+ Direction ,
5+ ScrollInfo ,
6+ ScrollPosition ,
7+ ScrollProps
8+ } from './types' ;
979
9810/**
9911 * useDetectScroll hook.
@@ -107,14 +19,24 @@ type ScrollProps = {
10719 * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';
10820 *
10921 * function App() {
22+ * const customElementRef = useRef<HTMLDivElement>(null);
23+ * const [customElement, setCustomElement] = useState<HTMLDivElement>();
24+ *
11025 * const { scrollDir, scrollPosition } = useDetectScroll({
26+ * target: customElement,
11127 * thr: 100,
11228 * axis: Axis.Y,
11329 * scrollUp: Direction.Up,
11430 * scrollDown: Direction.Down,
11531 * still: Direction.Still
11632 * });
11733 *
34+ * useEffect(() => {
35+ * if (customElementRef.current) {
36+ * setCustomElement(customElementRef.current);
37+ * }
38+ * }, [customElementRef]);
39+ *
11840 * return (
11941 * <div>
12042 * <p>Current scroll direction: {scrollDir}</p>
@@ -129,7 +51,7 @@ type ScrollProps = {
12951 */
13052function useDetectScroll ( props : ScrollProps = { } ) : ScrollInfo {
13153 const {
132- target = window ,
54+ target = typeof window !== 'undefined' ? window : undefined ,
13355 thr = 0 ,
13456 axis = Axis . Y ,
13557 scrollUp = axis === Axis . Y ? Direction . Up : Direction . Left ,
@@ -151,14 +73,13 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
15173
15274 /** Function to update scroll direction */
15375 const updateScrollDir = useCallback ( ( ) => {
76+ if ( ! target ) return ;
77+
15478 let scroll : number ;
15579 if ( target instanceof Window ) {
15680 scroll = axis === Axis . Y ? target . scrollY : target . scrollX ;
15781 } else {
158- scroll =
159- axis === Axis . Y
160- ? ( target as HTMLDivElement ) . scrollTop
161- : ( target as HTMLDivElement ) . scrollLeft ;
82+ scroll = axis === Axis . Y ? target . scrollTop : target . scrollLeft ;
16283 }
16384
16485 if ( Math . abs ( scroll - lastScroll . current ) >= threshold ) {
@@ -169,33 +90,33 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
16990 } , [ target , axis , threshold , scrollDown , scrollUp ] ) ;
17091
17192 useEffect ( ( ) => {
93+ if ( ! target ) {
94+ console . warn (
95+ 'useDetectScroll: target is not set. Falling back to window.'
96+ ) ;
97+ return ;
98+ }
99+
172100 /** Function to update scroll position */
173101 const updateScrollPosition = ( ) => {
174- const top =
175- target instanceof Window
176- ? target . scrollY
177- : ( target as HTMLDivElement ) . scrollTop ;
102+ if ( ! target ) return ;
103+
104+ const top = target instanceof Window ? target . scrollY : target . scrollTop ;
178105 const left =
179- target instanceof Window
180- ? target . scrollX
181- : ( target as HTMLDivElement ) . scrollLeft ;
106+ target instanceof Window ? target . scrollX : target . scrollLeft ;
107+
182108 const bottom =
183- document . documentElement . scrollHeight -
184109 ( target instanceof Window
185- ? target . innerHeight
186- : ( target as HTMLDivElement ) . scrollHeight ) -
187- top ;
110+ ? document . documentElement . scrollHeight - target . innerHeight
111+ : target . scrollHeight - target . clientHeight ) - top ;
188112 const right =
189- document . documentElement . scrollWidth -
190113 ( target instanceof Window
191- ? target . innerWidth
192- : ( target as HTMLDivElement ) . scrollWidth ) -
193- left ;
114+ ? document . documentElement . scrollWidth - target . innerWidth
115+ : target . scrollWidth - target . clientWidth ) - left ;
194116
195117 setScrollPosition ( { top, bottom, left, right } ) ;
196118 } ;
197119
198- /** Call the update function when the component mounts */
199120 updateScrollPosition ( ) ;
200121
201122 const targetElement = target as EventTarget ;
@@ -207,16 +128,20 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
207128 } , [ target ] ) ;
208129
209130 useEffect ( ( ) => {
131+ if ( ! target ) {
132+ console . warn (
133+ 'useDetectScroll: target is not set. Falling back to window.'
134+ ) ;
135+ return ;
136+ }
137+
210138 if ( target instanceof Window ) {
211139 lastScroll . current = axis === Axis . Y ? target . scrollY : target . scrollX ;
212140 } else {
213141 lastScroll . current =
214- axis === Axis . Y
215- ? ( target as HTMLDivElement ) . scrollTop
216- : ( target as HTMLDivElement ) . scrollLeft ;
142+ axis === Axis . Y ? target . scrollTop : target . scrollLeft ;
217143 }
218144
219- /** Function to handle onScroll event */
220145 const onScroll = ( ) => {
221146 if ( ! ticking . current ) {
222147 window . requestAnimationFrame ( updateScrollDir ) ;
@@ -233,4 +158,5 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
233158 return { scrollDir, scrollPosition } ;
234159}
235160
161+ export { Axis , Direction } ;
236162export default useDetectScroll ;
0 commit comments