yummies 7.10.0 → 7.11.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 (61) hide show
  1. package/async.cjs +11 -11
  2. package/async.cjs.map +1 -1
  3. package/async.d.ts +9 -11
  4. package/async.js +11 -11
  5. package/async.js.map +1 -1
  6. package/complex.cjs +32 -8
  7. package/complex.cjs.map +1 -1
  8. package/complex.d.ts +133 -13
  9. package/complex.js +32 -8
  10. package/complex.js.map +1 -1
  11. package/css.cjs.map +1 -1
  12. package/css.d.ts +3 -3
  13. package/css.js.map +1 -1
  14. package/date-time.cjs.map +1 -1
  15. package/date-time.js.map +1 -1
  16. package/format.cjs.map +1 -1
  17. package/format.d.ts +89 -4
  18. package/format.js.map +1 -1
  19. package/html.cjs.map +1 -1
  20. package/html.d.ts +3 -3
  21. package/html.js.map +1 -1
  22. package/id.cjs.map +1 -1
  23. package/id.d.ts +10 -10
  24. package/id.js.map +1 -1
  25. package/imports.cjs.map +1 -1
  26. package/imports.d.ts +5 -4
  27. package/imports.js.map +1 -1
  28. package/math.cjs.map +1 -1
  29. package/math.d.ts +1 -1
  30. package/math.js.map +1 -1
  31. package/media.cjs.map +1 -1
  32. package/media.d.ts +1 -1
  33. package/media.js.map +1 -1
  34. package/mobx.cjs.map +1 -1
  35. package/mobx.d.ts +165 -6
  36. package/mobx.js.map +1 -1
  37. package/ms.cjs.map +1 -1
  38. package/ms.d.ts +1 -1
  39. package/ms.js.map +1 -1
  40. package/package.json +5 -5
  41. package/parser.cjs.map +1 -1
  42. package/parser.d.ts +63 -0
  43. package/parser.js.map +1 -1
  44. package/react.cjs.map +1 -1
  45. package/react.d.ts +407 -9
  46. package/react.js.map +1 -1
  47. package/sound.cjs.map +1 -1
  48. package/sound.d.ts +1 -1
  49. package/sound.js.map +1 -1
  50. package/storage.cjs.map +1 -1
  51. package/storage.d.ts +7 -6
  52. package/storage.js.map +1 -1
  53. package/text.cjs.map +1 -1
  54. package/text.d.ts +5 -5
  55. package/text.js.map +1 -1
  56. package/type-guard.cjs.map +1 -1
  57. package/type-guard.d.ts +199 -42
  58. package/type-guard.js.map +1 -1
  59. package/vibrate.cjs.map +1 -1
  60. package/vibrate.d.ts +1 -1
  61. package/vibrate.js.map +1 -1
package/react.d.ts CHANGED
@@ -2,10 +2,65 @@ import * as react from 'react';
2
2
  import { RefObject, LegacyRef, MutableRefObject } from 'react';
3
3
  import { Maybe, AnyFunction } from 'yummies/types';
4
4
 
5
+ /**
6
+ * Assigns the same value to multiple React refs, including callback refs.
7
+ *
8
+ * @template T Referenced value type.
9
+ * @param value Value that should be written into every provided ref.
10
+ * @param refs Target refs to update.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * attachRefs(node, localRef, forwardedRef);
15
+ * ```
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * attachRefs(null, inputRef, (value) => console.log(value));
20
+ * ```
21
+ */
5
22
  declare const attachRefs: <T>(value: T | null, ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]) => void;
6
23
 
24
+ /**
25
+ * Creates a single `AbortController` instance for the component lifetime.
26
+ *
27
+ * The controller is aborted automatically during unmount.
28
+ *
29
+ * @returns Stable abort controller instance.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const controller = useAbortController();
34
+ * fetch('/api', { signal: controller.signal });
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const controller = useAbortController();
40
+ * controller.abort();
41
+ * ```
42
+ */
7
43
  declare const useAbortController: () => AbortController;
8
44
 
45
+ /**
46
+ * Returns an `AbortSignal` tied to the component lifecycle.
47
+ *
48
+ * The signal is aborted automatically on unmount.
49
+ *
50
+ * @returns Lifecycle-bound abort signal.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const signal = useAbortSignal();
55
+ * fetch('/api/users', { signal });
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const signal = useAbortSignal();
61
+ * someAsyncTask({ signal });
62
+ * ```
63
+ */
9
64
  declare const useAbortSignal: () => AbortSignal;
10
65
 
