@mantine/hooks 9.0.1 → 9.1.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.
Files changed (166) hide show
  1. package/cjs/index.cjs +8 -0
  2. package/cjs/use-click-outside/use-click-outside.cjs +11 -8
  3. package/cjs/use-click-outside/use-click-outside.cjs.map +1 -1
  4. package/cjs/use-clipboard/use-clipboard.cjs +13 -6
  5. package/cjs/use-clipboard/use-clipboard.cjs.map +1 -1
  6. package/cjs/use-collapse/use-collapse.cjs +1 -1
  7. package/cjs/use-collapse/use-collapse.cjs.map +1 -1
  8. package/cjs/use-collapse/use-horizontal-collapse.cjs +4 -3
  9. package/cjs/use-collapse/use-horizontal-collapse.cjs.map +1 -1
  10. package/cjs/use-counter/use-counter.cjs +12 -3
  11. package/cjs/use-counter/use-counter.cjs.map +1 -1
  12. package/cjs/use-debounced-callback/use-debounced-callback.cjs +28 -4
  13. package/cjs/use-debounced-callback/use-debounced-callback.cjs.map +1 -1
  14. package/cjs/use-debounced-state/use-debounced-state.cjs +1 -1
  15. package/cjs/use-debounced-state/use-debounced-state.cjs.map +1 -1
  16. package/cjs/use-debounced-value/use-debounced-value.cjs +22 -2
  17. package/cjs/use-debounced-value/use-debounced-value.cjs.map +1 -1
  18. package/cjs/use-event-listener/use-event-listener.cjs.map +1 -1
  19. package/cjs/use-favicon/use-favicon.cjs +3 -1
  20. package/cjs/use-favicon/use-favicon.cjs.map +1 -1
  21. package/cjs/use-fetch/use-fetch.cjs +7 -4
  22. package/cjs/use-fetch/use-fetch.cjs.map +1 -1
  23. package/cjs/use-file-dialog/use-file-dialog.cjs +1 -0
  24. package/cjs/use-file-dialog/use-file-dialog.cjs.map +1 -1
  25. package/cjs/use-floating-window/use-floating-window.cjs +33 -36
  26. package/cjs/use-floating-window/use-floating-window.cjs.map +1 -1
  27. package/cjs/use-focus-trap/use-focus-trap.cjs +12 -9
  28. package/cjs/use-focus-trap/use-focus-trap.cjs.map +1 -1
  29. package/cjs/use-fullscreen/use-fullscreen.cjs +3 -1
  30. package/cjs/use-fullscreen/use-fullscreen.cjs.map +1 -1
  31. package/cjs/use-headroom/use-headroom.cjs +4 -1
  32. package/cjs/use-headroom/use-headroom.cjs.map +1 -1
  33. package/cjs/use-hotkeys/parse-hotkey.cjs +1 -2
  34. package/cjs/use-hotkeys/parse-hotkey.cjs.map +1 -1
  35. package/cjs/use-hover/use-hover.cjs +1 -0
  36. package/cjs/use-hover/use-hover.cjs.map +1 -1
  37. package/cjs/use-in-viewport/use-in-viewport.cjs +11 -7
  38. package/cjs/use-in-viewport/use-in-viewport.cjs.map +1 -1
  39. package/cjs/use-interval/use-interval.cjs +15 -6
  40. package/cjs/use-interval/use-interval.cjs.map +1 -1
  41. package/cjs/use-local-storage/create-storage.cjs +1 -1
  42. package/cjs/use-local-storage/create-storage.cjs.map +1 -1
  43. package/cjs/use-long-press/use-long-press.cjs +6 -2
  44. package/cjs/use-long-press/use-long-press.cjs.map +1 -1
  45. package/cjs/use-mask/use-mask.cjs +457 -0
  46. package/cjs/use-mask/use-mask.cjs.map +1 -0
  47. package/cjs/use-mouse/use-mouse.cjs +2 -2
  48. package/cjs/use-mouse/use-mouse.cjs.map +1 -1
  49. package/cjs/use-move/use-move.cjs +8 -0
  50. package/cjs/use-move/use-move.cjs.map +1 -1
  51. package/cjs/use-orientation/use-orientation.cjs +8 -2
  52. package/cjs/use-orientation/use-orientation.cjs.map +1 -1
  53. package/cjs/use-os/use-os.cjs +1 -1
  54. package/cjs/use-os/use-os.cjs.map +1 -1
  55. package/cjs/use-radial-move/use-radial-move.cjs +4 -4
  56. package/cjs/use-radial-move/use-radial-move.cjs.map +1 -1
  57. package/cjs/use-roving-index/use-roving-index.cjs +200 -0
  58. package/cjs/use-roving-index/use-roving-index.cjs.map +1 -0
  59. package/cjs/use-scroll-direction/use-scroll-direction.cjs +7 -7
  60. package/cjs/use-scroll-direction/use-scroll-direction.cjs.map +1 -1
  61. package/cjs/use-scroll-into-view/use-scroll-into-view.cjs +14 -4
  62. package/cjs/use-scroll-into-view/use-scroll-into-view.cjs.map +1 -1
  63. package/cjs/use-scroll-spy/use-scroll-spy.cjs +7 -3
  64. package/cjs/use-scroll-spy/use-scroll-spy.cjs.map +1 -1
  65. package/cjs/use-scroller/use-scroller.cjs +3 -3
  66. package/cjs/use-scroller/use-scroller.cjs.map +1 -1
  67. package/cjs/use-set/use-set.cjs +6 -1
  68. package/cjs/use-set/use-set.cjs.map +1 -1
  69. package/cjs/use-throttled-callback/use-throttled-callback.cjs +3 -1
  70. package/cjs/use-throttled-callback/use-throttled-callback.cjs.map +1 -1
  71. package/cjs/use-timeout/use-timeout.cjs +3 -1
  72. package/cjs/use-timeout/use-timeout.cjs.map +1 -1
  73. package/cjs/use-viewport-size/use-viewport-size.cjs +3 -3
  74. package/cjs/use-viewport-size/use-viewport-size.cjs.map +1 -1
  75. package/cjs/use-window-scroll/use-window-scroll.cjs +2 -2
  76. package/cjs/use-window-scroll/use-window-scroll.cjs.map +1 -1
  77. package/esm/index.mjs +3 -1
  78. package/esm/use-click-outside/use-click-outside.mjs +11 -8
  79. package/esm/use-click-outside/use-click-outside.mjs.map +1 -1
  80. package/esm/use-clipboard/use-clipboard.mjs +14 -7
  81. package/esm/use-clipboard/use-clipboard.mjs.map +1 -1
  82. package/esm/use-collapse/use-collapse.mjs +1 -1
  83. package/esm/use-collapse/use-collapse.mjs.map +1 -1
  84. package/esm/use-collapse/use-horizontal-collapse.mjs +5 -4
  85. package/esm/use-collapse/use-horizontal-collapse.mjs.map +1 -1
  86. package/esm/use-counter/use-counter.mjs +12 -3
  87. package/esm/use-counter/use-counter.mjs.map +1 -1
  88. package/esm/use-debounced-callback/use-debounced-callback.mjs +28 -4
  89. package/esm/use-debounced-callback/use-debounced-callback.mjs.map +1 -1
  90. package/esm/use-debounced-state/use-debounced-state.mjs +1 -1
  91. package/esm/use-debounced-state/use-debounced-state.mjs.map +1 -1
  92. package/esm/use-debounced-value/use-debounced-value.mjs +22 -2
  93. package/esm/use-debounced-value/use-debounced-value.mjs.map +1 -1
  94. package/esm/use-event-listener/use-event-listener.mjs.map +1 -1
  95. package/esm/use-favicon/use-favicon.mjs +3 -1
  96. package/esm/use-favicon/use-favicon.mjs.map +1 -1
  97. package/esm/use-fetch/use-fetch.mjs +7 -4
  98. package/esm/use-fetch/use-fetch.mjs.map +1 -1
  99. package/esm/use-file-dialog/use-file-dialog.mjs +1 -0
  100. package/esm/use-file-dialog/use-file-dialog.mjs.map +1 -1
  101. package/esm/use-floating-window/use-floating-window.mjs +33 -36
  102. package/esm/use-floating-window/use-floating-window.mjs.map +1 -1
  103. package/esm/use-focus-trap/use-focus-trap.mjs +12 -9
  104. package/esm/use-focus-trap/use-focus-trap.mjs.map +1 -1
  105. package/esm/use-fullscreen/use-fullscreen.mjs +3 -1
  106. package/esm/use-fullscreen/use-fullscreen.mjs.map +1 -1
  107. package/esm/use-headroom/use-headroom.mjs +4 -1
  108. package/esm/use-headroom/use-headroom.mjs.map +1 -1
  109. package/esm/use-hotkeys/parse-hotkey.mjs +1 -2
  110. package/esm/use-hotkeys/parse-hotkey.mjs.map +1 -1
  111. package/esm/use-hover/use-hover.mjs +1 -0
  112. package/esm/use-hover/use-hover.mjs.map +1 -1
  113. package/esm/use-in-viewport/use-in-viewport.mjs +11 -7
  114. package/esm/use-in-viewport/use-in-viewport.mjs.map +1 -1
  115. package/esm/use-interval/use-interval.mjs +15 -6
  116. package/esm/use-interval/use-interval.mjs.map +1 -1
  117. package/esm/use-local-storage/create-storage.mjs +1 -1
  118. package/esm/use-local-storage/create-storage.mjs.map +1 -1
  119. package/esm/use-long-press/use-long-press.mjs +6 -2
  120. package/esm/use-long-press/use-long-press.mjs.map +1 -1
  121. package/esm/use-mask/use-mask.mjs +453 -0
  122. package/esm/use-mask/use-mask.mjs.map +1 -0
  123. package/esm/use-mouse/use-mouse.mjs +2 -2
  124. package/esm/use-mouse/use-mouse.mjs.map +1 -1
  125. package/esm/use-move/use-move.mjs +8 -0
  126. package/esm/use-move/use-move.mjs.map +1 -1
  127. package/esm/use-orientation/use-orientation.mjs +8 -2
  128. package/esm/use-orientation/use-orientation.mjs.map +1 -1
  129. package/esm/use-os/use-os.mjs +1 -1
  130. package/esm/use-os/use-os.mjs.map +1 -1
  131. package/esm/use-radial-move/use-radial-move.mjs +5 -5
  132. package/esm/use-radial-move/use-radial-move.mjs.map +1 -1
  133. package/esm/use-roving-index/use-roving-index.mjs +200 -0
  134. package/esm/use-roving-index/use-roving-index.mjs.map +1 -0
  135. package/esm/use-scroll-direction/use-scroll-direction.mjs +7 -7
  136. package/esm/use-scroll-direction/use-scroll-direction.mjs.map +1 -1
  137. package/esm/use-scroll-into-view/use-scroll-into-view.mjs +15 -5
  138. package/esm/use-scroll-into-view/use-scroll-into-view.mjs.map +1 -1
  139. package/esm/use-scroll-spy/use-scroll-spy.mjs +8 -4
  140. package/esm/use-scroll-spy/use-scroll-spy.mjs.map +1 -1
  141. package/esm/use-scroller/use-scroller.mjs +3 -3
  142. package/esm/use-scroller/use-scroller.mjs.map +1 -1
  143. package/esm/use-set/use-set.mjs +6 -1
  144. package/esm/use-set/use-set.mjs.map +1 -1
  145. package/esm/use-throttled-callback/use-throttled-callback.mjs +3 -1
  146. package/esm/use-throttled-callback/use-throttled-callback.mjs.map +1 -1
  147. package/esm/use-timeout/use-timeout.mjs +3 -1
  148. package/esm/use-timeout/use-timeout.mjs.map +1 -1
  149. package/esm/use-viewport-size/use-viewport-size.mjs +3 -3
  150. package/esm/use-viewport-size/use-viewport-size.mjs.map +1 -1
  151. package/esm/use-window-scroll/use-window-scroll.mjs +2 -2
  152. package/esm/use-window-scroll/use-window-scroll.mjs.map +1 -1
  153. package/lib/index.d.mts +5 -1
  154. package/lib/index.d.ts +5 -1
  155. package/lib/use-click-outside/use-click-outside.d.ts +1 -1
  156. package/lib/use-collapse/use-horizontal-collapse.d.ts +5 -0
  157. package/lib/use-counter/use-counter.d.ts +1 -0
  158. package/lib/use-debounced-callback/use-debounced-callback.d.ts +4 -0
  159. package/lib/use-debounced-value/use-debounced-value.d.ts +6 -1
  160. package/lib/use-event-listener/use-event-listener.d.ts +1 -1
  161. package/lib/use-hotkeys/parse-hotkey.d.ts +4 -5
  162. package/lib/use-long-press/use-long-press.d.ts +1 -0
  163. package/lib/use-mask/use-mask.d.ts +60 -0
  164. package/lib/use-roving-index/use-roving-index.d.ts +49 -0
  165. package/lib/use-scroll-into-view/use-scroll-into-view.d.ts +4 -1
  166. package/package.json +1 -1
package/cjs/index.cjs CHANGED
@@ -85,10 +85,15 @@ const require_use_selection = require("./use-selection/use-selection.cjs");
85
85
  const require_use_floating_window = require("./use-floating-window/use-floating-window.cjs");
86
86
  const require_use_collapse = require("./use-collapse/use-collapse.cjs");
87
87
  const require_use_horizontal_collapse = require("./use-collapse/use-horizontal-collapse.cjs");
88
+ const require_use_mask = require("./use-mask/use-mask.cjs");
89
+ const require_use_roving_index = require("./use-roving-index/use-roving-index.cjs");
88
90
  exports.assignRef = require_use_merged_ref.assignRef;
89
91
  exports.clamp = require_clamp.clamp;
90
92
  exports.clampUseMovePosition = require_use_move.clampUseMovePosition;
93
+ exports.formatMask = require_use_mask.formatMask;
94
+ exports.generatePattern = require_use_mask.generatePattern;
91
95
  exports.getHotkeyHandler = require_parse_hotkey.getHotkeyHandler;
96
+ exports.isMaskComplete = require_use_mask.isMaskComplete;
92
97
  exports.lowerFirst = require_lower_first.lowerFirst;
93
98
  exports.mergeRefs = require_use_merged_ref.mergeRefs;
