@musecat/functionkit 1.0.1 → 1.0.2

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.
Files changed (120) hide show
  1. package/.agents/references/components/ScrolltoTop.md +36 -0
  2. package/.agents/references/components/SwitchCase.md +47 -0
  3. package/.agents/references/components/ViewportPortal.md +34 -0
  4. package/.agents/references/cookie/cookie.md +47 -0
  5. package/.agents/references/datetime/dateTime.client.md +42 -0
  6. package/.agents/references/datetime/dateTime.server.md +42 -0
  7. package/.agents/references/datetime/dateTime.shared.md +86 -0
  8. package/.agents/references/hooks/useAvoidKeyboard.md +29 -0
  9. package/.agents/references/hooks/useCheckInvisible.md +36 -0
  10. package/.agents/references/hooks/useCheckScroll.md +36 -0
  11. package/.agents/references/hooks/useClientDateTime.md +39 -0
  12. package/.agents/references/hooks/useDebounce.md +46 -0
  13. package/.agents/references/hooks/useDebouncedCallback.md +34 -0
  14. package/.agents/references/hooks/useDoubleClick.md +40 -0
  15. package/.agents/references/hooks/useGeolocation.md +37 -0
  16. package/.agents/references/hooks/useHasMounted.md +27 -0
  17. package/.agents/references/hooks/useIntersectionObserver.md +37 -0
  18. package/.agents/references/hooks/useInterval.md +40 -0
  19. package/.agents/references/hooks/useKeyboardHeight.md +33 -0
  20. package/.agents/references/hooks/useKeyboardListNavigation.md +58 -0
  21. package/.agents/references/hooks/useLongPress.md +48 -0
  22. package/.agents/references/hooks/usePreservedCallback.md +33 -0
  23. package/.agents/references/hooks/usePreservedReference.md +34 -0
  24. package/.agents/references/hooks/useRefEffect.md +35 -0
  25. package/.agents/references/hooks/useRelativeDateTime.md +35 -0
  26. package/.agents/references/hooks/useTimeout.md +42 -0
  27. package/.agents/references/hooks/useToggleState.md +39 -0
  28. package/.agents/references/hooks/useViewportHeight.md +26 -0
  29. package/.agents/references/hooks/useViewportMatch.md +32 -0
  30. package/.agents/references/utils/browserStorage.md +41 -0
  31. package/.agents/references/utils/buildContext.md +47 -0
  32. package/.agents/references/utils/clipboardShare.md +59 -0
  33. package/.agents/references/utils/floatingMotion.md +67 -0
  34. package/.agents/references/utils/getDeviceInfo.md +43 -0
  35. package/.agents/references/utils/isEditableKeyboardTarget.md +35 -0
  36. package/.agents/references/utils/mergeRefs.md +29 -0
  37. package/.agents/references/utils/seen.md +37 -0
  38. package/.agents/references/utils/subscribeKeyboardHeight.md +35 -0
  39. package/AGENTS.md +103 -396
  40. package/README.md +18 -5
  41. package/index.ts +63 -68
  42. package/package.json +27 -13
  43. package/packages/components/ScrolltoTop.tsx +3 -3
  44. package/packages/components/SwitchCase.tsx +7 -7
  45. package/packages/components/ViewportPortal.tsx +23 -23
  46. package/packages/cookie/cookie.shared.ts +97 -101
  47. package/packages/datetime/dateTime.client.ts +86 -86
  48. package/packages/datetime/dateTime.server.ts +86 -86
  49. package/packages/datetime/dateTime.shared.ts +281 -281
  50. package/packages/hooks/useAvoidKeyboard.ts +15 -15
  51. package/packages/hooks/useCheckInvisible.ts +16 -16
  52. package/packages/hooks/useCheckScroll.ts +10 -10
  53. package/packages/hooks/useClientDateTime.ts +33 -33
  54. package/packages/hooks/useDebounce.ts +95 -95
  55. package/packages/hooks/useDebouncedCallback.ts +45 -45
  56. package/packages/hooks/useDoubleClick.ts +43 -43
  57. package/packages/hooks/useGeolocation.ts +130 -130
  58. package/packages/hooks/useHasMounted.ts +5 -5
  59. package/packages/hooks/useIntersectionObserver.ts +20 -20
  60. package/packages/hooks/useInterval.ts +46 -45
  61. package/packages/hooks/useKeyboardHeight.ts +9 -9
  62. package/packages/hooks/useKeyboardListNavigation.ts +156 -156
  63. package/packages/hooks/useLongPress.ts +98 -98
  64. package/packages/hooks/usePreservedCallback.ts +12 -12
  65. package/packages/hooks/usePreservedReference.ts +10 -10
  66. package/packages/hooks/useRefEffect.ts +19 -19
  67. package/packages/hooks/useRelativeDateTime.ts +37 -37
  68. package/packages/hooks/useTimeout.ts +41 -41
  69. package/packages/hooks/useToggleState.ts +5 -5
  70. package/packages/hooks/useViewportHeight.ts +13 -13
  71. package/packages/hooks/useViewportMatch.ts +16 -22
  72. package/packages/utils/browserStorage.ts +26 -26
  73. package/packages/utils/buildContext.tsx +10 -10
  74. package/packages/utils/checkDevice.ts +64 -64
  75. package/packages/utils/clipboardShare.tsx +31 -31
  76. package/packages/utils/clipboardShare.types.ts +7 -7
  77. package/packages/utils/floatingMotion.ts +71 -71
  78. package/packages/utils/keyboardTarget.ts +9 -9
  79. package/packages/utils/mergeRefs.ts +9 -9
  80. package/packages/utils/seen.ts +15 -15
  81. package/packages/utils/subscribeKeyboardHeight.ts +46 -46
  82. package/tests/components/ScrolltoTop.test.tsx +15 -0
  83. package/tests/components/SwitchCase.test.tsx +34 -0
  84. package/tests/components/ViewportPortal.test.tsx +42 -0
  85. package/tests/cookie/cookie.test.ts +156 -0
  86. package/tests/datetime/datetime.test.ts +250 -0
  87. package/tests/hooks/useAvoidKeyboard.test.ts +12 -0
  88. package/tests/hooks/useCheckInvisible.test.ts +28 -0
  89. package/tests/hooks/useCheckScroll.test.ts +23 -0
  90. package/tests/hooks/useClientDateTime.test.ts +14 -0
  91. package/tests/hooks/useDebounce.test.ts +71 -0
  92. package/tests/hooks/useDebouncedCallback.test.ts +34 -0
  93. package/tests/hooks/useDoubleClick.test.ts +31 -0
  94. package/tests/hooks/useGeolocation.test.ts +50 -0
  95. package/tests/hooks/useHasMounted.test.ts +10 -0
  96. package/tests/hooks/useIntersectionObserver.test.ts +13 -0
  97. package/tests/hooks/useInterval.test.ts +31 -0
  98. package/tests/hooks/useKeyboardHeight.test.ts +10 -0
  99. package/tests/hooks/useKeyboardListNavigation.test.ts +82 -0
  100. package/tests/hooks/useLongPress.test.ts +52 -0
  101. package/tests/hooks/usePreservedCallback.test.ts +35 -0
  102. package/tests/hooks/usePreservedReference.test.ts +35 -0
  103. package/tests/hooks/useRefEffect.test.ts +30 -0
  104. package/tests/hooks/useRelativeDateTime.test.ts +19 -0
  105. package/tests/hooks/useTimeout.test.ts +34 -0
  106. package/tests/hooks/useToggleState.test.ts +35 -0
  107. package/tests/hooks/useViewportHeight.test.ts +10 -0
  108. package/tests/hooks/useViewportMatch.test.ts +35 -0
  109. package/tests/setup.ts +9 -0
  110. package/tests/utils/browserStorage.test.ts +54 -0
  111. package/tests/utils/buildContext.test.tsx +27 -0
  112. package/tests/utils/checkDevice.test.ts +84 -0
  113. package/tests/utils/clipboardShare.test.ts +78 -0
  114. package/tests/utils/floatingMotion.test.ts +84 -0
  115. package/tests/utils/keyboardTarget.test.ts +44 -0
  116. package/tests/utils/mergeRefs.test.ts +18 -0
  117. package/tests/utils/seen.test.ts +31 -0
  118. package/tests/utils/subscribeKeyboardHeight.test.ts +50 -0
  119. package/tsconfig.json +16 -16
  120. package/vitest.config.ts +16 -0