11
66
  type ClickOutsideInput = {
@@ -13,30 +68,119 @@ type ClickOutsideInput = {
13
68
  onClick: VoidFunction;
14
69
  options?: AddEventListenerOptions;
15
70
  };
71
+ /**
72
+ * Calls a handler when a pointer interaction happens outside the referenced element.
73
+ *
74
+ * @param input Target element ref, callback and event listener options.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * useClickOutside({
79
+ * contentRef: modalRef,
80
+ * onClick: () => closeModal(),
81
+ * });
82
+ * ```
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * useClickOutside({
87
+ * contentRef: dropdownRef,
88
+ * onClick: hideDropdown,
89
+ * options: { capture: true },
90
+ * });
91
+ * ```
92
+ */
16
93
  declare const useClickOutside: ({ contentRef, onClick, options, }: ClickOutsideInput) => void;
17
94
 
18
95
  /**
19
96
  * React hook for creating a value exactly once.
20
- * useMemo doesn't give this guarantee unfortunately -
21
- * https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily
22
- * https://reactjs.org/docs/hooks-reference.html#usememo
23
- * @param defineValue Function which returns defined value.
97
+ *
98
+ * Unlike `useMemo`, this guarantees that the initializer is executed only once
99
+ * for the component lifetime.
100
+ *
101
+ * @template T Value type.
102
+ * @param defineValue Function that lazily creates the value.
103
+ * @returns Stable value created on the first render.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const id = useConstant(() => crypto.randomUUID());
108
+ * ```
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));
113
+ * ```
24
114
  */
25
115
  declare const useConstant: <T>(defineValue: () => T) => T;
26
116
 
27
117
  /**
28
- * React hook for creating a value exactly once.
29
- * useMemo doesn't give this guarantee unfortunately -
30
- * https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily
31
- * https://reactjs.org/docs/hooks-reference.html#usememo
32
- * @param defineFn Function which returns defined value.
118
+ * Creates a mutable ref whose value is initialized exactly once.
119
+ *
120
+ * @template T Ref value type.
121
+ * @param defineFn Function that lazily creates the initial ref value.
122
+ * @returns Mutable ref with a stable initialized value.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const cacheRef = useDefineRef(() => new Map());
127
+ * ```
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));
132
+ * ```
33
133
  */
34
134
  declare const useDefineRef: <T>(defineFn: () => T) => MutableRefObject<T>;
35
135
 
136
+ /**
137
+ * Resolves an element once after mount and stores it in a ref.
138
+ *
139
+ * @template T Element type.
140
+ * @param selector Function returning the target element.
141
+ * @returns Ref containing the selected element.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);
146
+ * ```
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);
151
+ * ```
152
+ */
36
153
  declare const useElementRef: <T extends HTMLElement>(selector: () => T) => react.MutableRefObject<T | undefined>;
37
154
 
38
155
  declare const useEvent: <H extends AnyFunction>(handler: H) => H;
39
156
 
157
+ /**
158
+ * Subscribes to a DOM event and keeps the latest handler without resubscribing
159
+ * on every render.
160
+ *
161
+ * Supports optional debounce and custom effect dependencies.
162
+ *
163
+ * @template EventName DOM event name from `HTMLElementEventMap`.
164
+ * @param config Event subscription configuration.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * useEventListener({
169
+ * event: 'click',
170
+ * handler: () => console.log('clicked'),
171
+ * });
172
+ * ```
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * useEventListener({
177
+ * event: 'scroll',
178
+ * node: window,
179
+ * debounce: 100,
180
+ * handler: () => console.log('scroll'),
181
+ * });
182
+ * ```
183
+ */
40
184
  declare const useEventListener: <EventName extends keyof HTMLElementEventMap>({ event, handler, options, deps, debounce, node, }: {
41
185
  event: EventName;
42
186
  handler: (e: HTMLElementEventMap[EventName]) => void;
@@ -52,10 +196,62 @@ interface FlagHook {
52
196
  enable: VoidFunction;
53
197
  disable: VoidFunction;
54
198
  }
199
+ /**
200
+ * Manages a reusable boolean flag object with stable helper methods.
201
+ *
202
+ * @param defaultValue Initial enabled state.
203
+ * @returns Stable object exposing current state and mutators.
204
+ *
205
+ * @example
206
+ * ```ts
207
+ * const modal = useFlag();
208
+ * modal.enable();
209
+ * ```
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * const loading = useFlag(true);
214
+ * loading.disable();
215
+ * ```
216
+ */
55
217
  declare const useFlag: (defaultValue?: boolean) => FlagHook;
56
218
 
219
+ /**
220
+ * Forces a component re-render by updating an internal dummy state.
221
+ *
222
+ * @returns Stable callback that triggers a re-render.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * const forceUpdate = useForceUpdate();
227
+ * forceUpdate();
228
+ * ```
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * const rerender = useForceUpdate();
233
+ * setTimeout(rerender, 1000);
234
+ * ```
235
+ */
57
236
  declare const useForceUpdate: () => () => void;
58
237
 
238
+ /**
239
+ * Captures an element's height the first time its ref becomes available.
240
+ *
241
+ * @template T Element type attached to the returned ref.
242
+ * @returns Ref and the initial measured height.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();
247
+ * ```
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * const state = useInitialHeight<HTMLTextAreaElement>();
252
+ * state.initialHeight;
253
+ * ```
254
+ */
59
255
  declare const useInitialHeight: <T extends HTMLElement>() => {
60
256
  ref: react.MutableRefObject<T | null>;
61
257
  initialHeight: number | undefined;
@@ -65,6 +261,25 @@ type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {
65
261
  abortSignal: AbortSignal;
66
262
  payload: TPayload;
67
263
  };
264
+ /**
265
+ * Builds a custom hook that creates an instance once and wires lifecycle helpers
266
+ * such as an `AbortSignal` and optional extension data into the factory.
267
+ *
268
+ * @template TExtension Extra configuration injected into every factory call.
269
+ * @param extension Optional static extension object merged into the factory config.
270
+ * @returns Hook factory that creates stable instances from a supplied factory.
271
+ *
272
+ * @example
273
+ * ```ts
274
+ * const useStoreInstance = createUseInstanceHook({ api });
275
+ * ```
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * const useService = createUseInstanceHook({ logger });
280
+ * const service = useService(({ logger, payload }) => new Service(logger, payload));
281
+ * ```
282
+ */
68
283
  declare const createUseInstanceHook: <TExtension = {}>(extension?: TExtension) => <TInstance, TPayload>(factory: (config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>) => TInstance, config?: {
69
284
  payload?: TPayload;
70
285
  onUpdate?: (payload: TPayload) => void;
@@ -79,6 +294,19 @@ declare const createUseInstanceHook: <TExtension = {}>(extension?: TExtension) =
79
294
  * @param factory - A factory function that takes a configuration and returns an instance.
80
295
  * @param config - An optional configuration containing additional input parameters and an update function.
81
296
  * @returns An instance created by the factory function.
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));
301
+ * ```
302
+ *
303
+ * @example
304
+ * ```ts
305
+ * const store = useInstance(
306
+ * ({ payload }) => new UserStore(payload),
307
+ * { payload: userId, onUpdate: (nextId) => console.log(nextId) },
308
+ * );
309
+ * ```
82
310
  */
83
311
  declare const useInstance: <TInstance, TPayload>(factory: (config: {
84
312
  abortSignal: AbortSignal;
@@ -88,28 +316,198 @@ declare const useInstance: <TInstance, TPayload>(factory: (config: {
88
316
  onUpdate?: ((payload: TPayload) => void) | undefined;
89
317
  } | undefined) => TInstance;
90
318
 
319
+ /**
320
+ * Creates a single `IntersectionObserver` instance and disposes it on unmount.
321
+ *
322
+ * @param callback Observer callback invoked for intersection changes.
323
+ * @param options Optional observer configuration.
324
+ * @returns Stable `IntersectionObserver` instance.
325
+ *
326
+ * @example
327
+ * ```ts
328
+ * const observer = useIntersectionObserver((entries) => {
329
+ * console.log(entries[0]?.isIntersecting);
330
+ * });
331
+ * ```
332
+ *
333
+ * @example
334
+ * ```ts
335
+ * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });
336
+ * observer.observe(element);
337
+ * ```
338
+ */
91
339
  declare const useIntersectionObserver: (callback: IntersectionObserverCallback, options?: IntersectionObserverInit) => IntersectionObserver;
92
340
 
341
+ /**
342
+ * Remembers and returns the last non-nullish value passed to the hook.
343
+ *
344
+ * @template T Value type.
345
+ * @param value Current value that may be `null` or `undefined`.
346
+ * @returns Current value when defined, otherwise the previous defined value.
347
+ *
348
+ * @example
349
+ * ```ts
350
+ * const title = useLastDefinedValue(props.title);
351
+ * ```
352
+ *
353
+ * @example
354
+ * ```ts
355
+ * const user = useLastDefinedValue<User | null>(selectedUser);
356
+ * ```
357
+ */
93
358
  declare const useLastDefinedValue: <T>(value: T) => T;
94
359
 
360
+ /**
361
+ * Returns a ref that always points to the last non-nullish value.
362
+ *
363
+ * @template T Value type.
364
+ * @param value Current value that may temporarily become `null` or `undefined`.
365
+ * @returns Ref containing the last defined value.
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * const latestUserRef = useLastValueRef(user);
370
+ * latestUserRef.current;
371
+ * ```
372
+ *
373
+ * @example
374
+ * ```ts
375
+ * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);
376
+ * ```
377
+ */
95
378
  declare const useLastValueRef: <T>(value: T | null | undefined) => react.MutableRefObject<T | null | undefined>;
96
379
 
380
+ /**
381
+ * Runs mount and unmount callbacks returned by a factory function.
382
+ *
383
+ * The latest factory is stored in a ref, while the effect itself is only
384
+ * subscribed once.
385
+ *
386
+ * @param fn Factory returning optional `mount` and `unmount` handlers.
387
+ *
388
+ * @example
389
+ * ```ts
390
+ * useLifeCycle(() => ({
391
+ * mount: () => console.log('mounted'),
392
+ * unmount: () => console.log('unmounted'),
393
+ * }));
394
+ * ```
395
+ *
396
+ * @example
397
+ * ```ts
398
+ * useLifeCycle(() => ({
399
+ * mount: subscribe,
400
+ * unmount: unsubscribe,
401
+ * }));
402
+ * ```
403
+ */
97
404
  declare const useLifeCycle: (fn: () => {
98
405
  mount?: VoidFunction;
99
406
  unmount?: VoidFunction;
100
407
  }) => void;
101
408
 
409
+ /**
410
+ * Creates a stable `ResizeObserver` instance and disconnects it on unmount.
411
+ *
412
+ * @param callback Resize observer callback.
413
+ * @returns Ref containing the observer instance.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * const observerRef = useResizeObserver((entries) => {
418
+ * console.log(entries[0]?.contentRect.width);
419
+ * });
420
+ * ```
421
+ *
422
+ * @example
423
+ * ```ts
424
+ * const resizeObserver = useResizeObserver(handleResize);
425
+ * resizeObserver.current.observe(element);
426
+ * ```
427
+ */
102
428
  declare const useResizeObserver: (callback: ResizeObserverCallback) => react.MutableRefObject<ResizeObserver>;
103
429
 
430
+ /**
431
+ * Returns a ref whose `current` value is synchronized with the latest input
432
+ * on every render.
433
+ *
434
+ * @template T Value type.
435
+ * @param value Current value to expose through the ref.
436
+ * @returns Ref containing the latest value.
437
+ *
438
+ * @example
439
+ * ```ts
440
+ * const latestHandler = useSyncRef(onSubmit);
441
+ * latestHandler.current();
442
+ * ```
443
+ *
444
+ * @example
445
+ * ```ts
446
+ * const latestValue = useSyncRef(props.value);
447
+ * latestValue.current;
448
+ * ```
449
+ */
104
450
  declare const useSyncRef: <T>(value: T) => react.MutableRefObject<T>;
105
451
 
452
+ /**
453
+ * Manages a boolean state and returns helpers to toggle or set it directly.
454
+ *
455
+ * @param initialState Initial boolean value.
456
+ * @returns Tuple with current state, toggle callback and raw setter.
457
+ *
458
+ * @example
459
+ * ```ts
460
+ * const [open, toggleOpen] = useToggle();
461
+ * toggleOpen();
462
+ * ```
463
+ *
464
+ * @example
465
+ * ```ts
466
+ * const [enabled, , setEnabled] = useToggle(true);
467
+ * setEnabled(false);
468
+ * ```
469
+ */
106
470
  declare const useToggle: (initialState?: boolean) => readonly [boolean, () => void, react.Dispatch<react.SetStateAction<boolean>>];
107
471
 
472
+ /**
473
+ * Wraps `useState` and returns the state value as an object with a `set` method.
474
+ *
475
+ * @template T State value type.
476
+ * @param defaults Initial state value or lazy initializer.
477
+ * @returns Object containing the current value and setter.
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * const counter = useValue(0);
482
+ * counter.set(1);
483
+ * ```
484
+ *
485
+ * @example
486
+ * ```ts
487
+ * const user = useValue(() => ({ name: 'Ann' }));
488
+ * user.value.name;
489
+ * ```
490
+ */
108
491
  declare const useValue: <T>(defaults: T | (() => T)) => {
109
492
  value: T;
110
493
  set: react.Dispatch<react.SetStateAction<T>>;
111
494
  };
112
495
 
496
+ /**
497
+ * Tracks `document.visibilityState` and updates when the page visibility changes.
498
+ *
499
+ * @returns Current document visibility state.
500
+ *
501
+ * @example
502
+ * ```ts
503
+ * const visibility = useVisibilityState();
504
+ * ```
505
+ *
506
+ * @example
507
+ * ```ts
508
+ * const isHidden = useVisibilityState() === 'hidden';
509
+ * ```
510
+ */
113
511
  declare const useVisibilityState: () => DocumentVisibilityState | undefined;
114
512
 
115
513
  export { attachRefs, createUseInstanceHook, useAbortController, useAbortSignal, useClickOutside, useConstant, useDefineRef, useElementRef, useEvent, useEventListener, useFlag, useForceUpdate, useInitialHeight, useInstance, useIntersectionObserver, useLastDefinedValue, useLastValueRef, useLifeCycle, useResizeObserver, useSyncRef, useToggle, useValue, useVisibilityState };
package/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n * useMemo doesn't give this guarantee unfortunately -\n * https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily\n * https://reactjs.org/docs/hooks-reference.html#usememo\n * @param defineValue Function which returns defined value.\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n * useMemo doesn't give this guarantee unfortunately -\n * https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily\n * https://reactjs.org/docs/hooks-reference.html#usememo\n * @param defineFn Function which returns defined value.\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","/**\n * A Hook to define an event handler with an always-stable function identity.\n *\n * borrowed from @gaeron\n * https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md\n */\nimport { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"names":["toggled"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Assigns the same value to multiple React refs, including callback refs.\n *\n * @template T Referenced value type.\n * @param value Value that should be written into every provided ref.\n * @param refs Target refs to update.\n *\n * @example\n * ```ts\n * attachRefs(node, localRef, forwardedRef);\n * ```\n *\n * @example\n * ```ts\n * attachRefs(null, inputRef, (value) => console.log(value));\n * ```\n */\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n *\n * Unlike `useMemo`, this guarantees that the initializer is executed only once\n * for the component lifetime.\n *\n * @template T Value type.\n * @param defineValue Function that lazily creates the value.\n * @returns Stable value created on the first render.\n *\n * @example\n * ```ts\n * const id = useConstant(() => crypto.randomUUID());\n * ```\n *\n * @example\n * ```ts\n * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));\n * ```\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\n/**\n * Creates a single `AbortController` instance for the component lifetime.\n *\n * The controller is aborted automatically during unmount.\n *\n * @returns Stable abort controller instance.\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * fetch('/api', { signal: controller.signal });\n * ```\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * controller.abort();\n * ```\n */\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\n/**\n * Returns an `AbortSignal` tied to the component lifecycle.\n *\n * The signal is aborted automatically on unmount.\n *\n * @returns Lifecycle-bound abort signal.\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * fetch('/api/users', { signal });\n * ```\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * someAsyncTask({ signal });\n * ```\n */\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref whose `current` value is synchronized with the latest input\n * on every render.\n *\n * @template T Value type.\n * @param value Current value to expose through the ref.\n * @returns Ref containing the latest value.\n *\n * @example\n * ```ts\n * const latestHandler = useSyncRef(onSubmit);\n * latestHandler.current();\n * ```\n *\n * @example\n * ```ts\n * const latestValue = useSyncRef(props.value);\n * latestValue.current;\n * ```\n */\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Subscribes to a DOM event and keeps the latest handler without resubscribing\n * on every render.\n *\n * Supports optional debounce and custom effect dependencies.\n *\n * @template EventName DOM event name from `HTMLElementEventMap`.\n * @param config Event subscription configuration.\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'click',\n * handler: () => console.log('clicked'),\n * });\n * ```\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'scroll',\n * node: window,\n * debounce: 100,\n * handler: () => console.log('scroll'),\n * });\n * ```\n */\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\n/**\n * Calls a handler when a pointer interaction happens outside the referenced element.\n *\n * @param input Target element ref, callback and event listener options.\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: modalRef,\n * onClick: () => closeModal(),\n * });\n * ```\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: dropdownRef,\n * onClick: hideDropdown,\n * options: { capture: true },\n * });\n * ```\n */\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * Creates a mutable ref whose value is initialized exactly once.\n *\n * @template T Ref value type.\n * @param defineFn Function that lazily creates the initial ref value.\n * @returns Mutable ref with a stable initialized value.\n *\n * @example\n * ```ts\n * const cacheRef = useDefineRef(() => new Map());\n * ```\n *\n * @example\n * ```ts\n * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));\n * ```\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\n/**\n * Resolves an element once after mount and stores it in a ref.\n *\n * @template T Element type.\n * @param selector Function returning the target element.\n * @returns Ref containing the selected element.\n *\n * @example\n * ```ts\n * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);\n * ```\n *\n * @example\n * ```ts\n * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);\n * ```\n */\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","/**\n * Creates an event callback with a stable function identity and up-to-date logic.\n *\n * Borrowed from the `useEvent` RFC idea by React contributors.\n *\n * @template H Handler function type.\n * @param handler Latest callback implementation.\n * @returns Stable callback that always delegates to the latest handler.\n *\n * @example\n * ```ts\n * const onClick = useEvent(() => {\n * console.log('clicked');\n * });\n * ```\n *\n * @example\n * ```ts\n * const onSubmit = useEvent((value: string) => save(value));\n * ```\n */\nimport { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\n/**\n * Manages a reusable boolean flag object with stable helper methods.\n *\n * @param defaultValue Initial enabled state.\n * @returns Stable object exposing current state and mutators.\n *\n * @example\n * ```ts\n * const modal = useFlag();\n * modal.enable();\n * ```\n *\n * @example\n * ```ts\n * const loading = useFlag(true);\n * loading.disable();\n * ```\n */\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Forces a component re-render by updating an internal dummy state.\n *\n * @returns Stable callback that triggers a re-render.\n *\n * @example\n * ```ts\n * const forceUpdate = useForceUpdate();\n * forceUpdate();\n * ```\n *\n * @example\n * ```ts\n * const rerender = useForceUpdate();\n * setTimeout(rerender, 1000);\n * ```\n */\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Captures an element's height the first time its ref becomes available.\n *\n * @template T Element type attached to the returned ref.\n * @returns Ref and the initial measured height.\n *\n * @example\n * ```ts\n * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();\n * ```\n *\n * @example\n * ```ts\n * const state = useInitialHeight<HTMLTextAreaElement>();\n * state.initialHeight;\n * ```\n */\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\n/**\n * Builds a custom hook that creates an instance once and wires lifecycle helpers\n * such as an `AbortSignal` and optional extension data into the factory.\n *\n * @template TExtension Extra configuration injected into every factory call.\n * @param extension Optional static extension object merged into the factory config.\n * @returns Hook factory that creates stable instances from a supplied factory.\n *\n * @example\n * ```ts\n * const useStoreInstance = createUseInstanceHook({ api });\n * ```\n *\n * @example\n * ```ts\n * const useService = createUseInstanceHook({ logger });\n * const service = useService(({ logger, payload }) => new Service(logger, payload));\n * ```\n */\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n *\n * @example\n * ```ts\n * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));\n * ```\n *\n * @example\n * ```ts\n * const store = useInstance(\n * ({ payload }) => new UserStore(payload),\n * { payload: userId, onUpdate: (nextId) => console.log(nextId) },\n * );\n * ```\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\n/**\n * Creates a single `IntersectionObserver` instance and disposes it on unmount.\n *\n * @param callback Observer callback invoked for intersection changes.\n * @param options Optional observer configuration.\n * @returns Stable `IntersectionObserver` instance.\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver((entries) => {\n * console.log(entries[0]?.isIntersecting);\n * });\n * ```\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });\n * observer.observe(element);\n * ```\n */\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\n/**\n * Remembers and returns the last non-nullish value passed to the hook.\n *\n * @template T Value type.\n * @param value Current value that may be `null` or `undefined`.\n * @returns Current value when defined, otherwise the previous defined value.\n *\n * @example\n * ```ts\n * const title = useLastDefinedValue(props.title);\n * ```\n *\n * @example\n * ```ts\n * const user = useLastDefinedValue<User | null>(selectedUser);\n * ```\n */\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref that always points to the last non-nullish value.\n *\n * @template T Value type.\n * @param value Current value that may temporarily become `null` or `undefined`.\n * @returns Ref containing the last defined value.\n *\n * @example\n * ```ts\n * const latestUserRef = useLastValueRef(user);\n * latestUserRef.current;\n * ```\n *\n * @example\n * ```ts\n * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);\n * ```\n */\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Runs mount and unmount callbacks returned by a factory function.\n *\n * The latest factory is stored in a ref, while the effect itself is only\n * subscribed once.\n *\n * @param fn Factory returning optional `mount` and `unmount` handlers.\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: () => console.log('mounted'),\n * unmount: () => console.log('unmounted'),\n * }));\n * ```\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: subscribe,\n * unmount: unsubscribe,\n * }));\n * ```\n */\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\n/**\n * Creates a stable `ResizeObserver` instance and disconnects it on unmount.\n *\n * @param callback Resize observer callback.\n * @returns Ref containing the observer instance.\n *\n * @example\n * ```ts\n * const observerRef = useResizeObserver((entries) => {\n * console.log(entries[0]?.contentRect.width);\n * });\n * ```\n *\n * @example\n * ```ts\n * const resizeObserver = useResizeObserver(handleResize);\n * resizeObserver.current.observe(element);\n * ```\n */\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Manages a boolean state and returns helpers to toggle or set it directly.\n *\n * @param initialState Initial boolean value.\n * @returns Tuple with current state, toggle callback and raw setter.\n *\n * @example\n * ```ts\n * const [open, toggleOpen] = useToggle();\n * toggleOpen();\n * ```\n *\n * @example\n * ```ts\n * const [enabled, , setEnabled] = useToggle(true);\n * setEnabled(false);\n * ```\n */\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\n/**\n * Wraps `useState` and returns the state value as an object with a `set` method.\n *\n * @template T State value type.\n * @param defaults Initial state value or lazy initializer.\n * @returns Object containing the current value and setter.\n *\n * @example\n * ```ts\n * const counter = useValue(0);\n * counter.set(1);\n * ```\n *\n * @example\n * ```ts\n * const user = useValue(() => ({ name: 'Ann' }));\n * user.value.name;\n * ```\n */\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * Tracks `document.visibilityState` and updates when the page visibility changes.\n *\n * @returns Current document visibility state.\n *\n * @example\n * ```ts\n * const visibility = useVisibilityState();\n * ```\n *\n * @example\n * ```ts\n * const isHidden = useVisibilityState() === 'hidden';\n * ```\n */\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"names":["toggled"],"mappings":"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"}
package/sound.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sound.cjs","sources":["../src/sound.ts"],"sourcesContent":["/**\n * Воспроизводит звук из файла\n */\nexport const playSound = async (\n file: string,\n { volume = 1 }: { volume?: number } = {},\n) => {\n let audio = new Audio(file);\n audio.volume = volume;\n audio.muted = !volume;\n await audio.play();\n audio.remove();\n // @ts-expect-error\n audio = null;\n};\n"],"names":[],"mappings":";;AAGO,MAAM,YAAY,OACvB,MACA,EAAE,SAAS,EAAA,IAA2B,CAAA,MACnC;AACH,MAAI,QAAQ,IAAI,MAAM,IAAI;AAC1B,QAAM,SAAS;AACf,QAAM,QAAQ,CAAC;AACf,QAAM,MAAM,KAAA;AACZ,QAAM,OAAA;AAEN,UAAQ;AACV;;"}
1
+ {"version":3,"file":"sound.cjs","sources":["../src/sound.ts"],"sourcesContent":["/**\n * Plays a sound from a file.\n */\nexport const playSound = async (\n file: string,\n { volume = 1 }: { volume?: number } = {},\n) => {\n let audio = new Audio(file);\n audio.volume = volume;\n audio.muted = !volume;\n await audio.play();\n audio.remove();\n // @ts-expect-error\n audio = null;\n};\n"],"names":[],"mappings":";;AAGO,MAAM,YAAY,OACvB,MACA,EAAE,SAAS,EAAA,IAA2B,CAAA,MACnC;AACH,MAAI,QAAQ,IAAI,MAAM,IAAI;AAC1B,QAAM,SAAS;AACf,QAAM,QAAQ,CAAC;AACf,QAAM,MAAM,KAAA;AACZ,QAAM,OAAA;AAEN,UAAQ;AACV;;"}
package/sound.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Воспроизводит звук из файла
2
+ * Plays a sound from a file.
3
3
  */
4
4
  declare const playSound: (file: string, { volume }?: {
5
5
  volume?: number;
package/sound.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sound.js","sources":["../src/sound.ts"],"sourcesContent":["/**\n * Воспроизводит звук из файла\n */\nexport const playSound = async (\n file: string,\n { volume = 1 }: { volume?: number } = {},\n) => {\n let audio = new Audio(file);\n audio.volume = volume;\n audio.muted = !volume;\n await audio.play();\n audio.remove();\n // @ts-expect-error\n audio = null;\n};\n"],"names":[],"mappings":"AAGO,MAAM,YAAY,OACvB,MACA,EAAE,SAAS,EAAA,IAA2B,CAAA,MACnC;AACH,MAAI,QAAQ,IAAI,MAAM,IAAI;AAC1B,QAAM,SAAS;AACf,QAAM,QAAQ,CAAC;AACf,QAAM,MAAM,KAAA;AACZ,QAAM,OAAA;AAEN,UAAQ;AACV;"}
1
+ {"version":3,"file":"sound.js","sources":["../src/sound.ts"],"sourcesContent":["/**\n * Plays a sound from a file.\n */\nexport const playSound = async (\n file: string,\n { volume = 1 }: { volume?: number } = {},\n) => {\n let audio = new Audio(file);\n audio.volume = volume;\n audio.muted = !volume;\n await audio.play();\n audio.remove();\n // @ts-expect-error\n audio = null;\n};\n"],"names":[],"mappings":"AAGO,MAAM,YAAY,OACvB,MACA,EAAE,SAAS,EAAA,IAA2B,CAAA,MACnC;AACH,MAAI,QAAQ,IAAI,MAAM,IAAI;AAC1B,QAAM,SAAS;AACf,QAAM,QAAQ,CAAC;AACf,QAAM,MAAM,KAAA;AACZ,QAAM,OAAA;AAEN,UAAQ;AACV;"}
package/storage.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"storage.cjs","sources":["../src/storage.ts"],"sourcesContent":["export type StorageType = 'session' | 'local';\n\nconst storages: Record<StorageType, Storage> = {\n session: sessionStorage,\n local: localStorage,\n};\n\nexport const createKey = (prefix: string, key: string, namespace?: string) =>\n `${prefix}${namespace ? `/${namespace}` : ''}/${key}`;\n\nconst parseStorageValue = <V>(value: unknown): V | null => {\n if (typeof value !== 'string') {\n return value as V;\n }\n\n try {\n const parsed = JSON.parse(value);\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst formatValueToStorage = (value: unknown): string => {\n return JSON.stringify(value);\n};\n\nexport interface SetToStorageConfig<V>\n extends Omit<GetFromStorageConfig<V>, 'fallback'> {\n value: V;\n}\n\nexport interface UnsetFromStorageConfig\n extends Omit<GetFromStorageConfig<any>, 'fallback'> {}\n\nexport interface GetFromStorageConfig<V> {\n /**\n * Ключ по которому можно получить значение из хранилища (имя ключа не полное, оно дополняется неймпспейсом проекта)\n */\n key: string;\n /**\n * Тип хранилища\n */\n type: StorageType;\n /**\n * дефолтное значение, которое будет использоваться если значения нет в хранилище\n */\n fallback?: V;\n /**\n * Доп. делитель в ключ/utils/types'е\n */\n namespace?: string;\n /**\n * Доп. делитель\n */\n prefix?: string;\n}\n\nexport type SetToStorageWrappedConfig<\n V,\n BaseConfig extends StorageConfigBase,\n> = Omit<\n SetToStorageConfig<V>,\n Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n> &\n Partial<\n Pick<\n SetToStorageConfig<V>,\n Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof SetToStorageConfig<V>>>;\n\nexport type UnsetFromStorageWrappedConfig<\n BaseConfig extends StorageConfigBase,\n> = Omit<\n UnsetFromStorageConfig,\n Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n> &\n Partial<\n Pick<\n UnsetFromStorageConfig,\n Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof UnsetFromStorageConfig>>;\n\nexport type GetFromStorageWrappedConfig<\n V,\n BaseConfig extends StorageConfigBase,\n> = Omit<\n GetFromStorageConfig<V>,\n Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n> &\n Partial<\n Pick<\n GetFromStorageConfig<V>,\n Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof GetFromStorageConfig<V>>>;\n\nexport type StorageConfigBase = Partial<\n Pick<GetFromStorageConfig<any>, 'prefix' | 'type'>\n>;\n\nexport interface StorageApi<BaseConfig extends StorageConfigBase> {\n set<Value>(config: SetToStorageWrappedConfig<Value, BaseConfig>): void;\n unset(config: UnsetFromStorageWrappedConfig<BaseConfig>): void;\n get<Value>(\n config: GetFromStorageWrappedConfig<Value, BaseConfig>,\n ): Value | null;\n}\n\n/**\n * Создает интерфейс для работы с хранилищем (localStorage, sessionStorage)\n */\nexport function createStorage<BaseConfig extends StorageConfigBase>(\n storageConfig: BaseConfig,\n): StorageApi<BaseConfig> {\n return {\n set: <Value>(cfg: SetToStorageWrappedConfig<Value, BaseConfig>) => {\n const config = cfg as unknown as SetToStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n const storage = storages[storageType];\n\n storage.setItem(\n createKey(storagePrefix, config.key, config.namespace),\n formatValueToStorage(config.value),\n );\n },\n unset: <Value>(cfg: UnsetFromStorageWrappedConfig<BaseConfig>) => {\n const config = cfg as unknown as SetToStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n const storage = storages[storageType];\n\n storage.removeItem(\n createKey(storagePrefix, config.key, config.namespace),\n );\n },\n get: <Value>(cfg: GetFromStorageWrappedConfig<Value, BaseConfig>) => {\n const config = cfg as unknown as GetFromStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n const storage = storages[storageType];\n\n return (\n parseStorageValue<Value>(\n storage.getItem(\n createKey(storagePrefix, config.key, config.namespace),\n ),\n ) ??\n config.fallback ??\n null\n );\n },\n } as const;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,WAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,OAAO;AACT;AAEO,MAAM,YAAY,CAAC,QAAgB,KAAa,cACrD,GAAG,MAAM,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE,IAAI,GAAG;AAErD,MAAM,oBAAoB,CAAI,UAA6B;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,uBAAuB,CAAC,UAA2B;AACvD,SAAO,KAAK,UAAU,KAAK;AAC7B;AA4FO,SAAS,cACd,eACwB;AACxB,SAAO;AAAA,IACL,KAAK,CAAQ,QAAsD;AACjE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AAEtD,YAAM,UAAU,SAAS,WAAW;AAEpC,cAAQ;AAAA,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,QACrD,qBAAqB,OAAO,KAAK;AAAA,MAAA;AAAA,IAErC;AAAA,IACA,OAAO,CAAQ,QAAmD;AAChE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AACtD,YAAM,UAAU,SAAS,WAAW;AAEpC,cAAQ;AAAA,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,MAAA;AAAA,IAEzD;AAAA,IACA,KAAK,CAAQ,QAAwD;AACnE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AAEtD,YAAM,UAAU,SAAS,WAAW;AAEpC,aACE;AAAA,QACE,QAAQ;AAAA,UACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,QAAA;AAAA,MACvD,KAEF,OAAO,YACP;AAAA,IAEJ;AAAA,EAAA;AAEJ;;;"}
1
+ {"version":3,"file":"storage.cjs","sources":["../src/storage.ts"],"sourcesContent":["export type StorageType = 'session' | 'local';\n\nconst storages: Record<StorageType, Storage> = {\n session: sessionStorage,\n local: localStorage,\n};\n\nexport const createKey = (prefix: string, key: string, namespace?: string) =>\n `${prefix}${namespace ? `/${namespace}` : ''}/${key}`;\n\nconst parseStorageValue = <V>(value: unknown): V | null => {\n if (typeof value !== 'string') {\n return value as V;\n }\n\n try {\n const parsed = JSON.parse(value);\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst formatValueToStorage = (value: unknown): string => {\n return JSON.stringify(value);\n};\n\nexport interface SetToStorageConfig<V>\n extends Omit<GetFromStorageConfig<V>, 'fallback'> {\n value: V;\n}\n\nexport interface UnsetFromStorageConfig\n extends Omit<GetFromStorageConfig<any>, 'fallback'> {}\n\nexport interface GetFromStorageConfig<V> {\n /**\n * Storage key used to retrieve the value.\n * The full key is extended with the project namespace.\n */\n key: string;\n /**\n * Storage type.\n */\n type: StorageType;\n /**\n * Default value used when there is no value in storage.\n */\n fallback?: V;\n /**\n * Optional namespace segment used in the generated key.\n */\n namespace?: string;\n /**\n * Optional key prefix.\n */\n prefix?: string;\n}\n\nexport type SetToStorageWrappedConfig<\n V,\n BaseConfig extends StorageConfigBase,\n> = Omit<\n SetToStorageConfig<V>,\n Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n> &\n Partial<\n Pick<\n SetToStorageConfig<V>,\n Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof SetToStorageConfig<V>>>;\n\nexport type UnsetFromStorageWrappedConfig<\n BaseConfig extends StorageConfigBase,\n> = Omit<\n UnsetFromStorageConfig,\n Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n> &\n Partial<\n Pick<\n UnsetFromStorageConfig,\n Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof UnsetFromStorageConfig>>;\n\nexport type GetFromStorageWrappedConfig<\n V,\n BaseConfig extends StorageConfigBase,\n> = Omit<\n GetFromStorageConfig<V>,\n Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n> &\n Partial<\n Pick<\n GetFromStorageConfig<V>,\n Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n >\n > &\n Pick<BaseConfig, Exclude<keyof BaseConfig, keyof GetFromStorageConfig<V>>>;\n\nexport type StorageConfigBase = Partial<\n Pick<GetFromStorageConfig<any>, 'prefix' | 'type'>\n>;\n\nexport interface StorageApi<BaseConfig extends StorageConfigBase> {\n set<Value>(config: SetToStorageWrappedConfig<Value, BaseConfig>): void;\n unset(config: UnsetFromStorageWrappedConfig<BaseConfig>): void;\n get<Value>(\n config: GetFromStorageWrappedConfig<Value, BaseConfig>,\n ): Value | null;\n}\n\n/**\n * Creates an interface for working with storage (`localStorage`, `sessionStorage`).\n */\nexport function createStorage<BaseConfig extends StorageConfigBase>(\n storageConfig: BaseConfig,\n): StorageApi<BaseConfig> {\n return {\n set: <Value>(cfg: SetToStorageWrappedConfig<Value, BaseConfig>) => {\n const config = cfg as unknown as SetToStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n const storage = storages[storageType];\n\n storage.setItem(\n createKey(storagePrefix, config.key, config.namespace),\n formatValueToStorage(config.value),\n );\n },\n unset: <Value>(cfg: UnsetFromStorageWrappedConfig<BaseConfig>) => {\n const config = cfg as unknown as SetToStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n const storage = storages[storageType];\n\n storage.removeItem(\n createKey(storagePrefix, config.key, config.namespace),\n );\n },\n get: <Value>(cfg: GetFromStorageWrappedConfig<Value, BaseConfig>) => {\n const config = cfg as unknown as GetFromStorageConfig<Value>;\n const storageType = (config.type ?? storageConfig.type!) as StorageType;\n const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n const storage = storages[storageType];\n\n return (\n parseStorageValue<Value>(\n storage.getItem(\n createKey(storagePrefix, config.key, config.namespace),\n ),\n ) ??\n config.fallback ??\n null\n );\n },\n } as const;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,WAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,OAAO;AACT;AAEO,MAAM,YAAY,CAAC,QAAgB,KAAa,cACrD,GAAG,MAAM,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE,IAAI,GAAG;AAErD,MAAM,oBAAoB,CAAI,UAA6B;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,uBAAuB,CAAC,UAA2B;AACvD,SAAO,KAAK,UAAU,KAAK;AAC7B;AA6FO,SAAS,cACd,eACwB;AACxB,SAAO;AAAA,IACL,KAAK,CAAQ,QAAsD;AACjE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AAEtD,YAAM,UAAU,SAAS,WAAW;AAEpC,cAAQ;AAAA,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,QACrD,qBAAqB,OAAO,KAAK;AAAA,MAAA;AAAA,IAErC;AAAA,IACA,OAAO,CAAQ,QAAmD;AAChE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AACtD,YAAM,UAAU,SAAS,WAAW;AAEpC,cAAQ;AAAA,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,MAAA;AAAA,IAEzD;AAAA,IACA,KAAK,CAAQ,QAAwD;AACnE,YAAM,SAAS;AACf,YAAM,cAAe,OAAO,QAAQ,cAAc;AAClD,YAAM,gBAAiB,OAAO,UAAU,cAAc;AAEtD,YAAM,UAAU,SAAS,WAAW;AAEpC,aACE;AAAA,QACE,QAAQ;AAAA,UACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS;AAAA,QAAA;AAAA,MACvD,KAEF,OAAO,YACP;AAAA,IAEJ;AAAA,EAAA;AAEJ;;;"}