94
99
  exports.normalizeRadialValue = require_use_radial_move.normalizeRadialValue;
@@ -97,6 +102,7 @@ exports.range = require_range.range;
97
102
  exports.readLocalStorageValue = require_use_local_storage.readLocalStorageValue;
98
103
  exports.readSessionStorageValue = require_use_session_storage.readSessionStorageValue;
99
104
  exports.shallowEqual = require_shallow_equal.shallowEqual;
105
+ exports.unformatMask = require_use_mask.unformatMask;
100
106
  exports.upperFirst = require_upper_first.upperFirst;
101
107
  exports.useCallbackRef = require_use_callback_ref.useCallbackRef;
102
108
  exports.useClickOutside = require_use_click_outside.useClickOutside;
@@ -142,6 +148,7 @@ exports.useLocalStorage = require_use_local_storage.useLocalStorage;
142
148
  exports.useLogger = require_use_logger.useLogger;
143
149
  exports.useLongPress = require_use_long_press.useLongPress;
144
150
  exports.useMap = require_use_map.useMap;
151
+ exports.useMask = require_use_mask.useMask;
145
152
  exports.useMediaQuery = require_use_media_query.useMediaQuery;
146
153
  exports.useMergedRef = require_use_merged_ref.useMergedRef;
147
154
  exports.useMounted = require_use_mounted.useMounted;
@@ -160,6 +167,7 @@ exports.useQueue = require_use_queue.useQueue;
160
167
  exports.useRadialMove = require_use_radial_move.useRadialMove;
161
168
  exports.useReducedMotion = require_use_reduced_motion.useReducedMotion;
162
169
  exports.useResizeObserver = require_use_resize_observer.useResizeObserver;
170
+ exports.useRovingIndex = require_use_roving_index.useRovingIndex;
163
171
  exports.useScrollDirection = require_use_scroll_direction.useScrollDirection;
164
172
  exports.useScrollIntoView = require_use_scroll_into_view.useScrollIntoView;
165
173
  exports.useScrollSpy = require_use_scroll_spy.useScrollSpy;
@@ -2,22 +2,25 @@
2
2
  let react = require("react");
3
3
  //#region packages/@mantine/hooks/src/use-click-outside/use-click-outside.ts
4
4
  const DEFAULT_EVENTS = ["mousedown", "touchstart"];
5
- function useClickOutside(callback, events, nodes) {
5
+ function useClickOutside(callback, events, nodes, enabled = true) {
6
6
  const ref = (0, react.useRef)(null);
7
7
  const eventsList = events || DEFAULT_EVENTS;
8
8
  const listener = (0, react.useEffectEvent)((event) => {
9
9
  const { target } = event ?? {};
10
- if (Array.isArray(nodes)) {
11
- const shouldIgnore = !document.body.contains(target) && target?.tagName !== "HTML";
12
- nodes.every((node) => !!node && !event.composedPath().includes(node)) && !shouldIgnore && callback(event);
13
- } else if (ref.current && !ref.current.contains(target)) callback(event);
10
+ if (!document.body.contains(target) && target?.tagName !== "HTML") return;
11
+ const path = event.composedPath();
12
+ if (Array.isArray(nodes)) nodes.every((node) => !!node && !path.includes(node)) && callback(event);
13
+ else if (ref.current && !path.includes(ref.current)) callback(event);
14
14
  });
15
+ const eventsKey = eventsList.join(",");
15
16
  (0, react.useEffect)(() => {
16
- eventsList.forEach((fn) => document.addEventListener(fn, listener));
17
+ if (!enabled) return;
18
+ const events = eventsKey.split(",");
19
+ events.forEach((fn) => document.addEventListener(fn, listener));
17
20
  return () => {
18
- eventsList.forEach((fn) => document.removeEventListener(fn, listener));
21
+ events.forEach((fn) => document.removeEventListener(fn, listener));
19
22
  };
20
- }, []);
23
+ }, [eventsKey, enabled]);
21
24
  return ref;
22
25
  }
23
26
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"use-click-outside.cjs","names":[],"sources":["../../src/use-click-outside/use-click-outside.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef } from 'react';\n\ntype EventType = MouseEvent | TouchEvent;\n\nconst DEFAULT_EVENTS = ['mousedown', 'touchstart'];\n\nexport function useClickOutside<T extends HTMLElement = any>(\n callback: (event: EventType) => void,\n events?: string[] | null,\n nodes?: (HTMLElement | null)[]\n) {\n const ref = useRef<T>(null);\n const eventsList = events || DEFAULT_EVENTS;\n\n const listener = useEffectEvent((event: Event) => {\n const { target } = event ?? {};\n if (Array.isArray(nodes)) {\n const shouldIgnore =\n !document.body.contains(target as Node) && (target as Element)?.tagName !== 'HTML';\n const shouldTrigger = nodes.every((node) => !!node && !event.composedPath().includes(node));\n shouldTrigger && !shouldIgnore && callback(event as EventType);\n } else if (ref.current && !ref.current.contains(target as Node)) {\n callback(event as EventType);\n }\n });\n\n useEffect(() => {\n eventsList.forEach((fn) => document.addEventListener(fn, listener));\n\n return () => {\n eventsList.forEach((fn) => document.removeEventListener(fn, listener));\n };\n }, []);\n\n return ref;\n}\n"],"mappings":";;;AAIA,MAAM,iBAAiB,CAAC,aAAa,aAAa;AAElD,SAAgB,gBACd,UACA,QACA,OACA;CACA,MAAM,OAAA,GAAA,MAAA,QAAgB,KAAK;CAC3B,MAAM,aAAa,UAAU;CAE7B,MAAM,YAAA,GAAA,MAAA,iBAA2B,UAAiB;EAChD,MAAM,EAAE,WAAW,SAAS,EAAE;AAC9B,MAAI,MAAM,QAAQ,MAAM,EAAE;GACxB,MAAM,eACJ,CAAC,SAAS,KAAK,SAAS,OAAe,IAAK,QAAoB,YAAY;AACxD,SAAM,OAAO,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,cAAc,CAAC,SAAS,KAAK,CAAC,IAC1E,CAAC,gBAAgB,SAAS,MAAmB;aACrD,IAAI,WAAW,CAAC,IAAI,QAAQ,SAAS,OAAe,CAC7D,UAAS,MAAmB;GAE9B;AAEF,EAAA,GAAA,MAAA,iBAAgB;AACd,aAAW,SAAS,OAAO,SAAS,iBAAiB,IAAI,SAAS,CAAC;AAEnE,eAAa;AACX,cAAW,SAAS,OAAO,SAAS,oBAAoB,IAAI,SAAS,CAAC;;IAEvE,EAAE,CAAC;AAEN,QAAO"}
1
+ {"version":3,"file":"use-click-outside.cjs","names":[],"sources":["../../src/use-click-outside/use-click-outside.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef } from 'react';\n\ntype EventType = MouseEvent | TouchEvent;\n\nconst DEFAULT_EVENTS = ['mousedown', 'touchstart'];\n\nexport function useClickOutside<T extends HTMLElement = any>(\n callback: (event: EventType) => void,\n events?: string[] | null,\n nodes?: (HTMLElement | null)[],\n enabled: boolean = true\n) {\n const ref = useRef<T>(null);\n const eventsList = events || DEFAULT_EVENTS;\n\n const listener = useEffectEvent((event: Event) => {\n const { target } = event ?? {};\n const shouldIgnore =\n !document.body.contains(target as Node) && (target as Element)?.tagName !== 'HTML';\n\n if (shouldIgnore) {\n return;\n }\n\n const path = event.composedPath();\n\n if (Array.isArray(nodes)) {\n const shouldTrigger = nodes.every((node) => !!node && !path.includes(node));\n shouldTrigger && callback(event as EventType);\n } else if (ref.current && !path.includes(ref.current)) {\n callback(event as EventType);\n }\n });\n\n const eventsKey = eventsList.join(',');\n\n useEffect(() => {\n if (!enabled) {\n return undefined;\n }\n\n const events = eventsKey.split(',');\n events.forEach((fn) => document.addEventListener(fn, listener));\n\n return () => {\n events.forEach((fn) => document.removeEventListener(fn, listener));\n };\n }, [eventsKey, enabled]);\n\n return ref;\n}\n"],"mappings":";;;AAIA,MAAM,iBAAiB,CAAC,aAAa,aAAa;AAElD,SAAgB,gBACd,UACA,QACA,OACA,UAAmB,MACnB;CACA,MAAM,OAAA,GAAA,MAAA,QAAgB,KAAK;CAC3B,MAAM,aAAa,UAAU;CAE7B,MAAM,YAAA,GAAA,MAAA,iBAA2B,UAAiB;EAChD,MAAM,EAAE,WAAW,SAAS,EAAE;AAI9B,MAFE,CAAC,SAAS,KAAK,SAAS,OAAe,IAAK,QAAoB,YAAY,OAG5E;EAGF,MAAM,OAAO,MAAM,cAAc;AAEjC,MAAI,MAAM,QAAQ,MAAM,CACA,OAAM,OAAO,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,SAAS,KAAK,CAAC,IAC1D,SAAS,MAAmB;WACpC,IAAI,WAAW,CAAC,KAAK,SAAS,IAAI,QAAQ,CACnD,UAAS,MAAmB;GAE9B;CAEF,MAAM,YAAY,WAAW,KAAK,IAAI;AAEtC,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,CAAC,QACH;EAGF,MAAM,SAAS,UAAU,MAAM,IAAI;AACnC,SAAO,SAAS,OAAO,SAAS,iBAAiB,IAAI,SAAS,CAAC;AAE/D,eAAa;AACX,UAAO,SAAS,OAAO,SAAS,oBAAoB,IAAI,SAAS,CAAC;;IAEnE,CAAC,WAAW,QAAQ,CAAC;AAExB,QAAO"}
@@ -1,23 +1,30 @@
1
1
  "use client";
2
2
  let react = require("react");
3
3
  //#region packages/@mantine/hooks/src/use-clipboard/use-clipboard.ts
