@tanstack/preact-pacer 0.22.1 → 0.24.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 (243) hide show
  1. package/README.md +17 -2
  2. package/dist/async-batcher/useAsyncBatchedCallback.d.ts +2 -5
  3. package/dist/async-batcher/useAsyncBatchedCallback.js +1 -2
  4. package/dist/async-batcher/useAsyncBatcher.d.ts +4 -8
  5. package/dist/async-batcher/useAsyncBatcher.js +1 -3
  6. package/dist/async-debouncer/useAsyncDebouncedCallback.d.ts +6 -7
  7. package/dist/async-debouncer/useAsyncDebouncedCallback.js +5 -4
  8. package/dist/async-debouncer/useAsyncDebouncer.d.ts +4 -7
  9. package/dist/async-debouncer/useAsyncDebouncer.js +1 -2
  10. package/dist/async-queuer/useAsyncQueuedState.d.ts +4 -7
  11. package/dist/async-queuer/useAsyncQueuedState.js +3 -4
  12. package/dist/async-queuer/useAsyncQueuer.d.ts +6 -9
  13. package/dist/async-queuer/useAsyncQueuer.js +3 -4
  14. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.d.ts +2 -5
  15. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.js +1 -2
  16. package/dist/async-rate-limiter/useAsyncRateLimiter.d.ts +4 -7
  17. package/dist/async-rate-limiter/useAsyncRateLimiter.js +1 -2
  18. package/dist/async-throttler/useAsyncThrottledCallback.d.ts +7 -9
  19. package/dist/async-throttler/useAsyncThrottledCallback.js +6 -6
  20. package/dist/async-throttler/useAsyncThrottler.d.ts +4 -7
  21. package/dist/async-throttler/useAsyncThrottler.js +1 -2
  22. package/dist/batcher/useBatchedCallback.d.ts +2 -5
  23. package/dist/batcher/useBatchedCallback.js +1 -2
  24. package/dist/batcher/useBatcher.d.ts +6 -11
  25. package/dist/batcher/useBatcher.js +3 -6
  26. package/dist/debouncer/useDebouncedCallback.d.ts +2 -5
  27. package/dist/debouncer/useDebouncedCallback.js +1 -2
  28. package/dist/debouncer/useDebouncedState.d.ts +2 -5
  29. package/dist/debouncer/useDebouncedState.js +1 -2
  30. package/dist/debouncer/useDebouncedValue.d.ts +2 -5
  31. package/dist/debouncer/useDebouncedValue.js +1 -2
  32. package/dist/debouncer/useDebouncer.d.ts +4 -7
  33. package/dist/debouncer/useDebouncer.js +1 -2
  34. package/dist/provider/PacerProvider.d.ts +6 -13
  35. package/dist/provider/PacerProvider.js +1 -2
  36. package/dist/queuer/useQueuedState.d.ts +2 -5
  37. package/dist/queuer/useQueuedState.js +1 -2
  38. package/dist/queuer/useQueuedValue.d.ts +2 -5
  39. package/dist/queuer/useQueuedValue.js +1 -2
  40. package/dist/queuer/useQueuer.d.ts +4 -7
  41. package/dist/queuer/useQueuer.js +1 -2
  42. package/dist/rate-limiter/useRateLimitedCallback.d.ts +2 -5
  43. package/dist/rate-limiter/useRateLimitedCallback.js +1 -2
  44. package/dist/rate-limiter/useRateLimitedState.d.ts +2 -5
  45. package/dist/rate-limiter/useRateLimitedState.js +1 -2
  46. package/dist/rate-limiter/useRateLimitedValue.d.ts +2 -5
  47. package/dist/rate-limiter/useRateLimitedValue.js +1 -2
  48. package/dist/rate-limiter/useRateLimiter.d.ts +4 -7
  49. package/dist/rate-limiter/useRateLimiter.js +1 -2
  50. package/dist/throttler/useThrottledCallback.d.ts +2 -5
  51. package/dist/throttler/useThrottledCallback.js +1 -2
  52. package/dist/throttler/useThrottledState.d.ts +2 -5
  53. package/dist/throttler/useThrottledState.js +1 -2
  54. package/dist/throttler/useThrottledValue.d.ts +2 -5
  55. package/dist/throttler/useThrottledValue.js +1 -2
  56. package/dist/throttler/useThrottler.d.ts +4 -7
  57. package/dist/throttler/useThrottler.js +1 -2
  58. package/package.json +24 -72
  59. package/dist/async-batcher/index.cjs +0 -13
  60. package/dist/async-batcher/index.d.cts +0 -4
  61. package/dist/async-batcher/useAsyncBatchedCallback.cjs +0 -51
  62. package/dist/async-batcher/useAsyncBatchedCallback.cjs.map +0 -1
  63. package/dist/async-batcher/useAsyncBatchedCallback.d.cts +0 -44
  64. package/dist/async-batcher/useAsyncBatchedCallback.js.map +0 -1
  65. package/dist/async-batcher/useAsyncBatcher.cjs +0 -217
  66. package/dist/async-batcher/useAsyncBatcher.cjs.map +0 -1
  67. package/dist/async-batcher/useAsyncBatcher.d.cts +0 -224
  68. package/dist/async-batcher/useAsyncBatcher.js.map +0 -1
  69. package/dist/async-debouncer/index.cjs +0 -13
  70. package/dist/async-debouncer/index.d.cts +0 -4
  71. package/dist/async-debouncer/useAsyncDebouncedCallback.cjs +0 -50
  72. package/dist/async-debouncer/useAsyncDebouncedCallback.cjs.map +0 -1
  73. package/dist/async-debouncer/useAsyncDebouncedCallback.d.cts +0 -46
  74. package/dist/async-debouncer/useAsyncDebouncedCallback.js.map +0 -1
  75. package/dist/async-debouncer/useAsyncDebouncer.cjs +0 -195
  76. package/dist/async-debouncer/useAsyncDebouncer.cjs.map +0 -1
  77. package/dist/async-debouncer/useAsyncDebouncer.d.cts +0 -203
  78. package/dist/async-debouncer/useAsyncDebouncer.js.map +0 -1
  79. package/dist/async-queuer/index.cjs +0 -13
  80. package/dist/async-queuer/index.d.cts +0 -4
  81. package/dist/async-queuer/useAsyncQueuedState.cjs +0 -154
  82. package/dist/async-queuer/useAsyncQueuedState.cjs.map +0 -1
  83. package/dist/async-queuer/useAsyncQueuedState.d.cts +0 -151
  84. package/dist/async-queuer/useAsyncQueuedState.js.map +0 -1
  85. package/dist/async-queuer/useAsyncQueuer.cjs +0 -217
  86. package/dist/async-queuer/useAsyncQueuer.cjs.map +0 -1
  87. package/dist/async-queuer/useAsyncQueuer.d.cts +0 -224
  88. package/dist/async-queuer/useAsyncQueuer.js.map +0 -1
  89. package/dist/async-rate-limiter/index.cjs +0 -13
  90. package/dist/async-rate-limiter/index.d.cts +0 -4
  91. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.cjs +0 -65
  92. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.cjs.map +0 -1
  93. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.d.cts +0 -61
  94. package/dist/async-rate-limiter/useAsyncRateLimitedCallback.js.map +0 -1
  95. package/dist/async-rate-limiter/useAsyncRateLimiter.cjs +0 -209
  96. package/dist/async-rate-limiter/useAsyncRateLimiter.cjs.map +0 -1
  97. package/dist/async-rate-limiter/useAsyncRateLimiter.d.cts +0 -220
  98. package/dist/async-rate-limiter/useAsyncRateLimiter.js.map +0 -1
  99. package/dist/async-retryer/index.cjs +0 -9
  100. package/dist/async-retryer/index.d.cts +0 -1
  101. package/dist/async-throttler/index.cjs +0 -13
  102. package/dist/async-throttler/index.d.cts +0 -4
  103. package/dist/async-throttler/useAsyncThrottledCallback.cjs +0 -48
  104. package/dist/async-throttler/useAsyncThrottledCallback.cjs.map +0 -1
  105. package/dist/async-throttler/useAsyncThrottledCallback.d.cts +0 -44
  106. package/dist/async-throttler/useAsyncThrottledCallback.js.map +0 -1
  107. package/dist/async-throttler/useAsyncThrottler.cjs +0 -206
  108. package/dist/async-throttler/useAsyncThrottler.cjs.map +0 -1
  109. package/dist/async-throttler/useAsyncThrottler.d.cts +0 -214
  110. package/dist/async-throttler/useAsyncThrottler.js.map +0 -1
  111. package/dist/batcher/index.cjs +0 -13
  112. package/dist/batcher/index.d.cts +0 -4
  113. package/dist/batcher/useBatchedCallback.cjs +0 -47
  114. package/dist/batcher/useBatchedCallback.cjs.map +0 -1
  115. package/dist/batcher/useBatchedCallback.d.cts +0 -42
  116. package/dist/batcher/useBatchedCallback.js.map +0 -1
  117. package/dist/batcher/useBatcher.cjs +0 -165
  118. package/dist/batcher/useBatcher.cjs.map +0 -1
  119. package/dist/batcher/useBatcher.d.cts +0 -175
  120. package/dist/batcher/useBatcher.js.map +0 -1
  121. package/dist/debouncer/index.cjs +0 -17
  122. package/dist/debouncer/index.d.cts +0 -6
  123. package/dist/debouncer/useDebouncedCallback.cjs +0 -48
  124. package/dist/debouncer/useDebouncedCallback.cjs.map +0 -1
  125. package/dist/debouncer/useDebouncedCallback.d.cts +0 -44
  126. package/dist/debouncer/useDebouncedCallback.js.map +0 -1
  127. package/dist/debouncer/useDebouncedState.cjs +0 -89
  128. package/dist/debouncer/useDebouncedState.cjs.map +0 -1
  129. package/dist/debouncer/useDebouncedState.d.cts +0 -81
  130. package/dist/debouncer/useDebouncedState.js.map +0 -1
  131. package/dist/debouncer/useDebouncedValue.cjs +0 -96
  132. package/dist/debouncer/useDebouncedValue.cjs.map +0 -1
  133. package/dist/debouncer/useDebouncedValue.d.cts +0 -90
  134. package/dist/debouncer/useDebouncedValue.js.map +0 -1
  135. package/dist/debouncer/useDebouncer.cjs +0 -141
  136. package/dist/debouncer/useDebouncer.cjs.map +0 -1
  137. package/dist/debouncer/useDebouncer.d.cts +0 -152
  138. package/dist/debouncer/useDebouncer.js.map +0 -1
  139. package/dist/index.cjs +0 -67
  140. package/dist/index.d.cts +0 -30
  141. package/dist/provider/PacerProvider.cjs +0 -26
  142. package/dist/provider/PacerProvider.cjs.map +0 -1
  143. package/dist/provider/PacerProvider.d.cts +0 -33
  144. package/dist/provider/PacerProvider.js.map +0 -1
  145. package/dist/provider/index.cjs +0 -6
  146. package/dist/provider/index.d.cts +0 -2
  147. package/dist/queuer/index.cjs +0 -15
  148. package/dist/queuer/index.d.cts +0 -5
  149. package/dist/queuer/useQueuedState.cjs +0 -129
  150. package/dist/queuer/useQueuedState.cjs.map +0 -1
  151. package/dist/queuer/useQueuedState.d.cts +0 -122
  152. package/dist/queuer/useQueuedState.js.map +0 -1
  153. package/dist/queuer/useQueuedValue.cjs +0 -115
  154. package/dist/queuer/useQueuedValue.cjs.map +0 -1
  155. package/dist/queuer/useQueuedValue.d.cts +0 -105
  156. package/dist/queuer/useQueuedValue.js.map +0 -1
  157. package/dist/queuer/useQueuer.cjs +0 -176
  158. package/dist/queuer/useQueuer.cjs.map +0 -1
  159. package/dist/queuer/useQueuer.d.cts +0 -186
  160. package/dist/queuer/useQueuer.js.map +0 -1
  161. package/dist/rate-limiter/index.cjs +0 -17
  162. package/dist/rate-limiter/index.d.cts +0 -6
  163. package/dist/rate-limiter/useRateLimitedCallback.cjs +0 -65
  164. package/dist/rate-limiter/useRateLimitedCallback.cjs.map +0 -1
  165. package/dist/rate-limiter/useRateLimitedCallback.d.cts +0 -61
  166. package/dist/rate-limiter/useRateLimitedCallback.js.map +0 -1
  167. package/dist/rate-limiter/useRateLimitedState.cjs +0 -115
  168. package/dist/rate-limiter/useRateLimitedState.cjs.map +0 -1
  169. package/dist/rate-limiter/useRateLimitedState.d.cts +0 -107
  170. package/dist/rate-limiter/useRateLimitedState.js.map +0 -1
  171. package/dist/rate-limiter/useRateLimitedValue.cjs +0 -102
  172. package/dist/rate-limiter/useRateLimitedValue.cjs.map +0 -1
  173. package/dist/rate-limiter/useRateLimitedValue.d.cts +0 -96
  174. package/dist/rate-limiter/useRateLimitedValue.js.map +0 -1
  175. package/dist/rate-limiter/useRateLimiter.cjs +0 -167
  176. package/dist/rate-limiter/useRateLimiter.cjs.map +0 -1
  177. package/dist/rate-limiter/useRateLimiter.d.cts +0 -179
  178. package/dist/rate-limiter/useRateLimiter.js.map +0 -1
  179. package/dist/throttler/index.cjs +0 -17
  180. package/dist/throttler/index.d.cts +0 -6
  181. package/dist/throttler/useThrottledCallback.cjs +0 -49
  182. package/dist/throttler/useThrottledCallback.cjs.map +0 -1
  183. package/dist/throttler/useThrottledCallback.d.cts +0 -45
  184. package/dist/throttler/useThrottledCallback.js.map +0 -1
  185. package/dist/throttler/useThrottledState.cjs +0 -100
  186. package/dist/throttler/useThrottledState.cjs.map +0 -1
  187. package/dist/throttler/useThrottledState.d.cts +0 -92
  188. package/dist/throttler/useThrottledState.js.map +0 -1
  189. package/dist/throttler/useThrottledValue.cjs +0 -91
  190. package/dist/throttler/useThrottledValue.cjs.map +0 -1
  191. package/dist/throttler/useThrottledValue.d.cts +0 -85
  192. package/dist/throttler/useThrottledValue.js.map +0 -1
  193. package/dist/throttler/useThrottler.cjs +0 -146
  194. package/dist/throttler/useThrottler.cjs.map +0 -1
  195. package/dist/throttler/useThrottler.d.cts +0 -157
  196. package/dist/throttler/useThrottler.js.map +0 -1
  197. package/dist/types/index.cjs +0 -9
  198. package/dist/types/index.d.cts +0 -1
  199. package/dist/utils/index.cjs +0 -9
  200. package/dist/utils/index.d.cts +0 -1
  201. package/src/async-batcher/index.ts +0 -4
  202. package/src/async-batcher/useAsyncBatchedCallback.ts +0 -53
  203. package/src/async-batcher/useAsyncBatcher.ts +0 -293
  204. package/src/async-debouncer/index.ts +0 -5
  205. package/src/async-debouncer/useAsyncDebouncedCallback.ts +0 -54
  206. package/src/async-debouncer/useAsyncDebouncer.ts +0 -274
  207. package/src/async-queuer/index.ts +0 -4
  208. package/src/async-queuer/useAsyncQueuedState.ts +0 -165
  209. package/src/async-queuer/useAsyncQueuer.ts +0 -293
  210. package/src/async-rate-limiter/index.ts +0 -5
  211. package/src/async-rate-limiter/useAsyncRateLimitedCallback.ts +0 -69
  212. package/src/async-rate-limiter/useAsyncRateLimiter.ts +0 -294
  213. package/src/async-retryer/index.ts +0 -2
  214. package/src/async-throttler/index.ts +0 -5
  215. package/src/async-throttler/useAsyncThrottledCallback.ts +0 -52
  216. package/src/async-throttler/useAsyncThrottler.ts +0 -285
  217. package/src/batcher/index.ts +0 -4
  218. package/src/batcher/useBatchedCallback.ts +0 -46
  219. package/src/batcher/useBatcher.ts +0 -241
  220. package/src/debouncer/index.ts +0 -7
  221. package/src/debouncer/useDebouncedCallback.ts +0 -51
  222. package/src/debouncer/useDebouncedState.ts +0 -106
  223. package/src/debouncer/useDebouncedValue.ts +0 -109
  224. package/src/debouncer/useDebouncer.ts +0 -219
  225. package/src/index.ts +0 -56
  226. package/src/provider/PacerProvider.tsx +0 -70
  227. package/src/provider/index.ts +0 -1
  228. package/src/queuer/index.ts +0 -5
  229. package/src/queuer/useQueuedState.ts +0 -133
  230. package/src/queuer/useQueuedValue.ts +0 -129
  231. package/src/queuer/useQueuer.ts +0 -251
  232. package/src/rate-limiter/index.ts +0 -6
  233. package/src/rate-limiter/useRateLimitedCallback.ts +0 -68
  234. package/src/rate-limiter/useRateLimitedState.ts +0 -124
  235. package/src/rate-limiter/useRateLimitedValue.ts +0 -110
  236. package/src/rate-limiter/useRateLimiter.ts +0 -244
  237. package/src/throttler/index.ts +0 -7
  238. package/src/throttler/useThrottledCallback.ts +0 -52
  239. package/src/throttler/useThrottledState.ts +0 -118
  240. package/src/throttler/useThrottledValue.ts +0 -104
  241. package/src/throttler/useThrottler.ts +0 -224
  242. package/src/types/index.ts +0 -1
  243. package/src/utils/index.ts +0 -1
