@tanstack/preact-pacer 0.18.0 → 0.19.1

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 (103) hide show
  1. package/dist/async-batcher/index.cjs +3 -3
  2. package/dist/async-batcher/index.d.cts +2 -2
  3. package/dist/async-batcher/index.d.ts +2 -2
  4. package/dist/async-batcher/useAsyncBatcher.cjs +35 -11
  5. package/dist/async-batcher/useAsyncBatcher.cjs.map +1 -1
  6. package/dist/async-batcher/useAsyncBatcher.d.cts +45 -10
  7. package/dist/async-batcher/useAsyncBatcher.d.ts +45 -10
  8. package/dist/async-batcher/useAsyncBatcher.js +32 -8
  9. package/dist/async-batcher/useAsyncBatcher.js.map +1 -1
  10. package/dist/async-debouncer/index.cjs +3 -3
  11. package/dist/async-debouncer/index.d.cts +2 -2
  12. package/dist/async-debouncer/index.d.ts +2 -2
  13. package/dist/async-debouncer/useAsyncDebouncer.cjs +35 -11
  14. package/dist/async-debouncer/useAsyncDebouncer.cjs.map +1 -1
  15. package/dist/async-debouncer/useAsyncDebouncer.d.cts +45 -10
  16. package/dist/async-debouncer/useAsyncDebouncer.d.ts +45 -10
  17. package/dist/async-debouncer/useAsyncDebouncer.js +32 -8
  18. package/dist/async-debouncer/useAsyncDebouncer.js.map +1 -1
  19. package/dist/async-queuer/index.cjs +3 -3
  20. package/dist/async-queuer/index.d.cts +2 -2
  21. package/dist/async-queuer/index.d.ts +2 -2
  22. package/dist/async-queuer/useAsyncQueuedState.cjs.map +1 -1
  23. package/dist/async-queuer/useAsyncQueuedState.d.cts +2 -2
  24. package/dist/async-queuer/useAsyncQueuedState.d.ts +2 -2
  25. package/dist/async-queuer/useAsyncQueuedState.js.map +1 -1
  26. package/dist/async-queuer/useAsyncQueuer.cjs +35 -11
  27. package/dist/async-queuer/useAsyncQueuer.cjs.map +1 -1
  28. package/dist/async-queuer/useAsyncQueuer.d.cts +45 -10
  29. package/dist/async-queuer/useAsyncQueuer.d.ts +45 -10
  30. package/dist/async-queuer/useAsyncQueuer.js +32 -8
  31. package/dist/async-queuer/useAsyncQueuer.js.map +1 -1
  32. package/dist/async-rate-limiter/index.cjs +3 -3
  33. package/dist/async-rate-limiter/index.d.cts +2 -2
  34. package/dist/async-rate-limiter/index.d.ts +2 -2
  35. package/dist/async-rate-limiter/useAsyncRateLimiter.cjs +35 -11
  36. package/dist/async-rate-limiter/useAsyncRateLimiter.cjs.map +1 -1
  37. package/dist/async-rate-limiter/useAsyncRateLimiter.d.cts +45 -10
  38. package/dist/async-rate-limiter/useAsyncRateLimiter.d.ts +45 -10
  39. package/dist/async-rate-limiter/useAsyncRateLimiter.js +32 -8
  40. package/dist/async-rate-limiter/useAsyncRateLimiter.js.map +1 -1
  41. package/dist/async-retryer/index.cjs +3 -3
  42. package/dist/async-throttler/index.cjs +3 -3
  43. package/dist/async-throttler/index.d.cts +2 -2
  44. package/dist/async-throttler/index.d.ts +2 -2
  45. package/dist/async-throttler/useAsyncThrottler.cjs +35 -11
  46. package/dist/async-throttler/useAsyncThrottler.cjs.map +1 -1
  47. package/dist/async-throttler/useAsyncThrottler.d.cts +45 -10
  48. package/dist/async-throttler/useAsyncThrottler.d.ts +45 -10
  49. package/dist/async-throttler/useAsyncThrottler.js +32 -8
  50. package/dist/async-throttler/useAsyncThrottler.js.map +1 -1
  51. package/dist/batcher/index.cjs +3 -3
  52. package/dist/batcher/useBatcher.cjs +35 -11
  53. package/dist/batcher/useBatcher.cjs.map +1 -1
  54. package/dist/batcher/useBatcher.d.cts +42 -7
  55. package/dist/batcher/useBatcher.d.ts +42 -7
  56. package/dist/batcher/useBatcher.js +32 -8
  57. package/dist/batcher/useBatcher.js.map +1 -1
  58. package/dist/debouncer/index.cjs +3 -3
  59. package/dist/debouncer/useDebouncer.cjs +35 -11
  60. package/dist/debouncer/useDebouncer.cjs.map +1 -1
  61. package/dist/debouncer/useDebouncer.d.cts +42 -7
  62. package/dist/debouncer/useDebouncer.d.ts +42 -7
  63. package/dist/debouncer/useDebouncer.js +32 -8
  64. package/dist/debouncer/useDebouncer.js.map +1 -1
  65. package/dist/index.cjs +3 -3
  66. package/dist/index.d.cts +6 -6
  67. package/dist/index.d.ts +6 -6
  68. package/dist/provider/PacerProvider.d.cts +1 -1
  69. package/dist/queuer/index.cjs +3 -3
  70. package/dist/queuer/useQueuer.cjs +35 -11
  71. package/dist/queuer/useQueuer.cjs.map +1 -1
  72. package/dist/queuer/useQueuer.d.cts +42 -7
  73. package/dist/queuer/useQueuer.d.ts +42 -7
  74. package/dist/queuer/useQueuer.js +32 -8
  75. package/dist/queuer/useQueuer.js.map +1 -1
  76. package/dist/rate-limiter/index.cjs +3 -3
  77. package/dist/rate-limiter/useRateLimiter.cjs +35 -11
  78. package/dist/rate-limiter/useRateLimiter.cjs.map +1 -1
  79. package/dist/rate-limiter/useRateLimiter.d.cts +42 -7
  80. package/dist/rate-limiter/useRateLimiter.d.ts +42 -7
  81. package/dist/rate-limiter/useRateLimiter.js +32 -8
  82. package/dist/rate-limiter/useRateLimiter.js.map +1 -1
  83. package/dist/throttler/index.cjs +3 -3
  84. package/dist/throttler/useThrottler.cjs +35 -11
  85. package/dist/throttler/useThrottler.cjs.map +1 -1
  86. package/dist/throttler/useThrottler.d.cts +42 -7
  87. package/dist/throttler/useThrottler.d.ts +42 -7
  88. package/dist/throttler/useThrottler.js +32 -8
  89. package/dist/throttler/useThrottler.js.map +1 -1
  90. package/dist/types/index.cjs +3 -3
  91. package/dist/utils/index.cjs +3 -3
  92. package/package.json +3 -3
  93. package/src/async-batcher/useAsyncBatcher.ts +64 -13
  94. package/src/async-debouncer/useAsyncDebouncer.ts +64 -13
  95. package/src/async-queuer/useAsyncQueuedState.ts +2 -2
  96. package/src/async-queuer/useAsyncQueuer.ts +64 -13
  97. package/src/async-rate-limiter/useAsyncRateLimiter.ts +64 -13
  98. package/src/async-throttler/useAsyncThrottler.ts +64 -13
  99. package/src/batcher/useBatcher.ts +61 -8
  100. package/src/debouncer/useDebouncer.ts +61 -8
  101. package/src/queuer/useQueuer.ts +61 -8
  102. package/src/rate-limiter/useRateLimiter.ts +61 -8
  103. package/src/throttler/useThrottler.ts +61 -8