4
- function useClipboard(options = { timeout: 2e3 }) {
4
+ function useClipboard(options = {}) {
5
+ const timeout = options.timeout ?? 2e3;
5
6
  const [error, setError] = (0, react.useState)(null);
6
7
  const [copied, setCopied] = (0, react.useState)(false);
7
- const [copyTimeout, setCopyTimeout] = (0, react.useState)(null);
8
+ const timeoutRef = (0, react.useRef)(null);
9
+ (0, react.useEffect)(() => () => {
10
+ window.clearTimeout(timeoutRef.current);
11
+ }, []);
8
12
  const handleCopyResult = (value) => {
9
- window.clearTimeout(copyTimeout);
10
- setCopyTimeout(window.setTimeout(() => setCopied(false), options.timeout));
13
+ window.clearTimeout(timeoutRef.current);
14
+ timeoutRef.current = window.setTimeout(() => setCopied(false), timeout);
11
15
  setCopied(value);
12
16
  };
13
17
  const copy = (value) => {
14
- if ("clipboard" in navigator) navigator.clipboard.writeText(value).then(() => handleCopyResult(true)).catch((err) => setError(err));
18
+ if ("clipboard" in navigator) navigator.clipboard.writeText(value).then(() => {
19
+ setError(null);
20
+ handleCopyResult(true);
21
+ }).catch((err) => setError(err));
15
22
  else setError(/* @__PURE__ */ new Error("useClipboard: navigator.clipboard is not supported"));
16
23
  };
17
24
  const reset = () => {
18
25
  setCopied(false);
19
26
  setError(null);
20
- window.clearTimeout(copyTimeout);
27
+ window.clearTimeout(timeoutRef.current);
21
28
  };
22
29
  return {
23
30
  copy,
@@ -1 +1 @@
1
- {"version":3,"file":"use-clipboard.cjs","names":[],"sources":["../../src/use-clipboard/use-clipboard.ts"],"sourcesContent":["import { useState } from 'react';\n\nexport interface UseClipboardInput {\n /** Time in ms after which the copied state will reset, `2000` by default */\n timeout?: number;\n}\n\nexport interface UseClipboardReturnValue {\n /** Function to copy value to clipboard */\n copy: (value: any) => void;\n\n /** Function to reset copied state and error */\n reset: () => void;\n\n /** Error if copying failed */\n error: Error | null;\n\n /** Boolean indicating if the value was copied successfully */\n copied: boolean;\n}\n\nexport function useClipboard(\n options: UseClipboardInput = { timeout: 2000 }\n): UseClipboardReturnValue {\n const [error, setError] = useState<Error | null>(null);\n const [copied, setCopied] = useState(false);\n const [copyTimeout, setCopyTimeout] = useState<number | null>(null);\n\n const handleCopyResult = (value: boolean) => {\n window.clearTimeout(copyTimeout!);\n setCopyTimeout(window.setTimeout(() => setCopied(false), options.timeout));\n setCopied(value);\n };\n\n const copy = (value: any) => {\n if ('clipboard' in navigator) {\n navigator.clipboard\n .writeText(value)\n .then(() => handleCopyResult(true))\n .catch((err) => setError(err));\n } else {\n setError(new Error('useClipboard: navigator.clipboard is not supported'));\n }\n };\n\n const reset = () => {\n setCopied(false);\n setError(null);\n window.clearTimeout(copyTimeout!);\n };\n\n return { copy, reset, error, copied };\n}\n\nexport namespace useClipboard {\n export type Input = UseClipboardInput;\n export type ReturnValue = UseClipboardReturnValue;\n}\n"],"mappings":";;;AAqBA,SAAgB,aACd,UAA6B,EAAE,SAAS,KAAM,EACrB;CACzB,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAmC,KAAK;CACtD,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,UAAsB,MAAM;CAC3C,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,UAA0C,KAAK;CAEnE,MAAM,oBAAoB,UAAmB;AAC3C,SAAO,aAAa,YAAa;AACjC,iBAAe,OAAO,iBAAiB,UAAU,MAAM,EAAE,QAAQ,QAAQ,CAAC;AAC1E,YAAU,MAAM;;CAGlB,MAAM,QAAQ,UAAe;AAC3B,MAAI,eAAe,UACjB,WAAU,UACP,UAAU,MAAM,CAChB,WAAW,iBAAiB,KAAK,CAAC,CAClC,OAAO,QAAQ,SAAS,IAAI,CAAC;MAEhC,0BAAS,IAAI,MAAM,qDAAqD,CAAC;;CAI7E,MAAM,cAAc;AAClB,YAAU,MAAM;AAChB,WAAS,KAAK;AACd,SAAO,aAAa,YAAa;;AAGnC,QAAO;EAAE;EAAM;EAAO;EAAO;EAAQ"}
1
+ {"version":3,"file":"use-clipboard.cjs","names":[],"sources":["../../src/use-clipboard/use-clipboard.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nexport interface UseClipboardInput {\n /** Time in ms after which the copied state will reset, `2000` by default */\n timeout?: number;\n}\n\nexport interface UseClipboardReturnValue {\n /** Function to copy value to clipboard */\n copy: (value: any) => void;\n\n /** Function to reset copied state and error */\n reset: () => void;\n\n /** Error if copying failed */\n error: Error | null;\n\n /** Boolean indicating if the value was copied successfully */\n copied: boolean;\n}\n\nexport function useClipboard(options: UseClipboardInput = {}): UseClipboardReturnValue {\n const timeout = options.timeout ?? 2000;\n const [error, setError] = useState<Error | null>(null);\n const [copied, setCopied] = useState(false);\n const timeoutRef = useRef<number | null>(null);\n\n useEffect(\n () => () => {\n window.clearTimeout(timeoutRef.current!);\n },\n []\n );\n\n const handleCopyResult = (value: boolean) => {\n window.clearTimeout(timeoutRef.current!);\n timeoutRef.current = window.setTimeout(() => setCopied(false), timeout);\n setCopied(value);\n };\n\n const copy = (value: any) => {\n if ('clipboard' in navigator) {\n navigator.clipboard\n .writeText(value)\n .then(() => {\n setError(null);\n handleCopyResult(true);\n })\n .catch((err) => setError(err));\n } else {\n setError(new Error('useClipboard: navigator.clipboard is not supported'));\n }\n };\n\n const reset = () => {\n setCopied(false);\n setError(null);\n window.clearTimeout(timeoutRef.current!);\n };\n\n return { copy, reset, error, copied };\n}\n\nexport namespace useClipboard {\n export type Input = UseClipboardInput;\n export type ReturnValue = UseClipboardReturnValue;\n}\n"],"mappings":";;;AAqBA,SAAgB,aAAa,UAA6B,EAAE,EAA2B;CACrF,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAmC,KAAK;CACtD,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,UAAsB,MAAM;CAC3C,MAAM,cAAA,GAAA,MAAA,QAAmC,KAAK;AAE9C,EAAA,GAAA,MAAA,uBACc;AACV,SAAO,aAAa,WAAW,QAAS;IAE1C,EAAE,CACH;CAED,MAAM,oBAAoB,UAAmB;AAC3C,SAAO,aAAa,WAAW,QAAS;AACxC,aAAW,UAAU,OAAO,iBAAiB,UAAU,MAAM,EAAE,QAAQ;AACvE,YAAU,MAAM;;CAGlB,MAAM,QAAQ,UAAe;AAC3B,MAAI,eAAe,UACjB,WAAU,UACP,UAAU,MAAM,CAChB,WAAW;AACV,YAAS,KAAK;AACd,oBAAiB,KAAK;IACtB,CACD,OAAO,QAAQ,SAAS,IAAI,CAAC;MAEhC,0BAAS,IAAI,MAAM,qDAAqD,CAAC;;CAI7E,MAAM,cAAc;AAClB,YAAU,MAAM;AAChB,WAAS,KAAK;AACd,SAAO,aAAa,WAAW,QAAS;;AAG1C,QAAO;EAAE;EAAM;EAAO;EAAO;EAAQ"}
@@ -32,7 +32,7 @@ function useCollapse({ transitionDuration, transitionTimingFunction = "ease", on
32
32
  }));
33
33
  };
34
34
  const getTransitionStyles = (height) => {
35
- const duration = transitionDuration || getAutoHeightDuration(height);
35
+ const duration = transitionDuration ?? getAutoHeightDuration(height);
36
36
  return { transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` };
37
37
  };
38
38
  require_use_did_update.useDidUpdate(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"use-collapse.cjs","names":["mergeRefs"],"sources":["../../src/use-collapse/use-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoHeightDuration(height: number | string) {\n if (!height || typeof height === 'string') {\n return 0;\n }\n const constant = height / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementHeight(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollHeight : 'auto';\n}\n\nexport interface UseCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content height */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseCollapseReturnValue {\n /** Current transition state */\n state: UseCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (input?: GetCollapsePropsInput) => GetCollapsePropsReturnValue;\n}\n\nexport function useCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseCollapseInput): UseCollapseReturnValue {\n const collapsedStyles = {\n height: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (height: number | string) => {\n const duration = transitionDuration || getAutoHeightDuration(height);\n return {\n transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'height', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), height });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), willChange: 'height', height });\n window.requestAnimationFrame(() => mergeStyles({ height: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'height') {\n return;\n }\n\n if (expanded) {\n const height = getElementHeight(elementRef);\n\n if (height === styles.height) {\n setStyles({});\n } else {\n mergeStyles({ height });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.height === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useCollapse {\n export type Input = UseCollapseInput;\n export type ReturnValue = UseCollapseReturnValue;\n export type State = UseCollapseState;\n}\n"],"mappings":";;;;;;AAKA,SAAS,sBAAsB,QAAyB;AACtD,KAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,QAAO;CAET,MAAM,WAAW,SAAS;AAC1B,QAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,GAAG;;AAGpE,SAAgB,iBAAiB,YAAiD;AAChF,QAAO,WAAW,UAAU,WAAW,QAAQ,eAAe;;AA8ChE,SAAgB,YAAY,EAC1B,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC2C;CAC3C,MAAM,kBAAkB;EACtB,QAAQ;EACR,UAAU;EACV,GAAI,cAAc,EAAE,GAAG,EAAE,SAAS,QAAQ;EAC3C;CAED,MAAM,0BAAA,GAAA,MAAA,sBAA8C,qBAAqB,CAAC;CAE1E,MAAM,cAAA,GAAA,MAAA,QAAiC,KAAK;CAC5C,MAAM,CAAC,QAAQ,iBAAA,GAAA,MAAA,UAAwC,WAAW,EAAE,GAAG,gBAAgB;CACvF,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAuC,WAAW,YAAY,SAAS;CACrF,MAAM,aAAa,cAAmD;AACpE,GAAA,GAAA,UAAA,iBAAgB,aAAa,UAAU,CAAC;;CAG1C,MAAM,eAAe,cAA6B;AAChD,aAAW,eAAe;GAAE,GAAG;GAAW,GAAG;GAAW,EAAE;;CAG5D,MAAM,uBAAuB,WAA4B;EACvD,MAAM,WAAW,sBAAsB,sBAAsB,OAAO;AACpE,SAAO,EACL,YAAY,UAAU,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,4BACxF;;AAGH,wBAAA,mBAAmB;AAGjB,MAFyB,uBAAuB,EAG9C,yBAAwB;AAG1B,MAAI,SACF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,WAAW,CAAC;AACrC,eAAY;IAAE,YAAY;IAAU,SAAS;IAAS,UAAU;IAAU,CAAC;AAC3E,UAAO,4BAA4B;IACjC,MAAM,SAAS,iBAAiB,WAAW;AAC3C,gBAAY;KAAE,GAAG,oBAAoB,OAAO;KAAE;KAAQ,CAAC;KACvD;IACF;MAEF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,UAAU,CAAC;GACpC,MAAM,SAAS,iBAAiB,WAAW;AAC3C,eAAY;IAAE,GAAG,oBAAoB,OAAO;IAAE,YAAY;IAAU;IAAQ,CAAC;AAC7E,UAAO,4BAA4B,YAAY;IAAE,QAAQ;IAAG,UAAU;IAAU,CAAC,CAAC;IAClF;IAEH,CAAC,SAAS,CAAC;CAEd,MAAM,uBAAuB,UAAuC;AAClE,MAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,SAChE;AAGF,MAAI,UAAU;GACZ,MAAM,SAAS,iBAAiB,WAAW;AAE3C,OAAI,WAAW,OAAO,OACpB,WAAU,EAAE,CAAC;OAEb,aAAY,EAAE,QAAQ,CAAC;AAGzB,YAAS,UAAU;AACnB,sBAAmB;aACV,OAAO,WAAW,GAAG;AAC9B,aAAU,gBAAgB;AAC1B,YAAS,SAAS;AAClB,sBAAmB;;;AAIvB,QAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKA,uBAAAA,UAAU,YAAY,OAAO,IAAI;GACtC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;IAAQ;GAC/D;EACF"}
1
+ {"version":3,"file":"use-collapse.cjs","names":["mergeRefs"],"sources":["../../src/use-collapse/use-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoHeightDuration(height: number | string) {\n if (!height || typeof height === 'string') {\n return 0;\n }\n const constant = height / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementHeight(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollHeight : 'auto';\n}\n\nexport interface UseCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content height */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseCollapseReturnValue {\n /** Current transition state */\n state: UseCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (input?: GetCollapsePropsInput) => GetCollapsePropsReturnValue;\n}\n\nexport function useCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseCollapseInput): UseCollapseReturnValue {\n const collapsedStyles = {\n height: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (height: number | string) => {\n const duration = transitionDuration ?? getAutoHeightDuration(height);\n return {\n transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'height', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), height });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const height = getElementHeight(elementRef);\n mergeStyles({ ...getTransitionStyles(height), willChange: 'height', height });\n window.requestAnimationFrame(() => mergeStyles({ height: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'height') {\n return;\n }\n\n if (expanded) {\n const height = getElementHeight(elementRef);\n\n if (height === styles.height) {\n setStyles({});\n } else {\n mergeStyles({ height });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.height === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useCollapse {\n export type Input = UseCollapseInput;\n export type ReturnValue = UseCollapseReturnValue;\n export type State = UseCollapseState;\n}\n"],"mappings":";;;;;;AAKA,SAAS,sBAAsB,QAAyB;AACtD,KAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,QAAO;CAET,MAAM,WAAW,SAAS;AAC1B,QAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,GAAG;;AAGpE,SAAgB,iBAAiB,YAAiD;AAChF,QAAO,WAAW,UAAU,WAAW,QAAQ,eAAe;;AA8ChE,SAAgB,YAAY,EAC1B,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC2C;CAC3C,MAAM,kBAAkB;EACtB,QAAQ;EACR,UAAU;EACV,GAAI,cAAc,EAAE,GAAG,EAAE,SAAS,QAAQ;EAC3C;CAED,MAAM,0BAAA,GAAA,MAAA,sBAA8C,qBAAqB,CAAC;CAE1E,MAAM,cAAA,GAAA,MAAA,QAAiC,KAAK;CAC5C,MAAM,CAAC,QAAQ,iBAAA,GAAA,MAAA,UAAwC,WAAW,EAAE,GAAG,gBAAgB;CACvF,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAuC,WAAW,YAAY,SAAS;CACrF,MAAM,aAAa,cAAmD;AACpE,GAAA,GAAA,UAAA,iBAAgB,aAAa,UAAU,CAAC;;CAG1C,MAAM,eAAe,cAA6B;AAChD,aAAW,eAAe;GAAE,GAAG;GAAW,GAAG;GAAW,EAAE;;CAG5D,MAAM,uBAAuB,WAA4B;EACvD,MAAM,WAAW,sBAAsB,sBAAsB,OAAO;AACpE,SAAO,EACL,YAAY,UAAU,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,4BACxF;;AAGH,wBAAA,mBAAmB;AAGjB,MAFyB,uBAAuB,EAG9C,yBAAwB;AAG1B,MAAI,SACF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,WAAW,CAAC;AACrC,eAAY;IAAE,YAAY;IAAU,SAAS;IAAS,UAAU;IAAU,CAAC;AAC3E,UAAO,4BAA4B;IACjC,MAAM,SAAS,iBAAiB,WAAW;AAC3C,gBAAY;KAAE,GAAG,oBAAoB,OAAO;KAAE;KAAQ,CAAC;KACvD;IACF;MAEF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,UAAU,CAAC;GACpC,MAAM,SAAS,iBAAiB,WAAW;AAC3C,eAAY;IAAE,GAAG,oBAAoB,OAAO;IAAE,YAAY;IAAU;IAAQ,CAAC;AAC7E,UAAO,4BAA4B,YAAY;IAAE,QAAQ;IAAG,UAAU;IAAU,CAAC,CAAC;IAClF;IAEH,CAAC,SAAS,CAAC;CAEd,MAAM,uBAAuB,UAAuC;AAClE,MAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,SAChE;AAGF,MAAI,UAAU;GACZ,MAAM,SAAS,iBAAiB,WAAW;AAE3C,OAAI,WAAW,OAAO,OACpB,WAAU,EAAE,CAAC;OAEb,aAAY,EAAE,QAAQ,CAAC;AAGzB,YAAS,UAAU;AACnB,sBAAmB;aACV,OAAO,WAAW,GAAG;AAC9B,aAAU,gBAAgB;AAC1B,YAAS,SAAS;AAClB,sBAAmB;;;AAIvB,QAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKA,uBAAAA,UAAU,YAAY,OAAO,IAAI;GACtC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;IAAQ;GAC/D;EACF"}
@@ -18,6 +18,7 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
18
18
  overflow: "hidden",
19
19
  ...keepMounted ? {} : { display: "none" }
20
20
  };
21
+ const onTransitionStartEvent = (0, react.useEffectEvent)(() => onTransitionStart?.());
21
22
  const elementRef = (0, react.useRef)(null);
22
23
  const [styles, setStylesRaw] = (0, react.useState)(expanded ? {} : collapsedStyles);
23
24
  const [state, setState] = (0, react.useState)(expanded ? "entered" : "exited");
@@ -31,11 +32,11 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
31
32
  }));
32
33
  };
33
34
  const getTransitionStyles = (width) => {
34
- const duration = transitionDuration || getAutoWidthDuration(width);
35
+ const duration = transitionDuration ?? getAutoWidthDuration(width);
35
36
  return { transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` };
36
37
  };
37
38
  require_use_did_update.useDidUpdate(() => {
38
- if (transitionDuration !== 0) onTransitionStart?.();
39
+ if (transitionDuration !== 0) onTransitionStartEvent();
39
40
  if (expanded) window.requestAnimationFrame(() => {
40
41
  (0, react_dom.flushSync)(() => setState("entering"));
41
42
  mergeStyles({
@@ -64,7 +65,7 @@ function useHorizontalCollapse({ transitionDuration, transitionTimingFunction =
64
65
  overflow: "hidden"
65
66
  }));
66
67
  });
67
- }, [expanded, onTransitionStart]);
68
+ }, [expanded]);
68
69
  const handleTransitionEnd = (event) => {
69
70
  if (event.target !== elementRef.current || event.propertyName !== "width") return;
70
71
  if (expanded) {
@@ -1 +1 @@
1
- {"version":3,"file":"use-horizontal-collapse.cjs","names":["mergeRefs"],"sources":["../../src/use-collapse/use-horizontal-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoWidthDuration(width: number | string) {\n if (!width || typeof width === 'string') {\n return 0;\n }\n const constant = width / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementWidth(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollWidth : 'auto';\n}\n\nexport interface UseHorizontalCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content width */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetHorizontalCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetHorizontalCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseHorizontalCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseHorizontalCollapseReturnValue {\n /** Current transition state */\n state: UseHorizontalCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (\n input?: GetHorizontalCollapsePropsInput\n ) => GetHorizontalCollapsePropsReturnValue;\n}\n\nexport function useHorizontalCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseHorizontalCollapseInput): UseHorizontalCollapseReturnValue {\n const collapsedStyles = {\n width: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseHorizontalCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (width: number | string) => {\n const duration = transitionDuration || getAutoWidthDuration(width);\n return {\n transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStart?.();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'width', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), width });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), willChange: 'width', width });\n window.requestAnimationFrame(() => mergeStyles({ width: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded, onTransitionStart]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'width') {\n return;\n }\n\n if (expanded) {\n const width = getElementWidth(elementRef);\n\n if (width === styles.width) {\n setStyles({});\n } else {\n mergeStyles({ width });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.width === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n"],"mappings":";;;;;;AAKA,SAAS,qBAAqB,OAAwB;AACpD,KAAI,CAAC,SAAS,OAAO,UAAU,SAC7B,QAAO;CAET,MAAM,WAAW,QAAQ;AACzB,QAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,GAAG;;AAGpE,SAAgB,gBAAgB,YAAiD;AAC/E,QAAO,WAAW,UAAU,WAAW,QAAQ,cAAc;;AAgD/D,SAAgB,sBAAsB,EACpC,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC+D;CAC/D,MAAM,kBAAkB;EACtB,OAAO;EACP,UAAU;EACV,GAAI,cAAc,EAAE,GAAG,EAAE,SAAS,QAAQ;EAC3C;CAED,MAAM,cAAA,GAAA,MAAA,QAAiC,KAAK;CAC5C,MAAM,CAAC,QAAQ,iBAAA,GAAA,MAAA,UAAwC,WAAW,EAAE,GAAG,gBAAgB;CACvF,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAiD,WAAW,YAAY,SAAS;CAC/F,MAAM,aAAa,cAAmD;AACpE,GAAA,GAAA,UAAA,iBAAgB,aAAa,UAAU,CAAC;;CAG1C,MAAM,eAAe,cAA6B;AAChD,aAAW,eAAe;GAAE,GAAG;GAAW,GAAG;GAAW,EAAE;;CAG5D,MAAM,uBAAuB,UAA2B;EACtD,MAAM,WAAW,sBAAsB,qBAAqB,MAAM;AAClE,SAAO,EACL,YAAY,SAAS,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,4BACvF;;AAGH,wBAAA,mBAAmB;AAGjB,MAFyB,uBAAuB,EAG9C,sBAAqB;AAGvB,MAAI,SACF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,WAAW,CAAC;AACrC,eAAY;IAAE,YAAY;IAAS,SAAS;IAAS,UAAU;IAAU,CAAC;AAC1E,UAAO,4BAA4B;IACjC,MAAM,QAAQ,gBAAgB,WAAW;AACzC,gBAAY;KAAE,GAAG,oBAAoB,MAAM;KAAE;KAAO,CAAC;KACrD;IACF;MAEF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,UAAU,CAAC;GACpC,MAAM,QAAQ,gBAAgB,WAAW;AACzC,eAAY;IAAE,GAAG,oBAAoB,MAAM;IAAE,YAAY;IAAS;IAAO,CAAC;AAC1E,UAAO,4BAA4B,YAAY;IAAE,OAAO;IAAG,UAAU;IAAU,CAAC,CAAC;IACjF;IAEH,CAAC,UAAU,kBAAkB,CAAC;CAEjC,MAAM,uBAAuB,UAAuC;AAClE,MAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,QAChE;AAGF,MAAI,UAAU;GACZ,MAAM,QAAQ,gBAAgB,WAAW;AAEzC,OAAI,UAAU,OAAO,MACnB,WAAU,EAAE,CAAC;OAEb,aAAY,EAAE,OAAO,CAAC;AAGxB,YAAS,UAAU;AACnB,sBAAmB;aACV,OAAO,UAAU,GAAG;AAC7B,aAAU,gBAAgB;AAC1B,YAAS,SAAS;AAClB,sBAAmB;;;AAIvB,QAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKA,uBAAAA,UAAU,YAAY,OAAO,IAAI;GACtC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;IAAQ;GAC/D;EACF"}
1
+ {"version":3,"file":"use-horizontal-collapse.cjs","names":["mergeRefs"],"sources":["../../src/use-collapse/use-horizontal-collapse.ts"],"sourcesContent":["import React, { CSSProperties, useEffectEvent, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\nimport { mergeRefs } from '../use-merged-ref/use-merged-ref';\n\nfunction getAutoWidthDuration(width: number | string) {\n if (!width || typeof width === 'string') {\n return 0;\n }\n const constant = width / 36;\n return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);\n}\n\nexport function getElementWidth(elementRef: React.RefObject<HTMLElement | null>) {\n return elementRef.current ? elementRef.current.scrollWidth : 'auto';\n}\n\nexport interface UseHorizontalCollapseInput {\n /** Expanded state */\n expanded: boolean;\n\n /** Transition duration in milliseconds, by default calculated based on content width */\n transitionDuration?: number;\n\n /** Transition timing function, `ease` by default */\n transitionTimingFunction?: string;\n\n /** Called when transition ends */\n onTransitionEnd?: () => void;\n\n /** Called when transition starts */\n onTransitionStart?: () => void;\n\n /** If true, collapsed content is kept in the DOM and hidden with `display: none` styles */\n keepMounted?: boolean;\n}\n\ninterface GetHorizontalCollapsePropsInput {\n style?: CSSProperties;\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface GetHorizontalCollapsePropsReturnValue {\n 'aria-hidden': boolean;\n inert: boolean;\n ref: React.RefCallback<HTMLDivElement>;\n onTransitionEnd: (event: React.TransitionEvent<Element>) => void;\n style: React.CSSProperties;\n}\n\nexport type UseHorizontalCollapseState = 'entering' | 'entered' | 'exiting' | 'exited';\n\nexport interface UseHorizontalCollapseReturnValue {\n /** Current transition state */\n state: UseHorizontalCollapseState;\n\n /** Props to pass down to the collapsible element */\n getCollapseProps: (\n input?: GetHorizontalCollapsePropsInput\n ) => GetHorizontalCollapsePropsReturnValue;\n}\n\nexport function useHorizontalCollapse({\n transitionDuration,\n transitionTimingFunction = 'ease',\n onTransitionEnd,\n onTransitionStart,\n expanded,\n keepMounted,\n}: UseHorizontalCollapseInput): UseHorizontalCollapseReturnValue {\n const collapsedStyles = {\n width: 0,\n overflow: 'hidden',\n ...(keepMounted ? {} : { display: 'none' }),\n };\n\n const onTransitionStartEvent = useEffectEvent(() => onTransitionStart?.());\n\n const elementRef = useRef<HTMLElement>(null);\n const [styles, setStylesRaw] = useState<CSSProperties>(expanded ? {} : collapsedStyles);\n const [state, setState] = useState<UseHorizontalCollapseState>(expanded ? 'entered' : 'exited');\n const setStyles = (newStyles: React.SetStateAction<CSSProperties>) => {\n flushSync(() => setStylesRaw(newStyles));\n };\n\n const mergeStyles = (newStyles: CSSProperties) => {\n setStyles((oldStyles) => ({ ...oldStyles, ...newStyles }));\n };\n\n const getTransitionStyles = (width: number | string) => {\n const duration = transitionDuration ?? getAutoWidthDuration(width);\n return {\n transition: `width ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}`,\n };\n };\n\n useDidUpdate(() => {\n const shouldTransition = transitionDuration !== 0;\n\n if (shouldTransition) {\n onTransitionStartEvent();\n }\n\n if (expanded) {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('entering'));\n mergeStyles({ willChange: 'width', display: 'block', overflow: 'hidden' });\n window.requestAnimationFrame(() => {\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), width });\n });\n });\n } else {\n window.requestAnimationFrame(() => {\n flushSync(() => setState('exiting'));\n const width = getElementWidth(elementRef);\n mergeStyles({ ...getTransitionStyles(width), willChange: 'width', width });\n window.requestAnimationFrame(() => mergeStyles({ width: 0, overflow: 'hidden' }));\n });\n }\n }, [expanded]);\n\n const handleTransitionEnd = (event: React.TransitionEvent): void => {\n if (event.target !== elementRef.current || event.propertyName !== 'width') {\n return;\n }\n\n if (expanded) {\n const width = getElementWidth(elementRef);\n\n if (width === styles.width) {\n setStyles({});\n } else {\n mergeStyles({ width });\n }\n\n setState('entered');\n onTransitionEnd?.();\n } else if (styles.width === 0) {\n setStyles(collapsedStyles);\n setState('exited');\n onTransitionEnd?.();\n }\n };\n\n return {\n state,\n getCollapseProps: (input) => ({\n 'aria-hidden': !expanded,\n inert: !expanded,\n ref: mergeRefs(elementRef, input?.ref),\n onTransitionEnd: handleTransitionEnd,\n style: { boxSizing: 'border-box', ...input?.style, ...styles },\n }),\n };\n}\n\nexport namespace useHorizontalCollapse {\n export type Input = UseHorizontalCollapseInput;\n export type ReturnValue = UseHorizontalCollapseReturnValue;\n export type State = UseHorizontalCollapseState;\n}\n"],"mappings":";;;;;;AAKA,SAAS,qBAAqB,OAAwB;AACpD,KAAI,CAAC,SAAS,OAAO,UAAU,SAC7B,QAAO;CAET,MAAM,WAAW,QAAQ;AACzB,QAAO,KAAK,OAAO,IAAI,KAAK,YAAY,MAAO,WAAW,KAAK,GAAG;;AAGpE,SAAgB,gBAAgB,YAAiD;AAC/E,QAAO,WAAW,UAAU,WAAW,QAAQ,cAAc;;AAgD/D,SAAgB,sBAAsB,EACpC,oBACA,2BAA2B,QAC3B,iBACA,mBACA,UACA,eAC+D;CAC/D,MAAM,kBAAkB;EACtB,OAAO;EACP,UAAU;EACV,GAAI,cAAc,EAAE,GAAG,EAAE,SAAS,QAAQ;EAC3C;CAED,MAAM,0BAAA,GAAA,MAAA,sBAA8C,qBAAqB,CAAC;CAE1E,MAAM,cAAA,GAAA,MAAA,QAAiC,KAAK;CAC5C,MAAM,CAAC,QAAQ,iBAAA,GAAA,MAAA,UAAwC,WAAW,EAAE,GAAG,gBAAgB;CACvF,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAiD,WAAW,YAAY,SAAS;CAC/F,MAAM,aAAa,cAAmD;AACpE,GAAA,GAAA,UAAA,iBAAgB,aAAa,UAAU,CAAC;;CAG1C,MAAM,eAAe,cAA6B;AAChD,aAAW,eAAe;GAAE,GAAG;GAAW,GAAG;GAAW,EAAE;;CAG5D,MAAM,uBAAuB,UAA2B;EACtD,MAAM,WAAW,sBAAsB,qBAAqB,MAAM;AAClE,SAAO,EACL,YAAY,SAAS,SAAS,KAAK,yBAAyB,YAAY,SAAS,KAAK,4BACvF;;AAGH,wBAAA,mBAAmB;AAGjB,MAFyB,uBAAuB,EAG9C,yBAAwB;AAG1B,MAAI,SACF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,WAAW,CAAC;AACrC,eAAY;IAAE,YAAY;IAAS,SAAS;IAAS,UAAU;IAAU,CAAC;AAC1E,UAAO,4BAA4B;IACjC,MAAM,QAAQ,gBAAgB,WAAW;AACzC,gBAAY;KAAE,GAAG,oBAAoB,MAAM;KAAE;KAAO,CAAC;KACrD;IACF;MAEF,QAAO,4BAA4B;AACjC,IAAA,GAAA,UAAA,iBAAgB,SAAS,UAAU,CAAC;GACpC,MAAM,QAAQ,gBAAgB,WAAW;AACzC,eAAY;IAAE,GAAG,oBAAoB,MAAM;IAAE,YAAY;IAAS;IAAO,CAAC;AAC1E,UAAO,4BAA4B,YAAY;IAAE,OAAO;IAAG,UAAU;IAAU,CAAC,CAAC;IACjF;IAEH,CAAC,SAAS,CAAC;CAEd,MAAM,uBAAuB,UAAuC;AAClE,MAAI,MAAM,WAAW,WAAW,WAAW,MAAM,iBAAiB,QAChE;AAGF,MAAI,UAAU;GACZ,MAAM,QAAQ,gBAAgB,WAAW;AAEzC,OAAI,UAAU,OAAO,MACnB,WAAU,EAAE,CAAC;OAEb,aAAY,EAAE,OAAO,CAAC;AAGxB,YAAS,UAAU;AACnB,sBAAmB;aACV,OAAO,UAAU,GAAG;AAC7B,aAAU,gBAAgB;AAC1B,YAAS,SAAS;AAClB,sBAAmB;;;AAIvB,QAAO;EACL;EACA,mBAAmB,WAAW;GAC5B,eAAe,CAAC;GAChB,OAAO,CAAC;GACR,KAAKA,uBAAAA,UAAU,YAAY,OAAO,IAAI;GACtC,iBAAiB;GACjB,OAAO;IAAE,WAAW;IAAc,GAAG,OAAO;IAAO,GAAG;IAAQ;GAC/D;EACF"}
@@ -7,14 +7,23 @@ const DEFAULT_OPTIONS = {
7
7
  max: Infinity
8
8
  };
9
9
  function useCounter(initialValue = 0, options) {
10
- const { min, max } = {
10
+ const { min, max, step: _step = 1 } = {
11
11
  ...DEFAULT_OPTIONS,
12
12
  ...options
13
13
  };
14
+ const step = Math.abs(_step);
14
15
  const [count, setCount] = (0, react.useState)(require_clamp.clamp(initialValue, min, max));
15
16
  return [count, {
16
- increment: (0, react.useCallback)(() => setCount((current) => require_clamp.clamp(current + 1, min, max)), [min, max]),
17
- decrement: (0, react.useCallback)(() => setCount((current) => require_clamp.clamp(current - 1, min, max)), [min, max]),
17
+ increment: (0, react.useCallback)(() => setCount((current) => require_clamp.clamp(current + step, min, max)), [
18
+ min,
19
+ max,
20
+ step
21
+ ]),
22
+ decrement: (0, react.useCallback)(() => setCount((current) => require_clamp.clamp(current - step, min, max)), [
23
+ min,
24
+ max,
25
+ step
26
+ ]),
18
27
  set: (0, react.useCallback)((value) => setCount(require_clamp.clamp(value, min, max)), [min, max]),
19
28
  reset: (0, react.useCallback)(() => setCount(require_clamp.clamp(initialValue, min, max)), [
20
29
  initialValue,
@@ -1 +1 @@
1
- {"version":3,"file":"use-counter.cjs","names":["clamp"],"sources":["../../src/use-counter/use-counter.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { clamp } from '../utils';\n\nconst DEFAULT_OPTIONS = {\n min: -Infinity,\n max: Infinity,\n};\n\nexport interface UseCounterOptions {\n min?: number;\n max?: number;\n}\n\nexport interface UseCounterHandlers {\n increment: () => void;\n decrement: () => void;\n set: (value: number) => void;\n reset: () => void;\n}\n\nexport type UseCounterReturnValue = [number, UseCounterHandlers];\n\nexport function useCounter(initialValue = 0, options?: UseCounterOptions): UseCounterReturnValue {\n const { min, max } = { ...DEFAULT_OPTIONS, ...options };\n const [count, setCount] = useState<number>(clamp(initialValue, min, max));\n\n const increment = useCallback(\n () => setCount((current) => clamp(current + 1, min, max)),\n [min, max]\n );\n\n const decrement = useCallback(\n () => setCount((current) => clamp(current - 1, min, max)),\n [min, max]\n );\n\n const set = useCallback((value: number) => setCount(clamp(value, min, max)), [min, max]);\n\n const reset = useCallback(\n () => setCount(clamp(initialValue, min, max)),\n [initialValue, min, max]\n );\n\n return [count, { increment, decrement, set, reset }];\n}\n\nexport namespace useCounter {\n export type Options = UseCounterOptions;\n export type Handlers = UseCounterHandlers;\n export type ReturnValue = UseCounterReturnValue;\n}\n"],"mappings":";;;;AAGA,MAAM,kBAAkB;CACtB,KAAK;CACL,KAAK;CACN;AAgBD,SAAgB,WAAW,eAAe,GAAG,SAAoD;CAC/F,MAAM,EAAE,KAAK,QAAQ;EAAE,GAAG;EAAiB,GAAG;EAAS;CACvD,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAA6BA,cAAAA,MAAM,cAAc,KAAK,IAAI,CAAC;AAmBzE,QAAO,CAAC,OAAO;EAAE,YAAA,GAAA,MAAA,mBAhBT,UAAU,YAAYA,cAAAA,MAAM,UAAU,GAAG,KAAK,IAAI,CAAC,EACzD,CAAC,KAAK,IAAI,CACX;EAc2B,YAAA,GAAA,MAAA,mBAXpB,UAAU,YAAYA,cAAAA,MAAM,UAAU,GAAG,KAAK,IAAI,CAAC,EACzD,CAAC,KAAK,IAAI,CACX;EASsC,MAAA,GAAA,MAAA,cAPd,UAAkB,SAASA,cAAAA,MAAM,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;EAO5C,QAAA,GAAA,MAAA,mBAJpC,SAASA,cAAAA,MAAM,cAAc,KAAK,IAAI,CAAC,EAC7C;GAAC;GAAc;GAAK;GAAI,CACzB;EAEkD,CAAC"}
1
+ {"version":3,"file":"use-counter.cjs","names":["clamp"],"sources":["../../src/use-counter/use-counter.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { clamp } from '../utils';\n\nconst DEFAULT_OPTIONS = {\n min: -Infinity,\n max: Infinity,\n};\n\nexport interface UseCounterOptions {\n min?: number;\n max?: number;\n step?: number;\n}\n\nexport interface UseCounterHandlers {\n increment: () => void;\n decrement: () => void;\n set: (value: number) => void;\n reset: () => void;\n}\n\nexport type UseCounterReturnValue = [number, UseCounterHandlers];\n\nexport function useCounter(initialValue = 0, options?: UseCounterOptions): UseCounterReturnValue {\n const { min, max, step: _step = 1 } = { ...DEFAULT_OPTIONS, ...options };\n const step = Math.abs(_step);\n const [count, setCount] = useState<number>(clamp(initialValue, min, max));\n\n const increment = useCallback(\n () => setCount((current) => clamp(current + step, min, max)),\n [min, max, step]\n );\n\n const decrement = useCallback(\n () => setCount((current) => clamp(current - step, min, max)),\n [min, max, step]\n );\n\n const set = useCallback((value: number) => setCount(clamp(value, min, max)), [min, max]);\n\n const reset = useCallback(\n () => setCount(clamp(initialValue, min, max)),\n [initialValue, min, max]\n );\n\n return [count, { increment, decrement, set, reset }];\n}\n\nexport namespace useCounter {\n export type Options = UseCounterOptions;\n export type Handlers = UseCounterHandlers;\n export type ReturnValue = UseCounterReturnValue;\n}\n"],"mappings":";;;;AAGA,MAAM,kBAAkB;CACtB,KAAK;CACL,KAAK;CACN;AAiBD,SAAgB,WAAW,eAAe,GAAG,SAAoD;CAC/F,MAAM,EAAE,KAAK,KAAK,MAAM,QAAQ,MAAM;EAAE,GAAG;EAAiB,GAAG;EAAS;CACxE,MAAM,OAAO,KAAK,IAAI,MAAM;CAC5B,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAA6BA,cAAAA,MAAM,cAAc,KAAK,IAAI,CAAC;AAmBzE,QAAO,CAAC,OAAO;EAAE,YAAA,GAAA,MAAA,mBAhBT,UAAU,YAAYA,cAAAA,MAAM,UAAU,MAAM,KAAK,IAAI,CAAC,EAC5D;GAAC;GAAK;GAAK;GAAK,CACjB;EAc2B,YAAA,GAAA,MAAA,mBAXpB,UAAU,YAAYA,cAAAA,MAAM,UAAU,MAAM,KAAK,IAAI,CAAC,EAC5D;GAAC;GAAK;GAAK;GAAK,CACjB;EASsC,MAAA,GAAA,MAAA,cAPd,UAAkB,SAASA,cAAAA,MAAM,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;EAO5C,QAAA,GAAA,MAAA,mBAJpC,SAASA,cAAAA,MAAM,cAAc,KAAK,IAAI,CAAC,EAC7C;GAAC;GAAc;GAAK;GAAI,CACzB;EAEkD,CAAC"}
@@ -3,22 +3,38 @@ const require_use_callback_ref = require("../utils/use-callback-ref/use-callback
3
3
  let react = require("react");
4
4
  //#region packages/@mantine/hooks/src/use-debounced-callback/use-debounced-callback.ts
5
5
  function useDebouncedCallback(callback, options) {
6
- const { delay, flushOnUnmount, leading } = typeof options === "number" ? {
6
+ const { delay, flushOnUnmount, leading, maxWait } = typeof options === "number" ? {
7
7
  delay: options,
8
8
  flushOnUnmount: false,
9
- leading: false
9
+ leading: false,
10
+ maxWait: void 0
10
11
  } : options;
11
12
  const handleCallback = require_use_callback_ref.useCallbackRef(callback);
12
13
  const debounceTimerRef = (0, react.useRef)(0);
14
+ const maxWaitTimerRef = (0, react.useRef)(0);
15
+ const latestArgsRef = (0, react.useRef)(null);
13
16
  const lastCallback = (0, react.useMemo)(() => {
14
17
  const currentCallback = Object.assign((...args) => {
15
18
  window.clearTimeout(debounceTimerRef.current);
19
+ latestArgsRef.current = args;
16
20
  const isFirstCall = currentCallback._isFirstCall;
17
21
  currentCallback._isFirstCall = false;
18
22
  function clearTimeoutAndLeadingRef() {
19
23
  window.clearTimeout(debounceTimerRef.current);
24
+ window.clearTimeout(maxWaitTimerRef.current);
20
25
  debounceTimerRef.current = 0;
26
+ maxWaitTimerRef.current = 0;
21
27
  currentCallback._isFirstCall = true;
28
+ currentCallback._hasPendingCallback = false;
29
+ }
30
+ function startMaxWaitTimer() {
31
+ if (maxWait !== void 0 && maxWaitTimerRef.current === 0) maxWaitTimerRef.current = window.setTimeout(() => {
32
+ if (debounceTimerRef.current !== 0) {
33
+ const latestArgs = latestArgsRef.current;
34
+ clearTimeoutAndLeadingRef();
35
+ handleCallback(...latestArgs);
36
+ }
37
+ }, maxWait);
22
38
  }
23
39
  if (leading && isFirstCall) {
24
40
  handleCallback(...args);
@@ -37,9 +53,11 @@ function useDebouncedCallback(callback, options) {
37
53
  currentCallback.flush = flush;
38
54
  currentCallback.cancel = cancel;
39
55
  debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);
56
+ startMaxWaitTimer();
40
57
  return;
41
58
  }
42
59
  if (leading && !isFirstCall) {
60
+ currentCallback._hasPendingCallback = true;
43
61
  const flush = () => {
44
62
  if (debounceTimerRef.current !== 0) {
45
63
  clearTimeoutAndLeadingRef();
@@ -55,8 +73,10 @@ function useDebouncedCallback(callback, options) {
55
73
  clearTimeoutAndLeadingRef();
56
74
  };
57
75
  debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);
76
+ startMaxWaitTimer();
58
77
  return;
59
78
  }
79
+ currentCallback._hasPendingCallback = true;
60
80
  const flush = () => {
61
81
  if (debounceTimerRef.current !== 0) {
62
82
  clearTimeoutAndLeadingRef();
@@ -69,16 +89,20 @@ function useDebouncedCallback(callback, options) {
69
89
  currentCallback.flush = flush;
70
90
  currentCallback.cancel = cancel;
71
91
  debounceTimerRef.current = window.setTimeout(flush, delay);
92
+ startMaxWaitTimer();
72
93
  }, {
73
94
  flush: () => {},
74
95
  cancel: () => {},
75
- _isFirstCall: true
96
+ isPending: () => currentCallback._hasPendingCallback,
97
+ _isFirstCall: true,
98
+ _hasPendingCallback: false
76
99
  });
77
100
  return currentCallback;
78
101
  }, [
79
102
  handleCallback,
80
103
  delay,
81
- leading
104
+ leading,
105
+ maxWait
82
106
  ]);
83
107
  (0, react.useEffect)(() => () => {
84
108
  if (flushOnUnmount) lastCallback.flush();
@@ -1 +1 @@
1
- {"version":3,"file":"use-debounced-callback.cjs","names":["useCallbackRef"],"sources":["../../src/use-debounced-callback/use-debounced-callback.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport interface UseDebouncedCallbackOptions {\n delay: number;\n flushOnUnmount?: boolean;\n leading?: boolean;\n}\n\nexport type UseDebouncedCallbackReturnValue<T extends (...args: any[]) => any> = ((\n ...args: Parameters<T>\n) => void) & { flush: () => void; cancel: () => void };\n\nexport function useDebouncedCallback<T extends (...args: any[]) => any>(\n callback: T,\n options: number | UseDebouncedCallbackOptions\n) {\n const { delay, flushOnUnmount, leading } =\n typeof options === 'number'\n ? { delay: options, flushOnUnmount: false, leading: false }\n : options;\n\n const handleCallback = useCallbackRef(callback);\n const debounceTimerRef = useRef(0);\n\n const lastCallback = useMemo(() => {\n const currentCallback = Object.assign(\n (...args: Parameters<T>) => {\n window.clearTimeout(debounceTimerRef.current);\n\n const isFirstCall = currentCallback._isFirstCall;\n currentCallback._isFirstCall = false;\n\n function clearTimeoutAndLeadingRef() {\n window.clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = 0;\n currentCallback._isFirstCall = true;\n }\n\n if (leading && isFirstCall) {\n handleCallback(...args);\n\n const resetLeadingState = () => {\n clearTimeoutAndLeadingRef();\n };\n\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);\n return;\n }\n\n if (leading && !isFirstCall) {\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n\n const resetLeadingState = () => {\n clearTimeoutAndLeadingRef();\n };\n debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);\n return;\n }\n\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n debounceTimerRef.current = window.setTimeout(flush, delay);\n },\n {\n flush: () => {},\n cancel: () => {},\n _isFirstCall: true,\n }\n );\n return currentCallback;\n }, [handleCallback, delay, leading]);\n\n useEffect(\n () => () => {\n if (flushOnUnmount) {\n lastCallback.flush();\n } else {\n lastCallback.cancel();\n }\n },\n [lastCallback, flushOnUnmount]\n );\n\n return lastCallback;\n}\n\nexport namespace useDebouncedCallback {\n export type Options = UseDebouncedCallbackOptions;\n export type ReturnValue<T extends (...args: any[]) => any> = UseDebouncedCallbackReturnValue<T>;\n}\n"],"mappings":";;;;AAaA,SAAgB,qBACd,UACA,SACA;CACA,MAAM,EAAE,OAAO,gBAAgB,YAC7B,OAAO,YAAY,WACf;EAAE,OAAO;EAAS,gBAAgB;EAAO,SAAS;EAAO,GACzD;CAEN,MAAM,iBAAiBA,yBAAAA,eAAe,SAAS;CAC/C,MAAM,oBAAA,GAAA,MAAA,QAA0B,EAAE;CAElC,MAAM,gBAAA,GAAA,MAAA,eAA6B;EACjC,MAAM,kBAAkB,OAAO,QAC5B,GAAG,SAAwB;AAC1B,UAAO,aAAa,iBAAiB,QAAQ;GAE7C,MAAM,cAAc,gBAAgB;AACpC,mBAAgB,eAAe;GAE/B,SAAS,4BAA4B;AACnC,WAAO,aAAa,iBAAiB,QAAQ;AAC7C,qBAAiB,UAAU;AAC3B,oBAAgB,eAAe;;AAGjC,OAAI,WAAW,aAAa;AAC1B,mBAAe,GAAG,KAAK;IAEvB,MAAM,0BAA0B;AAC9B,gCAA2B;;IAG7B,MAAM,cAAc;AAClB,SAAI,iBAAiB,YAAY,GAAG;AAClC,iCAA2B;AAC3B,qBAAe,GAAG,KAAK;;;IAI3B,MAAM,eAAe;AACnB,gCAA2B;;AAG7B,oBAAgB,QAAQ;AACxB,oBAAgB,SAAS;AACzB,qBAAiB,UAAU,OAAO,WAAW,mBAAmB,MAAM;AACtE;;AAGF,OAAI,WAAW,CAAC,aAAa;IAC3B,MAAM,cAAc;AAClB,SAAI,iBAAiB,YAAY,GAAG;AAClC,iCAA2B;AAC3B,qBAAe,GAAG,KAAK;;;IAI3B,MAAM,eAAe;AACnB,gCAA2B;;AAG7B,oBAAgB,QAAQ;AACxB,oBAAgB,SAAS;IAEzB,MAAM,0BAA0B;AAC9B,gCAA2B;;AAE7B,qBAAiB,UAAU,OAAO,WAAW,mBAAmB,MAAM;AACtE;;GAGF,MAAM,cAAc;AAClB,QAAI,iBAAiB,YAAY,GAAG;AAClC,gCAA2B;AAC3B,oBAAe,GAAG,KAAK;;;GAI3B,MAAM,eAAe;AACnB,+BAA2B;;AAG7B,mBAAgB,QAAQ;AACxB,mBAAgB,SAAS;AACzB,oBAAiB,UAAU,OAAO,WAAW,OAAO,MAAM;KAE5D;GACE,aAAa;GACb,cAAc;GACd,cAAc;GACf,CACF;AACD,SAAO;IACN;EAAC;EAAgB;EAAO;EAAQ,CAAC;AAEpC,EAAA,GAAA,MAAA,uBACc;AACV,MAAI,eACF,cAAa,OAAO;MAEpB,cAAa,QAAQ;IAGzB,CAAC,cAAc,eAAe,CAC/B;AAED,QAAO"}
1
+ {"version":3,"file":"use-debounced-callback.cjs","names":["useCallbackRef"],"sources":["../../src/use-debounced-callback/use-debounced-callback.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport interface UseDebouncedCallbackOptions {\n delay: number;\n flushOnUnmount?: boolean;\n leading?: boolean;\n maxWait?: number;\n}\n\nexport type UseDebouncedCallbackReturnValue<T extends (...args: any[]) => any> = ((\n ...args: Parameters<T>\n) => void) & { flush: () => void; cancel: () => void; isPending: () => boolean };\n\nexport function useDebouncedCallback<T extends (...args: any[]) => any>(\n callback: T,\n options: number | UseDebouncedCallbackOptions\n) {\n const { delay, flushOnUnmount, leading, maxWait } =\n typeof options === 'number'\n ? {\n delay: options,\n flushOnUnmount: false,\n leading: false,\n maxWait: undefined as number | undefined,\n }\n : options;\n\n const handleCallback = useCallbackRef(callback);\n const debounceTimerRef = useRef(0);\n const maxWaitTimerRef = useRef(0);\n const latestArgsRef = useRef<Parameters<T> | null>(null);\n\n const lastCallback = useMemo(() => {\n const currentCallback = Object.assign(\n (...args: Parameters<T>) => {\n window.clearTimeout(debounceTimerRef.current);\n latestArgsRef.current = args;\n\n const isFirstCall = currentCallback._isFirstCall;\n currentCallback._isFirstCall = false;\n\n function clearTimeoutAndLeadingRef() {\n window.clearTimeout(debounceTimerRef.current);\n window.clearTimeout(maxWaitTimerRef.current);\n debounceTimerRef.current = 0;\n maxWaitTimerRef.current = 0;\n currentCallback._isFirstCall = true;\n currentCallback._hasPendingCallback = false;\n }\n\n function startMaxWaitTimer() {\n if (maxWait !== undefined && maxWaitTimerRef.current === 0) {\n maxWaitTimerRef.current = window.setTimeout(() => {\n if (debounceTimerRef.current !== 0) {\n const latestArgs = latestArgsRef.current!;\n clearTimeoutAndLeadingRef();\n handleCallback(...latestArgs);\n }\n }, maxWait);\n }\n }\n\n if (leading && isFirstCall) {\n handleCallback(...args);\n\n const resetLeadingState = () => {\n clearTimeoutAndLeadingRef();\n };\n\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);\n startMaxWaitTimer();\n return;\n }\n\n if (leading && !isFirstCall) {\n currentCallback._hasPendingCallback = true;\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n\n const resetLeadingState = () => {\n clearTimeoutAndLeadingRef();\n };\n debounceTimerRef.current = window.setTimeout(resetLeadingState, delay);\n startMaxWaitTimer();\n return;\n }\n\n currentCallback._hasPendingCallback = true;\n\n const flush = () => {\n if (debounceTimerRef.current !== 0) {\n clearTimeoutAndLeadingRef();\n handleCallback(...args);\n }\n };\n\n const cancel = () => {\n clearTimeoutAndLeadingRef();\n };\n\n currentCallback.flush = flush;\n currentCallback.cancel = cancel;\n debounceTimerRef.current = window.setTimeout(flush, delay);\n startMaxWaitTimer();\n },\n {\n flush: () => {},\n cancel: () => {},\n isPending: () => currentCallback._hasPendingCallback,\n _isFirstCall: true,\n _hasPendingCallback: false,\n }\n );\n return currentCallback;\n }, [handleCallback, delay, leading, maxWait]);\n\n useEffect(\n () => () => {\n if (flushOnUnmount) {\n lastCallback.flush();\n } else {\n lastCallback.cancel();\n }\n },\n [lastCallback, flushOnUnmount]\n );\n\n return lastCallback;\n}\n\nexport namespace useDebouncedCallback {\n export type Options = UseDebouncedCallbackOptions;\n export type ReturnValue<T extends (...args: any[]) => any> = UseDebouncedCallbackReturnValue<T>;\n}\n"],"mappings":";;;;AAcA,SAAgB,qBACd,UACA,SACA;CACA,MAAM,EAAE,OAAO,gBAAgB,SAAS,YACtC,OAAO,YAAY,WACf;EACE,OAAO;EACP,gBAAgB;EAChB,SAAS;EACT,SAAS,KAAA;EACV,GACD;CAEN,MAAM,iBAAiBA,yBAAAA,eAAe,SAAS;CAC/C,MAAM,oBAAA,GAAA,MAAA,QAA0B,EAAE;CAClC,MAAM,mBAAA,GAAA,MAAA,QAAyB,EAAE;CACjC,MAAM,iBAAA,GAAA,MAAA,QAA6C,KAAK;CAExD,MAAM,gBAAA,GAAA,MAAA,eAA6B;EACjC,MAAM,kBAAkB,OAAO,QAC5B,GAAG,SAAwB;AAC1B,UAAO,aAAa,iBAAiB,QAAQ;AAC7C,iBAAc,UAAU;GAExB,MAAM,cAAc,gBAAgB;AACpC,mBAAgB,eAAe;GAE/B,SAAS,4BAA4B;AACnC,WAAO,aAAa,iBAAiB,QAAQ;AAC7C,WAAO,aAAa,gBAAgB,QAAQ;AAC5C,qBAAiB,UAAU;AAC3B,oBAAgB,UAAU;AAC1B,oBAAgB,eAAe;AAC/B,oBAAgB,sBAAsB;;GAGxC,SAAS,oBAAoB;AAC3B,QAAI,YAAY,KAAA,KAAa,gBAAgB,YAAY,EACvD,iBAAgB,UAAU,OAAO,iBAAiB;AAChD,SAAI,iBAAiB,YAAY,GAAG;MAClC,MAAM,aAAa,cAAc;AACjC,iCAA2B;AAC3B,qBAAe,GAAG,WAAW;;OAE9B,QAAQ;;AAIf,OAAI,WAAW,aAAa;AAC1B,mBAAe,GAAG,KAAK;IAEvB,MAAM,0BAA0B;AAC9B,gCAA2B;;IAG7B,MAAM,cAAc;AAClB,SAAI,iBAAiB,YAAY,GAAG;AAClC,iCAA2B;AAC3B,qBAAe,GAAG,KAAK;;;IAI3B,MAAM,eAAe;AACnB,gCAA2B;;AAG7B,oBAAgB,QAAQ;AACxB,oBAAgB,SAAS;AACzB,qBAAiB,UAAU,OAAO,WAAW,mBAAmB,MAAM;AACtE,uBAAmB;AACnB;;AAGF,OAAI,WAAW,CAAC,aAAa;AAC3B,oBAAgB,sBAAsB;IACtC,MAAM,cAAc;AAClB,SAAI,iBAAiB,YAAY,GAAG;AAClC,iCAA2B;AAC3B,qBAAe,GAAG,KAAK;;;IAI3B,MAAM,eAAe;AACnB,gCAA2B;;AAG7B,oBAAgB,QAAQ;AACxB,oBAAgB,SAAS;IAEzB,MAAM,0BAA0B;AAC9B,gCAA2B;;AAE7B,qBAAiB,UAAU,OAAO,WAAW,mBAAmB,MAAM;AACtE,uBAAmB;AACnB;;AAGF,mBAAgB,sBAAsB;GAEtC,MAAM,cAAc;AAClB,QAAI,iBAAiB,YAAY,GAAG;AAClC,gCAA2B;AAC3B,oBAAe,GAAG,KAAK;;;GAI3B,MAAM,eAAe;AACnB,+BAA2B;;AAG7B,mBAAgB,QAAQ;AACxB,mBAAgB,SAAS;AACzB,oBAAiB,UAAU,OAAO,WAAW,OAAO,MAAM;AAC1D,sBAAmB;KAErB;GACE,aAAa;GACb,cAAc;GACd,iBAAiB,gBAAgB;GACjC,cAAc;GACd,qBAAqB;GACtB,CACF;AACD,SAAO;IACN;EAAC;EAAgB;EAAO;EAAS;EAAQ,CAAC;AAE7C,EAAA,GAAA,MAAA,uBACc;AACV,MAAI,eACF,cAAa,OAAO;MAEpB,cAAa,QAAQ;IAGzB,CAAC,cAAc,eAAe,CAC/B;AAED,QAAO"}
@@ -15,7 +15,7 @@ function useDebouncedState(defaultValue, wait, options = { leading: false }) {
15
15
  setValue(newValue);
16
16
  }, wait);
17
17
  leadingRef.current = false;
18
- }, [options.leading])];
18
+ }, [options.leading, wait])];
19
19
  }
20
20
  //#endregion
21
21
  exports.useDebouncedState = useDebouncedState;
@@ -1 +1 @@
1
- {"version":3,"file":"use-debounced-state.cjs","names":[],"sources":["../../src/use-debounced-state/use-debounced-state.ts"],"sourcesContent":["import { SetStateAction, useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseDebouncedStateOptions {\n leading?: boolean;\n}\n\nexport type UseDebouncedStateReturnValue<T> = [T, (newValue: SetStateAction<T>) => void];\n\nexport function useDebouncedState<T = any>(\n defaultValue: T,\n wait: number,\n options: UseDebouncedStateOptions = { leading: false }\n): UseDebouncedStateReturnValue<T> {\n const [value, setValue] = useState(defaultValue);\n const timeoutRef = useRef<number | null>(null);\n const leadingRef = useRef(true);\n\n const clearTimeout = () => window.clearTimeout(timeoutRef.current!);\n useEffect(() => clearTimeout, []);\n\n const debouncedSetValue = useCallback(\n (newValue: SetStateAction<T>) => {\n clearTimeout();\n if (leadingRef.current && options.leading) {\n setValue(newValue);\n } else {\n timeoutRef.current = window.setTimeout(() => {\n leadingRef.current = true;\n setValue(newValue);\n }, wait);\n }\n leadingRef.current = false;\n },\n [options.leading]\n );\n\n return [value, debouncedSetValue] as const;\n}\n\nexport namespace useDebouncedState {\n export type Options = UseDebouncedStateOptions;\n export type ReturnValue<T> = UseDebouncedStateReturnValue<T>;\n}\n"],"mappings":";;;AAQA,SAAgB,kBACd,cACA,MACA,UAAoC,EAAE,SAAS,OAAO,EACrB;CACjC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAqB,aAAa;CAChD,MAAM,cAAA,GAAA,MAAA,QAAmC,KAAK;CAC9C,MAAM,cAAA,GAAA,MAAA,QAAoB,KAAK;CAE/B,MAAM,qBAAqB,OAAO,aAAa,WAAW,QAAS;AACnE,EAAA,GAAA,MAAA,iBAAgB,cAAc,EAAE,CAAC;AAkBjC,QAAO,CAAC,QAAA,GAAA,MAAA,cAfL,aAAgC;AAC/B,gBAAc;AACd,MAAI,WAAW,WAAW,QAAQ,QAChC,UAAS,SAAS;MAElB,YAAW,UAAU,OAAO,iBAAiB;AAC3C,cAAW,UAAU;AACrB,YAAS,SAAS;KACjB,KAAK;AAEV,aAAW,UAAU;IAEvB,CAAC,QAAQ,QAAQ,CAClB,CAEgC"}
1
+ {"version":3,"file":"use-debounced-state.cjs","names":[],"sources":["../../src/use-debounced-state/use-debounced-state.ts"],"sourcesContent":["import { SetStateAction, useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseDebouncedStateOptions {\n leading?: boolean;\n}\n\nexport type UseDebouncedStateReturnValue<T> = [T, (newValue: SetStateAction<T>) => void];\n\nexport function useDebouncedState<T = any>(\n defaultValue: T,\n wait: number,\n options: UseDebouncedStateOptions = { leading: false }\n): UseDebouncedStateReturnValue<T> {\n const [value, setValue] = useState(defaultValue);\n const timeoutRef = useRef<number | null>(null);\n const leadingRef = useRef(true);\n\n const clearTimeout = () => window.clearTimeout(timeoutRef.current!);\n useEffect(() => clearTimeout, []);\n\n const debouncedSetValue = useCallback(\n (newValue: SetStateAction<T>) => {\n clearTimeout();\n if (leadingRef.current && options.leading) {\n setValue(newValue);\n } else {\n timeoutRef.current = window.setTimeout(() => {\n leadingRef.current = true;\n setValue(newValue);\n }, wait);\n }\n leadingRef.current = false;\n },\n [options.leading, wait]\n );\n\n return [value, debouncedSetValue] as const;\n}\n\nexport namespace useDebouncedState {\n export type Options = UseDebouncedStateOptions;\n export type ReturnValue<T> = UseDebouncedStateReturnValue<T>;\n}\n"],"mappings":";;;AAQA,SAAgB,kBACd,cACA,MACA,UAAoC,EAAE,SAAS,OAAO,EACrB;CACjC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAqB,aAAa;CAChD,MAAM,cAAA,GAAA,MAAA,QAAmC,KAAK;CAC9C,MAAM,cAAA,GAAA,MAAA,QAAoB,KAAK;CAE/B,MAAM,qBAAqB,OAAO,aAAa,WAAW,QAAS;AACnE,EAAA,GAAA,MAAA,iBAAgB,cAAc,EAAE,CAAC;AAkBjC,QAAO,CAAC,QAAA,GAAA,MAAA,cAfL,aAAgC;AAC/B,gBAAc;AACd,MAAI,WAAW,WAAW,QAAQ,QAChC,UAAS,SAAS;MAElB,YAAW,UAAU,OAAO,iBAAiB;AAC3C,cAAW,UAAU;AACrB,YAAS,SAAS;KACjB,KAAK;AAEV,aAAW,UAAU;IAEvB,CAAC,QAAQ,SAAS,KAAK,CACxB,CAEgC"}
@@ -6,7 +6,20 @@ function useDebouncedValue(value, wait, options = { leading: false }) {
6
6
  const mountedRef = (0, react.useRef)(false);
7
7
  const timeoutRef = (0, react.useRef)(null);
8
8
  const cooldownRef = (0, react.useRef)(false);
9
- const cancel = (0, react.useCallback)(() => window.clearTimeout(timeoutRef.current), []);
9
+ const latestValueRef = (0, react.useRef)(value);
10
+ latestValueRef.current = value;
11
+ const cancel = (0, react.useCallback)(() => {
12
+ window.clearTimeout(timeoutRef.current);
13
+ timeoutRef.current = null;
14
+ cooldownRef.current = false;
15
+ }, []);
16
+ const flush = (0, react.useCallback)(() => {
17
+ if (timeoutRef.current) {
18
+ cancel();
19
+ cooldownRef.current = false;
20
+ setValue(latestValueRef.current);
21
+ }
22
+ }, []);
10
23
  (0, react.useEffect)(() => {
11
24
  if (mountedRef.current) if (!cooldownRef.current && options.leading) {
12
25
  cooldownRef.current = true;
@@ -27,7 +40,14 @@ function useDebouncedValue(value, wait, options = { leading: false }) {
27
40
  mountedRef.current = true;
28
41
  return cancel;
29
42
  }, []);
30
- return [_value, cancel];
43
+ return [
44
+ _value,
45
+ cancel,
46
+ {
47
+ cancel,
48
+ flush
49
+ }
50
+ ];
31
51
  }
32
52
  //#endregion
33
53
  exports.useDebouncedValue = useDebouncedValue;
@@ -1 +1 @@
1
- {"version":3,"file":"use-debounced-value.cjs","names":[],"sources":["../../src/use-debounced-value/use-debounced-value.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseDebouncedValueOptions {\n leading?: boolean;\n}\n\nexport type UseDebouncedValueReturnValue<T> = [T, () => void];\n\nexport function useDebouncedValue<T = any>(\n value: T,\n wait: number,\n options: UseDebouncedValueOptions = { leading: false }\n): UseDebouncedValueReturnValue<T> {\n const [_value, setValue] = useState(value);\n const mountedRef = useRef(false);\n const timeoutRef = useRef<number | null>(null);\n const cooldownRef = useRef(false);\n\n const cancel = useCallback(() => window.clearTimeout(timeoutRef.current!), []);\n\n useEffect(() => {\n if (mountedRef.current) {\n if (!cooldownRef.current && options.leading) {\n cooldownRef.current = true;\n setValue(value);\n } else {\n cancel();\n timeoutRef.current = window.setTimeout(() => {\n cooldownRef.current = false;\n setValue(value);\n }, wait);\n }\n }\n }, [value, options.leading, wait]);\n\n useEffect(() => {\n mountedRef.current = true;\n return cancel;\n }, []);\n\n return [_value, cancel];\n}\n\nexport namespace useDebouncedValue {\n export type Options = UseDebouncedValueOptions;\n export type ReturnValue<T> = UseDebouncedValueReturnValue<T>;\n}\n"],"mappings":";;;AAQA,SAAgB,kBACd,OACA,MACA,UAAoC,EAAE,SAAS,OAAO,EACrB;CACjC,MAAM,CAAC,QAAQ,aAAA,GAAA,MAAA,UAAqB,MAAM;CAC1C,MAAM,cAAA,GAAA,MAAA,QAAoB,MAAM;CAChC,MAAM,cAAA,GAAA,MAAA,QAAmC,KAAK;CAC9C,MAAM,eAAA,GAAA,MAAA,QAAqB,MAAM;CAEjC,MAAM,UAAA,GAAA,MAAA,mBAA2B,OAAO,aAAa,WAAW,QAAS,EAAE,EAAE,CAAC;AAE9E,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,WAAW,QACb,KAAI,CAAC,YAAY,WAAW,QAAQ,SAAS;AAC3C,eAAY,UAAU;AACtB,YAAS,MAAM;SACV;AACL,WAAQ;AACR,cAAW,UAAU,OAAO,iBAAiB;AAC3C,gBAAY,UAAU;AACtB,aAAS,MAAM;MACd,KAAK;;IAGX;EAAC;EAAO,QAAQ;EAAS;EAAK,CAAC;AAElC,EAAA,GAAA,MAAA,iBAAgB;AACd,aAAW,UAAU;AACrB,SAAO;IACN,EAAE,CAAC;AAEN,QAAO,CAAC,QAAQ,OAAO"}
1
+ {"version":3,"file":"use-debounced-value.cjs","names":[],"sources":["../../src/use-debounced-value/use-debounced-value.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseDebouncedValueOptions {\n leading?: boolean;\n}\n\nexport interface UseDebouncedValueHandlers {\n cancel: () => void;\n flush: () => void;\n}\n\nexport type UseDebouncedValueReturnValue<T> = [T, () => void, UseDebouncedValueHandlers];\n\nexport function useDebouncedValue<T = any>(\n value: T,\n wait: number,\n options: UseDebouncedValueOptions = { leading: false }\n): UseDebouncedValueReturnValue<T> {\n const [_value, setValue] = useState(value);\n const mountedRef = useRef(false);\n const timeoutRef = useRef<number | null>(null);\n const cooldownRef = useRef(false);\n\n const latestValueRef = useRef(value);\n latestValueRef.current = value;\n\n const cancel = useCallback(() => {\n window.clearTimeout(timeoutRef.current!);\n timeoutRef.current = null;\n cooldownRef.current = false;\n }, []);\n\n const flush = useCallback(() => {\n if (timeoutRef.current) {\n cancel();\n cooldownRef.current = false;\n setValue(latestValueRef.current);\n }\n }, []);\n\n useEffect(() => {\n if (mountedRef.current) {\n if (!cooldownRef.current && options.leading) {\n cooldownRef.current = true;\n setValue(value);\n } else {\n cancel();\n timeoutRef.current = window.setTimeout(() => {\n cooldownRef.current = false;\n setValue(value);\n }, wait);\n }\n }\n }, [value, options.leading, wait]);\n\n useEffect(() => {\n mountedRef.current = true;\n return cancel;\n }, []);\n\n return [_value, cancel, { cancel, flush }];\n}\n\nexport namespace useDebouncedValue {\n export type Handlers = UseDebouncedValueHandlers;\n export type Options = UseDebouncedValueOptions;\n export type ReturnValue<T> = UseDebouncedValueReturnValue<T>;\n}\n"],"mappings":";;;AAaA,SAAgB,kBACd,OACA,MACA,UAAoC,EAAE,SAAS,OAAO,EACrB;CACjC,MAAM,CAAC,QAAQ,aAAA,GAAA,MAAA,UAAqB,MAAM;CAC1C,MAAM,cAAA,GAAA,MAAA,QAAoB,MAAM;CAChC,MAAM,cAAA,GAAA,MAAA,QAAmC,KAAK;CAC9C,MAAM,eAAA,GAAA,MAAA,QAAqB,MAAM;CAEjC,MAAM,kBAAA,GAAA,MAAA,QAAwB,MAAM;AACpC,gBAAe,UAAU;CAEzB,MAAM,UAAA,GAAA,MAAA,mBAA2B;AAC/B,SAAO,aAAa,WAAW,QAAS;AACxC,aAAW,UAAU;AACrB,cAAY,UAAU;IACrB,EAAE,CAAC;CAEN,MAAM,SAAA,GAAA,MAAA,mBAA0B;AAC9B,MAAI,WAAW,SAAS;AACtB,WAAQ;AACR,eAAY,UAAU;AACtB,YAAS,eAAe,QAAQ;;IAEjC,EAAE,CAAC;AAEN,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,WAAW,QACb,KAAI,CAAC,YAAY,WAAW,QAAQ,SAAS;AAC3C,eAAY,UAAU;AACtB,YAAS,MAAM;SACV;AACL,WAAQ;AACR,cAAW,UAAU,OAAO,iBAAiB;AAC3C,gBAAY,UAAU;AACtB,aAAS,MAAM;MACd,KAAK;;IAGX;EAAC;EAAO,QAAQ;EAAS;EAAK,CAAC;AAElC,EAAA,GAAA,MAAA,iBAAgB;AACd,aAAW,UAAU;AACrB,SAAO;IACN,EAAE,CAAC;AAEN,QAAO;EAAC;EAAQ;EAAQ;GAAE;GAAQ;GAAO;EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-event-listener.cjs","names":[],"sources":["../../src/use-event-listener/use-event-listener.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\n\nexport function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = any>(\n type: K,\n listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions\n): React.RefCallback<T | null> {\n const previousListener = useRef<Function | null>(null);\n const previousNode = useRef<T | null>(null);\n\n const callbackRef: React.RefCallback<T | null> = useCallback(\n (node) => {\n if (!node) {\n return;\n }\n\n if (previousNode.current && previousListener.current) {\n previousNode.current.removeEventListener(type, previousListener.current as any, options);\n }\n\n node.addEventListener(type, listener as any, options);\n previousNode.current = node;\n previousListener.current = listener;\n },\n [type, listener, options]\n );\n\n useEffect(\n () => () => {\n if (previousNode.current && previousListener.current) {\n previousNode.current.removeEventListener(type, previousListener.current as any, options);\n }\n },\n [type, options]\n );\n\n return callbackRef;\n}\n"],"mappings":";;;AAEA,SAAgB,iBACd,MACA,UACA,SAC6B;CAC7B,MAAM,oBAAA,GAAA,MAAA,QAA2C,KAAK;CACtD,MAAM,gBAAA,GAAA,MAAA,QAAgC,KAAK;CAE3C,MAAM,eAAA,GAAA,MAAA,cACH,SAAS;AACR,MAAI,CAAC,KACH;AAGF,MAAI,aAAa,WAAW,iBAAiB,QAC3C,cAAa,QAAQ,oBAAoB,MAAM,iBAAiB,SAAgB,QAAQ;AAG1F,OAAK,iBAAiB,MAAM,UAAiB,QAAQ;AACrD,eAAa,UAAU;AACvB,mBAAiB,UAAU;IAE7B;EAAC;EAAM;EAAU;EAAQ,CAC1B;AAED,EAAA,GAAA,MAAA,uBACc;AACV,MAAI,aAAa,WAAW,iBAAiB,QAC3C,cAAa,QAAQ,oBAAoB,MAAM,iBAAiB,SAAgB,QAAQ;IAG5F,CAAC,MAAM,QAAQ,CAChB;AAED,QAAO"}
1
+ {"version":3,"file":"use-event-listener.cjs","names":[],"sources":["../../src/use-event-listener/use-event-listener.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\n\nexport function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = any>(\n type: K,\n listener: (this: T, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions\n): React.RefCallback<T | null> {\n const previousListener = useRef<Function | null>(null);\n const previousNode = useRef<T | null>(null);\n\n const callbackRef: React.RefCallback<T | null> = useCallback(\n (node) => {\n if (!node) {\n return;\n }\n\n if (previousNode.current && previousListener.current) {\n previousNode.current.removeEventListener(type, previousListener.current as any, options);\n }\n\n node.addEventListener(type, listener as any, options);\n previousNode.current = node;\n previousListener.current = listener;\n },\n [type, listener, options]\n );\n\n useEffect(\n () => () => {\n if (previousNode.current && previousListener.current) {\n previousNode.current.removeEventListener(type, previousListener.current as any, options);\n }\n },\n [type, options]\n );\n\n return callbackRef;\n}\n"],"mappings":";;;AAEA,SAAgB,iBACd,MACA,UACA,SAC6B;CAC7B,MAAM,oBAAA,GAAA,MAAA,QAA2C,KAAK;CACtD,MAAM,gBAAA,GAAA,MAAA,QAAgC,KAAK;CAE3C,MAAM,eAAA,GAAA,MAAA,cACH,SAAS;AACR,MAAI,CAAC,KACH;AAGF,MAAI,aAAa,WAAW,iBAAiB,QAC3C,cAAa,QAAQ,oBAAoB,MAAM,iBAAiB,SAAgB,QAAQ;AAG1F,OAAK,iBAAiB,MAAM,UAAiB,QAAQ;AACrD,eAAa,UAAU;AACvB,mBAAiB,UAAU;IAE7B;EAAC;EAAM;EAAU;EAAQ,CAC1B;AAED,EAAA,GAAA,MAAA,uBACc;AACV,MAAI,aAAa,WAAW,iBAAiB,QAC3C,cAAa,QAAQ,oBAAoB,MAAM,iBAAiB,SAAgB,QAAQ;IAG5F,CAAC,MAAM,QAAQ,CAChB;AAED,QAAO"}
@@ -20,7 +20,9 @@ function useFavicon(url) {
20
20
  document.querySelector("head").appendChild(element);
21
21
  }
22
22
  const splittedUrl = url.split(".");
23
- link.current.setAttribute("type", MIME_TYPES[splittedUrl[splittedUrl.length - 1].toLowerCase()]);
23
+ const mimeType = MIME_TYPES[splittedUrl[splittedUrl.length - 1].toLowerCase()];
24
+ if (mimeType) link.current.setAttribute("type", mimeType);
25
+ else link.current.removeAttribute("type");
24
26
  link.current.setAttribute("href", url);
25
27
  }, [url]);
26
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-favicon.cjs","names":[],"sources":["../../src/use-favicon/use-favicon.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useIsomorphicEffect } from '../use-isomorphic-effect/use-isomorphic-effect';\n\nconst MIME_TYPES: Record<string, string> = {\n ico: 'image/x-icon',\n png: 'image/png',\n svg: 'image/svg+xml',\n gif: 'image/gif',\n};\n\nexport function useFavicon(url: string) {\n const link = useRef<HTMLLinkElement>(null);\n\n useIsomorphicEffect(() => {\n if (!url) {\n return;\n }\n\n if (!link.current) {\n const existingElements = document.querySelectorAll<HTMLLinkElement>('link[rel*=\"icon\"]');\n existingElements.forEach((element) => document.head.removeChild(element));\n\n const element = document.createElement('link');\n element.rel = 'shortcut icon';\n link.current = element;\n document.querySelector('head')!.appendChild(element);\n }\n\n const splittedUrl = url.split('.');\n link.current.setAttribute(\n 'type',\n MIME_TYPES[splittedUrl[splittedUrl.length - 1].toLowerCase()]\n );\n link.current.setAttribute('href', url);\n }, [url]);\n}\n"],"mappings":";;;;AAGA,MAAM,aAAqC;CACzC,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACN;AAED,SAAgB,WAAW,KAAa;CACtC,MAAM,QAAA,GAAA,MAAA,QAA+B,KAAK;AAE1C,+BAAA,0BAA0B;AACxB,MAAI,CAAC,IACH;AAGF,MAAI,CAAC,KAAK,SAAS;AACQ,YAAS,iBAAkC,sBAAoB,CACvE,SAAS,YAAY,SAAS,KAAK,YAAY,QAAQ,CAAC;GAEzE,MAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,WAAQ,MAAM;AACd,QAAK,UAAU;AACf,YAAS,cAAc,OAAO,CAAE,YAAY,QAAQ;;EAGtD,MAAM,cAAc,IAAI,MAAM,IAAI;AAClC,OAAK,QAAQ,aACX,QACA,WAAW,YAAY,YAAY,SAAS,GAAG,aAAa,EAC7D;AACD,OAAK,QAAQ,aAAa,QAAQ,IAAI;IACrC,CAAC,IAAI,CAAC"}
1
+ {"version":3,"file":"use-favicon.cjs","names":[],"sources":["../../src/use-favicon/use-favicon.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useIsomorphicEffect } from '../use-isomorphic-effect/use-isomorphic-effect';\n\nconst MIME_TYPES: Record<string, string> = {\n ico: 'image/x-icon',\n png: 'image/png',\n svg: 'image/svg+xml',\n gif: 'image/gif',\n};\n\nexport function useFavicon(url: string) {\n const link = useRef<HTMLLinkElement>(null);\n\n useIsomorphicEffect(() => {\n if (!url) {\n return;\n }\n\n if (!link.current) {\n const existingElements = document.querySelectorAll<HTMLLinkElement>('link[rel*=\"icon\"]');\n existingElements.forEach((element) => document.head.removeChild(element));\n\n const element = document.createElement('link');\n element.rel = 'shortcut icon';\n link.current = element;\n document.querySelector('head')!.appendChild(element);\n }\n\n const splittedUrl = url.split('.');\n const extension = splittedUrl[splittedUrl.length - 1].toLowerCase();\n const mimeType = MIME_TYPES[extension];\n\n if (mimeType) {\n link.current.setAttribute('type', mimeType);\n } else {\n link.current.removeAttribute('type');\n }\n\n link.current.setAttribute('href', url);\n }, [url]);\n}\n"],"mappings":";;;;AAGA,MAAM,aAAqC;CACzC,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACN;AAED,SAAgB,WAAW,KAAa;CACtC,MAAM,QAAA,GAAA,MAAA,QAA+B,KAAK;AAE1C,+BAAA,0BAA0B;AACxB,MAAI,CAAC,IACH;AAGF,MAAI,CAAC,KAAK,SAAS;AACQ,YAAS,iBAAkC,sBAAoB,CACvE,SAAS,YAAY,SAAS,KAAK,YAAY,QAAQ,CAAC;GAEzE,MAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,WAAQ,MAAM;AACd,QAAK,UAAU;AACf,YAAS,cAAc,OAAO,CAAE,YAAY,QAAQ;;EAGtD,MAAM,cAAc,IAAI,MAAM,IAAI;EAElC,MAAM,WAAW,WADC,YAAY,YAAY,SAAS,GAAG,aAAa;AAGnE,MAAI,SACF,MAAK,QAAQ,aAAa,QAAQ,SAAS;MAE3C,MAAK,QAAQ,gBAAgB,OAAO;AAGtC,OAAK,QAAQ,aAAa,QAAQ,IAAI;IACrC,CAAC,IAAI,CAAC"}
@@ -11,9 +11,12 @@ function useFetch(url, { autoInvoke = true, ...options } = {}) {
11
11
  controller.current = new AbortController();
12
12
  setLoading(true);
13
13
  return fetch(url, {
14
- signal: controller.current.signal,
15
- ...options
16
- }).then((res) => res.json()).then((res) => {
14
+ ...options,
15
+ signal: controller.current.signal
16
+ }).then((res) => {
17
+ if (!res.ok) throw new Error(`Request failed with status ${res.status}`);
18
+ return res.json();
19
+ }).then((res) => {
17
20
  setData(res);
18
21
  setLoading(false);
19
22
  return res;
@@ -22,7 +25,7 @@ function useFetch(url, { autoInvoke = true, ...options } = {}) {
22
25
  if (err.name !== "AbortError") setError(err);
23
26
  return err;
24
27
  });
25
- }, [url]);
28
+ }, [url, JSON.stringify(options)]);
26
29
  const abort = (0, react.useCallback)(() => {
27
30
  if (controller.current) controller.current?.abort("");
28
31
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"use-fetch.cjs","names":[],"sources":["../../src/use-fetch/use-fetch.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseFetchOptions extends RequestInit {\n autoInvoke?: boolean;\n}\n\nexport interface UseFetchReturnValue<T> {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<any>;\n abort: () => void;\n}\n\nexport function useFetch<T>(\n url: string,\n { autoInvoke = true, ...options }: UseFetchOptions = {}\n): UseFetchReturnValue<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const controller = useRef<AbortController | null>(null);\n\n const refetch = useCallback(() => {\n if (controller.current) {\n controller.current.abort();\n }\n\n controller.current = new AbortController();\n\n setLoading(true);\n\n return fetch(url, { signal: controller.current.signal, ...options })\n .then((res) => res.json())\n .then((res) => {\n setData(res);\n setLoading(false);\n return res as T;\n })\n .catch((err) => {\n setLoading(false);\n\n if (err.name !== 'AbortError') {\n setError(err);\n }\n\n return err;\n });\n }, [url]);\n\n const abort = useCallback(() => {\n if (controller.current) {\n controller.current?.abort('');\n }\n }, []);\n\n useEffect(() => {\n if (autoInvoke) {\n refetch();\n }\n\n return () => {\n if (controller.current) {\n controller.current.abort('');\n }\n };\n }, [refetch, autoInvoke]);\n\n return { data, loading, error, refetch, abort };\n}\n\nexport namespace useFetch {\n export type Options = UseFetchOptions;\n export type ReturnValue<T> = UseFetchReturnValue<T>;\n}\n"],"mappings":";;;AAcA,SAAgB,SACd,KACA,EAAE,aAAa,MAAM,GAAG,YAA6B,EAAE,EAC/B;CACxB,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAA8B,KAAK;CAChD,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAAuB,MAAM;CAC7C,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAmC,KAAK;CACtD,MAAM,cAAA,GAAA,MAAA,QAA4C,KAAK;CAEvD,MAAM,WAAA,GAAA,MAAA,mBAA4B;AAChC,MAAI,WAAW,QACb,YAAW,QAAQ,OAAO;AAG5B,aAAW,UAAU,IAAI,iBAAiB;AAE1C,aAAW,KAAK;AAEhB,SAAO,MAAM,KAAK;GAAE,QAAQ,WAAW,QAAQ;GAAQ,GAAG;GAAS,CAAC,CACjE,MAAM,QAAQ,IAAI,MAAM,CAAC,CACzB,MAAM,QAAQ;AACb,WAAQ,IAAI;AACZ,cAAW,MAAM;AACjB,UAAO;IACP,CACD,OAAO,QAAQ;AACd,cAAW,MAAM;AAEjB,OAAI,IAAI,SAAS,aACf,UAAS,IAAI;AAGf,UAAO;IACP;IACH,CAAC,IAAI,CAAC;CAET,MAAM,SAAA,GAAA,MAAA,mBAA0B;AAC9B,MAAI,WAAW,QACb,YAAW,SAAS,MAAM,GAAG;IAE9B,EAAE,CAAC;AAEN,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,WACF,UAAS;AAGX,eAAa;AACX,OAAI,WAAW,QACb,YAAW,QAAQ,MAAM,GAAG;;IAG/B,CAAC,SAAS,WAAW,CAAC;AAEzB,QAAO;EAAE;EAAM;EAAS;EAAO;EAAS;EAAO"}
1
+ {"version":3,"file":"use-fetch.cjs","names":[],"sources":["../../src/use-fetch/use-fetch.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseFetchOptions extends RequestInit {\n autoInvoke?: boolean;\n}\n\nexport interface UseFetchReturnValue<T> {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<any>;\n abort: () => void;\n}\n\nexport function useFetch<T>(\n url: string,\n { autoInvoke = true, ...options }: UseFetchOptions = {}\n): UseFetchReturnValue<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const controller = useRef<AbortController | null>(null);\n\n const refetch = useCallback(() => {\n if (controller.current) {\n controller.current.abort();\n }\n\n controller.current = new AbortController();\n\n setLoading(true);\n\n return fetch(url, { ...options, signal: controller.current.signal })\n .then((res) => {\n if (!res.ok) {\n throw new Error(`Request failed with status ${res.status}`);\n }\n return res.json();\n })\n .then((res) => {\n setData(res);\n setLoading(false);\n return res as T;\n })\n .catch((err) => {\n setLoading(false);\n\n if (err.name !== 'AbortError') {\n setError(err);\n }\n\n return err;\n });\n }, [url, JSON.stringify(options)]);\n\n const abort = useCallback(() => {\n if (controller.current) {\n controller.current?.abort('');\n }\n }, []);\n\n useEffect(() => {\n if (autoInvoke) {\n refetch();\n }\n\n return () => {\n if (controller.current) {\n controller.current.abort('');\n }\n };\n }, [refetch, autoInvoke]);\n\n return { data, loading, error, refetch, abort };\n}\n\nexport namespace useFetch {\n export type Options = UseFetchOptions;\n export type ReturnValue<T> = UseFetchReturnValue<T>;\n}\n"],"mappings":";;;AAcA,SAAgB,SACd,KACA,EAAE,aAAa,MAAM,GAAG,YAA6B,EAAE,EAC/B;CACxB,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAA8B,KAAK;CAChD,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAAuB,MAAM;CAC7C,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAmC,KAAK;CACtD,MAAM,cAAA,GAAA,MAAA,QAA4C,KAAK;CAEvD,MAAM,WAAA,GAAA,MAAA,mBAA4B;AAChC,MAAI,WAAW,QACb,YAAW,QAAQ,OAAO;AAG5B,aAAW,UAAU,IAAI,iBAAiB;AAE1C,aAAW,KAAK;AAEhB,SAAO,MAAM,KAAK;GAAE,GAAG;GAAS,QAAQ,WAAW,QAAQ;GAAQ,CAAC,CACjE,MAAM,QAAQ;AACb,OAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,8BAA8B,IAAI,SAAS;AAE7D,UAAO,IAAI,MAAM;IACjB,CACD,MAAM,QAAQ;AACb,WAAQ,IAAI;AACZ,cAAW,MAAM;AACjB,UAAO;IACP,CACD,OAAO,QAAQ;AACd,cAAW,MAAM;AAEjB,OAAI,IAAI,SAAS,aACf,UAAS,IAAI;AAGf,UAAO;IACP;IACH,CAAC,KAAK,KAAK,UAAU,QAAQ,CAAC,CAAC;CAElC,MAAM,SAAA,GAAA,MAAA,mBAA0B;AAC9B,MAAI,WAAW,QACb,YAAW,SAAS,MAAM,GAAG;IAE9B,EAAE,CAAC;AAEN,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,WACF,UAAS;AAGX,eAAa;AACX,OAAI,WAAW,QACb,YAAW,QAAQ,MAAM,GAAG;;IAG/B,CAAC,SAAS,WAAW,CAAC;AAEzB,QAAO;EAAE;EAAM;EAAS;EAAO;EAAS;EAAO"}
@@ -43,6 +43,7 @@ function useFileDialog(input = {}) {
43
43
  inputRef.current = createInput(options);
44
44
  if (inputRef.current) {
45
45
  inputRef.current.addEventListener("change", handleChange, { once: true });
46
+ if (options.onCancel) inputRef.current.addEventListener("cancel", options.onCancel, { once: true });
46
47
  document.body.appendChild(inputRef.current);
47
48
  }
48
49
  }, [options, handleChange]);