@@ -7,164 +7,164 @@ const FIRST_ITEM_KEYS = new Set(["ArrowDown", "ArrowRight", "Home"]);
7
7
  const LAST_ITEM_KEYS = new Set(["ArrowUp", "ArrowLeft", "End"]);
8
8
 
9
9
  type UseKeyboardListNavigationOptions = {
10
- itemCount: number;
10
+ itemCount: number;
11
11
  };
12
12
 
13
13
  export function useKeyboardListNavigation({
14
- itemCount,
14
+ itemCount,
15
15
  }: UseKeyboardListNavigationOptions) {
16
- const [activeIndex, setActiveIndex] = useState(-1);
17
- const itemRefs = useRef<(HTMLElement | null)[]>([]);
18
-
19
- const setItemRef = useCallback(
20
- (index: number, element: HTMLElement | null) => {
21
- itemRefs.current[index] = element;
22
- },
23
- [],
24
- );
25
-
26
- const focusItem = useCallback((index: number) => {
27
- const target = itemRefs.current[index];
28
- if (!target) {
29
- return false;
30
- }
31
-
32
- setActiveIndex(index);
33
- target.focus();
34
- target.scrollIntoView({
35
- block: "nearest",
36
- inline: "nearest",
37
- });
38
- return true;
39
- }, []);
40
-
41
- const focusBoundaryItem = useCallback(
42
- (key: string) => {
43
- if (itemCount === 0) {
44
- return false;
45
- }
46
-
47
- if (FIRST_ITEM_KEYS.has(key)) {
48
- return focusItem(0);
49
- }
50
-
51
- if (LAST_ITEM_KEYS.has(key)) {
52
- return focusItem(itemCount - 1);
53
- }
54
-
55
- return false;
56
- },
57
- [focusItem, itemCount],
58
- );
59
-
60
- const moveActiveItem = useCallback(
61
- (key: string) => {
62
- if (itemCount === 0) {
63
- return false;
64
- }
65
-
66
- if (key === "Home") {
67
- return focusItem(0);
68
- }
69
-
70
- if (key === "End") {
71
- return focusItem(itemCount - 1);
72
- }
73
-
74
- if (key === "ArrowDown" || key === "ArrowRight") {
75
- const nextIndex = activeIndex < 0 ? 0 : (activeIndex + 1) % itemCount;
76
- return focusItem(nextIndex);
77
- }
78
-
79
- if (key === "ArrowUp" || key === "ArrowLeft") {
80
- const nextIndex =
81
- activeIndex < 0
82
- ? itemCount - 1
83
- : (activeIndex - 1 + itemCount) % itemCount;
84
- return focusItem(nextIndex);
85
- }
86
-
87
- return false;
88
- },
89
- [activeIndex, focusItem, itemCount],
90
- );
91
-
92
- const clickActiveItem = useCallback(() => {
93
- if (activeIndex < 0) {
94
- return false;
95
- }
96
-
97
- itemRefs.current[activeIndex]?.click();
98
- return true;
99
- }, [activeIndex]);
100
-
101
- const handleListKeyDown = useCallback(
102
- (
103
- event: React.KeyboardEvent<HTMLElement>,
104
- options?: { container?: HTMLElement | null },
105
- ) => {
106
- if (itemCount === 0 || event.defaultPrevented) {
107
- return;
108
- }
109
-
110
- const target = event.target as HTMLElement | null;
111
-
112
- if (!target) {
113
- return;
114
- }
115
-
116
- if (isEditableKeyboardTarget(target)) {
117
- return;
118
- }
119
-
120
- if (options?.container && !options.container.contains(target)) {
121
- return;
122
- }
123
-
124
- if (event.key === "Escape") {
125
- setActiveIndex(-1);
126
- return;
127
- }
128
-
129
- if (
130
- event.key === "Enter" ||
131
- event.key === " " ||
132
- event.key === "ArrowDown" ||
133
- event.key === "ArrowUp" ||
134
- event.key === "ArrowLeft" ||
135
- event.key === "ArrowRight" ||
136
- event.key === "Home" ||
137
- event.key === "End"
138
- ) {
139
- event.preventDefault();
140
- }
141
-
142
- if (event.key === "Enter" || event.key === " ") {
143
- clickActiveItem();
144
- return;
145
- }
146
-
147
- if (moveActiveItem(event.key)) {
148
- return;
149
- }
150
-
151
- if (focusBoundaryItem(event.key)) {
152
- return;
153
- }
154
- },
155
- [clickActiveItem, moveActiveItem, focusBoundaryItem, itemCount],
156
- );
157
-
158
- useEffect(() => {
159
- itemRefs.current = itemRefs.current.slice(0, itemCount);
160
- }, [itemCount]);
161
-
162
- return {
163
- activeIndex,
164
- setActiveIndex,
165
- setItemRef,
166
- clickActiveItem,
167
- focusBoundaryItem,
168
- handleListKeyDown,
169
- };
16
+ const [activeIndex, setActiveIndex] = useState(-1);
17
+ const itemRefs = useRef<(HTMLElement | null)[]>([]);
18
+
19
+ const setItemRef = useCallback(
20
+ (index: number, element: HTMLElement | null) => {
21
+ itemRefs.current[index] = element;
22
+ },
23
+ [],
24
+ );
25
+
26
+ const focusItem = useCallback((index: number) => {
27
+ const target = itemRefs.current[index];
28
+ if (!target) {
29
+ return false;
30
+ }
31
+
32
+ setActiveIndex(index);
33
+ target.focus();
34
+ target.scrollIntoView({
35
+ block: "nearest",
36
+ inline: "nearest",
37
+ });
38
+ return true;
39
+ }, []);
40
+
41
+ const focusBoundaryItem = useCallback(
42
+ (key: string) => {
43
+ if (itemCount === 0) {
44
+ return false;
45
+ }
46
+
47
+ if (FIRST_ITEM_KEYS.has(key)) {
48
+ return focusItem(0);
49
+ }
50
+
51
+ if (LAST_ITEM_KEYS.has(key)) {
52
+ return focusItem(itemCount - 1);
53
+ }
54
+
55
+ return false;
56
+ },
57
+ [focusItem, itemCount],
58
+ );
59
+
60
+ const moveActiveItem = useCallback(
61
+ (key: string) => {
62
+ if (itemCount === 0) {
63
+ return false;
64
+ }
65
+
66
+ if (key === "Home") {
67
+ return focusItem(0);
68
+ }
69
+
70
+ if (key === "End") {
71
+ return focusItem(itemCount - 1);
72
+ }
73
+
74
+ if (key === "ArrowDown" || key === "ArrowRight") {
75
+ const nextIndex = activeIndex < 0 ? 0 : (activeIndex + 1) % itemCount;
76
+ return focusItem(nextIndex);
77
+ }
78
+
79
+ if (key === "ArrowUp" || key === "ArrowLeft") {
80
+ const nextIndex =
81
+ activeIndex < 0
82
+ ? itemCount - 1
83
+ : (activeIndex - 1 + itemCount) % itemCount;
84
+ return focusItem(nextIndex);
85
+ }
86
+
87
+ return false;
88
+ },
89
+ [activeIndex, focusItem, itemCount],
90
+ );
91
+
92
+ const clickActiveItem = useCallback(() => {
93
+ if (activeIndex < 0) {
94
+ return false;
95
+ }
96
+
97
+ itemRefs.current[activeIndex]?.click();
98
+ return true;
99
+ }, [activeIndex]);
100
+
101
+ const handleListKeyDown = useCallback(
102
+ (
103
+ event: React.KeyboardEvent<HTMLElement>,
104
+ options?: { container?: HTMLElement | null },
105
+ ) => {
106
+ if (itemCount === 0 || event.defaultPrevented) {
107
+ return;
108
+ }
109
+
110
+ const target = event.target as HTMLElement | null;
111
+
112
+ if (!target) {
113
+ return;
114
+ }
115
+
116
+ if (isEditableKeyboardTarget(target)) {
117
+ return;
118
+ }
119
+
120
+ if (options?.container && !options.container.contains(target)) {
121
+ return;
122
+ }
123
+
124
+ if (event.key === "Escape") {
125
+ setActiveIndex(-1);
126
+ return;
127
+ }
128
+
129
+ if (
130
+ event.key === "Enter" ||
131
+ event.key === " " ||
132
+ event.key === "ArrowDown" ||
133
+ event.key === "ArrowUp" ||
134
+ event.key === "ArrowLeft" ||
135
+ event.key === "ArrowRight" ||
136
+ event.key === "Home" ||
137
+ event.key === "End"
138
+ ) {
139
+ event.preventDefault();
140
+ }
141
+
142
+ if (event.key === "Enter" || event.key === " ") {
143
+ clickActiveItem();
144
+ return;
145
+ }
146
+
147
+ if (moveActiveItem(event.key)) {
148
+ return;
149
+ }
150
+
151
+ if (focusBoundaryItem(event.key)) {
152
+ return;
153
+ }
154
+ },
155
+ [clickActiveItem, moveActiveItem, focusBoundaryItem, itemCount],
156
+ );
157
+
158
+ useEffect(() => {
159
+ itemRefs.current = itemRefs.current.slice(0, itemCount);
160
+ }, [itemCount]);
161
+
162
+ return {
163
+ activeIndex,
164
+ setActiveIndex,
165
+ setItemRef,
166
+ clickActiveItem,
167
+ focusBoundaryItem,
168
+ handleListKeyDown,
169
+ };
170
170
  }