@@ -1,241 +0,0 @@
1
- import { useEffect, useMemo, useState } from 'preact/hooks'
2
- import { Batcher } from '@tanstack/pacer/batcher'
3
- import { shallow, useSelector } from '@tanstack/preact-store'
4
- import { useDefaultPacerOptions } from '../provider/PacerProvider'
5
- import type { Store } from '@tanstack/preact-store'
6
- import type { BatcherOptions, BatcherState } from '@tanstack/pacer/batcher'
7
- import type { ComponentChildren } from 'preact'
8
-
9
- export interface PreactBatcherOptions<
10
- TValue,
11
- TSelected = {},
12
- > extends BatcherOptions<TValue> {
13
- /**
14
- * Optional callback invoked when the component unmounts. Receives the batcher instance.
15
- * When provided, replaces the default cleanup (cancel); use it to call flush(), reset(), cancel(), add logging, etc.
16
- */
17
- onUnmount?: (batcher: PreactBatcher<TValue, TSelected>) => void
18
- }
19
-
20
- export interface PreactBatcher<TValue, TSelected = {}> extends Omit<
21
- Batcher<TValue>,
22
- 'store'
23
- > {
24
- /**
25
- * A Preact HOC (Higher Order Component) that allows you to subscribe to the batcher state.
26
- *
27
- * This is useful for opting into state re-renders for specific parts of the batcher state
28
- * deep in your component tree without needing to pass a selector to the hook.
29
- *
30
- * @example
31
- * <batcher.Subscribe selector={(state) => ({ size: state.size })}>
32
- * {({ size }) => (
33
- * <div>Batch Size: {size}</div>
34
- * )}
35
- * </batcher.Subscribe>
36
- */
37
- Subscribe: <TSelected>(props: {
38
- selector: (state: BatcherState<TValue>) => TSelected
39
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren
40
- }) => ComponentChildren
41
- /**
42
- * Reactive state that will be updated and re-rendered when the batcher state changes
43
- *
44
- * Use this instead of `batcher.store.state`
45
- */
46
- readonly state: Readonly<TSelected>
47
- /**
48
- * @deprecated Use `batcher.state` instead of `batcher.store.state` if you want to read reactive state.
49
- * The state on the store object is not reactive, as it has not been wrapped in a `useSelector` hook internally.
50
- * Although, you can make the state reactive by using the `useSelector` in your own usage.
51
- */
52
- readonly store: Store<Readonly<BatcherState<TValue>>>
53
- }
54
-
55
- /**
56
- * A Preact hook that creates and manages a Batcher instance.
57
- *
58
- * This is a lower-level hook that provides direct access to the Batcher's functionality without
59
- * any built-in state management. This allows you to integrate it with any state management solution
60
- * you prefer (useState, Redux, Zustand, etc.) by utilizing the onItemsChange callback.
61
- *
62
- * The Batcher collects items and processes them in batches based on configurable conditions:
63
- * - Maximum batch size
64
- * - Time-based batching (process after X milliseconds)
65
- * - Custom batch processing logic via getShouldExecute
66
- *
67
- * ## State Management and Selector
68
- *
69
- * The hook uses TanStack Store for reactive state management. You can subscribe to state changes
70
- * in two ways:
71
- *
72
- * **1. Using `batcher.Subscribe` HOC (Recommended for component tree subscriptions)**
73
- *
74
- * Use the `Subscribe` HOC to subscribe to state changes deep in your component tree without
75
- * needing to pass a selector to the hook. This is ideal when you want to subscribe to state
76
- * in child components.
77
- *
78
- * **2. Using the `selector` parameter (For hook-level subscriptions)**
79
- *
80
- * The `selector` parameter allows you to specify which state changes will trigger a re-render
81
- * at the hook level, optimizing performance by preventing unnecessary re-renders when irrelevant
82
- * state changes occur.
83
- *
84
- * **By default, there will be no reactive state subscriptions** and you must opt-in to state
85
- * tracking by providing a selector function or using the `Subscribe` HOC. This prevents unnecessary
86
- * re-renders and gives you full control over when your component updates.
87
- *
88
- * Available state properties:
89
- * - `executionCount`: Number of batch executions that have been completed
90
- * - `isEmpty`: Whether the batcher has no items to process
91
- * - `isPending`: Whether the batcher is waiting for the timeout to trigger batch processing
92
- * - `isRunning`: Whether the batcher is active and will process items automatically
93
- * - `items`: Array of items currently queued for batch processing
94
- * - `size`: Number of items currently in the batch queue
95
- * - `status`: Current processing status ('idle' | 'pending')
96
- * - `totalItemsProcessed`: Total number of items processed across all batches
97
- *
98
- * ## Unmount behavior
99
- *
100
- * By default, the hook cancels any pending batch when the component unmounts.
101
- * Use the `onUnmount` option to customize this. For example, to flush pending work instead:
102
- *
103
- * ```tsx
104
- * const batcher = useBatcher(fn, {
105
- * maxSize: 10,
106
- * wait: 2000,
107
- * onUnmount: (b) => b.flush()
108
- * });
109
- * ```
110
- *
111
- * @example
112
- * ```tsx
113
- * // Default behavior - no reactive state subscriptions
114
- * const batcher = useBatcher<number>(
115
- * (items) => console.log('Processing batch:', items),
116
- * { maxSize: 5, wait: 2000 }
117
- * );
118
- *
119
- * // Subscribe to state changes deep in component tree using Subscribe HOC
120
- * <batcher.Subscribe selector={(state) => ({ size: state.size })}>
121
- * {({ size }) => (
122
- * <div>Batch Size: {size}</div>
123
- * )}
124
- * </batcher.Subscribe>
125
- *
126
- * // Opt-in to re-render when batch size changes at hook level (optimized for displaying queue size)
127
- * const batcher = useBatcher<number>(
128
- * (items) => console.log('Processing batch:', items),
129
- * { maxSize: 5, wait: 2000 },
130
- * (state) => ({
131
- * size: state.size,
132
- * isEmpty: state.isEmpty
133
- * })
134
- * );
135
- *
136
- * // Opt-in to re-render when execution metrics change (optimized for stats display)
137
- * const batcher = useBatcher<number>(
138
- * (items) => console.log('Processing batch:', items),
139
- * { maxSize: 5, wait: 2000 },
140
- * (state) => ({
141
- * executionCount: state.executionCount,
142
- * totalItemsProcessed: state.totalItemsProcessed
143
- * })
144
- * );
145
- *
146
- * // Opt-in to re-render when processing state changes (optimized for loading indicators)
147
- * const batcher = useBatcher<number>(
148
- * (items) => console.log('Processing batch:', items),
149
- * { maxSize: 5, wait: 2000 },
150
- * (state) => ({
151
- * isPending: state.isPending,
152
- * isRunning: state.isRunning,
153
- * status: state.status
154
- * })
155
- * );
156
- *
157
- * // Example with custom state management and batching
158
- * const [items, setItems] = useState([]);
159
- *
160
- * const batcher = useBatcher<number>(
161
- * (items) => console.log('Processing batch:', items),
162
- * {
163
- * maxSize: 5,
164
- * wait: 2000,
165
- * onItemsChange: (batcher) => setItems(batcher.peekAllItems()),
166
- * getShouldExecute: (items) => items.length >= 3
167
- * }
168
- * );
169
- *
170
- * // Add items to batch - they'll be processed when conditions are met
171
- * batcher.addItem(1);
172
- * batcher.addItem(2);
173
- * batcher.addItem(3); // Triggers batch processing
174
- *
175
- * // Control the batcher
176
- * batcher.stop(); // Pause batching
177
- * batcher.start(); // Resume batching
178
- *
179
- * // Access the selected state (will be empty object {} unless selector provided)
180
- * const { size, isPending } = batcher.state;
181
- * ```
182
- */
183
- export function useBatcher<TValue, TSelected = {}>(
184
- fn: (items: Array<TValue>) => void,
185
- options: PreactBatcherOptions<TValue, TSelected> = {},
186
- selector: (state: BatcherState<TValue>) => TSelected = () =>
187
- ({}) as TSelected,
188
- ): PreactBatcher<TValue, TSelected> {
189
- const mergedOptions = {
190
- ...useDefaultPacerOptions().batcher,
191
- ...options,
192
- } as PreactBatcherOptions<TValue, TSelected>
193
-
194
- const [batcher] = useState(() => {
195
- const batcherInstance = new Batcher<TValue>(
196
- fn,
197
- mergedOptions,
198
- ) as unknown as PreactBatcher<TValue, TSelected>
199
-
200
- batcherInstance.Subscribe = function Subscribe<TSelected>(props: {
201
- selector: (state: BatcherState<TValue>) => TSelected
202
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren
203
- }) {
204
- const selected = useSelector(batcherInstance.store, props.selector, {
205
- compare: shallow,
206
- })
207
-
208
- return typeof props.children === 'function'
209
- ? props.children(selected)
210
- : props.children
211
- }
212
-
213
- return batcherInstance
214
- })
215
-
216
- batcher.fn = fn
217
- batcher.setOptions(mergedOptions)
218
-
219
- /* eslint-disable react-hooks/exhaustive-deps -- cleanup only; runs on unmount */
220
- useEffect(() => {
221
- return () => {
222
- if (mergedOptions.onUnmount) {
223
- mergedOptions.onUnmount(batcher)
224
- } else {
225
- batcher.cancel()
226
- }
227
- }
228
- }, [])
229
- /* eslint-enable react-hooks/exhaustive-deps */
230
-
231
- const state = useSelector(batcher.store, selector, { compare: shallow })
232
-
233
- return useMemo(
234
- () =>
235
- ({
236
- ...batcher,
237
- state,
238
- }) as PreactBatcher<TValue, TSelected>, // omit `store` in favor of `state`
239
- [batcher, state],
240
- )
241
- }
@@ -1,7 +0,0 @@
1
- // re-export everything from the core pacer package, BUT ONLY from the debouncer module
2
- export * from '@tanstack/pacer/debouncer'
3
-
4
- export * from './useDebouncedCallback'
5
- export * from './useDebouncedState'
6
- export * from './useDebouncedValue'
7
- export * from './useDebouncer'
@@ -1,51 +0,0 @@
1
- import { useCallback } from 'preact/hooks'
2
- import { useDebouncer } from './useDebouncer'
3
- import type { PreactDebouncerOptions } from './useDebouncer'
4
- import type { AnyFunction } from '@tanstack/pacer/types'
5
-
6
- /**
7
- * A Preact hook that creates a debounced version of a callback function.
8
- * This hook is essentially a wrapper around the basic `debounce` function
9
- * that is exported from `@tanstack/pacer`,
10
- * but optimized for Preact with reactive options and a stable function reference.
11
- *
12
- * The debounced function will only execute after the specified wait time has elapsed
13
- * since its last invocation. If called again before the wait time expires, the timer
14
- * resets and starts waiting again.
15
- *
16
- * This hook provides a simpler API compared to `useDebouncer`, making it ideal for basic
17
- * debouncing needs. However, it does not expose the underlying Debouncer instance.
18
- *
19
- * For advanced usage requiring features like:
20
- * - Manual cancellation
21
- * - Access to execution counts
22
- * - Custom useCallback dependencies
23
- *
24
- * Consider using the `useDebouncer` hook instead.
25
- *
26
- * @example
27
- * ```tsx
28
- * // Debounce a search handler
29
- * const handleSearch = useDebouncedCallback((query: string) => {
30
- * fetchSearchResults(query);
31
- * }, {
32
- * wait: 500 // Wait 500ms between executions
33
- * });
34
- *
35
- * // Use in an input
36
- * <input
37
- * type="search"
38
- * onChange={(e) => handleSearch(e.target.value)}
39
- * />
40
- * ```
41
- */
42
- export function useDebouncedCallback<TFn extends AnyFunction>(
43
- fn: TFn,
44
- options: PreactDebouncerOptions<TFn, {}>,
45
- ): (...args: Parameters<TFn>) => void {
46
- const debouncedFn = useDebouncer(fn, options).maybeExecute
47
- return useCallback(
48
- (...args: Parameters<TFn>) => debouncedFn(...args),
49
- [debouncedFn],
50
- )
51
- }
@@ -1,106 +0,0 @@
1
- import { useState } from 'preact/hooks'
2
- import { useDebouncer } from './useDebouncer'
3
- import type { PreactDebouncer, PreactDebouncerOptions } from './useDebouncer'
4
- import type { Dispatch, StateUpdater } from 'preact/hooks'
5
- import type { DebouncerState } from '@tanstack/pacer/debouncer'
6
-
7
- /**
8
- * A Preact hook that creates a debounced state value, combining Preact's useState with debouncing functionality.
9
- * This hook provides both the current debounced value and methods to update it.
10
- *
11
- * The state value is only updated after the specified wait time has elapsed since the last update attempt.
12
- * If another update is attempted before the wait time expires, the timer resets and starts waiting again.
13
- * This is useful for handling frequent state updates that should be throttled, like search input values
14
- * or window resize dimensions.
15
- *
16
- * The hook returns a tuple containing:
17
- * - The current debounced value
18
- * - A function to update the debounced value
19
- * - The debouncer instance with additional control methods
20
- *
21
- * ## State Management and Selector
22
- *
23
- * The hook uses TanStack Store for reactive state management via the underlying debouncer instance.
24
- * The `selector` parameter allows you to specify which debouncer state changes will trigger a re-render,
25
- * optimizing performance by preventing unnecessary re-renders when irrelevant state changes occur.
26
- *
27
- * **By default, there will be no reactive state subscriptions** and you must opt-in to state
28
- * tracking by providing a selector function. This prevents unnecessary re-renders and gives you
29
- * full control over when your component updates. Only when you provide a selector will the
30
- * component re-render when the selected state values change.
31
- *
32
- * Available debouncer state properties:
33
- * - `canLeadingExecute`: Whether the debouncer can execute on the leading edge
34
- * - `executionCount`: Number of function executions that have been completed
35
- * - `isPending`: Whether the debouncer is waiting for the timeout to trigger execution
36
- * - `lastArgs`: The arguments from the most recent call to maybeExecute
37
- * - `status`: Current execution status ('disabled' | 'idle' | 'pending')
38
- *
39
- * @example
40
- * ```tsx
41
- * // Default behavior - no reactive state subscriptions
42
- * const [searchTerm, setSearchTerm, debouncer] = useDebouncedState('', {
43
- * wait: 500 // Wait 500ms after last keystroke
44
- * });
45
- *
46
- * // Opt-in to re-render when pending state changes (optimized for loading indicators)
47
- * const [searchTerm, setSearchTerm, debouncer] = useDebouncedState(
48
- * '',
49
- * { wait: 500 },
50
- * (state) => ({ isPending: state.isPending })
51
- * );
52
- *
53
- * // Opt-in to re-render when execution count changes (optimized for tracking executions)
54
- * const [searchTerm, setSearchTerm, debouncer] = useDebouncedState(
55
- * '',
56
- * { wait: 500 },
57
- * (state) => ({ executionCount: state.executionCount })
58
- * );
59
- *
60
- * // Opt-in to re-render when debouncing status changes (optimized for status display)
61
- * const [searchTerm, setSearchTerm, debouncer] = useDebouncedState(
62
- * '',
63
- * { wait: 500 },
64
- * (state) => ({
65
- * status: state.status,
66
- * canLeadingExecute: state.canLeadingExecute
67
- * })
68
- * );
69
- *
70
- * // Update value - will be debounced
71
- * const handleChange = (e) => {
72
- * setSearchTerm(e.target.value);
73
- * };
74
- *
75
- * // Access the selected debouncer state (will be empty object {} unless selector provided)
76
- * const { isPending, executionCount } = debouncer.state;
77
- * ```
78
- */
79
- export function useDebouncedState<
80
- TValue,
81
- TSelected = DebouncerState<Dispatch<StateUpdater<TValue>>>,
82
- >(
83
- value: TValue,
84
- options: PreactDebouncerOptions<Dispatch<StateUpdater<TValue>>, TSelected>,
85
- selector?: (
86
- state: DebouncerState<Dispatch<StateUpdater<TValue>>>,
87
- ) => TSelected,
88
- ): [
89
- TValue,
90
- Dispatch<StateUpdater<TValue>>,
91
- PreactDebouncer<Dispatch<StateUpdater<TValue>>, TSelected>,
92
- ] {
93
- const [debouncedValue, setDebouncedValue] = useState(value)
94
- const debouncer = useDebouncer(
95
- setDebouncedValue,
96
- options,
97
- selector as (
98
- state: DebouncerState<Dispatch<StateUpdater<TValue>>>,
99
- ) => TSelected,
100
- )
101
- return [
102
- debouncedValue,
103
- debouncer.maybeExecute as Dispatch<StateUpdater<TValue>>,
104
- debouncer,
105
- ]
106
- }
@@ -1,109 +0,0 @@
1
- import { useEffect } from 'preact/hooks'
2
- import { useDebouncedState } from './useDebouncedState'
3
- import type { PreactDebouncer, PreactDebouncerOptions } from './useDebouncer'
4
- import type { Dispatch, StateUpdater } from 'preact/hooks'
5
- import type { DebouncerState } from '@tanstack/pacer/debouncer'
6
-
7
- /**
8
- * A Preact hook that creates a debounced value that updates only after a specified delay.
9
- * Unlike useDebouncedState, this hook automatically tracks changes to the input value
10
- * and updates the debounced value accordingly.
11
- *
12
- * The debounced value will only update after the specified wait time has elapsed since
13
- * the last change to the input value. If the input value changes again before the wait
14
- * time expires, the timer resets and starts waiting again.
15
- *
16
- * This is useful for deriving debounced values from props or state that change frequently,
17
- * like search queries or form inputs, where you want to limit how often downstream effects
18
- * or calculations occur.
19
- *
20
- * The hook returns the current debounced value and the underlying debouncer instance.
21
- * The debouncer instance can be used to access additional functionality like cancellation
22
- * and execution counts.
23
- *
24
- * ## State Management and Selector
25
- *
26
- * The hook uses TanStack Store for reactive state management via the underlying debouncer instance.
27
- * The `selector` parameter allows you to specify which debouncer state changes will trigger a re-render,
28
- * optimizing performance by preventing unnecessary re-renders when irrelevant state changes occur.
29
- *
30
- * **By default, there will be no reactive state subscriptions** and you must opt-in to state
31
- * tracking by providing a selector function. This prevents unnecessary re-renders and gives you
32
- * full control over when your component updates. Only when you provide a selector will the
33
- * component re-render when the selected state values change.
34
- *
35
- * Available debouncer state properties:
36
- * - `canLeadingExecute`: Whether the debouncer can execute on the leading edge
37
- * - `executionCount`: Number of function executions that have been completed
38
- * - `isPending`: Whether the debouncer is waiting for the timeout to trigger execution
39
- * - `lastArgs`: The arguments from the most recent call to maybeExecute
40
- * - `status`: Current execution status ('disabled' | 'idle' | 'pending')
41
- *
42
- * @example
43
- * ```tsx
44
- * // Default behavior - no reactive state subscriptions
45
- * const [searchQuery, setSearchQuery] = useState('');
46
- * const [debouncedQuery, debouncer] = useDebouncedValue(searchQuery, {
47
- * wait: 500 // Wait 500ms after last change
48
- * });
49
- *
50
- * // Opt-in to re-render when pending state changes (optimized for loading indicators)
51
- * const [debouncedQuery, debouncer] = useDebouncedValue(
52
- * searchQuery,
53
- * { wait: 500 },
54
- * (state) => ({ isPending: state.isPending })
55
- * );
56
- *
57
- * // Opt-in to re-render when execution count changes (optimized for tracking executions)
58
- * const [debouncedQuery, debouncer] = useDebouncedValue(
59
- * searchQuery,
60
- * { wait: 500 },
61
- * (state) => ({ executionCount: state.executionCount })
62
- * );
63
- *
64
- * // Opt-in to re-render when debouncing status changes (optimized for status display)
65
- * const [debouncedQuery, debouncer] = useDebouncedValue(
66
- * searchQuery,
67
- * { wait: 500 },
68
- * (state) => ({
69
- * status: state.status,
70
- * canLeadingExecute: state.canLeadingExecute
71
- * })
72
- * );
73
- *
74
- * // debouncedQuery will update 500ms after searchQuery stops changing
75
- * useEffect(() => {
76
- * fetchSearchResults(debouncedQuery);
77
- * }, [debouncedQuery]);
78
- *
79
- * // Handle input changes
80
- * const handleChange = (e) => {
81
- * setSearchQuery(e.target.value);
82
- * };
83
- *
84
- * // Access the selected debouncer state (will be empty object {} unless selector provided)
85
- * const { isPending, executionCount } = debouncer.state;
86
- * ```
87
- */
88
- export function useDebouncedValue<
89
- TValue,
90
- TSelected = DebouncerState<Dispatch<StateUpdater<TValue>>>,
91
- >(
92
- value: TValue,
93
- options: PreactDebouncerOptions<Dispatch<StateUpdater<TValue>>, TSelected>,
94
- selector?: (
95
- state: DebouncerState<Dispatch<StateUpdater<TValue>>>,
96
- ) => TSelected,
97
- ): [TValue, PreactDebouncer<Dispatch<StateUpdater<TValue>>, TSelected>] {
98
- const [debouncedValue, setDebouncedValue, debouncer] = useDebouncedState(
99
- value,
100
- options,
101
- selector,
102
- )
103
-
104
- useEffect(() => {
105
- ;(setDebouncedValue as (value: TValue) => void)(value)
106
- }, [value, setDebouncedValue])
107
-
108
- return [debouncedValue, debouncer]
109
- }