|
1 |
| -import { 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 thr represents the threshold value for scroll detection. |
74 |
| - */ |
75 |
| - thr?: number; |
76 |
| - /** |
77 |
| - * The axis represents the scroll axis (x or y). |
78 |
| - */ |
79 |
| - axis?: Axis; |
80 |
| - /** |
81 |
| - * The scrollUp represents the scroll direction when moving up. |
82 |
| - */ |
83 |
| - scrollUp?: Direction; |
84 |
| - /** |
85 |
| - * The scrollDown represents the scroll direction when moving down. |
86 |
| - */ |
87 |
| - scrollDown?: Direction; |
88 |
| - /** |
89 |
| - * The still represents the scroll direction when the user is not scrolling. |
90 |
| - */ |
91 |
| - still?: Direction; |
92 |
| -}; |
93 |
| - |
94 |
| -/** |
95 |
| - * useDetectScroll hook. |
96 |
| - * |
97 |
| - * This hook provides a mechanism to detect the scroll direction and position. |
98 |
| - * It will return the scroll direction as a string (up, down, left, right, or still) based on user scrolling, |
99 |
| - * as well as the scroll position from the top, bottom, left, and right edges of the page. |
100 |
| - * |
101 |
| - * @example |
102 |
| - * |
103 |
| - * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction'; |
104 |
| - * |
105 |
| - * function App() { |
106 |
| - * const { scrollDir, scrollPosition } = useDetectScroll({ |
107 |
| - * thr: 100, |
108 |
| - * axis: Axis.Y, |
109 |
| - * scrollUp: Direction.Up, |
110 |
| - * scrollDown: Direction.Down, |
111 |
| - * still: Direction.Still |
112 |
| - * }); |
113 |
| - * |
114 |
| - * return ( |
115 |
| - * <div> |
116 |
| - * <p>Current scroll direction: {scrollDir}</p> |
117 |
| - * <p>Scroll position - Top: {scrollPosition.top}, Bottom: {scrollPosition.bottom}, |
118 |
| - * Left: {scrollPosition.left}, Right: {scrollPosition.right}</p> |
119 |
| - * </div> |
120 |
| - * ); |
121 |
| - * } |
122 |
| - * |
123 |
| - * @param {ScrollProps} props - The properties related to scrolling. |
124 |
| - * @returns {ScrollInfo} - The current direction and position of scrolling. |
125 |
| - */ |
126 |
| -function useDetectScroll(props: ScrollProps = {}): ScrollInfo { |
127 |
| - const { |
128 |
| - thr = 0, |
129 |
| - axis = Axis.Y, |
130 |
| - scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left, |
131 |
| - scrollDown = axis === Axis.Y ? Direction.Down : Direction.Right, |
132 |
| - still = Direction.Still |
133 |
| - } = props; |
134 |
| - |
135 |
| - const [scrollDir, setScrollDir] = useState<Direction>(still); |
136 |
| - const [scrollPosition, setScrollPosition] = useState<ScrollPosition>({ |
137 |
| - top: 0, |
138 |
| - bottom: 0, |
139 |
| - left: 0, |
140 |
| - right: 0 |
141 |
| - }); |
142 |
| - |
143 |
| - const threshold = Math.max(0, thr); |
144 |
| - const ticking = useRef(false); |
145 |
| - const lastScroll = useRef(0); |
146 |
| - |
147 |
| - /** Function to update scroll direction */ |
148 |
| - const updateScrollDir = useCallback(() => { |
149 |
| - const scroll = axis === Axis.Y ? window.scrollY : window.scrollX; |
150 |
| - |
151 |
| - if (Math.abs(scroll - lastScroll.current) >= threshold) { |
152 |
| - setScrollDir(scroll > lastScroll.current ? scrollDown : scrollUp); |
153 |
| - lastScroll.current = Math.max(0, scroll); |
154 |
| - } |
155 |
| - ticking.current = false; |
156 |
| - }, [axis, threshold, scrollDown, scrollUp]); |
157 |
| - |
158 |
| - useEffect(() => { |
159 |
| - /** Function to update scroll position */ |
160 |
| - const updateScrollPosition = () => { |
161 |
| - const top = window.scrollY; |
162 |
| - const left = window.scrollX; |
163 |
| - const bottom = |
164 |
| - document.documentElement.scrollHeight - window.innerHeight - top; |
165 |
| - const right = |
166 |
| - document.documentElement.scrollWidth - window.innerWidth - left; |
167 |
| - |
168 |
| - setScrollPosition({ top, bottom, left, right }); |
169 |
| - }; |
170 |
| - |
171 |
| - /** Call the update function when the component mounts */ |
172 |
| - updateScrollPosition(); |
173 |
| - |
174 |
| - window.addEventListener('scroll', updateScrollPosition); |
175 |
| - |
176 |
| - return () => { |
177 |
| - window.removeEventListener('scroll', updateScrollPosition); |
178 |
| - }; |
179 |
| - }, []); |
180 |
| - |
181 |
| - useEffect(() => { |
182 |
| - lastScroll.current = axis === Axis.Y ? window.scrollY : window.scrollX; |
183 |
| - |
184 |
| - /** Function to handle onScroll event */ |
185 |
| - const onScroll = () => { |
186 |
| - if (!ticking.current) { |
187 |
| - window.requestAnimationFrame(updateScrollDir); |
188 |
| - ticking.current = true; |
189 |
| - } |
190 |
| - }; |
191 |
| - |
192 |
| - window.addEventListener('scroll', onScroll); |
193 |
| - |
194 |
| - return () => window.removeEventListener('scroll', onScroll); |
195 |
| - }, [axis, updateScrollDir]); |
196 |
| - |
197 |
| - return { scrollDir, scrollPosition }; |
198 |
| -} |
| 1 | +import useDetectScroll from './useDetectScroll'; |
199 | 2 |
|
200 | 3 | export default useDetectScroll;
|
| 4 | +export { Axis, Direction } from './types'; |
0 commit comments