@@ -3,118 +3,118 @@
3
3
  import { type MouseEvent, type TouchEvent, useCallback, useRef } from "react";
4
4
 
5
5
  export type UseLongPressOptions<E extends HTMLElement> = {
6
- delay?: number;
7
- moveThreshold?: {
8
- x?: number;
9
- y?: number;
10
- };
11
- onClick?: (event: MouseEvent<E> | TouchEvent<E>) => void;
12
- onLongPressEnd?: (event: MouseEvent<E> | TouchEvent<E>) => void;
6
+ delay?: number;
7
+ moveThreshold?: {
8
+ x?: number;
9
+ y?: number;
10
+ };
11
+ onClick?: (event: MouseEvent<E> | TouchEvent<E>) => void;
12
+ onLongPressEnd?: (event: MouseEvent<E> | TouchEvent<E>) => void;
13
13
  };
14
14
 
15
15
  export function useLongPress<E extends HTMLElement = HTMLElement>(
16
- onLongPress: (event: MouseEvent<E> | TouchEvent<E>) => void,
17
- {
18
- delay = 500,
19
- moveThreshold,
20
- onClick,
21
- onLongPressEnd,
22
- }: UseLongPressOptions<E> = {},
16
+ onLongPress: (event: MouseEvent<E> | TouchEvent<E>) => void,
17
+ {
18
+ delay = 500,
19
+ moveThreshold,
20
+ onClick,
21
+ onLongPressEnd,
22
+ }: UseLongPressOptions<E> = {},
23
23
  ) {
24
- const timeoutRef = useRef<number | null>(null);
25
- const isLongPressActiveRef = useRef(false);
26
- const initialPositionRef = useRef({ x: 0, y: 0 });
24
+ const timeoutRef = useRef<number | null>(null);
25
+ const isLongPressActiveRef = useRef(false);
26
+ const initialPositionRef = useRef({ x: 0, y: 0 });
27
27
 
28
- const savedOnLongPress = useRef(onLongPress);
29
- const savedOnClick = useRef(onClick);
30
- const savedOnLongPressEnd = useRef(onLongPressEnd);
31
- savedOnLongPress.current = onLongPress;
32
- savedOnClick.current = onClick;
33
- savedOnLongPressEnd.current = onLongPressEnd;
28
+ const savedOnLongPress = useRef(onLongPress);
29
+ const savedOnClick = useRef(onClick);
30
+ const savedOnLongPressEnd = useRef(onLongPressEnd);
31
+ savedOnLongPress.current = onLongPress;
32
+ savedOnClick.current = onClick;
33
+ savedOnLongPressEnd.current = onLongPressEnd;
34
34
 
35
- const hasThreshold =
36
- moveThreshold?.x !== undefined || moveThreshold?.y !== undefined;
35
+ const hasThreshold =
36
+ moveThreshold?.x !== undefined || moveThreshold?.y !== undefined;
37
37
 
38
- const getClientPosition = useCallback(
39
- (event: MouseEvent<E> | TouchEvent<E>) => {
40
- if ("touches" in event.nativeEvent) {
41
- const touch = event.nativeEvent.touches[0];
42
- return { x: touch.clientX, y: touch.clientY };
43
- }
44
- return {
45
- x: event.nativeEvent.clientX,
46
- y: event.nativeEvent.clientY,
47
- };
48
- },
49
- [],
50
- );
38
+ const getClientPosition = useCallback(
39
+ (event: MouseEvent<E> | TouchEvent<E>) => {
40
+ if ("touches" in event.nativeEvent) {
41
+ const touch = event.nativeEvent.touches[0];
42
+ return { x: touch.clientX, y: touch.clientY };
43
+ }
44
+ return {
45
+ x: event.nativeEvent.clientX,
46
+ y: event.nativeEvent.clientY,
47
+ };
48
+ },
49
+ [],
50
+ );
51
51
 
52
- const isMovedBeyondThreshold = useCallback(
53
- (event: MouseEvent<E> | TouchEvent<E>) => {
54
- const { x, y } = getClientPosition(event);
55
- const deltaX = Math.abs(x - initialPositionRef.current.x);
56
- const deltaY = Math.abs(y - initialPositionRef.current.y);
52
+ const isMovedBeyondThreshold = useCallback(
53
+ (event: MouseEvent<E> | TouchEvent<E>) => {
54
+ const { x, y } = getClientPosition(event);
55
+ const deltaX = Math.abs(x - initialPositionRef.current.x);
56
+ const deltaY = Math.abs(y - initialPositionRef.current.y);
57
57
 
58
- return (
59
- (moveThreshold?.x !== undefined && deltaX > moveThreshold.x) ||
60
- (moveThreshold?.y !== undefined && deltaY > moveThreshold.y)
61
- );
62
- },
63
- [getClientPosition, moveThreshold],
64
- );
58
+ return (
59
+ (moveThreshold?.x !== undefined && deltaX > moveThreshold.x) ||
60
+ (moveThreshold?.y !== undefined && deltaY > moveThreshold.y)
61
+ );
62
+ },
63
+ [getClientPosition, moveThreshold],
64
+ );
65
65
 
66
- const cancelLongPress = useCallback(() => {
67
- if (timeoutRef.current !== null) {
68
- window.clearTimeout(timeoutRef.current);
69
- timeoutRef.current = null;
70
- }
71
- }, []);
66
+ const cancelLongPress = useCallback(() => {
67
+ if (timeoutRef.current !== null) {
68
+ window.clearTimeout(timeoutRef.current);
69
+ timeoutRef.current = null;
70
+ }
71
+ }, []);
72
72
 
73
- const handlePressStart = useCallback(
74
- (event: MouseEvent<E> | TouchEvent<E>) => {
75
- cancelLongPress();
76
- initialPositionRef.current = getClientPosition(event);
77
- isLongPressActiveRef.current = false;
73
+ const handlePressStart = useCallback(
74
+ (event: MouseEvent<E> | TouchEvent<E>) => {
75
+ cancelLongPress();
76
+ initialPositionRef.current = getClientPosition(event);
77
+ isLongPressActiveRef.current = false;
78
78
 
79
- timeoutRef.current = window.setTimeout(() => {
80
- isLongPressActiveRef.current = true;
81
- savedOnLongPress.current(event);
82
- }, delay);
83
- },
84
- [cancelLongPress, delay, getClientPosition],
85
- );
79
+ timeoutRef.current = window.setTimeout(() => {
80
+ isLongPressActiveRef.current = true;
81
+ savedOnLongPress.current(event);
82
+ }, delay);
83
+ },
84
+ [cancelLongPress, delay, getClientPosition],
85
+ );
86
86
 
87
- const handlePressEnd = useCallback(
88
- (event: MouseEvent<E> | TouchEvent<E>) => {
89
- if (isLongPressActiveRef.current) {
90
- savedOnLongPressEnd.current?.(event);
91
- } else if (timeoutRef.current !== null) {
92
- savedOnClick.current?.(event);
93
- }
87
+ const handlePressEnd = useCallback(
88
+ (event: MouseEvent<E> | TouchEvent<E>) => {
89
+ if (isLongPressActiveRef.current) {
90
+ savedOnLongPressEnd.current?.(event);
91
+ } else if (timeoutRef.current !== null) {
92
+ savedOnClick.current?.(event);
93
+ }
94
94
 
95
- cancelLongPress();
96
- isLongPressActiveRef.current = false;
97
- },
98
- [cancelLongPress],
99
- );
95
+ cancelLongPress();
96
+ isLongPressActiveRef.current = false;
97
+ },
98
+ [cancelLongPress],
99
+ );
100
100
 
101
- const handlePressMove = useCallback(
102
- (event: MouseEvent<E> | TouchEvent<E>) => {
103
- if (timeoutRef.current !== null && isMovedBeyondThreshold(event)) {
104
- cancelLongPress();
105
- }
106
- },
107
- [cancelLongPress, isMovedBeyondThreshold],
108
- );
101
+ const handlePressMove = useCallback(
102
+ (event: MouseEvent<E> | TouchEvent<E>) => {
103
+ if (timeoutRef.current !== null && isMovedBeyondThreshold(event)) {
104
+ cancelLongPress();
105
+ }
106
+ },
107
+ [cancelLongPress, isMovedBeyondThreshold],
108
+ );
109
109
 
110
- return {
111
- onMouseDown: handlePressStart,
112
- onMouseUp: handlePressEnd,
113
- onMouseLeave: cancelLongPress,
114
- onTouchStart: handlePressStart,
115
- onTouchEnd: handlePressEnd,
116
- ...(hasThreshold
117
- ? { onTouchMove: handlePressMove, onMouseMove: handlePressMove }
118
- : {}),
119
- };
110
+ return {
111
+ onMouseDown: handlePressStart,
112
+ onMouseUp: handlePressEnd,
113
+ onMouseLeave: cancelLongPress,
114
+ onTouchStart: handlePressStart,
115
+ onTouchEnd: handlePressEnd,
116
+ ...(hasThreshold
117
+ ? { onTouchMove: handlePressMove, onMouseMove: handlePressMove }
118
+ : {}),
119
+ };
120
120
  }
