@smakss/react-scroll-direction 4.0.4 → 4.2.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -43,6 +43,7 @@ import useDetectScroll, {
43
43
 
44
44
  The `useDetectScroll` hook takes an options object with the following properties:
45
45
 
46
+ - `target`: The target scrollable element from which to detect scroll direction and position (default: `window`, must be an `HTMLDivElement`).
46
47
  - `thr`: Threshold for scroll direction change detection (default: `0`, accepts only positive values).
47
48
  - `axis`: Defines the scroll axis (`"y"` or `"x"`, default: `"y"`).
48
49
  - `scrollUp`: Value returned when scrolling up (y-axis) or left (x-axis) (default: `"up"` for y-axis, `"left"` for x-axis).
@@ -74,6 +75,21 @@ const { scrollDir, scrollPosition } = useDetectScroll({ axis: Axis.X });
74
75
  // scrollPosition: { top, bottom, left, right }
75
76
  ```
76
77
 
78
+ To use a custom scrollable element as a target rather than the default window:
79
+
80
+ ```js
81
+ const customElementRef = useRef<HTMLDivElement>(null);
82
+ const [customElement, setCustomElement] = useState<HTMLDivElement>();
83
+
84
+ const scrollDir = useDetectScroll({target: customElement});
85
+
86
+ useEffect(() => {
87
+ if(customElementRef.current) {
88
+ setHomepageElement(customElementRef.current);
89
+ }
90
+ }, [customElementRef])
91
+ ```
92
+
77
93
  ## Contributing
78
94
 
79
95
  Interested in making contributions to this project? Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines and details.
package/dist/index.d.ts CHANGED
@@ -1,35 +1,4 @@
1
- /** Enumeration for axis values */
2
- export declare enum Axis {
3
- X = "x",
4
- Y = "y"
5
- }
6
- /** Enumeration for direction values */
7
- export declare enum Direction {
8
- Up = "up",
9
- Down = "down",
10
- Left = "left",
11
- Right = "right",
12
- Still = "still"
13
- }
14
- type ScrollPosition = {
15
- top: number;
16
- bottom: number;
17
- left: number;
18
- right: number;
19
- };
20
- /** Type declaration for the returned scroll information */
21
- type ScrollInfo = {
22
- scrollDir: Direction;
23
- scrollPosition: ScrollPosition;
24
- };
25
- /** Type declaration for scroll properties */
26
- type ScrollProps = {
27
- thr?: number;
28
- axis?: Axis;
29
- scrollUp?: Direction;
30
- scrollDown?: Direction;
31
- still?: Direction;
32
- };
1
+ import { Axis, Direction, ScrollInfo, ScrollProps } from './types';
33
2
  /**
34
3
  * useDetectScroll hook.
35
4
  *
@@ -42,7 +11,11 @@ type ScrollProps = {
42
11
  * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';
43
12
  *
44
13
  * function App() {
14
+ * const customElementRef = useRef<HTMLDivElement>(null);
15
+ * const [customElement, setCustomElement] = useState<HTMLDivElement>();
16
+ *
45
17
  * const { scrollDir, scrollPosition } = useDetectScroll({
18
+ * target: customElement,
46
19
  * thr: 100,
47
20
  * axis: Axis.Y,
48
21
  * scrollUp: Direction.Up,
@@ -50,6 +23,12 @@ type ScrollProps = {
50
23
  * still: Direction.Still
51
24
  * });
52
25
  *
26
+ * useEffect(() => {
27
+ * if (customElementRef.current) {
28
+ * setCustomElement(customElementRef.current);
29
+ * }
30
+ * }, [customElementRef]);
31
+ *
53
32
  * return (
54
33
  * <div>
55
34
  * <p>Current scroll direction: {scrollDir}</p>
@@ -63,4 +42,5 @@ type ScrollProps = {
63
42
  * @returns {ScrollInfo} - The current direction and position of scrolling.
64
43
  */
65
44
  declare function useDetectScroll(props?: ScrollProps): ScrollInfo;
45
+ export { Axis, Direction };
66
46
  export default useDetectScroll;
package/dist/index.js CHANGED
@@ -1,20 +1,42 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ import { useState, useRef, useCallback, useEffect } from 'react';
2
2
 
3
3
  /** Enumeration for axis values */
4
4
  var Axis;
5
5
  (function (Axis) {
6
+ /**
7
+ * The x-axis represents the horizontal direction.
8
+ */
6
9
  Axis["X"] = "x";
10
+ /**
11
+ * The y-axis represents the vertical direction.
12
+ */
7
13
  Axis["Y"] = "y";
8
14
  })(Axis || (Axis = {}));
9
15
  /** Enumeration for direction values */
10
16
  var Direction;
11
17
  (function (Direction) {
18
+ /**
19
+ * The up direction represents the scroll direction moving towards the top.
20
+ */
12
21
  Direction["Up"] = "up";
22
+ /**
23
+ * The down direction represents the scroll direction moving towards the bottom.
24
+ */
13
25
  Direction["Down"] = "down";
26
+ /**
27
+ * The left direction represents the scroll direction moving towards the left.
28
+ */
14
29
  Direction["Left"] = "left";
30
+ /**
31
+ * The right direction represents the scroll direction moving towards the right.
32
+ */
15
33
  Direction["Right"] = "right";
34
+ /**
35
+ * The still direction represents the scroll direction when the user is not scrolling.
36
+ */
16
37
  Direction["Still"] = "still";
17
38
  })(Direction || (Direction = {}));
39
+
18
40
  /**
19
41
  * useDetectScroll hook.
20
42
  *
@@ -27,7 +49,11 @@ var Direction;
27
49
  * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';
28
50
  *
29
51
  * function App() {
52
+ * const customElementRef = useRef<HTMLDivElement>(null);
53
+ * const [customElement, setCustomElement] = useState<HTMLDivElement>();
54
+ *
30
55
  * const { scrollDir, scrollPosition } = useDetectScroll({
56
+ * target: customElement,
31
57
  * thr: 100,
32
58
  * axis: Axis.Y,
33
59
  * scrollUp: Direction.Up,
@@ -35,6 +61,12 @@ var Direction;
35
61
  * still: Direction.Still
36
62
  * });
37
63
  *
64
+ * useEffect(() => {
65
+ * if (customElementRef.current) {
66
+ * setCustomElement(customElementRef.current);
67
+ * }
68
+ * }, [customElementRef]);
69
+ *
38
70
  * return (
39
71
  * <div>
40
72
  * <p>Current scroll direction: {scrollDir}</p>
@@ -48,7 +80,7 @@ var Direction;
48
80
  * @returns {ScrollInfo} - The current direction and position of scrolling.
49
81
  */
50
82
  function useDetectScroll(props = {}) {
51
- const { thr = 0, axis = Axis.Y, scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left, scrollDown = axis === Axis.Y ? Direction.Down : Direction.Right, still = Direction.Still } = props;
83
+ const { target = typeof window !== 'undefined' ? window : undefined, thr = 0, axis = Axis.Y, scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left, scrollDown = axis === Axis.Y ? Direction.Down : Direction.Right, still = Direction.Still } = props;
52
84
  const [scrollDir, setScrollDir] = useState(still);
53
85
  const [scrollPosition, setScrollPosition] = useState({
54
86
  top: 0,
@@ -57,45 +89,73 @@ function useDetectScroll(props = {}) {
57
89
  right: 0
58
90
  });
59
91
  const threshold = Math.max(0, thr);
60
- let ticking = false;
61
- let lastScroll = 0;
92
+ const ticking = useRef(false);
93
+ const lastScroll = useRef(0);
62
94
  /** Function to update scroll direction */
63
95
  const updateScrollDir = useCallback(() => {
64
- const scroll = axis === Axis.Y ? window.scrollY : window.scrollX;
65
- if (Math.abs(scroll - lastScroll) >= threshold) {
66
- setScrollDir(scroll > lastScroll ? scrollDown : scrollUp);
67
- lastScroll = Math.max(0, scroll);
96
+ if (!target)
97
+ return;
98
+ let scroll;
99
+ if (target instanceof Window) {
100
+ scroll = axis === Axis.Y ? target.scrollY : target.scrollX;
101
+ }
102
+ else {
103
+ scroll = axis === Axis.Y ? target.scrollTop : target.scrollLeft;
104
+ }
105
+ if (Math.abs(scroll - lastScroll.current) >= threshold) {
106
+ setScrollDir(scroll > lastScroll.current ? scrollDown : scrollUp);
107
+ lastScroll.current = Math.max(0, scroll);
68
108
  }
69
- ticking = false;
70
- }, [axis, threshold, scrollDown, scrollUp]);
109
+ ticking.current = false;
110
+ }, [target, axis, threshold, scrollDown, scrollUp]);
71
111
  useEffect(() => {
112
+ if (!target) {
113
+ console.warn('useDetectScroll: target is not set. Falling back to window.');
114
+ return;
115
+ }
72
116
  /** Function to update scroll position */
73
117
  const updateScrollPosition = () => {
74
- const top = window.scrollY;
75
- const left = window.scrollX;
76
- const bottom = document.documentElement.scrollHeight - window.innerHeight - top;
77
- const right = document.documentElement.scrollWidth - window.innerWidth - left;
118
+ if (!target)
119
+ return;
120
+ const top = target instanceof Window ? target.scrollY : target.scrollTop;
121
+ const left = target instanceof Window ? target.scrollX : target.scrollLeft;
122
+ const bottom = (target instanceof Window
123
+ ? document.documentElement.scrollHeight - target.innerHeight
124
+ : target.scrollHeight - target.clientHeight) - top;
125
+ const right = (target instanceof Window
126
+ ? document.documentElement.scrollWidth - target.innerWidth
127
+ : target.scrollWidth - target.clientWidth) - left;
78
128
  setScrollPosition({ top, bottom, left, right });
79
129
  };
80
- /** Call the update function when the component mounts */
81
130
  updateScrollPosition();
82
- window.addEventListener('scroll', updateScrollPosition);
131
+ const targetElement = target;
132
+ targetElement.addEventListener('scroll', updateScrollPosition);
83
133
  return () => {
84
- window.removeEventListener('scroll', updateScrollPosition);
134
+ targetElement.removeEventListener('scroll', updateScrollPosition);
85
135
  };
86
- }, []);
136
+ }, [target]);
87
137
  useEffect(() => {
88
- lastScroll = axis === Axis.Y ? window.scrollY : window.scrollX;
89
- /** Function to handle onScroll event */
138
+ if (!target) {
139
+ console.warn('useDetectScroll: target is not set. Falling back to window.');
140
+ return;
141
+ }
142
+ if (target instanceof Window) {
143
+ lastScroll.current = axis === Axis.Y ? target.scrollY : target.scrollX;
144
+ }
145
+ else {
146
+ lastScroll.current =
147
+ axis === Axis.Y ? target.scrollTop : target.scrollLeft;
148
+ }
90
149
  const onScroll = () => {
91
- if (!ticking) {
150
+ if (!ticking.current) {
92
151
  window.requestAnimationFrame(updateScrollDir);
93
- ticking = true;
152
+ ticking.current = true;
94
153
  }
95
154
  };
96
- window.addEventListener('scroll', onScroll);
97
- return () => window.removeEventListener('scroll', onScroll);
98
- }, [updateScrollDir]);
155
+ const targetElement = target;
156
+ targetElement.addEventListener('scroll', onScroll);
157
+ return () => targetElement.removeEventListener('scroll', onScroll);
158
+ }, [target, axis, updateScrollDir]);
99
159
  return { scrollDir, scrollPosition };
100
160
  }
101
161
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\n\n/** Enumeration for axis values */\nexport enum Axis {\n X = 'x',\n Y = 'y'\n}\n\n/** Enumeration for direction values */\nexport enum Direction {\n Up = 'up',\n Down = 'down',\n Left = 'left',\n Right = 'right',\n Still = 'still'\n}\n\ntype ScrollPosition = {\n top: number;\n bottom: number;\n left: number;\n right: number;\n};\n\n/** Type declaration for the returned scroll information */\ntype ScrollInfo = {\n scrollDir: Direction;\n scrollPosition: ScrollPosition;\n};\n\n/** Type declaration for scroll properties */\ntype ScrollProps = {\n thr?: number;\n axis?: Axis;\n scrollUp?: Direction;\n scrollDown?: Direction;\n still?: Direction;\n};\n\n/**\n * useDetectScroll hook.\n *\n * This hook provides a mechanism to detect the scroll direction and position.\n * It will return the scroll direction as a string (up, down, left, right, or still) based on user scrolling,\n * as well as the scroll position from the top, bottom, left, and right edges of the page.\n *\n * @example\n *\n * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';\n *\n * function App() {\n * const { scrollDir, scrollPosition } = useDetectScroll({\n * thr: 100,\n * axis: Axis.Y,\n * scrollUp: Direction.Up,\n * scrollDown: Direction.Down,\n * still: Direction.Still\n * });\n *\n * return (\n * <div>\n * <p>Current scroll direction: {scrollDir}</p>\n * <p>Scroll position - Top: {scrollPosition.top}, Bottom: {scrollPosition.bottom},\n * Left: {scrollPosition.left}, Right: {scrollPosition.right}</p>\n * </div>\n * );\n * }\n *\n * @param {ScrollProps} props - The properties related to scrolling.\n * @returns {ScrollInfo} - The current direction and position of scrolling.\n */\nfunction useDetectScroll(props: ScrollProps = {}): ScrollInfo {\n const {\n thr = 0,\n axis = Axis.Y,\n scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left,\n scrollDown = axis === Axis.Y ? Direction.Down : Direction.Right,\n still = Direction.Still\n } = props;\n\n const [scrollDir, setScrollDir] = useState<Direction>(still);\n const [scrollPosition, setScrollPosition] = useState<ScrollPosition>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0\n });\n\n const threshold = Math.max(0, thr);\n let ticking = false;\n let lastScroll = 0;\n\n /** Function to update scroll direction */\n const updateScrollDir = useCallback(() => {\n const scroll = axis === Axis.Y ? window.scrollY : window.scrollX;\n\n if (Math.abs(scroll - lastScroll) >= threshold) {\n setScrollDir(scroll > lastScroll ? scrollDown : scrollUp);\n lastScroll = Math.max(0, scroll);\n }\n ticking = false;\n }, [axis, threshold, scrollDown, scrollUp]);\n\n useEffect(() => {\n /** Function to update scroll position */\n const updateScrollPosition = () => {\n const top = window.scrollY;\n const left = window.scrollX;\n const bottom =\n document.documentElement.scrollHeight - window.innerHeight - top;\n const right =\n document.documentElement.scrollWidth - window.innerWidth - left;\n\n setScrollPosition({ top, bottom, left, right });\n };\n\n /** Call the update function when the component mounts */\n updateScrollPosition();\n\n window.addEventListener('scroll', updateScrollPosition);\n\n return () => {\n window.removeEventListener('scroll', updateScrollPosition);\n };\n }, []);\n\n useEffect(() => {\n lastScroll = axis === Axis.Y ? window.scrollY : window.scrollX;\n\n /** Function to handle onScroll event */\n const onScroll = () => {\n if (!ticking) {\n window.requestAnimationFrame(updateScrollDir);\n ticking = true;\n }\n };\n\n window.addEventListener('scroll', onScroll);\n\n return () => window.removeEventListener('scroll', onScroll);\n }, [updateScrollDir]);\n\n return { scrollDir, scrollPosition };\n}\n\nexport default useDetectScroll;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["/** Enumeration for axis values */\nexport enum Axis {\n /**\n * The x-axis represents the horizontal direction.\n */\n X = 'x',\n /**\n * The y-axis represents the vertical direction.\n */\n Y = 'y'\n}\n\n/** Enumeration for direction values */\nexport enum Direction {\n /**\n * The up direction represents the scroll direction moving towards the top.\n */\n Up = 'up',\n /**\n * The down direction represents the scroll direction moving towards the bottom.\n */\n Down = 'down',\n /**\n * The left direction represents the scroll direction moving towards the left.\n */\n Left = 'left',\n /**\n * The right direction represents the scroll direction moving towards the right.\n */\n Right = 'right',\n /**\n * The still direction represents the scroll direction when the user is not scrolling.\n */\n Still = 'still'\n}\n\nexport type ScrollPosition = {\n /**\n * The top position represents the distance from the top edge of the page.\n */\n top: number;\n /**\n * The bottom position represents the distance from the bottom edge of the page.\n */\n bottom: number;\n /**\n * The left position represents the distance from the left edge of the page.\n */\n left: number;\n /**\n * The right position represents the distance from the right edge of the page.\n */\n right: number;\n};\n\n/** Type declaration for the returned scroll information */\nexport type ScrollInfo = {\n /**\n * The scrollDir represents the current scroll direction.\n */\n scrollDir: Direction;\n /**\n * The scrollPosition represents the current scroll position.\n */\n scrollPosition: ScrollPosition;\n};\n\n/** Type declaration for scroll properties */\nexport type ScrollProps = {\n /**\n * The target represents the scrollable element to check for scroll detection.\n */\n target?: HTMLDivElement | Window;\n /**\n * The thr represents the threshold value for scroll detection.\n */\n thr?: number;\n /**\n * The axis represents the scroll axis (x or y).\n */\n axis?: Axis;\n /**\n * The scrollUp represents the scroll direction when moving up.\n */\n scrollUp?: Direction;\n /**\n * The scrollDown represents the scroll direction when moving down.\n */\n scrollDown?: Direction;\n /**\n * The still represents the scroll direction when the user is not scrolling.\n */\n still?: Direction;\n};\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport {\n Axis,\n Direction,\n ScrollInfo,\n ScrollPosition,\n ScrollProps\n} from './types';\n\n/**\n * useDetectScroll hook.\n *\n * This hook provides a mechanism to detect the scroll direction and position.\n * It will return the scroll direction as a string (up, down, left, right, or still) based on user scrolling,\n * as well as the scroll position from the top, bottom, left, and right edges of the page.\n *\n * @example\n *\n * import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';\n *\n * function App() {\n * const customElementRef = useRef<HTMLDivElement>(null);\n * const [customElement, setCustomElement] = useState<HTMLDivElement>();\n *\n * const { scrollDir, scrollPosition } = useDetectScroll({\n * target: customElement,\n * thr: 100,\n * axis: Axis.Y,\n * scrollUp: Direction.Up,\n * scrollDown: Direction.Down,\n * still: Direction.Still\n * });\n *\n * useEffect(() => {\n * if (customElementRef.current) {\n * setCustomElement(customElementRef.current);\n * }\n * }, [customElementRef]);\n *\n * return (\n * <div>\n * <p>Current scroll direction: {scrollDir}</p>\n * <p>Scroll position - Top: {scrollPosition.top}, Bottom: {scrollPosition.bottom},\n * Left: {scrollPosition.left}, Right: {scrollPosition.right}</p>\n * </div>\n * );\n * }\n *\n * @param {ScrollProps} props - The properties related to scrolling.\n * @returns {ScrollInfo} - The current direction and position of scrolling.\n */\nfunction useDetectScroll(props: ScrollProps = {}): ScrollInfo {\n const {\n target = typeof window !== 'undefined' ? window : undefined,\n thr = 0,\n axis = Axis.Y,\n scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left,\n scrollDown = axis === Axis.Y ? Direction.Down : Direction.Right,\n still = Direction.Still\n } = props;\n\n const [scrollDir, setScrollDir] = useState<Direction>(still);\n const [scrollPosition, setScrollPosition] = useState<ScrollPosition>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0\n });\n\n const threshold = Math.max(0, thr);\n const ticking = useRef(false);\n const lastScroll = useRef(0);\n\n /** Function to update scroll direction */\n const updateScrollDir = useCallback(() => {\n if (!target) return;\n\n let scroll: number;\n if (target instanceof Window) {\n scroll = axis === Axis.Y ? target.scrollY : target.scrollX;\n } else {\n scroll = axis === Axis.Y ? target.scrollTop : target.scrollLeft;\n }\n\n if (Math.abs(scroll - lastScroll.current) >= threshold) {\n setScrollDir(scroll > lastScroll.current ? scrollDown : scrollUp);\n lastScroll.current = Math.max(0, scroll);\n }\n ticking.current = false;\n }, [target, axis, threshold, scrollDown, scrollUp]);\n\n useEffect(() => {\n if (!target) {\n console.warn(\n 'useDetectScroll: target is not set. Falling back to window.'\n );\n return;\n }\n\n /** Function to update scroll position */\n const updateScrollPosition = () => {\n if (!target) return;\n\n const top = target instanceof Window ? target.scrollY : target.scrollTop;\n const left =\n target instanceof Window ? target.scrollX : target.scrollLeft;\n\n const bottom =\n (target instanceof Window\n ? document.documentElement.scrollHeight - target.innerHeight\n : target.scrollHeight - target.clientHeight) - top;\n const right =\n (target instanceof Window\n ? document.documentElement.scrollWidth - target.innerWidth\n : target.scrollWidth - target.clientWidth) - left;\n\n setScrollPosition({ top, bottom, left, right });\n };\n\n updateScrollPosition();\n\n const targetElement = target as EventTarget;\n targetElement.addEventListener('scroll', updateScrollPosition);\n\n return () => {\n targetElement.removeEventListener('scroll', updateScrollPosition);\n };\n }, [target]);\n\n useEffect(() => {\n if (!target) {\n console.warn(\n 'useDetectScroll: target is not set. Falling back to window.'\n );\n return;\n }\n\n if (target instanceof Window) {\n lastScroll.current = axis === Axis.Y ? target.scrollY : target.scrollX;\n } else {\n lastScroll.current =\n axis === Axis.Y ? target.scrollTop : target.scrollLeft;\n }\n\n const onScroll = () => {\n if (!ticking.current) {\n window.requestAnimationFrame(updateScrollDir);\n ticking.current = true;\n }\n };\n\n const targetElement = target as EventTarget;\n targetElement.addEventListener('scroll', onScroll);\n\n return () => targetElement.removeEventListener('scroll', onScroll);\n }, [target, axis, updateScrollDir]);\n\n return { scrollDir, scrollPosition };\n}\n\nexport { Axis, Direction };\nexport default useDetectScroll;\n"],"names":[],"mappings":";;AAAA;IACY,KASX;AATD,CAAA,UAAY,IAAI,EAAA;AACd;;AAEG;AACH,IAAA,IAAA,CAAA,GAAA,CAAA,GAAA,GAAO,CAAA;AACP;;AAEG;AACH,IAAA,IAAA,CAAA,GAAA,CAAA,GAAA,GAAO,CAAA;AACT,CAAC,EATW,IAAI,KAAJ,IAAI,GASf,EAAA,CAAA,CAAA,CAAA;AAED;IACY,UAqBX;AArBD,CAAA,UAAY,SAAS,EAAA;AACnB;;AAEG;AACH,IAAA,SAAA,CAAA,IAAA,CAAA,GAAA,IAAS,CAAA;AACT;;AAEG;AACH,IAAA,SAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACb;;AAEG;AACH,IAAA,SAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACb;;AAEG;AACH,IAAA,SAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf;;AAEG;AACH,IAAA,SAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACjB,CAAC,EArBW,SAAS,KAAT,SAAS,GAqBpB,EAAA,CAAA,CAAA;;ACzBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCG;AACH,SAAS,eAAe,CAAC,KAAA,GAAqB,EAAE,EAAA;AAC9C,IAAA,MAAM,EACJ,MAAM,GAAG,OAAO,MAAM,KAAK,WAAW,GAAG,MAAM,GAAG,SAAS,EAC3D,GAAG,GAAG,CAAC,EACP,IAAI,GAAG,IAAI,CAAC,CAAC,EACb,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,EAC1D,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,KAAK,EAC/D,KAAK,GAAG,SAAS,CAAC,KAAK,EACxB,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAY,KAAK,CAAC,CAAC;AAC7D,IAAA,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAiB;AACnE,QAAA,GAAG,EAAE,CAAC;AACN,QAAA,MAAM,EAAE,CAAC;AACT,QAAA,IAAI,EAAE,CAAC;AACP,QAAA,KAAK,EAAE,CAAC;AACT,KAAA,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;;AAG7B,IAAA,MAAM,eAAe,GAAG,WAAW,CAAC,MAAK;AACvC,QAAA,IAAI,CAAC,MAAM;YAAE,OAAO;AAEpB,QAAA,IAAI,MAAc,CAAC;AACnB,QAAA,IAAI,MAAM,YAAY,MAAM,EAAE;AAC5B,YAAA,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;SAC5D;aAAM;AACL,YAAA,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;SACjE;AAED,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,SAAS,EAAE;AACtD,YAAA,YAAY,CAAC,MAAM,GAAG,UAAU,CAAC,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC,CAAC;YAClE,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;SAC1C;AACD,QAAA,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;AAC1B,KAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEpD,SAAS,CAAC,MAAK;QACb,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,CAAC,IAAI,CACV,6DAA6D,CAC9D,CAAC;YACF,OAAO;SACR;;QAGD,MAAM,oBAAoB,GAAG,MAAK;AAChC,YAAA,IAAI,CAAC,MAAM;gBAAE,OAAO;AAEpB,YAAA,MAAM,GAAG,GAAG,MAAM,YAAY,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;AACzE,YAAA,MAAM,IAAI,GACR,MAAM,YAAY,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC;AAEhE,YAAA,MAAM,MAAM,GACV,CAAC,MAAM,YAAY,MAAM;kBACrB,QAAQ,CAAC,eAAe,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW;kBAC1D,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC;AACvD,YAAA,MAAM,KAAK,GACT,CAAC,MAAM,YAAY,MAAM;kBACrB,QAAQ,CAAC,eAAe,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU;kBACxD,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC;YAEtD,iBAAiB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAClD,SAAC,CAAC;AAEF,QAAA,oBAAoB,EAAE,CAAC;QAEvB,MAAM,aAAa,GAAG,MAAqB,CAAC;AAC5C,QAAA,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;AAE/D,QAAA,OAAO,MAAK;AACV,YAAA,aAAa,CAAC,mBAAmB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;AACpE,SAAC,CAAC;AACJ,KAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,SAAS,CAAC,MAAK;QACb,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,CAAC,IAAI,CACV,6DAA6D,CAC9D,CAAC;YACF,OAAO;SACR;AAED,QAAA,IAAI,MAAM,YAAY,MAAM,EAAE;YAC5B,UAAU,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;SACxE;aAAM;AACL,YAAA,UAAU,CAAC,OAAO;AAChB,gBAAA,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;SAC1D;QAED,MAAM,QAAQ,GAAG,MAAK;AACpB,YAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;AACpB,gBAAA,MAAM,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;AAC9C,gBAAA,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;aACxB;AACH,SAAC,CAAC;QAEF,MAAM,aAAa,GAAG,MAAqB,CAAC;AAC5C,QAAA,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEnD,OAAO,MAAM,aAAa,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;KACpE,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;AAEpC,IAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AACvC;;;;"}
@@ -0,0 +1,90 @@
1
+ /** Enumeration for axis values */
2
+ export declare enum Axis {
3
+ /**
4
+ * The x-axis represents the horizontal direction.
5
+ */
6
+ X = "x",
7
+ /**
8
+ * The y-axis represents the vertical direction.
9
+ */
10
+ Y = "y"
11
+ }
12
+ /** Enumeration for direction values */
13
+ export declare enum Direction {
14
+ /**
15
+ * The up direction represents the scroll direction moving towards the top.
16
+ */
17
+ Up = "up",
18
+ /**
19
+ * The down direction represents the scroll direction moving towards the bottom.
20
+ */
21
+ Down = "down",
22
+ /**
23
+ * The left direction represents the scroll direction moving towards the left.
24
+ */
25
+ Left = "left",
26
+ /**
27
+ * The right direction represents the scroll direction moving towards the right.
28
+ */
29
+ Right = "right",
30
+ /**
31
+ * The still direction represents the scroll direction when the user is not scrolling.
32
+ */
33
+ Still = "still"
34
+ }
35
+ export type ScrollPosition = {
36
+ /**
37
+ * The top position represents the distance from the top edge of the page.
38
+ */
39
+ top: number;
40
+ /**
41
+ * The bottom position represents the distance from the bottom edge of the page.
42
+ */
43
+ bottom: number;
44
+ /**
45
+ * The left position represents the distance from the left edge of the page.
46
+ */
47
+ left: number;
48
+ /**
49
+ * The right position represents the distance from the right edge of the page.
50
+ */
51
+ right: number;
52
+ };
53
+ /** Type declaration for the returned scroll information */
54
+ export type ScrollInfo = {
55
+ /**
56
+ * The scrollDir represents the current scroll direction.
57
+ */
58
+ scrollDir: Direction;
59
+ /**
60
+ * The scrollPosition represents the current scroll position.
61
+ */
62
+ scrollPosition: ScrollPosition;
63
+ };
64
+ /** Type declaration for scroll properties */
65
+ export type ScrollProps = {
66
+ /**
67
+ * The target represents the scrollable element to check for scroll detection.
68
+ */
69
+ target?: HTMLDivElement | Window;
70
+ /**
71
+ * The thr represents the threshold value for scroll detection.
72
+ */
73
+ thr?: number;
74
+ /**
75
+ * The axis represents the scroll axis (x or y).
76
+ */
77
+ axis?: Axis;
78
+ /**
79
+ * The scrollUp represents the scroll direction when moving up.
80
+ */
81
+ scrollUp?: Direction;
82
+ /**
83
+ * The scrollDown represents the scroll direction when moving down.
84
+ */
85
+ scrollDown?: Direction;
86
+ /**
87
+ * The still represents the scroll direction when the user is not scrolling.
88
+ */
89
+ still?: Direction;
90
+ };
package/package.json CHANGED
@@ -5,21 +5,22 @@
5
5
  },
6
6
  "description": "Enhance your React apps with advanced scroll detection using @smakss/react-scroll-direction. This powerful hook not only detects scroll direction but also provides scroll position information. Ideal for React, Remix, Next.js, and Gatsby projects, it comes with adjustable sensitivity and supports ES Modules.",
7
7
  "devDependencies": {
8
- "@commitlint/cli": "^18.6.0",
9
- "@commitlint/config-conventional": "^18.6.0",
8
+ "@commitlint/cli": "^19.2.1",
9
+ "@commitlint/config-conventional": "^19.1.0",
10
10
  "@rollup/plugin-node-resolve": "^15.2.3",
11
11
  "@rollup/plugin-typescript": "^11.1.6",
12
- "@types/react": "^18.2.55",
13
- "@typescript-eslint/eslint-plugin": "^7.0.1",
14
- "@typescript-eslint/parser": "^7.0.1",
15
- "eslint": "^8.56.0",
12
+ "@types/react": "^18.2.74",
13
+ "@typescript-eslint/eslint-plugin": "^7.5.0",
14
+ "@typescript-eslint/parser": "^7.5.0",
15
+ "eslint": "^8.57.0",
16
16
  "eslint-config-prettier": "^9.1.0",
17
17
  "eslint-plugin-prettier": "^5.1.3",
18
- "husky": "^9.0.10",
18
+ "eslint-plugin-react-hooks": "^4.6.0",
19
+ "husky": "^9.0.11",
19
20
  "lint-staged": "^15.2.2",
20
21
  "prettier": "^3.2.5",
21
- "rollup": "^4.10.0",
22
- "typescript": "^5.3.3"
22
+ "rollup": "^4.14.0",
23
+ "typescript": "^5.4.4"
23
24
  },
24
25
  "engines": {
25
26
  "node": ">=18.0.0"
@@ -74,9 +75,10 @@
74
75
  "lint": "eslint --cache --cache-location ./node_modules/.cache/.eslintcache --ext js,jsx,ts,tsx --max-warnings=0 .",
75
76
  "lint:fix": "eslint src/**/*.ts --fix",
76
77
  "setup": "yarn && husky install",
77
- "typecheck": "tsc -b ."
78
+ "typecheck": "tsc -b .",
79
+ "update:deps": "rm -rf node_modules yarn.lock && ncu -u && yarn"
78
80
  },
79
81
  "type": "module",
80
82
  "types": "./dist/index.d.ts",
81
- "version": "4.0.4"
83
+ "version": "4.2.0-beta.0"
82
84
  }