@@ -8,11 +8,29 @@ import type {
8
8
  RateLimiterState,
9
9
  } from '@tanstack/pacer/rate-limiter'
10
10
  import type { AnyFunction } from '@tanstack/pacer/types'
11
+ import type { ComponentChildren } from 'preact'
11
12
 
12
13
  export interface PreactRateLimiter<
13
14
  TFn extends AnyFunction,
14
15
  TSelected = {},
15
16
  > extends Omit<RateLimiter<TFn>, 'store'> {
17
+ /**
18
+ * A Preact HOC (Higher Order Component) that allows you to subscribe to the rate limiter state.
19
+ *
20
+ * This is useful for opting into state re-renders for specific parts of the rate limiter state
21
+ * deep in your component tree without needing to pass a selector to the hook.
22
+ *
23
+ * @example
24
+ * <rateLimiter.Subscribe selector={(state) => ({ rejectionCount: state.rejectionCount })}>
25
+ * {({ rejectionCount }) => (
26
+ * <div>Rejections: {rejectionCount}</div>
27
+ * )}
28
+ * </rateLimiter.Subscribe>
29
+ */
30
+ Subscribe: <TSelected>(props: {
31
+ selector: (state: RateLimiterState) => TSelected
32
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
33
+ }) => ComponentChildren
16
34
  /**
17
35
  * Reactive state that will be updated and re-rendered when the rate limiter state changes
18
36
  *
@@ -50,14 +68,24 @@ export interface PreactRateLimiter<
50
68
  *
51
69
  * ## State Management and Selector
52
70
  *
53
- * The hook uses TanStack Store for reactive state management. The `selector` parameter allows you
54
- * to specify which state changes will trigger a re-render, optimizing performance by preventing
55
- * unnecessary re-renders when irrelevant state changes occur.
71
+ * The hook uses TanStack Store for reactive state management. You can subscribe to state changes
72
+ * in two ways:
73
+ *
74
+ * **1. Using `rateLimiter.Subscribe` HOC (Recommended for component tree subscriptions)**
75
+ *
76
+ * Use the `Subscribe` HOC to subscribe to state changes deep in your component tree without
77
+ * needing to pass a selector to the hook. This is ideal when you want to subscribe to state
78
+ * in child components.
79
+ *
80
+ * **2. Using the `selector` parameter (For hook-level subscriptions)**
81
+ *
82
+ * The `selector` parameter allows you to specify which state changes will trigger a re-render
83
+ * at the hook level, optimizing performance by preventing unnecessary re-renders when irrelevant
84
+ * state changes occur.
56
85
  *
57
86
  * **By default, there will be no reactive state subscriptions** and you must opt-in to state
58
- * tracking by providing a selector function. This prevents unnecessary re-renders and gives you
59
- * full control over when your component updates. Only when you provide a selector will the
60
- * component re-render when the selected state values change.
87
+ * tracking by providing a selector function or using the `Subscribe` HOC. This prevents unnecessary
88
+ * re-renders and gives you full control over when your component updates.
61
89
  *
62
90
  * Available state properties:
63
91
  * - `executionCount`: Number of function executions that have been completed
@@ -80,7 +108,14 @@ export interface PreactRateLimiter<
80
108
  * windowType: 'sliding',
81
109
  * });
82
110
  *
83
- * // Opt-in to re-render when execution count changes (optimized for tracking successful executions)
111
+ * // Subscribe to state changes deep in component tree using Subscribe HOC
112
+ * <rateLimiter.Subscribe selector={(state) => ({ rejectionCount: state.rejectionCount })}>
113
+ * {({ rejectionCount }) => (
114
+ * <div>Rejections: {rejectionCount}</div>
115
+ * )}
116
+ * </rateLimiter.Subscribe>
117
+ *
118
+ * // Opt-in to re-render when execution count changes at hook level (optimized for tracking successful executions)
84
119
  * const rateLimiter = useRateLimiter(
85
120
  * apiCall,
86
121
  * {
@@ -151,7 +186,25 @@ export function useRateLimiter<TFn extends AnyFunction, TSelected = {}>(
151
186
  ...options,
152
187
  } as RateLimiterOptions<TFn>
153
188
 
154
- const [rateLimiter] = useState(() => new RateLimiter<TFn>(fn, mergedOptions))
189
+ const [rateLimiter] = useState(() => {
190
+ const rateLimiterInstance = new RateLimiter<TFn>(
191
+ fn,
192
+ mergedOptions,
193
+ ) as unknown as PreactRateLimiter<TFn, TSelected>
194
+
195
+ rateLimiterInstance.Subscribe = function Subscribe<TSelected>(props: {
196
+ selector: (state: RateLimiterState) => TSelected
197
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
198
+ }) {
199
+ const selected = useStore(rateLimiterInstance.store, props.selector)
200
+
201
+ return typeof props.children === 'function'
202
+ ? props.children(selected)
203
+ : props.children
204
+ }
205
+
206
+ return rateLimiterInstance
207
+ })
155
208
 
156
209
  rateLimiter.fn = fn
157
210
  rateLimiter.setOptions(mergedOptions)
@@ -8,11 +8,29 @@ import type {
8
8
  ThrottlerOptions,
9
9
  ThrottlerState,
10
10
  } from '@tanstack/pacer/throttler'
11
+ import type { ComponentChildren } from 'preact'
11
12
 
12
13
  export interface PreactThrottler<
13
14
  TFn extends AnyFunction,
14
15
  TSelected = {},
15
16
  > extends Omit<Throttler<TFn>, 'store'> {
17
+ /**
18
+ * A Preact HOC (Higher Order Component) that allows you to subscribe to the throttler state.
19
+ *
20
+ * This is useful for opting into state re-renders for specific parts of the throttler state
21
+ * deep in your component tree without needing to pass a selector to the hook.
22
+ *
23
+ * @example
24
+ * <throttler.Subscribe selector={(state) => ({ isPending: state.isPending })}>
25
+ * {({ isPending }) => (
26
+ * <div>{isPending ? 'Loading...' : 'Ready'}</div>
27
+ * )}
28
+ * </throttler.Subscribe>
29
+ */
30
+ Subscribe: <TSelected>(props: {
31
+ selector: (state: ThrottlerState<TFn>) => TSelected
32
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
33
+ }) => ComponentChildren
16
34
  /**
17
35
  * Reactive state that will be updated and re-rendered when the throttler state changes
18
36
  *
@@ -40,14 +58,24 @@ export interface PreactThrottler<
40
58
  *
41
59
  * ## State Management and Selector
42
60
  *
43
- * The hook uses TanStack Store for reactive state management. The `selector` parameter allows you
44
- * to specify which state changes will trigger a re-render, optimizing performance by preventing
45
- * unnecessary re-renders when irrelevant state changes occur.
61
+ * The hook uses TanStack Store for reactive state management. You can subscribe to state changes
62
+ * in two ways:
63
+ *
64
+ * **1. Using `throttler.Subscribe` HOC (Recommended for component tree subscriptions)**
65
+ *
66
+ * Use the `Subscribe` HOC to subscribe to state changes deep in your component tree without
67
+ * needing to pass a selector to the hook. This is ideal when you want to subscribe to state
68
+ * in child components.
69
+ *
70
+ * **2. Using the `selector` parameter (For hook-level subscriptions)**
71
+ *
72
+ * The `selector` parameter allows you to specify which state changes will trigger a re-render
73
+ * at the hook level, optimizing performance by preventing unnecessary re-renders when irrelevant
74
+ * state changes occur.
46
75
  *
47
76
  * **By default, there will be no reactive state subscriptions** and you must opt-in to state
48
- * tracking by providing a selector function. This prevents unnecessary re-renders and gives you
49
- * full control over when your component updates. Only when you provide a selector will the
50
- * component re-render when the selected state values change.
77
+ * tracking by providing a selector function or using the `Subscribe` HOC. This prevents unnecessary
78
+ * re-renders and gives you full control over when your component updates.
51
79
  *
52
80
  * Available state properties:
53
81
  * - `executionCount`: Number of function executions that have been completed
@@ -63,7 +91,14 @@ export interface PreactThrottler<
63
91
  * const [value, setValue] = useState(0);
64
92
  * const throttler = useThrottler(setValue, { wait: 1000 });
65
93
  *
66
- * // Opt-in to re-render when execution count changes (optimized for tracking executions)
94
+ * // Subscribe to state changes deep in component tree using Subscribe HOC
95
+ * <throttler.Subscribe selector={(state) => ({ isPending: state.isPending })}>
96
+ * {({ isPending }) => (
97
+ * <div>{isPending ? 'Processing...' : 'Ready'}</div>
98
+ * )}
99
+ * </throttler.Subscribe>
100
+ *
101
+ * // Opt-in to re-render when execution count changes at hook level (optimized for tracking executions)
67
102
  * const [value, setValue] = useState(0);
68
103
  * const throttler = useThrottler(
69
104
  * setValue,
@@ -117,7 +152,25 @@ export function useThrottler<TFn extends AnyFunction, TSelected = {}>(
117
152
  ...options,
118
153
  } as ThrottlerOptions<TFn>
119
154
 
120
- const [throttler] = useState(() => new Throttler<TFn>(fn, mergedOptions))
155
+ const [throttler] = useState(() => {
156
+ const throttlerInstance = new Throttler<TFn>(
157
+ fn,
158
+ mergedOptions,
159
+ ) as unknown as PreactThrottler<TFn, TSelected>
160
+
161
+ throttlerInstance.Subscribe = function Subscribe<TSelected>(props: {
162
+ selector: (state: ThrottlerState<TFn>) => TSelected
163
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
164
+ }) {
165
+ const selected = useStore(throttlerInstance.store, props.selector)
166
+
167
+ return typeof props.children === 'function'
168
+ ? props.children(selected)
169
+ : props.children
170
+ }
171
+
172
+ return throttlerInstance
173
+ })
121
174
 
122
175
  throttler.fn = fn
123
176
  throttler.setOptions(mergedOptions)