@@ -3,19 +3,19 @@
3
3
  import { useCallback, useEffect, useRef } from "react";
4
4
 
5
5
  export function usePreservedCallback<
6
- Arguments extends unknown[] = unknown[],
7
- ReturnValue = unknown,
6
+ Arguments extends unknown[] = unknown[],
7
+ ReturnValue = unknown,
8
8
  >(callback: (...args: Arguments) => ReturnValue) {
9
- const callbackRef = useRef(callback);
9
+ const callbackRef = useRef(callback);
10
10
 
11
- useEffect(
12
- function syncCallbackRef() {
13
- callbackRef.current = callback;
14
- },
15
- [callback],
16
- );
11
+ useEffect(
12
+ function syncCallbackRef() {
13
+ callbackRef.current = callback;
14
+ },
15
+ [callback],
16
+ );
17
17
 
18
- return useCallback((...args: Arguments) => {
19
- return callbackRef.current(...args);
20
- }, []);
18
+ return useCallback((...args: Arguments) => {
19
+ return callbackRef.current(...args);
20
+ }, []);
21
21
  }
@@ -3,19 +3,19 @@
3
3
  import { useMemo, useRef } from "react";
4
4
 
5
5
  function areDeeplyEqual<T>(a: T, b: T): boolean {
6
- return JSON.stringify(a) === JSON.stringify(b);
6
+ return JSON.stringify(a) === JSON.stringify(b);
7
7
  }
