@zentauri-ui/zentauri-components 1.9.2 → 2.0.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 (215) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +32 -5
  3. package/cli/registry.json +14 -0
  4. package/dist/{chunk-L4PDJ6IB.mjs → chunk-44NX3DAZ.mjs} +3 -3
  5. package/dist/{chunk-L4PDJ6IB.mjs.map → chunk-44NX3DAZ.mjs.map} +1 -1
  6. package/dist/chunk-FAMHSJTK.js +19 -0
  7. package/dist/{chunk-AQHY4S33.js.map → chunk-FAMHSJTK.js.map} +1 -1
  8. package/dist/chunk-I42UYWYA.mjs +128 -0
  9. package/dist/chunk-I42UYWYA.mjs.map +1 -0
  10. package/dist/{chunk-5J6QMTES.js → chunk-IKXO5SJ4.js} +21 -5
  11. package/dist/chunk-IKXO5SJ4.js.map +1 -0
  12. package/dist/{chunk-OPUO55TO.mjs → chunk-JXSM2EHC.mjs} +3 -3
  13. package/dist/{chunk-OPUO55TO.mjs.map → chunk-JXSM2EHC.mjs.map} +1 -1
  14. package/dist/{chunk-LQPKZ5ZD.js → chunk-LS4GY2ZQ.js} +6 -6
  15. package/dist/{chunk-LQPKZ5ZD.js.map → chunk-LS4GY2ZQ.js.map} +1 -1
  16. package/dist/{chunk-VIKQGO4W.mjs → chunk-VQQHVKEU.mjs} +21 -5
  17. package/dist/{chunk-VIKQGO4W.mjs.map → chunk-VQQHVKEU.mjs.map} +1 -1
  18. package/dist/chunk-ZVRGLG35.js +144 -0
  19. package/dist/chunk-ZVRGLG35.js.map +1 -0
  20. package/dist/design-system/combobox.d.ts +124 -0
  21. package/dist/design-system/combobox.d.ts.map +1 -0
  22. package/dist/design-system/facade.js +6 -5
  23. package/dist/design-system/facade.js.map +1 -1
  24. package/dist/design-system/facade.mjs +5 -4
  25. package/dist/design-system/facade.mjs.map +1 -1
  26. package/dist/design-system/index.d.ts +1 -0
  27. package/dist/design-system/index.d.ts.map +1 -1
  28. package/dist/hooks/index.d.ts +13 -0
  29. package/dist/hooks/index.d.ts.map +1 -1
  30. package/dist/hooks/useCookie/index.d.ts +2 -0
  31. package/dist/hooks/useCookie/index.d.ts.map +1 -0
  32. package/dist/hooks/useCookie/useCookie.d.ts +36 -0
  33. package/dist/hooks/useCookie/useCookie.d.ts.map +1 -0
  34. package/dist/hooks/useCookie.js +82 -0
  35. package/dist/hooks/useCookie.js.map +1 -0
  36. package/dist/hooks/useCookie.mjs +80 -0
  37. package/dist/hooks/useCookie.mjs.map +1 -0
  38. package/dist/hooks/useCountdown/index.d.ts +2 -0
  39. package/dist/hooks/useCountdown/index.d.ts.map +1 -0
  40. package/dist/hooks/useCountdown/useCountdown.d.ts +40 -0
  41. package/dist/hooks/useCountdown/useCountdown.d.ts.map +1 -0
  42. package/dist/hooks/useCountdown.js +60 -0
  43. package/dist/hooks/useCountdown.js.map +1 -0
  44. package/dist/hooks/useCountdown.mjs +58 -0
  45. package/dist/hooks/useCountdown.mjs.map +1 -0
  46. package/dist/hooks/useEventListener/index.d.ts +2 -0
  47. package/dist/hooks/useEventListener/index.d.ts.map +1 -0
  48. package/dist/hooks/useEventListener/useEventListener.d.ts +22 -0
  49. package/dist/hooks/useEventListener/useEventListener.d.ts.map +1 -0
  50. package/dist/hooks/useEventListener.js +45 -0
  51. package/dist/hooks/useEventListener.js.map +1 -0
  52. package/dist/hooks/useEventListener.mjs +43 -0
  53. package/dist/hooks/useEventListener.mjs.map +1 -0
  54. package/dist/hooks/useGeolocation/index.d.ts +2 -0
  55. package/dist/hooks/useGeolocation/index.d.ts.map +1 -0
  56. package/dist/hooks/useGeolocation/useGeolocation.d.ts +48 -0
  57. package/dist/hooks/useGeolocation/useGeolocation.d.ts.map +1 -0
  58. package/dist/hooks/useGeolocation.js +111 -0
  59. package/dist/hooks/useGeolocation.js.map +1 -0
  60. package/dist/hooks/useGeolocation.mjs +109 -0
  61. package/dist/hooks/useGeolocation.mjs.map +1 -0
  62. package/dist/hooks/useHotkeys/index.d.ts +2 -0
  63. package/dist/hooks/useHotkeys/index.d.ts.map +1 -0
  64. package/dist/hooks/useHotkeys/useHotkeys.d.ts +24 -0
  65. package/dist/hooks/useHotkeys/useHotkeys.d.ts.map +1 -0
  66. package/dist/hooks/useHotkeys.js +86 -0
  67. package/dist/hooks/useHotkeys.js.map +1 -0
  68. package/dist/hooks/useHotkeys.mjs +84 -0
  69. package/dist/hooks/useHotkeys.mjs.map +1 -0
  70. package/dist/hooks/useIdleTimeout/index.d.ts +2 -0
  71. package/dist/hooks/useIdleTimeout/index.d.ts.map +1 -0
  72. package/dist/hooks/useIdleTimeout/useIdleTimeout.d.ts +31 -0
  73. package/dist/hooks/useIdleTimeout/useIdleTimeout.d.ts.map +1 -0
  74. package/dist/hooks/useIdleTimeout.js +77 -0
  75. package/dist/hooks/useIdleTimeout.js.map +1 -0
  76. package/dist/hooks/useIdleTimeout.mjs +75 -0
  77. package/dist/hooks/useIdleTimeout.mjs.map +1 -0
  78. package/dist/hooks/useInterval/index.d.ts +2 -0
  79. package/dist/hooks/useInterval/index.d.ts.map +1 -0
  80. package/dist/hooks/useInterval/useInterval.d.ts +12 -0
  81. package/dist/hooks/useInterval/useInterval.d.ts.map +1 -0
  82. package/dist/hooks/useInterval.js +27 -0
  83. package/dist/hooks/useInterval.js.map +1 -0
  84. package/dist/hooks/useInterval.mjs +25 -0
  85. package/dist/hooks/useInterval.mjs.map +1 -0
  86. package/dist/hooks/useKeyPress/index.d.ts +2 -0
  87. package/dist/hooks/useKeyPress/index.d.ts.map +1 -0
  88. package/dist/hooks/useKeyPress/useKeyPress.d.ts +15 -0
  89. package/dist/hooks/useKeyPress/useKeyPress.d.ts.map +1 -0
  90. package/dist/hooks/useKeyPress.js +47 -0
  91. package/dist/hooks/useKeyPress.js.map +1 -0
  92. package/dist/hooks/useKeyPress.mjs +45 -0
  93. package/dist/hooks/useKeyPress.mjs.map +1 -0
  94. package/dist/hooks/useLongPress/index.d.ts +2 -0
  95. package/dist/hooks/useLongPress/index.d.ts.map +1 -0
  96. package/dist/hooks/useLongPress/useLongPress.d.ts +46 -0
  97. package/dist/hooks/useLongPress/useLongPress.d.ts.map +1 -0
  98. package/dist/hooks/useLongPress.js +116 -0
  99. package/dist/hooks/useLongPress.js.map +1 -0
  100. package/dist/hooks/useLongPress.mjs +114 -0
  101. package/dist/hooks/useLongPress.mjs.map +1 -0
  102. package/dist/hooks/usePrevious/index.d.ts +2 -0
  103. package/dist/hooks/usePrevious/index.d.ts.map +1 -0
  104. package/dist/hooks/usePrevious/usePrevious.d.ts +13 -0
  105. package/dist/hooks/usePrevious/usePrevious.d.ts.map +1 -0
  106. package/dist/hooks/usePrevious.js +17 -0
  107. package/dist/hooks/usePrevious.js.map +1 -0
  108. package/dist/hooks/usePrevious.mjs +15 -0
  109. package/dist/hooks/usePrevious.mjs.map +1 -0
  110. package/dist/hooks/useScrollPosition/index.d.ts +2 -0
  111. package/dist/hooks/useScrollPosition/index.d.ts.map +1 -0
  112. package/dist/hooks/useScrollPosition/useScrollPosition.d.ts +37 -0
  113. package/dist/hooks/useScrollPosition/useScrollPosition.d.ts.map +1 -0
  114. package/dist/hooks/useScrollPosition.js +41 -0
  115. package/dist/hooks/useScrollPosition.js.map +1 -0
  116. package/dist/hooks/useScrollPosition.mjs +39 -0
  117. package/dist/hooks/useScrollPosition.mjs.map +1 -0
  118. package/dist/hooks/useTimeout/index.d.ts +2 -0
  119. package/dist/hooks/useTimeout/index.d.ts.map +1 -0
  120. package/dist/hooks/useTimeout/useTimeout.d.ts +19 -0
  121. package/dist/hooks/useTimeout/useTimeout.d.ts.map +1 -0
  122. package/dist/hooks/useTimeout.js +38 -0
  123. package/dist/hooks/useTimeout.js.map +1 -0
  124. package/dist/hooks/useTimeout.mjs +36 -0
  125. package/dist/hooks/useTimeout.mjs.map +1 -0
  126. package/dist/hooks/useVirtualList/index.d.ts +2 -0
  127. package/dist/hooks/useVirtualList/index.d.ts.map +1 -0
  128. package/dist/hooks/useVirtualList/useVirtualList.d.ts +47 -0
  129. package/dist/hooks/useVirtualList/useVirtualList.d.ts.map +1 -0
  130. package/dist/hooks/useVirtualList.js +87 -0
  131. package/dist/hooks/useVirtualList.js.map +1 -0
  132. package/dist/hooks/useVirtualList.mjs +85 -0
  133. package/dist/hooks/useVirtualList.mjs.map +1 -0
  134. package/dist/lib/facade.d.ts.map +1 -1
  135. package/dist/ui/buttons/animated.js +8 -7
  136. package/dist/ui/buttons/animated.js.map +1 -1
  137. package/dist/ui/buttons/animated.mjs +6 -5
  138. package/dist/ui/buttons/animated.mjs.map +1 -1
  139. package/dist/ui/buttons.js +9 -8
  140. package/dist/ui/buttons.mjs +7 -6
  141. package/dist/ui/combobox/combobox-base.d.ts +37 -0
  142. package/dist/ui/combobox/combobox-base.d.ts.map +1 -0
  143. package/dist/ui/combobox/combobox.d.ts +6 -0
  144. package/dist/ui/combobox/combobox.d.ts.map +1 -0
  145. package/dist/ui/combobox/index.d.ts +4 -0
  146. package/dist/ui/combobox/index.d.ts.map +1 -0
  147. package/dist/ui/combobox/types.d.ts +70 -0
  148. package/dist/ui/combobox/types.d.ts.map +1 -0
  149. package/dist/ui/combobox/variants.d.ts +17 -0
  150. package/dist/ui/combobox/variants.d.ts.map +1 -0
  151. package/dist/ui/combobox.js +510 -0
  152. package/dist/ui/combobox.js.map +1 -0
  153. package/dist/ui/combobox.mjs +495 -0
  154. package/dist/ui/combobox.mjs.map +1 -0
  155. package/dist/ui/dynamic-stepper.js +18 -17
  156. package/dist/ui/dynamic-stepper.js.map +1 -1
  157. package/dist/ui/dynamic-stepper.mjs +7 -6
  158. package/dist/ui/dynamic-stepper.mjs.map +1 -1
  159. package/dist/ui/pagination.js +14 -13
  160. package/dist/ui/pagination.js.map +1 -1
  161. package/dist/ui/pagination.mjs +6 -5
  162. package/dist/ui/pagination.mjs.map +1 -1
  163. package/package.json +1 -1
  164. package/src/design-system/combobox.ts +204 -0
  165. package/src/design-system/index.ts +1 -0
  166. package/src/hooks/index.ts +50 -0
  167. package/src/hooks/useCookie/index.ts +5 -0
  168. package/src/hooks/useCookie/useCookie.test.ts +57 -0
  169. package/src/hooks/useCookie/useCookie.ts +133 -0
  170. package/src/hooks/useCountdown/index.ts +5 -0
  171. package/src/hooks/useCountdown/useCountdown.test.ts +113 -0
  172. package/src/hooks/useCountdown/useCountdown.ts +106 -0
  173. package/src/hooks/useEventListener/index.ts +4 -0
  174. package/src/hooks/useEventListener/useEventListener.test.ts +60 -0
  175. package/src/hooks/useEventListener/useEventListener.ts +98 -0
  176. package/src/hooks/useGeolocation/index.ts +6 -0
  177. package/src/hooks/useGeolocation/useGeolocation.test.ts +108 -0
  178. package/src/hooks/useGeolocation/useGeolocation.ts +173 -0
  179. package/src/hooks/useHotkeys/index.ts +5 -0
  180. package/src/hooks/useHotkeys/useHotkeys.test.ts +82 -0
  181. package/src/hooks/useHotkeys/useHotkeys.ts +130 -0
  182. package/src/hooks/useIdleTimeout/index.ts +5 -0
  183. package/src/hooks/useIdleTimeout/useIdleTimeout.test.ts +97 -0
  184. package/src/hooks/useIdleTimeout/useIdleTimeout.ts +111 -0
  185. package/src/hooks/useInterval/index.ts +1 -0
  186. package/src/hooks/useInterval/useInterval.test.ts +56 -0
  187. package/src/hooks/useInterval/useInterval.ts +36 -0
  188. package/src/hooks/useKeyPress/index.ts +1 -0
  189. package/src/hooks/useKeyPress/useKeyPress.test.ts +67 -0
  190. package/src/hooks/useKeyPress/useKeyPress.ts +65 -0
  191. package/src/hooks/useLongPress/index.ts +5 -0
  192. package/src/hooks/useLongPress/useLongPress.test.ts +180 -0
  193. package/src/hooks/useLongPress/useLongPress.ts +177 -0
  194. package/src/hooks/usePrevious/index.ts +1 -0
  195. package/src/hooks/usePrevious/usePrevious.test.ts +33 -0
  196. package/src/hooks/usePrevious/usePrevious.ts +24 -0
  197. package/src/hooks/useScrollPosition/index.ts +5 -0
  198. package/src/hooks/useScrollPosition/useScrollPosition.test.ts +69 -0
  199. package/src/hooks/useScrollPosition/useScrollPosition.ts +88 -0
  200. package/src/hooks/useTimeout/index.ts +1 -0
  201. package/src/hooks/useTimeout/useTimeout.test.ts +63 -0
  202. package/src/hooks/useTimeout/useTimeout.ts +58 -0
  203. package/src/hooks/useVirtualList/index.ts +6 -0
  204. package/src/hooks/useVirtualList/useVirtualList.test.ts +102 -0
  205. package/src/hooks/useVirtualList/useVirtualList.ts +144 -0
  206. package/src/lib/facade.test.ts +7 -7
  207. package/src/lib/facade.ts +6 -2
  208. package/src/ui/combobox/combobox-base.tsx +552 -0
  209. package/src/ui/combobox/combobox.test.tsx +292 -0
  210. package/src/ui/combobox/combobox.tsx +8 -0
  211. package/src/ui/combobox/index.ts +33 -0
  212. package/src/ui/combobox/types.ts +91 -0
  213. package/src/ui/combobox/variants.ts +58 -0
  214. package/dist/chunk-5J6QMTES.js.map +0 -1
  215. package/dist/chunk-AQHY4S33.js +0 -19
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useLongPress/useLongPress.ts"],"names":[],"mappings":"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","file":"useLongPress.mjs","sourcesContent":["\"use client\";\n\nimport type {\n MouseEvent as ReactMouseEvent,\n PointerEvent as ReactPointerEvent,\n} from \"react\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport type UseLongPressOptions = {\n /** Hold duration in milliseconds before the press counts as \"long\" (default `500`). */\n thresholdMs?: number;\n /** Pointer travel in pixels that cancels the press (default `10`). */\n moveTolerancePx?: number;\n /** Called when the pointer goes down (press attempt starts). */\n onStart?: (event: ReactPointerEvent) => void;\n /** Called on release after a long press fired. */\n onFinish?: (event: ReactPointerEvent) => void;\n /** Called when the press is released or cancelled before the threshold. */\n onCancel?: (event: ReactPointerEvent) => void;\n};\n\nexport type UseLongPressHandlers = {\n onPointerDown: (event: ReactPointerEvent) => void;\n onPointerMove: (event: ReactPointerEvent) => void;\n onPointerUp: (event: ReactPointerEvent) => void;\n onPointerLeave: (event: ReactPointerEvent) => void;\n /** Handles browser-level pointer cancellation (e.g. system interruption, scroll takeover). */\n onPointerCancel: (event: ReactPointerEvent) => void;\n /**\n * Suppresses the synthetic `click` event that fires after a successful long press.\n * Spread alongside the other handlers to prevent unintended navigation or button actions.\n */\n onClick: (event: ReactMouseEvent) => void;\n};\n\n/**\n * Long-press gesture detection built on pointer events, so it works for mouse, touch, and pen.\n *\n * Spread the returned handlers onto the target element. After the pointer is held\n * `thresholdMs` without travelling more than `moveTolerancePx`, `callback` fires once;\n * releasing afterwards calls `onFinish`, while early release / movement / leaving the\n * element calls `onCancel`.\n *\n * Only the primary button (button 0 / left click / first touch contact) starts a long press;\n * right and middle mouse buttons are ignored.\n *\n * Pair with `touch-action` / `select-none` CSS on touch targets to suppress native\n * scrolling or text selection during the hold where needed.\n *\n * @param callback - Invoked once when the press crosses the threshold.\n * @param options - {@link UseLongPressOptions}\n * @returns Spreadable pointer handlers ({@link UseLongPressHandlers}).\n */\nexport function useLongPress(\n callback: (event: ReactPointerEvent) => void,\n options: UseLongPressOptions = {},\n): UseLongPressHandlers {\n const {\n thresholdMs = 500,\n moveTolerancePx = 10,\n onStart,\n onFinish,\n onCancel,\n } = options;\n\n const callbackRef = useRef(callback);\n const onStartRef = useRef(onStart);\n const onFinishRef = useRef(onFinish);\n const onCancelRef = useRef(onCancel);\n\n useEffect(() => {\n callbackRef.current = callback;\n onStartRef.current = onStart;\n onFinishRef.current = onFinish;\n onCancelRef.current = onCancel;\n }, [callback, onCancel, onFinish, onStart]);\n\n const timeoutRef = useRef<number | undefined>(undefined);\n const triggeredRef = useRef(false);\n const pressingRef = useRef(false);\n const originRef = useRef({ x: 0, y: 0 });\n\n const stopTimer = useCallback(() => {\n if (timeoutRef.current !== undefined) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n }, []);\n\n useEffect(() => stopTimer, [stopTimer]);\n\n const cancel = useCallback(\n (event: ReactPointerEvent) => {\n if (!pressingRef.current) {\n return;\n }\n pressingRef.current = false;\n stopTimer();\n if (!triggeredRef.current) {\n onCancelRef.current?.(event);\n }\n },\n [stopTimer],\n );\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent) => {\n // Only respond to the primary button (left click / first touch contact).\n // event.button > 0 catches right (2) and middle (1) mouse buttons.\n if (event.button > 0) {\n return;\n }\n pressingRef.current = true;\n triggeredRef.current = false;\n originRef.current = { x: event.clientX, y: event.clientY };\n onStartRef.current?.(event);\n stopTimer();\n timeoutRef.current = window.setTimeout(() => {\n timeoutRef.current = undefined;\n if (pressingRef.current) {\n triggeredRef.current = true;\n callbackRef.current(event);\n }\n }, thresholdMs);\n },\n [stopTimer, thresholdMs],\n );\n\n const onPointerMove = useCallback(\n (event: ReactPointerEvent) => {\n if (!pressingRef.current || triggeredRef.current) {\n return;\n }\n const dx = event.clientX - originRef.current.x;\n const dy = event.clientY - originRef.current.y;\n if (Math.hypot(dx, dy) > moveTolerancePx) {\n cancel(event);\n }\n },\n [cancel, moveTolerancePx],\n );\n\n const onPointerUp = useCallback(\n (event: ReactPointerEvent) => {\n if (!pressingRef.current) {\n return;\n }\n const triggered = triggeredRef.current;\n pressingRef.current = false;\n stopTimer();\n if (triggered) {\n onFinishRef.current?.(event);\n } else {\n onCancelRef.current?.(event);\n }\n },\n [stopTimer],\n );\n\n // After a successful long press the browser fires a synthetic `click` event on pointer up.\n // This handler suppresses it so navigation and button actions aren't triggered unexpectedly.\n const onClick = useCallback((event: ReactMouseEvent) => {\n if (triggeredRef.current) {\n event.preventDefault();\n triggeredRef.current = false;\n }\n }, []);\n\n return {\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerLeave: cancel,\n onPointerCancel: cancel,\n onClick,\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export { usePrevious } from "./usePrevious";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePrevious/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns the value passed in on the previous render (`undefined` on first render).
3
+ *
4
+ * The ref is updated in an effect after each committed render, so during a render
5
+ * you always see the value from the previous one — handy for diffing props/state,
6
+ * animation direction, or "changed since last render" checks.
7
+ *
8
+ * @typeParam T - Tracked value type.
9
+ * @param value - The current value to track.
10
+ * @returns The value from the previous render, or `undefined` before the first update.
11
+ */
12
+ export declare function usePrevious<T>(value: T): T | undefined;
13
+ //# sourceMappingURL=usePrevious.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePrevious.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePrevious/usePrevious.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAQtD"}
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ require('../chunk-PZ5AY32C.js');
5
+ var react = require('react');
6
+
7
+ function usePrevious(value) {
8
+ const previousRef = react.useRef(void 0);
9
+ react.useEffect(() => {
10
+ previousRef.current = value;
11
+ }, [value]);
12
+ return previousRef.current;
13
+ }
14
+
15
+ exports.usePrevious = usePrevious;
16
+ //# sourceMappingURL=usePrevious.js.map
17
+ //# sourceMappingURL=usePrevious.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/usePrevious/usePrevious.ts"],"names":["useRef","useEffect"],"mappings":";;;;;AAeO,SAAS,YAAe,KAAA,EAAyB;AACtD,EAAA,MAAM,WAAA,GAAcA,aAAsB,MAAS,CAAA;AAEnD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AAAA,EACxB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,WAAA,CAAY,OAAA;AACrB","file":"usePrevious.js","sourcesContent":["\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/**\n * Returns the value passed in on the previous render (`undefined` on first render).\n *\n * The ref is updated in an effect after each committed render, so during a render\n * you always see the value from the previous one — handy for diffing props/state,\n * animation direction, or \"changed since last render\" checks.\n *\n * @typeParam T - Tracked value type.\n * @param value - The current value to track.\n * @returns The value from the previous render, or `undefined` before the first update.\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const previousRef = useRef<T | undefined>(undefined);\n\n useEffect(() => {\n previousRef.current = value;\n }, [value]);\n\n return previousRef.current;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import '../chunk-J5LGTIGS.mjs';
3
+ import { useRef, useEffect } from 'react';
4
+
5
+ function usePrevious(value) {
6
+ const previousRef = useRef(void 0);
7
+ useEffect(() => {
8
+ previousRef.current = value;
9
+ }, [value]);
10
+ return previousRef.current;
11
+ }
12
+
13
+ export { usePrevious };
14
+ //# sourceMappingURL=usePrevious.mjs.map
15
+ //# sourceMappingURL=usePrevious.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/usePrevious/usePrevious.ts"],"names":[],"mappings":";;;AAeO,SAAS,YAAe,KAAA,EAAyB;AACtD,EAAA,MAAM,WAAA,GAAc,OAAsB,MAAS,CAAA;AAEnD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AAAA,EACxB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,WAAA,CAAY,OAAA;AACrB","file":"usePrevious.mjs","sourcesContent":["\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/**\n * Returns the value passed in on the previous render (`undefined` on first render).\n *\n * The ref is updated in an effect after each committed render, so during a render\n * you always see the value from the previous one — handy for diffing props/state,\n * animation direction, or \"changed since last render\" checks.\n *\n * @typeParam T - Tracked value type.\n * @param value - The current value to track.\n * @returns The value from the previous render, or `undefined` before the first update.\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const previousRef = useRef<T | undefined>(undefined);\n\n useEffect(() => {\n previousRef.current = value;\n }, [value]);\n\n return previousRef.current;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export { useScrollPosition, type ScrollPosition, type UseScrollPositionParams, } from "./useScrollPosition";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useScrollPosition/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { RefCallback, RefObject } from "react";
2
+ export type ScrollPosition = {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ export type UseScrollPositionParams<T extends HTMLElement = HTMLElement> = {
7
+ /**
8
+ * Scroll container to observe via a pre-populated RefObject.
9
+ * For elements that mount asynchronously, use the returned `setRef` callback ref instead.
10
+ */
11
+ target?: RefObject<T | null>;
12
+ };
13
+ export type UseScrollPositionResult<T extends HTMLElement = HTMLElement> = ScrollPosition & {
14
+ /**
15
+ * Callback ref to attach to a scroll container — works correctly with elements
16
+ * that are null on initial render (lazy / conditional mounts). Pass this as `ref`
17
+ * on the scrollable element when you cannot guarantee the ref is populated at mount.
18
+ */
19
+ setRef: RefCallback<T>;
20
+ };
21
+ /**
22
+ * Tracks the scroll offset of the window (default) or a scrollable element.
23
+ *
24
+ * - Window mode reads `scrollX` / `scrollY`; element mode reads `scrollLeft` / `scrollTop`.
25
+ * - Subscribes with a passive `scroll` listener and reads the initial position on mount.
26
+ * - Pass a pre-populated `target` RefObject **or** use the returned `setRef` callback ref on
27
+ * the scrollable element. Prefer `setRef` for elements that may be null on the first render
28
+ * (conditional mounts, portals) — it stores the element in state so the effect re-attaches
29
+ * correctly when the element becomes available.
30
+ * - For high-frequency consumers, derive throttled values downstream (e.g. with
31
+ * `useThrottledCallback`) rather than throttling the source of truth.
32
+ *
33
+ * @param params - {@link UseScrollPositionParams}
34
+ * @returns Latest `{ x, y }` scroll offset in pixels plus a `setRef` callback ref.
35
+ */
36
+ export declare function useScrollPosition<T extends HTMLElement = HTMLElement>(params?: UseScrollPositionParams<T>): UseScrollPositionResult<T>;
37
+ //# sourceMappingURL=useScrollPosition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollPosition.d.ts","sourceRoot":"","sources":["../../../src/hooks/useScrollPosition/useScrollPosition.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpD,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACzE;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IACrE,cAAc,GAAG;IACf;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CACxB,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACnE,MAAM,GAAE,uBAAuB,CAAC,CAAC,CAAM,GACtC,uBAAuB,CAAC,CAAC,CAAC,CA0C5B"}
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ require('../chunk-PZ5AY32C.js');
5
+ var react = require('react');
6
+
7
+ function useScrollPosition(params = {}) {
8
+ const { target } = params;
9
+ const [element, setElement] = react.useState(
10
+ () => target?.current ?? null
11
+ );
12
+ const [position, setPosition] = react.useState({ x: 0, y: 0 });
13
+ react.useEffect(() => {
14
+ if (target?.current != null) {
15
+ setElement(target.current);
16
+ }
17
+ }, [target]);
18
+ const setRef = react.useCallback((node) => {
19
+ setElement(node);
20
+ }, []);
21
+ react.useEffect(() => {
22
+ const node = element ?? (typeof window === "undefined" ? null : window);
23
+ if (node == null) {
24
+ return;
25
+ }
26
+ const read = () => element == null ? { x: window.scrollX, y: window.scrollY } : { x: element.scrollLeft, y: element.scrollTop };
27
+ const onScroll = () => {
28
+ setPosition(read());
29
+ };
30
+ onScroll();
31
+ node.addEventListener("scroll", onScroll, { passive: true });
32
+ return () => {
33
+ node.removeEventListener("scroll", onScroll);
34
+ };
35
+ }, [element]);
36
+ return { x: position.x, y: position.y, setRef };
37
+ }
38
+
39
+ exports.useScrollPosition = useScrollPosition;
40
+ //# sourceMappingURL=useScrollPosition.js.map
41
+ //# sourceMappingURL=useScrollPosition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useScrollPosition/useScrollPosition.ts"],"names":["useState","useEffect","useCallback"],"mappings":";;;;;AA2CO,SAAS,iBAAA,CACd,MAAA,GAAqC,EAAC,EACV;AAC5B,EAAA,MAAM,EAAE,QAAO,GAAI,MAAA;AAInB,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,cAAA;AAAA,IAC5B,MAAM,QAAQ,OAAA,IAAW;AAAA,GAC3B;AACA,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,cAAA,CAAyB,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAGvE,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAA,EAAQ,WAAW,IAAA,EAAM;AAC3B,MAAA,UAAA,CAAW,OAAO,OAAO,CAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,MAAA,GAASC,iBAAA,CAAY,CAAC,IAAA,KAAmB;AAC7C,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAA,GACJ,OAAA,KAAY,OAAO,MAAA,KAAW,cAAc,IAAA,GAAO,MAAA,CAAA;AACrD,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAO,MACX,OAAA,IAAW,OACP,EAAE,CAAA,EAAG,OAAO,OAAA,EAAS,CAAA,EAAG,MAAA,CAAO,OAAA,KAC/B,EAAE,CAAA,EAAG,QAAQ,UAAA,EAAY,CAAA,EAAG,QAAQ,SAAA,EAAU;AACpD,IAAA,MAAM,WAAW,MAAM;AACrB,MAAA,WAAA,CAAY,MAAM,CAAA;AAAA,IACpB,CAAA;AACA,IAAA,QAAA,EAAS;AACT,IAAA,IAAA,CAAK,iBAAiB,QAAA,EAAU,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AAC3D,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,mBAAA,CAAoB,UAAU,QAAQ,CAAA;AAAA,IAC7C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,EAAE,CAAA,EAAG,QAAA,CAAS,GAAG,CAAA,EAAG,QAAA,CAAS,GAAG,MAAA,EAAO;AAChD","file":"useScrollPosition.js","sourcesContent":["\"use client\";\n\nimport type { RefCallback, RefObject } from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport type ScrollPosition = {\n x: number;\n y: number;\n};\n\nexport type UseScrollPositionParams<T extends HTMLElement = HTMLElement> = {\n /**\n * Scroll container to observe via a pre-populated RefObject.\n * For elements that mount asynchronously, use the returned `setRef` callback ref instead.\n */\n target?: RefObject<T | null>;\n};\n\nexport type UseScrollPositionResult<T extends HTMLElement = HTMLElement> =\n ScrollPosition & {\n /**\n * Callback ref to attach to a scroll container — works correctly with elements\n * that are null on initial render (lazy / conditional mounts). Pass this as `ref`\n * on the scrollable element when you cannot guarantee the ref is populated at mount.\n */\n setRef: RefCallback<T>;\n };\n\n/**\n * Tracks the scroll offset of the window (default) or a scrollable element.\n *\n * - Window mode reads `scrollX` / `scrollY`; element mode reads `scrollLeft` / `scrollTop`.\n * - Subscribes with a passive `scroll` listener and reads the initial position on mount.\n * - Pass a pre-populated `target` RefObject **or** use the returned `setRef` callback ref on\n * the scrollable element. Prefer `setRef` for elements that may be null on the first render\n * (conditional mounts, portals) — it stores the element in state so the effect re-attaches\n * correctly when the element becomes available.\n * - For high-frequency consumers, derive throttled values downstream (e.g. with\n * `useThrottledCallback`) rather than throttling the source of truth.\n *\n * @param params - {@link UseScrollPositionParams}\n * @returns Latest `{ x, y }` scroll offset in pixels plus a `setRef` callback ref.\n */\nexport function useScrollPosition<T extends HTMLElement = HTMLElement>(\n params: UseScrollPositionParams<T> = {},\n): UseScrollPositionResult<T> {\n const { target } = params;\n\n // Track the element in state so the scroll listener effect reruns when the element\n // is assigned (handles callback-ref / lazy-mount patterns).\n const [element, setElement] = useState<T | null>(\n () => target?.current ?? null,\n );\n const [position, setPosition] = useState<ScrollPosition>({ x: 0, y: 0 });\n\n // Sync element state when the target RefObject changes (pre-populated refs).\n useEffect(() => {\n if (target?.current != null) {\n setElement(target.current);\n }\n }, [target]);\n\n const setRef = useCallback((node: T | null) => {\n setElement(node);\n }, []);\n\n useEffect(() => {\n const node: Window | T | null =\n element ?? (typeof window === \"undefined\" ? null : window);\n if (node == null) {\n return;\n }\n const read = (): ScrollPosition =>\n element == null\n ? { x: window.scrollX, y: window.scrollY }\n : { x: element.scrollLeft, y: element.scrollTop };\n const onScroll = () => {\n setPosition(read());\n };\n onScroll();\n node.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n node.removeEventListener(\"scroll\", onScroll);\n };\n }, [element]);\n\n return { x: position.x, y: position.y, setRef };\n}\n"]}
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import '../chunk-J5LGTIGS.mjs';
3
+ import { useState, useEffect, useCallback } from 'react';
4
+
5
+ function useScrollPosition(params = {}) {
6
+ const { target } = params;
7
+ const [element, setElement] = useState(
8
+ () => target?.current ?? null
9
+ );
10
+ const [position, setPosition] = useState({ x: 0, y: 0 });
11
+ useEffect(() => {
12
+ if (target?.current != null) {
13
+ setElement(target.current);
14
+ }
15
+ }, [target]);
16
+ const setRef = useCallback((node) => {
17
+ setElement(node);
18
+ }, []);
19
+ useEffect(() => {
20
+ const node = element ?? (typeof window === "undefined" ? null : window);
21
+ if (node == null) {
22
+ return;
23
+ }
24
+ const read = () => element == null ? { x: window.scrollX, y: window.scrollY } : { x: element.scrollLeft, y: element.scrollTop };
25
+ const onScroll = () => {
26
+ setPosition(read());
27
+ };
28
+ onScroll();
29
+ node.addEventListener("scroll", onScroll, { passive: true });
30
+ return () => {
31
+ node.removeEventListener("scroll", onScroll);
32
+ };
33
+ }, [element]);
34
+ return { x: position.x, y: position.y, setRef };
35
+ }
36
+
37
+ export { useScrollPosition };
38
+ //# sourceMappingURL=useScrollPosition.mjs.map
39
+ //# sourceMappingURL=useScrollPosition.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useScrollPosition/useScrollPosition.ts"],"names":[],"mappings":";;;AA2CO,SAAS,iBAAA,CACd,MAAA,GAAqC,EAAC,EACV;AAC5B,EAAA,MAAM,EAAE,QAAO,GAAI,MAAA;AAInB,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA;AAAA,IAC5B,MAAM,QAAQ,OAAA,IAAW;AAAA,GAC3B;AACA,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAAyB,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAGvE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAA,EAAQ,WAAW,IAAA,EAAM;AAC3B,MAAA,UAAA,CAAW,OAAO,OAAO,CAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,IAAA,KAAmB;AAC7C,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAA,GACJ,OAAA,KAAY,OAAO,MAAA,KAAW,cAAc,IAAA,GAAO,MAAA,CAAA;AACrD,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAO,MACX,OAAA,IAAW,OACP,EAAE,CAAA,EAAG,OAAO,OAAA,EAAS,CAAA,EAAG,MAAA,CAAO,OAAA,KAC/B,EAAE,CAAA,EAAG,QAAQ,UAAA,EAAY,CAAA,EAAG,QAAQ,SAAA,EAAU;AACpD,IAAA,MAAM,WAAW,MAAM;AACrB,MAAA,WAAA,CAAY,MAAM,CAAA;AAAA,IACpB,CAAA;AACA,IAAA,QAAA,EAAS;AACT,IAAA,IAAA,CAAK,iBAAiB,QAAA,EAAU,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AAC3D,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,mBAAA,CAAoB,UAAU,QAAQ,CAAA;AAAA,IAC7C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,EAAE,CAAA,EAAG,QAAA,CAAS,GAAG,CAAA,EAAG,QAAA,CAAS,GAAG,MAAA,EAAO;AAChD","file":"useScrollPosition.mjs","sourcesContent":["\"use client\";\n\nimport type { RefCallback, RefObject } from \"react\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport type ScrollPosition = {\n x: number;\n y: number;\n};\n\nexport type UseScrollPositionParams<T extends HTMLElement = HTMLElement> = {\n /**\n * Scroll container to observe via a pre-populated RefObject.\n * For elements that mount asynchronously, use the returned `setRef` callback ref instead.\n */\n target?: RefObject<T | null>;\n};\n\nexport type UseScrollPositionResult<T extends HTMLElement = HTMLElement> =\n ScrollPosition & {\n /**\n * Callback ref to attach to a scroll container — works correctly with elements\n * that are null on initial render (lazy / conditional mounts). Pass this as `ref`\n * on the scrollable element when you cannot guarantee the ref is populated at mount.\n */\n setRef: RefCallback<T>;\n };\n\n/**\n * Tracks the scroll offset of the window (default) or a scrollable element.\n *\n * - Window mode reads `scrollX` / `scrollY`; element mode reads `scrollLeft` / `scrollTop`.\n * - Subscribes with a passive `scroll` listener and reads the initial position on mount.\n * - Pass a pre-populated `target` RefObject **or** use the returned `setRef` callback ref on\n * the scrollable element. Prefer `setRef` for elements that may be null on the first render\n * (conditional mounts, portals) — it stores the element in state so the effect re-attaches\n * correctly when the element becomes available.\n * - For high-frequency consumers, derive throttled values downstream (e.g. with\n * `useThrottledCallback`) rather than throttling the source of truth.\n *\n * @param params - {@link UseScrollPositionParams}\n * @returns Latest `{ x, y }` scroll offset in pixels plus a `setRef` callback ref.\n */\nexport function useScrollPosition<T extends HTMLElement = HTMLElement>(\n params: UseScrollPositionParams<T> = {},\n): UseScrollPositionResult<T> {\n const { target } = params;\n\n // Track the element in state so the scroll listener effect reruns when the element\n // is assigned (handles callback-ref / lazy-mount patterns).\n const [element, setElement] = useState<T | null>(\n () => target?.current ?? null,\n );\n const [position, setPosition] = useState<ScrollPosition>({ x: 0, y: 0 });\n\n // Sync element state when the target RefObject changes (pre-populated refs).\n useEffect(() => {\n if (target?.current != null) {\n setElement(target.current);\n }\n }, [target]);\n\n const setRef = useCallback((node: T | null) => {\n setElement(node);\n }, []);\n\n useEffect(() => {\n const node: Window | T | null =\n element ?? (typeof window === \"undefined\" ? null : window);\n if (node == null) {\n return;\n }\n const read = (): ScrollPosition =>\n element == null\n ? { x: window.scrollX, y: window.scrollY }\n : { x: element.scrollLeft, y: element.scrollTop };\n const onScroll = () => {\n setPosition(read());\n };\n onScroll();\n node.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n node.removeEventListener(\"scroll\", onScroll);\n };\n }, [element]);\n\n return { x: position.x, y: position.y, setRef };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export { useTimeout, type UseTimeoutResult } from "./useTimeout";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTimeout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type UseTimeoutResult = {
2
+ /** Cancel the pending timeout (no-op if already fired or cleared). */
3
+ clear: () => void;
4
+ /** Cancel any pending timeout and schedule a fresh one with the current delay. */
5
+ reset: () => void;
6
+ };
7
+ /**
8
+ * Declarative `setTimeout`: runs `callback` once after `delayMs` milliseconds with automatic cleanup.
9
+ *
10
+ * - The latest callback is kept in a ref, so a new inline function each render does not reschedule.
11
+ * - Pass `null` as the delay to cancel scheduling entirely.
12
+ * - Changing `delayMs` cancels the pending timeout and schedules a new one.
13
+ *
14
+ * @param callback - Function invoked when the timeout fires.
15
+ * @param delayMs - Delay in milliseconds, or `null` to disable.
16
+ * @returns `{ clear, reset }` to cancel or restart the timeout imperatively.
17
+ */
18
+ export declare function useTimeout(callback: () => void, delayMs: number | null): UseTimeoutResult;
19
+ //# sourceMappingURL=useTimeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimeout.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTimeout/useTimeout.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,sEAAsE;IACtE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,kFAAkF;IAClF,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,gBAAgB,CAgClB"}
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ require('../chunk-PZ5AY32C.js');
5
+ var react = require('react');
6
+
7
+ function useTimeout(callback, delayMs) {
8
+ const callbackRef = react.useRef(callback);
9
+ const timeoutRef = react.useRef(void 0);
10
+ react.useEffect(() => {
11
+ callbackRef.current = callback;
12
+ }, [callback]);
13
+ const clear = react.useCallback(() => {
14
+ if (timeoutRef.current !== void 0) {
15
+ window.clearTimeout(timeoutRef.current);
16
+ timeoutRef.current = void 0;
17
+ }
18
+ }, []);
19
+ const reset = react.useCallback(() => {
20
+ clear();
21
+ if (delayMs == null) {
22
+ return;
23
+ }
24
+ timeoutRef.current = window.setTimeout(() => {
25
+ timeoutRef.current = void 0;
26
+ callbackRef.current();
27
+ }, delayMs);
28
+ }, [clear, delayMs]);
29
+ react.useEffect(() => {
30
+ reset();
31
+ return clear;
32
+ }, [clear, reset]);
33
+ return { clear, reset };
34
+ }
35
+
36
+ exports.useTimeout = useTimeout;
37
+ //# sourceMappingURL=useTimeout.js.map
38
+ //# sourceMappingURL=useTimeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useTimeout/useTimeout.ts"],"names":["useRef","useEffect","useCallback"],"mappings":";;;;;AAsBO,SAAS,UAAA,CACd,UACA,OAAA,EACkB;AAClB,EAAA,MAAM,WAAA,GAAcA,aAAO,QAAQ,CAAA;AACnC,EAAA,MAAM,UAAA,GAAaA,aAA2B,MAAS,CAAA;AAEvD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EACxB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,KAAA,GAAQC,kBAAY,MAAM;AAC9B,IAAA,IAAI,UAAA,CAAW,YAAY,MAAA,EAAW;AACpC,MAAA,MAAA,CAAO,YAAA,CAAa,WAAW,OAAO,CAAA;AACtC,MAAA,UAAA,CAAW,OAAA,GAAU,MAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQA,kBAAY,MAAM;AAC9B,IAAA,KAAA,EAAM;AACN,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,OAAA,GAAU,MAAA,CAAO,UAAA,CAAW,MAAM;AAC3C,MAAA,UAAA,CAAW,OAAA,GAAU,MAAA;AACrB,MAAA,WAAA,CAAY,OAAA,EAAQ;AAAA,IACtB,GAAG,OAAO,CAAA;AAAA,EACZ,CAAA,EAAG,CAAC,KAAA,EAAO,OAAO,CAAC,CAAA;AAEnB,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,KAAA,EAAM;AACN,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,EAAG,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAEjB,EAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AACxB","file":"useTimeout.js","sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport type UseTimeoutResult = {\n /** Cancel the pending timeout (no-op if already fired or cleared). */\n clear: () => void;\n /** Cancel any pending timeout and schedule a fresh one with the current delay. */\n reset: () => void;\n};\n\n/**\n * Declarative `setTimeout`: runs `callback` once after `delayMs` milliseconds with automatic cleanup.\n *\n * - The latest callback is kept in a ref, so a new inline function each render does not reschedule.\n * - Pass `null` as the delay to cancel scheduling entirely.\n * - Changing `delayMs` cancels the pending timeout and schedules a new one.\n *\n * @param callback - Function invoked when the timeout fires.\n * @param delayMs - Delay in milliseconds, or `null` to disable.\n * @returns `{ clear, reset }` to cancel or restart the timeout imperatively.\n */\nexport function useTimeout(\n callback: () => void,\n delayMs: number | null,\n): UseTimeoutResult {\n const callbackRef = useRef(callback);\n const timeoutRef = useRef<number | undefined>(undefined);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const clear = useCallback(() => {\n if (timeoutRef.current !== undefined) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n }, []);\n\n const reset = useCallback(() => {\n clear();\n if (delayMs == null) {\n return;\n }\n timeoutRef.current = window.setTimeout(() => {\n timeoutRef.current = undefined;\n callbackRef.current();\n }, delayMs);\n }, [clear, delayMs]);\n\n useEffect(() => {\n reset();\n return clear;\n }, [clear, reset]);\n\n return { clear, reset };\n}\n"]}
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import '../chunk-J5LGTIGS.mjs';
3
+ import { useRef, useEffect, useCallback } from 'react';
4
+
5
+ function useTimeout(callback, delayMs) {
6
+ const callbackRef = useRef(callback);
7
+ const timeoutRef = useRef(void 0);
8
+ useEffect(() => {
9
+ callbackRef.current = callback;
10
+ }, [callback]);
11
+ const clear = useCallback(() => {
12
+ if (timeoutRef.current !== void 0) {
13
+ window.clearTimeout(timeoutRef.current);
14
+ timeoutRef.current = void 0;
15
+ }
16
+ }, []);
17
+ const reset = useCallback(() => {
18
+ clear();
19
+ if (delayMs == null) {
20
+ return;
21
+ }
22
+ timeoutRef.current = window.setTimeout(() => {
23
+ timeoutRef.current = void 0;
24
+ callbackRef.current();
25
+ }, delayMs);
26
+ }, [clear, delayMs]);
27
+ useEffect(() => {
28
+ reset();
29
+ return clear;
30
+ }, [clear, reset]);
31
+ return { clear, reset };
32
+ }
33
+
34
+ export { useTimeout };
35
+ //# sourceMappingURL=useTimeout.mjs.map
36
+ //# sourceMappingURL=useTimeout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useTimeout/useTimeout.ts"],"names":[],"mappings":";;;AAsBO,SAAS,UAAA,CACd,UACA,OAAA,EACkB;AAClB,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AACnC,EAAA,MAAM,UAAA,GAAa,OAA2B,MAAS,CAAA;AAEvD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EACxB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,IAAI,UAAA,CAAW,YAAY,MAAA,EAAW;AACpC,MAAA,MAAA,CAAO,YAAA,CAAa,WAAW,OAAO,CAAA;AACtC,MAAA,UAAA,CAAW,OAAA,GAAU,MAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,KAAA,EAAM;AACN,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,OAAA,GAAU,MAAA,CAAO,UAAA,CAAW,MAAM;AAC3C,MAAA,UAAA,CAAW,OAAA,GAAU,MAAA;AACrB,MAAA,WAAA,CAAY,OAAA,EAAQ;AAAA,IACtB,GAAG,OAAO,CAAA;AAAA,EACZ,CAAA,EAAG,CAAC,KAAA,EAAO,OAAO,CAAC,CAAA;AAEnB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,KAAA,EAAM;AACN,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,EAAG,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAEjB,EAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AACxB","file":"useTimeout.mjs","sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport type UseTimeoutResult = {\n /** Cancel the pending timeout (no-op if already fired or cleared). */\n clear: () => void;\n /** Cancel any pending timeout and schedule a fresh one with the current delay. */\n reset: () => void;\n};\n\n/**\n * Declarative `setTimeout`: runs `callback` once after `delayMs` milliseconds with automatic cleanup.\n *\n * - The latest callback is kept in a ref, so a new inline function each render does not reschedule.\n * - Pass `null` as the delay to cancel scheduling entirely.\n * - Changing `delayMs` cancels the pending timeout and schedules a new one.\n *\n * @param callback - Function invoked when the timeout fires.\n * @param delayMs - Delay in milliseconds, or `null` to disable.\n * @returns `{ clear, reset }` to cancel or restart the timeout imperatively.\n */\nexport function useTimeout(\n callback: () => void,\n delayMs: number | null,\n): UseTimeoutResult {\n const callbackRef = useRef(callback);\n const timeoutRef = useRef<number | undefined>(undefined);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const clear = useCallback(() => {\n if (timeoutRef.current !== undefined) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = undefined;\n }\n }, []);\n\n const reset = useCallback(() => {\n clear();\n if (delayMs == null) {\n return;\n }\n timeoutRef.current = window.setTimeout(() => {\n timeoutRef.current = undefined;\n callbackRef.current();\n }, delayMs);\n }, [clear, delayMs]);\n\n useEffect(() => {\n reset();\n return clear;\n }, [clear, reset]);\n\n return { clear, reset };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export { useVirtualList, type UseVirtualListParams, type UseVirtualListResult, type VirtualItem, } from "./useVirtualList";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useVirtualList/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { RefCallback } from "react";
2
+ export type VirtualItem = {
3
+ /** Index into your data array. */
4
+ index: number;
5
+ /** Offset from the top of the scroll content in pixels (use for `translateY` / `top`). */
6
+ start: number;
7
+ /** Row height in pixels. */
8
+ size: number;
9
+ };
10
+ export type UseVirtualListParams = {
11
+ /** Total number of rows in the list. */
12
+ itemCount: number;
13
+ /** Fixed height of every row in pixels (must be > 0). */
14
+ itemHeight: number;
15
+ /** Extra rows rendered above and below the viewport (default `3`). */
16
+ overscan?: number;
17
+ };
18
+ export type UseVirtualListResult = {
19
+ /** Callback ref for the scrollable container (needs `overflow-y: auto` and a bounded height). */
20
+ setContainerRef: RefCallback<HTMLElement>;
21
+ /** The rows to render, each with its absolute `start` offset. */
22
+ virtualItems: VirtualItem[];
23
+ /** Height of the full list content; set it on an inner spacer element. */
24
+ totalHeight: number;
25
+ /** First rendered index (after overscan). */
26
+ startIndex: number;
27
+ /** Last rendered index (after overscan), `-1` when empty. */
28
+ endIndex: number;
29
+ /** Scroll the container so the given row is at the top. */
30
+ scrollToIndex: (index: number) => void;
31
+ };
32
+ /**
33
+ * Headless fixed-height list virtualization: renders only the rows visible in the
34
+ * scroll container (plus `overscan`), so lists of tens of thousands of rows stay cheap.
35
+ *
36
+ * Markup recipe: outer container gets `setContainerRef` + `overflow-y: auto` and a height;
37
+ * inside it, one relative spacer div with `height: totalHeight`; each virtual item is
38
+ * absolutely positioned at `translateY(item.start)` with `height: item.size`.
39
+ *
40
+ * Viewport size tracks `ResizeObserver` (when available) and scroll position tracks a
41
+ * passive `scroll` listener. For variable-height rows, reach for a dedicated virtualizer.
42
+ *
43
+ * @param params - {@link UseVirtualListParams}
44
+ * @returns {@link UseVirtualListResult}
45
+ */
46
+ export declare function useVirtualList({ itemCount, itemHeight, overscan, }: UseVirtualListParams): UseVirtualListResult;
47
+ //# sourceMappingURL=useVirtualList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVirtualList.d.ts","sourceRoot":"","sources":["../../../src/hooks/useVirtualList/useVirtualList.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAGzC,MAAM,MAAM,WAAW,GAAG;IACxB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,iGAAiG;IACjG,eAAe,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAC1C,iEAAiE;IACjE,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,UAAU,EACV,QAAY,GACb,EAAE,oBAAoB,GAAG,oBAAoB,CAuF7C"}
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ require('../chunk-PZ5AY32C.js');
5
+ var react = require('react');
6
+
7
+ function useVirtualList({
8
+ itemCount,
9
+ itemHeight,
10
+ overscan = 3
11
+ }) {
12
+ const [container, setContainer] = react.useState(null);
13
+ const [scrollTop, setScrollTop] = react.useState(0);
14
+ const [viewportHeight, setViewportHeight] = react.useState(0);
15
+ const setContainerRef = react.useCallback((node) => {
16
+ setContainer(node);
17
+ }, []);
18
+ react.useEffect(() => {
19
+ if (container == null) {
20
+ return;
21
+ }
22
+ const onScroll = () => {
23
+ setScrollTop(container.scrollTop);
24
+ };
25
+ const measure = () => {
26
+ setViewportHeight(container.clientHeight);
27
+ };
28
+ measure();
29
+ onScroll();
30
+ container.addEventListener("scroll", onScroll, { passive: true });
31
+ let observer;
32
+ if (typeof ResizeObserver !== "undefined") {
33
+ observer = new ResizeObserver(measure);
34
+ observer.observe(container);
35
+ }
36
+ return () => {
37
+ container.removeEventListener("scroll", onScroll);
38
+ observer?.disconnect();
39
+ };
40
+ }, [container]);
41
+ const safeItemCount = Math.max(0, Math.floor(itemCount));
42
+ const safeItemHeight = Math.max(1, itemHeight);
43
+ const safeOverscan = Math.max(0, Math.floor(overscan));
44
+ const totalHeight = safeItemCount * safeItemHeight;
45
+ const startIndex = safeItemCount === 0 ? 0 : Math.max(
46
+ 0,
47
+ Math.floor(scrollTop / safeItemHeight) - safeOverscan
48
+ );
49
+ const endIndex = safeItemCount === 0 ? -1 : Math.min(
50
+ safeItemCount - 1,
51
+ Math.ceil((scrollTop + viewportHeight) / safeItemHeight) - 1 + safeOverscan
52
+ );
53
+ const virtualItems = react.useMemo(() => {
54
+ const items = [];
55
+ for (let index = startIndex; index <= endIndex; index += 1) {
56
+ items.push({
57
+ index,
58
+ start: index * safeItemHeight,
59
+ size: safeItemHeight
60
+ });
61
+ }
62
+ return items;
63
+ }, [endIndex, safeItemHeight, startIndex]);
64
+ const scrollToIndex = react.useCallback(
65
+ (index) => {
66
+ if (container == null || safeItemCount === 0) {
67
+ return;
68
+ }
69
+ const clamped = Math.min(Math.max(index, 0), safeItemCount - 1);
70
+ container.scrollTop = clamped * safeItemHeight;
71
+ setScrollTop(container.scrollTop);
72
+ },
73
+ [container, safeItemCount, safeItemHeight]
74
+ );
75
+ return {
76
+ setContainerRef,
77
+ virtualItems,
78
+ totalHeight,
79
+ startIndex,
80
+ endIndex,
81
+ scrollToIndex
82
+ };
83
+ }
84
+
85
+ exports.useVirtualList = useVirtualList;
86
+ //# sourceMappingURL=useVirtualList.js.map
87
+ //# sourceMappingURL=useVirtualList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useVirtualList/useVirtualList.ts"],"names":["useState","useCallback","useEffect","useMemo"],"mappings":"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","file":"useVirtualList.js","sourcesContent":["\"use client\";\n\nimport type { RefCallback } from \"react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\nexport type VirtualItem = {\n /** Index into your data array. */\n index: number;\n /** Offset from the top of the scroll content in pixels (use for `translateY` / `top`). */\n start: number;\n /** Row height in pixels. */\n size: number;\n};\n\nexport type UseVirtualListParams = {\n /** Total number of rows in the list. */\n itemCount: number;\n /** Fixed height of every row in pixels (must be > 0). */\n itemHeight: number;\n /** Extra rows rendered above and below the viewport (default `3`). */\n overscan?: number;\n};\n\nexport type UseVirtualListResult = {\n /** Callback ref for the scrollable container (needs `overflow-y: auto` and a bounded height). */\n setContainerRef: RefCallback<HTMLElement>;\n /** The rows to render, each with its absolute `start` offset. */\n virtualItems: VirtualItem[];\n /** Height of the full list content; set it on an inner spacer element. */\n totalHeight: number;\n /** First rendered index (after overscan). */\n startIndex: number;\n /** Last rendered index (after overscan), `-1` when empty. */\n endIndex: number;\n /** Scroll the container so the given row is at the top. */\n scrollToIndex: (index: number) => void;\n};\n\n/**\n * Headless fixed-height list virtualization: renders only the rows visible in the\n * scroll container (plus `overscan`), so lists of tens of thousands of rows stay cheap.\n *\n * Markup recipe: outer container gets `setContainerRef` + `overflow-y: auto` and a height;\n * inside it, one relative spacer div with `height: totalHeight`; each virtual item is\n * absolutely positioned at `translateY(item.start)` with `height: item.size`.\n *\n * Viewport size tracks `ResizeObserver` (when available) and scroll position tracks a\n * passive `scroll` listener. For variable-height rows, reach for a dedicated virtualizer.\n *\n * @param params - {@link UseVirtualListParams}\n * @returns {@link UseVirtualListResult}\n */\nexport function useVirtualList({\n itemCount,\n itemHeight,\n overscan = 3,\n}: UseVirtualListParams): UseVirtualListResult {\n const [container, setContainer] = useState<HTMLElement | null>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [viewportHeight, setViewportHeight] = useState(0);\n\n const setContainerRef = useCallback((node: HTMLElement | null) => {\n setContainer(node);\n }, []);\n\n useEffect(() => {\n if (container == null) {\n return;\n }\n const onScroll = () => {\n setScrollTop(container.scrollTop);\n };\n const measure = () => {\n setViewportHeight(container.clientHeight);\n };\n measure();\n onScroll();\n container.addEventListener(\"scroll\", onScroll, { passive: true });\n let observer: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(measure);\n observer.observe(container);\n }\n return () => {\n container.removeEventListener(\"scroll\", onScroll);\n observer?.disconnect();\n };\n }, [container]);\n\n const safeItemCount = Math.max(0, Math.floor(itemCount));\n const safeItemHeight = Math.max(1, itemHeight);\n const safeOverscan = Math.max(0, Math.floor(overscan));\n\n const totalHeight = safeItemCount * safeItemHeight;\n const startIndex =\n safeItemCount === 0\n ? 0\n : Math.max(\n 0,\n Math.floor(scrollTop / safeItemHeight) - safeOverscan,\n );\n const endIndex =\n safeItemCount === 0\n ? -1\n : Math.min(\n safeItemCount - 1,\n Math.ceil((scrollTop + viewportHeight) / safeItemHeight) -\n 1 +\n safeOverscan,\n );\n\n const virtualItems = useMemo(() => {\n const items: VirtualItem[] = [];\n for (let index = startIndex; index <= endIndex; index += 1) {\n items.push({\n index,\n start: index * safeItemHeight,\n size: safeItemHeight,\n });\n }\n return items;\n }, [endIndex, safeItemHeight, startIndex]);\n\n const scrollToIndex = useCallback(\n (index: number) => {\n if (container == null || safeItemCount === 0) {\n return;\n }\n const clamped = Math.min(Math.max(index, 0), safeItemCount - 1);\n container.scrollTop = clamped * safeItemHeight;\n setScrollTop(container.scrollTop);\n },\n [container, safeItemCount, safeItemHeight],\n );\n\n return {\n setContainerRef,\n virtualItems,\n totalHeight,\n startIndex,\n endIndex,\n scrollToIndex,\n };\n}\n"]}
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ import '../chunk-J5LGTIGS.mjs';
3
+ import { useState, useCallback, useEffect, useMemo } from 'react';
4
+
5
+ function useVirtualList({
6
+ itemCount,
7
+ itemHeight,
8
+ overscan = 3
9
+ }) {
10
+ const [container, setContainer] = useState(null);
11
+ const [scrollTop, setScrollTop] = useState(0);
12
+ const [viewportHeight, setViewportHeight] = useState(0);
13
+ const setContainerRef = useCallback((node) => {
14
+ setContainer(node);
15
+ }, []);
16
+ useEffect(() => {
17
+ if (container == null) {
18
+ return;
19
+ }
20
+ const onScroll = () => {
21
+ setScrollTop(container.scrollTop);
22
+ };
23
+ const measure = () => {
24
+ setViewportHeight(container.clientHeight);
25
+ };
26
+ measure();
27
+ onScroll();
28
+ container.addEventListener("scroll", onScroll, { passive: true });
29
+ let observer;
30
+ if (typeof ResizeObserver !== "undefined") {
31
+ observer = new ResizeObserver(measure);
32
+ observer.observe(container);
33
+ }
34
+ return () => {
35
+ container.removeEventListener("scroll", onScroll);
36
+ observer?.disconnect();
37
+ };
38
+ }, [container]);
39
+ const safeItemCount = Math.max(0, Math.floor(itemCount));
40
+ const safeItemHeight = Math.max(1, itemHeight);
41
+ const safeOverscan = Math.max(0, Math.floor(overscan));
42
+ const totalHeight = safeItemCount * safeItemHeight;
43
+ const startIndex = safeItemCount === 0 ? 0 : Math.max(
44
+ 0,
45
+ Math.floor(scrollTop / safeItemHeight) - safeOverscan
46
+ );
47
+ const endIndex = safeItemCount === 0 ? -1 : Math.min(
48
+ safeItemCount - 1,
49
+ Math.ceil((scrollTop + viewportHeight) / safeItemHeight) - 1 + safeOverscan
50
+ );
51
+ const virtualItems = useMemo(() => {
52
+ const items = [];
53
+ for (let index = startIndex; index <= endIndex; index += 1) {
54
+ items.push({
55
+ index,
56
+ start: index * safeItemHeight,
57
+ size: safeItemHeight
58
+ });
59
+ }
60
+ return items;
61
+ }, [endIndex, safeItemHeight, startIndex]);
62
+ const scrollToIndex = useCallback(
63
+ (index) => {
64
+ if (container == null || safeItemCount === 0) {
65
+ return;
66
+ }
67
+ const clamped = Math.min(Math.max(index, 0), safeItemCount - 1);
68
+ container.scrollTop = clamped * safeItemHeight;
69
+ setScrollTop(container.scrollTop);
70
+ },
71
+ [container, safeItemCount, safeItemHeight]
72
+ );
73
+ return {
74
+ setContainerRef,
75
+ virtualItems,
76
+ totalHeight,
77
+ startIndex,
78
+ endIndex,
79
+ scrollToIndex
80
+ };
81
+ }
82
+
83
+ export { useVirtualList };
84
+ //# sourceMappingURL=useVirtualList.mjs.map
85
+ //# sourceMappingURL=useVirtualList.mjs.map