|
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