frosty 0.0.13 → 0.0.14

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 (65) hide show
  1. package/dist/_native.js +3 -4
  2. package/dist/_native.js.map +1 -1
  3. package/dist/_native.mjs +2 -3
  4. package/dist/_native.mjs.map +1 -1
  5. package/dist/dom.js +3 -4
  6. package/dist/dom.js.map +1 -1
  7. package/dist/dom.mjs +3 -4
  8. package/dist/dom.mjs.map +1 -1
  9. package/dist/index.d.ts +307 -6
  10. package/dist/index.js +668 -27
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +639 -6
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/internals/{common-CEjwzc0j.js → common-FG7T3c2f.js} +2 -2
  15. package/dist/internals/{common-CEjwzc0j.js.map → common-FG7T3c2f.js.map} +1 -1
  16. package/dist/internals/{common-CQOkvSXp.mjs → common-KSKXTzR8.mjs} +2 -2
  17. package/dist/internals/{common-CQOkvSXp.mjs.map → common-KSKXTzR8.mjs.map} +1 -1
  18. package/dist/internals/{renderer-CTxeL82F.mjs → renderer-GTnF-hYa.mjs} +2 -3
  19. package/dist/internals/{renderer-CTxeL82F.mjs.map → renderer-GTnF-hYa.mjs.map} +1 -1
  20. package/dist/internals/{renderer-BL3b1IbL.js → renderer-jjw2FwKT.js} +8 -9
  21. package/dist/internals/{renderer-BL3b1IbL.js.map → renderer-jjw2FwKT.js.map} +1 -1
  22. package/dist/internals/{sync-Cq3pCYO3.mjs → sync-B9zfuWYQ.mjs} +60 -60
  23. package/dist/internals/sync-B9zfuWYQ.mjs.map +1 -0
  24. package/dist/internals/{sync-CSxmMfGm.js → sync-BIbWmXEq.js} +74 -74
  25. package/dist/internals/sync-BIbWmXEq.js.map +1 -0
  26. package/dist/internals/{state-BiYNImPF.mjs → utils-BJL3yvTI.mjs} +61 -48
  27. package/dist/internals/utils-BJL3yvTI.mjs.map +1 -0
  28. package/dist/internals/{state-DH_D-jro.js → utils-Bipfwp1R.js} +61 -47
  29. package/dist/internals/utils-Bipfwp1R.js.map +1 -0
  30. package/dist/jsx-runtime.js +29 -2
  31. package/dist/jsx-runtime.js.map +1 -1
  32. package/dist/jsx-runtime.mjs +29 -2
  33. package/dist/jsx-runtime.mjs.map +1 -1
  34. package/dist/server-dom.js +3 -4
  35. package/dist/server-dom.js.map +1 -1
  36. package/dist/server-dom.mjs +3 -4
  37. package/dist/server-dom.mjs.map +1 -1
  38. package/dist/web.d.ts +2 -2
  39. package/dist/web.js +30 -15
  40. package/dist/web.js.map +1 -1
  41. package/dist/web.mjs +26 -11
  42. package/dist/web.mjs.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/hooks.d.ts +0 -301
  45. package/dist/hooks.d.ts.map +0 -1
  46. package/dist/hooks.js +0 -456
  47. package/dist/hooks.js.map +0 -1
  48. package/dist/hooks.mjs +0 -447
  49. package/dist/hooks.mjs.map +0 -1
  50. package/dist/internals/fragment-B0rB4qEp.js +0 -32
  51. package/dist/internals/fragment-B0rB4qEp.js.map +0 -1
  52. package/dist/internals/fragment-DPs1AriN.mjs +0 -30
  53. package/dist/internals/fragment-DPs1AriN.mjs.map +0 -1
  54. package/dist/internals/state-0jEjYdYV.js +0 -203
  55. package/dist/internals/state-0jEjYdYV.js.map +0 -1
  56. package/dist/internals/state-BiYNImPF.mjs.map +0 -1
  57. package/dist/internals/state-DH_D-jro.js.map +0 -1
  58. package/dist/internals/state-zydBhS8M.mjs +0 -197
  59. package/dist/internals/state-zydBhS8M.mjs.map +0 -1
  60. package/dist/internals/sync-CSxmMfGm.js.map +0 -1
  61. package/dist/internals/sync-Cq3pCYO3.mjs.map +0 -1
  62. package/dist/internals/utils-DAEKakog.mjs +0 -42
  63. package/dist/internals/utils-DAEKakog.mjs.map +0 -1
  64. package/dist/internals/utils-Dc66ARNS.js +0 -44
  65. package/dist/internals/utils-Dc66ARNS.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,16 +2,641 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var state = require('./internals/state-0jEjYdYV.js');