8
8
 
9
9
  export function usePreservedReference<T>(
10
- value: T,
11
- areValuesEqual: (a: T, b: T) => boolean = areDeeplyEqual,
10
+ value: T,
11
+ areValuesEqual: (a: T, b: T) => boolean = areDeeplyEqual,
12
12
  ): T {
13
- const ref = useRef(value);
13
+ const ref = useRef(value);
14
14
 
15
- return useMemo(() => {
16
- if (!areValuesEqual(ref.current, value)) {
17
- ref.current = value;
18
- }
19
- return ref.current;
20
- }, [areValuesEqual, value]);
15
+ return useMemo(() => {
16
+ if (!areValuesEqual(ref.current, value)) {
17
+ ref.current = value;
18
+ }
19
+ return ref.current;
20
+ }, [areValuesEqual, value]);
21
21
  }
@@ -7,29 +7,29 @@ import { usePreservedCallback } from "./usePreservedCallback";
7
7
  export type CleanupCallback = () => void;
8
8
 
9
9
  export function useRefEffect<RefElement extends HTMLElement = HTMLElement>(
10
- callback: (element: RefElement) => CleanupCallback | undefined,
11
- deps: DependencyList,
10
+ callback: (element: RefElement) => CleanupCallback | undefined,
11
+ deps: DependencyList,
12
12
  ): (element: RefElement | null) => void {
13
- const preservedCallback = usePreservedCallback(callback);
14
- const cleanupCallbackRef = useRef<CleanupCallback>(() => {});
13
+ const preservedCallback = usePreservedCallback(callback);
14
+ const cleanupCallbackRef = useRef<CleanupCallback>(() => {});
15
15
 
16
- const effect = useCallback(
17
- (element: RefElement | null) => {
18
- cleanupCallbackRef.current();
19
- cleanupCallbackRef.current = () => {};
16
+ const effect = useCallback(
17
+ (element: RefElement | null) => {
18
+ cleanupCallbackRef.current();
19
+ cleanupCallbackRef.current = () => {};
20
20
 
21
- if (element == null) {
22
- return;
23
- }
21
+ if (element == null) {
22
+ return;
23
+ }
24
24
 
25
- const cleanup = preservedCallback(element);
25
+ const cleanup = preservedCallback(element);
26
26
 
27
- if (typeof cleanup === "function") {
28
- cleanupCallbackRef.current = cleanup;
29
- }
30
- },
31
- [preservedCallback, ...deps],
32
- );
27
+ if (typeof cleanup === "function") {
28
+ cleanupCallbackRef.current = cleanup;
29
+ }
30
+ },
31
+ [preservedCallback, ...deps],
32
+ );
33
33
 
34
- return effect;
34
+ return effect;
35
35
  }