6
- var sync = require('./internals/sync-CSxmMfGm.js');
7
- var state$1 = require('./internals/state-DH_D-jro.js');
8
5
  var _ = require('lodash');
6
+ var sync = require('./internals/sync-BIbWmXEq.js');
7
+ var utils = require('./internals/utils-Bipfwp1R.js');
8
+ var jsxRuntime = require('./jsx-runtime.js');
9
9
  var component = require('./internals/component-DJsXAx2C.js');
10
- var fragment = require('./internals/fragment-B0rB4qEp.js');
11
10
  var runtime = require('./internals/runtime-CHi74WKN.js');
12
- var utils = require('./internals/utils-Dc66ARNS.js');
13
11
  require('myers.js');
14
12
 
13
+ //
14
+ // memo.ts
15
+ //
16
+ // The MIT License
17
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
18
+ //
19
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ // of this software and associated documentation files (the "Software"), to deal
21
+ // in the Software without restriction, including without limitation the rights
22
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ // copies of the Software, and to permit persons to whom the Software is
24
+ // furnished to do so, subject to the following conditions:
25
+ //
26
+ // The above copyright notice and this permission notice shall be included in
27
+ // all copies or substantial portions of the Software.
28
+ //
29
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35
+ // THE SOFTWARE.
36
+ //
37
+ function useRef(initialValue) {
38
+ return sync._useMemo('useRef', () => ({ current: initialValue }), null);
39
+ }
40
+ /**
41
+ * Associates a reference with a value created by an initializer function.
42
+ *
43
+ * @template T The type of the reference.
44
+ * @template R The type of the value created by the initializer function.
45
+ * @param ref A reference object or a callback function to receive the value.
46
+ * @param init A function that initializes and returns the value to associate with the reference.
47
+ * @param deps An optional dependency array. The initializer function is re-executed when the dependencies change.
48
+ */
49
+ const useRefHandle = (ref, init, deps) => sync._useEffect('useRefHandle', () => {
50
+ try {
51
+ if (ref) {
52
+ const _ref = init();
53
+ if (typeof ref === 'function')
54
+ ref(_ref);
55
+ else if (typeof ref === 'object')
56
+ ref.current = _ref;
57
+ }
58
+ return () => void 0;
59
+ }
60
+ catch (e) {
61
+ console.error(e);
62
+ return () => void 0;
63
+ }
64
+ }, deps);
65
+
66
+ //
67
+ // memo.ts
68
+ //
69
+ // The MIT License
70
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
71
+ //
72
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
73
+ // of this software and associated documentation files (the "Software"), to deal
74
+ // in the Software without restriction, including without limitation the rights
75
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76
+ // copies of the Software, and to permit persons to whom the Software is
77
+ // furnished to do so, subject to the following conditions:
78
+ //
79
+ // The above copyright notice and this permission notice shall be included in
80
+ // all copies or substantial portions of the Software.
81
+ //
82
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
83
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
85
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
88
+ // THE SOFTWARE.
89
+ //
90
+ function useState(initialState) {
91
+ const { value, setValue } = sync._useMemo('useState', ({ node }) => {
92
+ const state = {
93
+ value: _.isFunction(initialState) ? initialState() : initialState,
94
+ setValue: (dispatch) => {
95
+ state.value = _.isFunction(dispatch) ? dispatch(state.value) : dispatch;
96
+ node?._setDirty();
97
+ },
98
+ };
99
+ return state;
100
+ }, null);
101
+ return [value, setValue];
102
+ }
103
+
104
+ //
105
+ // animate.ts
106
+ //
107
+ // The MIT License
108
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
109
+ //
110
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
111
+ // of this software and associated documentation files (the "Software"), to deal
112
+ // in the Software without restriction, including without limitation the rights
113
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
114
+ // copies of the Software, and to permit persons to whom the Software is
115
+ // furnished to do so, subject to the following conditions:
116
+ //
117
+ // The above copyright notice and this permission notice shall be included in
118
+ // all copies or substantial portions of the Software.
119
+ //
120
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
121
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
122
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
123
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
124
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
125
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
126
+ // THE SOFTWARE.
127
+ //
128
+ const interpolate = (value) => ({ inputRange, outputRange }) => {
129
+ const [inputMin, inputMax] = inputRange;
130
+ const [outputMin, outputMax] = outputRange;
131
+ // Safeguard against division by zero
132
+ if (inputMax === inputMin) {
133
+ throw new Error('Input range must have distinct values.');
134
+ }
135
+ const t = (value - inputMin) / (inputMax - inputMin);
136
+ const interpolatedValue = outputMin + t * (outputMax - outputMin);
137
+ return {
138
+ value: interpolatedValue,
139
+ interpolate: interpolate(interpolatedValue),
140
+ };
141
+ };
142
+ /**
143
+ * A hook to manage animations with support for starting, stopping, and interpolating values.
144
+ *
145
+ * @param initialValue - The initial value of the animation.
146
+ *
147
+ * @returns An object containing:
148
+ * - `value`: The current animated value.
149
+ * - `stop`: A function to stop the animation.
150
+ * - `start`: A function to start the animation with specified options.
151
+ * - `interpolate`: A function to interpolate the current value based on input and output ranges.
152
+ */
153
+ const useAnimate = (initialValue) => {
154
+ const [value, setValue] = useState(initialValue);
155
+ const ref = useRef();
156
+ const _stop = () => {
157
+ const { interval, callback } = ref.current ?? {};
158
+ ref.current = undefined;
159
+ if (interval)
160
+ clearInterval(interval);
161
+ return callback;
162
+ };
163
+ const stop = sync.useCallback(() => {
164
+ const callback = _stop();
165
+ if (_.isFunction(callback))
166
+ callback({ value, finished: false });
167
+ });
168
+ const start = sync.useCallback(({ fromValue = value, toValue, duration, easing = (x) => x, delay = 0, onCompleted, }) => {
169
+ _stop();
170
+ const start = Date.now();
171
+ if (duration > 0) {
172
+ ref.current = {
173
+ interval: setInterval(() => {
174
+ const t = (Date.now() - start) / duration - delay;
175
+ if (t >= 1) {
176
+ clearInterval(ref.current?.interval);
177
+ ref.current = undefined;
178
+ setValue(toValue);
179
+ if (_.isFunction(onCompleted))
180
+ onCompleted({ value: toValue, finished: true });
181
+ }
182
+ else if (t >= 0) {
183
+ setValue((toValue - fromValue) * easing(_.clamp(t, 0, 1)) + fromValue);
184
+ }
185
+ }, 16),
186
+ callback: onCompleted,
187
+ };
188
+ }
189
+ });
190
+ return {
191
+ value,
192
+ stop,
193
+ start,
194
+ interpolate: interpolate(value),
195
+ };
196
+ };
197
+
198
+ //
199
+ // debounce.ts
200
+ //
201
+ // The MIT License
202
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
203
+ //
204
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
205
+ // of this software and associated documentation files (the "Software"), to deal
206
+ // in the Software without restriction, including without limitation the rights
207
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
208
+ // copies of the Software, and to permit persons to whom the Software is
209
+ // furnished to do so, subject to the following conditions:
210
+ //
211
+ // The above copyright notice and this permission notice shall be included in
212
+ // all copies or substantial portions of the Software.
213
+ //
214
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
215
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
216
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
217
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
218
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
219
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
220
+ // THE SOFTWARE.
221
+ //
222
+ const debounce = (callback, settings) => {
223
+ const { wait, ...options } = settings;
224
+ return _.debounce(callback, wait, {
225
+ ...options,
226
+ leading: 'leading' in options ? !!options.leading : true,
227
+ trailing: 'trailing' in options ? !!options.trailing : true,
228
+ });
229
+ };
230
+ const asyncDebounce = (func, settings) => {
231
+ let preflight;
232
+ const debounced = debounce(async (resolve, ...args) => {
233
+ const result = func(...args);
234
+ if (_.isFunction(resolve))
235
+ resolve(result);
236
+ return result;
237
+ }, settings);
238
+ return (...args) => {
239
+ if (_.isNil(preflight)) {
240
+ preflight = new Promise(r => debounced(r, ...args));
241
+ return preflight;
242
+ }
243
+ return debounced(undefined, ...args) ?? preflight;
244
+ };
245
+ };
246
+ /**
247
+ * A hook that creates a debounced version of a function.
248
+ * The debounced function delays invoking the callback until after
249
+ * the specified wait time has elapsed since the last time it was called.
250
+ *
251
+ * This is useful for optimizing performance in scenarios where frequent
252
+ * function calls (e.g., during user input or window resizing) can be expensive.
253
+ *
254
+ * @template T The type of the callback function.
255
+ * @param callback The function to debounce.
256
+ * @param settings Configuration options for debouncing, including:
257
+ * - `wait` (number): The number of milliseconds to delay.
258
+ * - Other lodash debounce options such as `leading` and `trailing`.
259
+ * @returns A debounced version of the callback function.
260
+ */
261
+ const useDebounce = (callback, settings) => {
262
+ const store = sync._useMemo('useDebounce', () => {
263
+ const store = {
264
+ current: callback,
265
+ stable: debounce(((...args) => store.current(...args)), settings),
266
+ };
267
+ return store;
268
+ }, null);
269
+ store.current = callback;
270
+ return store.stable;
271
+ };
272
+ /**
273
+ * A hook that creates a debounced version of an asynchronous function.
274
+ * The debounced function delays invoking the callback until after
275
+ * the specified wait time has elapsed since the last time it was called.
276
+ *
277
+ * This is particularly useful for scenarios where frequent API calls
278
+ * or other asynchronous operations need to be throttled to improve performance.
279
+ *
280
+ * @template T The type of the asynchronous callback function.
281
+ * @param callback The asynchronous function to debounce.
282
+ * @param settings Configuration options for debouncing, including:
283
+ * - `wait` (number): The number of milliseconds to delay.
284
+ * - Other lodash debounce options such as `leading` and `trailing`.
285
+ * @returns A debounced version of the asynchronous callback function.
286
+ */
287
+ const useAsyncDebounce = (callback, settings) => {
288
+ const store = sync._useMemo('useAsyncDebounce', () => {
289
+ const store = {
290
+ current: callback,
291
+ stable: asyncDebounce(((...args) => store.current(...args)), settings),
292
+ };
293
+ return store;
294
+ }, null);
295
+ store.current = callback;
296
+ return store.stable;
297
+ };
298
+
299
+ const Context = utils.createContext({
300
+ errors: [],
301
+ setErrors: () => { },
302
+ });
303
+ /**
304
+ * A context provider component for managing asynchronous resource errors.
305
+ *
306
+ * This component provides a shared context for tracking errors encountered during
307
+ * asynchronous operations. It allows child components to access and manage these errors
308
+ * using the `useResourceErrors` hook.
309
+ *
310
+ * ### Usage:
311
+ * Wrap your application or specific parts of it with this component to enable error tracking:
312
+ *
313
+ * ```tsx
314
+ * <ResourceErrors>
315
+ * <YourComponent />
316
+ * </ResourceErrors>
317
+ * ```
318
+ *
319
+ * @param children - The child components that will have access to the error context.
320
+ *
321
+ * @returns A context provider that wraps the provided children.
322
+ */
323
+ const ResourceErrors = ({ children }) => {
324
+ const [errors, setErrors] = useState([]);
325
+ const value = sync.useMemo(() => ({ errors, setErrors }), [errors, setErrors]);
326
+ return (jsxRuntime.jsx(Context, { value: value, children: children }));
327
+ };
328
+ /**
329
+ * A hook to access the list of asynchronous resource errors.
330
+ *
331
+ * This hook allows components to retrieve the current list of errors being tracked
332
+ * in the `ResourceErrors` context. It must be used within a component that is
333
+ * a descendant of the `ResourceErrors` provider.
334
+ *
335
+ * ### Usage:
336
+ * ```tsx
337
+ * const errors = useResourceErrors();
338
+ *
339
+ * errors.forEach(({ token, error, refresh }) => {
340
+ * console.error(`Error [${token}]:`, error);
341
+ * // Optionally call refresh() to retry the operation
342
+ * });
343
+ * ```
344
+ *
345
+ * @returns The list of errors currently being tracked in the context. Each error includes:
346
+ * - `token`: A unique identifier for the error.
347
+ * - `error`: The error object or message.
348
+ * - `refresh`: A function to retry the operation that caused the error.
349
+ */
350
+ const useResourceErrors = () => utils.useContext(Context).errors;
351
+
352
+ //
353
+ // index.ts
354
+ //
355
+ // The MIT License
356
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
357
+ //
358
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
359
+ // of this software and associated documentation files (the "Software"), to deal
360
+ // in the Software without restriction, including without limitation the rights
361
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
362
+ // copies of the Software, and to permit persons to whom the Software is
363
+ // furnished to do so, subject to the following conditions:
364
+ //
365
+ // The above copyright notice and this permission notice shall be included in
366
+ // all copies or substantial portions of the Software.
367
+ //
368
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
369
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
370
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
371
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
372
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
373
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
374
+ // THE SOFTWARE.
375
+ //
376
+ /**
377
+ * A hook to manage asynchronous resources with support for debouncing, error handling, and state management.
378
+ *
379
+ * @template T - The type of the resource being fetched.
380
+ * @template P - The type of the parameters passed to the fetch function.
381
+ *
382
+ * @param config - The fetch function or a configuration object containing the fetch function and optional debounce settings.
383
+ * @param deps - An optional dependency array to control when the resource is refreshed.
384
+ *
385
+ * @returns An object containing:
386
+ * - `count`: The number of times the resource has been fetched.
387
+ * - `refreshing`: A boolean indicating if the resource is currently being refreshed.
388
+ * - `loading`: A boolean indicating if the resource is currently being loaded.
389
+ * - `resource`: The fetched resource.
390
+ * - `error`: Any error encountered during the fetch.
391
+ * - `cancel`: A function to cancel the current fetch operation.
392
+ * - `refresh`: A function to refresh the resource.
393
+ * - `next`: A function to fetch the next set of data (for paginated resources).
394
+ * - `setResource`: A function to manually update the resource state.
395
+ */
396
+ const useResource = (config, deps) => {
397
+ const fetch = _.isFunction(config) ? config : config.fetch;
398
+ const debounce = _.isFunction(config) ? {} : config.debounce;
399
+ const [state, setState] = useState({});
400
+ const _dispatch = (token, next) => setState(state => state.token === token ? ({
401
+ ...(_.isFunction(next) ? next(state.flag ? state : _.omit(state, 'resource', 'error')) : next),
402
+ count: state.flag ? state.count : (state.count ?? 0) + 1,
403
+ flag: true,
404
+ }) : state);
405
+ const _fetch = useAsyncDebounce(async (type, abort, reset, param, prevState) => {
406
+ const token = _.uniqueId();
407
+ setState(state => ({ ...state, type, token, abort, flag: !reset }));
408
+ try {
409
+ const resource = await fetch({
410
+ param,
411
+ prevState,
412
+ abortSignal: abort.signal,
413
+ dispatch: (next) => {
414
+ _dispatch(token, state => ({
415
+ ...state,
416
+ resource: _.isFunction(next) ? next(state.resource) : next,
417
+ }));
418
+ },
419
+ });
420
+ _dispatch(token, state => ({ resource: resource ?? state.resource }));
421
+ }
422
+ catch (error) {
423
+ _dispatch(token, state => ({
424
+ resource: state.resource,
425
+ error,
426
+ }));
427
+ }
428
+ }, debounce ?? {});
429
+ sync.useEffect(() => {
430
+ const controller = new AbortController();
431
+ void _fetch('refresh', controller, true);
432
+ return () => controller.abort();
433
+ }, deps ?? []);
434
+ const _cancelRef = sync.useCallback((reason) => { state.abort?.abort(reason); });
435
+ const _refreshRef = sync.useCallback((param) => _fetch('refresh', new AbortController(), true, param));
436
+ const _nextRef = sync.useCallback((param) => _fetch('next', new AbortController(), false, param, state.resource));
437
+ const _setResRef = sync.useCallback((resource) => setState(state => ({
438
+ ..._.omit(state, 'resource', 'error'),
439
+ resource: _.isFunction(resource) ? resource(state.resource) : resource,
440
+ })));
441
+ const { setErrors } = utils.useContext(Context);
442
+ sync.useEffect(() => {
443
+ const { type, abort, token = _.uniqueId(), error } = state;
444
+ if (!error)
445
+ return;
446
+ setErrors(v => [...v, {
447
+ token,
448
+ error,
449
+ refresh: _refreshRef,
450
+ refreshing: !_.isNil(abort) && type === 'refresh',
451
+ loading: !_.isNil(abort),
452
+ }]);
453
+ return () => setErrors(v => _.filter(v, x => x.token !== token));
454
+ }, [state]);
455
+ return {
456
+ count: state.count ?? 0,
457
+ refreshing: !_.isNil(state.abort) && state.type === 'refresh',
458
+ loading: !_.isNil(state.abort),
459
+ resource: state.resource,
460
+ error: state.error,
461
+ cancel: _cancelRef,
462
+ refresh: _refreshRef,
463
+ next: _nextRef,
464
+ setResource: _setResRef,
465
+ };
466
+ };
467
+ /**
468
+ * A hook to manage asynchronous iterable resources, such as streams or paginated data.
469
+ *
470
+ * @template T - The type of the resource items being fetched.
471
+ * @template P - The type of the parameters passed to the fetch function.
472
+ *
473
+ * @param config - The fetch function or a configuration object containing the fetch function and optional debounce settings.
474
+ * @param deps - An optional dependency array to control when the resource is refreshed.
475
+ *
476
+ * @returns An object containing the same properties as `useResource`, but optimized for iterable resources.
477
+ */
478
+ const useIterableResource = (config, deps) => {
479
+ const fetch = _.isFunction(config) ? config : config.fetch;
480
+ const debounce = _.isFunction(config) ? {} : config.debounce;
481
+ const { next, ...result } = useResource({
482
+ fetch: async ({ dispatch, abortSignal, param }) => {
483
+ const resource = await fetch({ abortSignal, param });
484
+ for await (const item of resource) {
485
+ dispatch(items => items ? [...items, item] : [item]);
486
+ }
487
+ },
488
+ debounce,
489
+ }, deps);
490
+ return result;
491
+ };
492
+
493
+ //
494
+ // interval.ts
495
+ //
496
+ // The MIT License
497
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
498
+ //
499
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
500
+ // of this software and associated documentation files (the "Software"), to deal
501
+ // in the Software without restriction, including without limitation the rights
502
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
503
+ // copies of the Software, and to permit persons to whom the Software is
504
+ // furnished to do so, subject to the following conditions:
505
+ //
506
+ // The above copyright notice and this permission notice shall be included in
507
+ // all copies or substantial portions of the Software.
508
+ //
509
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
510
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
511
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
512
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
513
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
514
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
515
+ // THE SOFTWARE.
516
+ //
517
+ /**
518
+ * A hook that repeatedly calls the provided callback function at the specified interval.
519
+ *
520
+ * @param callback - The function to be executed at each interval.
521
+ * @param ms - The delay in milliseconds between each call to the callback. If not provided, the interval will not be set.
522
+ * @returns void
523
+ *
524
+ * @example
525
+ * useInterval(() => {
526
+ * // Code to run every 1000ms
527
+ * }, 1000);
528
+ */
529
+ const useInterval = (callback, ms) => sync.useEffect(() => {
530
+ const interval = setInterval(() => {
531
+ callback();
532
+ }, ms);
533
+ return () => clearInterval(interval);
534
+ }, []);
535
+
536
+ //
537
+ // store.ts
538
+ //
539
+ // The MIT License
540
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
541
+ //
542
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
543
+ // of this software and associated documentation files (the "Software"), to deal
544
+ // in the Software without restriction, including without limitation the rights
545
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
546
+ // copies of the Software, and to permit persons to whom the Software is
547
+ // furnished to do so, subject to the following conditions:
548
+ //
549
+ // The above copyright notice and this permission notice shall be included in
550
+ // all copies or substantial portions of the Software.
551
+ //
552
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
553
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
554
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
555
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
556
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
557
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
558
+ // THE SOFTWARE.
559
+ //
560
+ /**
561
+ * A class representing a store that holds a value and allows for subscription
562
+ * to changes in that value.
563
+ *
564
+ * @template T - The type of the value stored in the store.
565
+ *
566
+ * @example
567
+ * const store = createStore(0);
568
+ * store.setValue(1);
569
+ * store.subscribe((oldVal, newVal) => {
570
+ * console.log(`Value changed from ${oldVal} to ${newVal}`);
571
+ * });
572
+ */
573
+ class Store {
574
+ #listeners = new Set();
575
+ #value;
576
+ /** @internal */
577
+ constructor(initialValue) {
578
+ this.#value = initialValue;
579
+ }
580
+ /**
581
+ * Gets the current value of the store.
582
+ *
583
+ * @returns The current value of the store.
584
+ */
585
+ get value() {
586
+ return this.#value;
587
+ }
588
+ /**
589
+ * Sets the value of the store and notifies all subscribers.
590
+ *
591
+ * @param dispatch - The new value or a function that returns the new value.
592
+ */
593
+ setValue(dispatch) {
594
+ const oldVal = this.#value;
595
+ dispatch = _.isFunction(dispatch) ? dispatch(this.#value) : this.#value;
596
+ this.#listeners.forEach(listener => void listener(oldVal, this.#value));
597
+ }
598
+ /**
599
+ * Subscribes to changes in the store's value.
600
+ *
601
+ * @param callback - The function to call when the value changes.
602
+ * @returns A function to unsubscribe from the store.
603
+ */
604
+ subscribe(callback) {
605
+ this.#listeners.add(callback);
606
+ return () => { this.#listeners.delete(callback); };
607
+ }
608
+ }
609
+ /**
610
+ * Creates a new store with the given initial value.
611
+ *
612
+ * @param initialValue - The initial value to be stored.
613
+ * @returns {Store<T>} A new store instance.
614
+ *
615
+ * @example
616
+ * const counterStore = createStore(0);
617
+ */
618
+ const createStore = (initialValue) => new Store(initialValue);
619
+ /**
620
+ * A hook to subscribe to a store and select a slice of its state.
621
+ * The component will re-render when the selected state changes.
622
+ *
623
+ * @param store - The store instance to subscribe to.
624
+ * @param selector - A function to select a part of the store's state. Defaults to the entire state.
625
+ * @param equal - A function to compare selected values for equality. Defaults to deep equality.
626
+ * @returns The selected slice of the store's state.
627
+ *
628
+ * @example
629
+ * const count = useStore(counterStore);
630
+ *
631
+ * @example
632
+ * // Using a selector
633
+ * const userName = useStore(userStore, user => user.name);
634
+ */
635
+ const useStore = (store, selector = v => v, equal = _.isEqual) => sync.useSyncExternalStore((onStoreChange) => store.subscribe((oldVal, newVal) => {
636
+ if (equal(selector(oldVal), selector(newVal)))
637
+ onStoreChange();
638
+ }), () => selector(store.value));
639
+
15
640
  //
16
641
  // stack.ts
17
642
  //
@@ -47,7 +672,7 @@ require('myers.js');
47
672
  * @throws Will throw an error if the function is called outside of a valid render context.
48
673
  */
49
674
  const useStack = () => {
50
- const state = state$1.reconciler.currentHookState;
675
+ const state = utils.reconciler.currentHookState;
51
676
  if (!state)
52
677
  throw Error('useStack must be used within a render function.');
53
678
  return _.map(state.stack, x => x._component);
@@ -119,44 +744,60 @@ function useReducer(reducer, initialState) {
119
744
  var common = /*#__PURE__*/Object.freeze({
120
745
  __proto__: null,
121
746
  ComponentNode: component.ComponentNode,
122
- ErrorBoundary: state$1.ErrorBoundary,
123
- Fragment: fragment.Fragment,
124
- PropsProvider: state$1.PropsProvider,
125
- createContext: state$1.createContext,
747
+ ErrorBoundary: utils.ErrorBoundary,
748
+ Fragment: jsxRuntime.Fragment,
749
+ PropsProvider: utils.PropsProvider,
750
+ ResourceErrors: ResourceErrors,
751
+ createContext: utils.createContext,
126
752
  createElement: runtime.createElement,
753
+ createStore: createStore,
127
754
  mergeRefs: utils.mergeRefs,
128
- useAsyncDebounce: state.useAsyncDebounce,
755
+ useAnimate: useAnimate,
756
+ useAsyncDebounce: useAsyncDebounce,
129
757
  useCallback: sync.useCallback,
130
- useContext: state$1.useContext,
131
- useDebounce: state.useDebounce,
758
+ useContext: utils.useContext,
759
+ useDebounce: useDebounce,
132
760
  useEffect: sync.useEffect,
761
+ useInterval: useInterval,
762
+ useIterableResource: useIterableResource,
133
763
  useMemo: sync.useMemo,
134
764
  useReducer: useReducer,
135
- useRef: state.useRef,
136
- useRefHandle: state.useRefHandle,
765
+ useRef: useRef,
766
+ useRefHandle: useRefHandle,
767
+ useResource: useResource,
768
+ useResourceErrors: useResourceErrors,
137
769
  useStack: useStack,
138
- useState: state.useState,
770
+ useState: useState,
771
+ useStore: useStore,
139
772
  useSyncExternalStore: sync.useSyncExternalStore
140
773
  });
141
774
 
142
- exports.useAsyncDebounce = state.useAsyncDebounce;
143
- exports.useDebounce = state.useDebounce;
144
- exports.useRef = state.useRef;
145
- exports.useRefHandle = state.useRefHandle;
146
- exports.useState = state.useState;
147
775
  exports.useCallback = sync.useCallback;
148
776
  exports.useEffect = sync.useEffect;
149
777
  exports.useMemo = sync.useMemo;
150
778
  exports.useSyncExternalStore = sync.useSyncExternalStore;
151
- exports.ErrorBoundary = state$1.ErrorBoundary;
152
- exports.PropsProvider = state$1.PropsProvider;
153
- exports.createContext = state$1.createContext;
154
- exports.useContext = state$1.useContext;
779
+ exports.ErrorBoundary = utils.ErrorBoundary;
780
+ exports.PropsProvider = utils.PropsProvider;
781
+ exports.createContext = utils.createContext;
782
+ exports.mergeRefs = utils.mergeRefs;
783
+ exports.useContext = utils.useContext;
784
+ exports.Fragment = jsxRuntime.Fragment;
155
785
  exports.ComponentNode = component.ComponentNode;
156
- exports.Fragment = fragment.Fragment;
157
786
  exports.createElement = runtime.createElement;
158
- exports.mergeRefs = utils.mergeRefs;
787
+ exports.ResourceErrors = ResourceErrors;
788
+ exports.createStore = createStore;
159
789
  exports.default = common;
790
+ exports.useAnimate = useAnimate;
791
+ exports.useAsyncDebounce = useAsyncDebounce;
792
+ exports.useDebounce = useDebounce;
793
+ exports.useInterval = useInterval;
794
+ exports.useIterableResource = useIterableResource;
160
795
  exports.useReducer = useReducer;
796
+ exports.useRef = useRef;
797
+ exports.useRefHandle = useRefHandle;
798
+ exports.useResource = useResource;
799
+ exports.useResourceErrors = useResourceErrors;
161
800
  exports.useStack = useStack;
801
+ exports.useState = useState;
802
+ exports.useStore = useStore;
162
803
  //# sourceMappingURL=index.js.map