yummies 7.11.0 → 7.12.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 (146) hide show
  1. package/async.cjs +162 -48
  2. package/async.cjs.map +1 -1
  3. package/async.d.ts +108 -7
  4. package/async.js +163 -54
  5. package/async.js.map +1 -1
  6. package/chunk-CVq3Gv4J.cjs +50 -0
  7. package/chunk-YKewjYmz.js +37 -0
  8. package/common.cjs +48 -8
  9. package/common.cjs.map +1 -1
  10. package/common.d.ts +35 -2
  11. package/common.js +49 -11
  12. package/common.js.map +1 -1
  13. package/complex.cjs +275 -128
  14. package/complex.cjs.map +1 -1
  15. package/complex.js +275 -133
  16. package/complex.js.map +1 -1
  17. package/cookie.cjs +17 -7
  18. package/cookie.cjs.map +1 -1
  19. package/cookie.d.ts +8 -0
  20. package/cookie.js +18 -9
  21. package/cookie.js.map +1 -1
  22. package/css.cjs +147 -39
  23. package/css.cjs.map +1 -1
  24. package/css.d.ts +98 -6
  25. package/css.js +143 -41
  26. package/css.js.map +1 -1
  27. package/data.cjs +90 -55
  28. package/data.cjs.map +1 -1
  29. package/data.d.ts +32 -0
  30. package/data.js +91 -61
  31. package/data.js.map +1 -1
  32. package/date-time.cjs +578 -412
  33. package/date-time.cjs.map +1 -1
  34. package/date-time.d.ts +88 -0
  35. package/date-time.js +575 -421
  36. package/date-time.js.map +1 -1
  37. package/device.cjs +48 -23
  38. package/device.cjs.map +1 -1
  39. package/device.d.ts +32 -0
  40. package/device.js +49 -31
  41. package/device.js.map +1 -1
  42. package/encodings.cjs +275 -266
  43. package/encodings.cjs.map +1 -1
  44. package/encodings.d.ts +8 -0
  45. package/encodings.js +276 -268
  46. package/encodings.js.map +1 -1
  47. package/errors.cjs +20 -18
  48. package/errors.cjs.map +1 -1
  49. package/errors.js +19 -19
  50. package/errors.js.map +1 -1
  51. package/file.cjs +42 -24
  52. package/file.cjs.map +1 -1
  53. package/file.d.ts +16 -0
  54. package/file.js +43 -27
  55. package/file.js.map +1 -1
  56. package/format.cjs +125 -83
  57. package/format.cjs.map +1 -1
  58. package/format.js +118 -82
  59. package/format.js.map +1 -1
  60. package/html.cjs +226 -137
  61. package/html.cjs.map +1 -1
  62. package/html.d.ts +64 -0
  63. package/html.js +223 -150
  64. package/html.js.map +1 -1
  65. package/id.cjs +74 -17
  66. package/id.cjs.map +1 -1
  67. package/id.js +73 -24
  68. package/id.js.map +1 -1
  69. package/imports.cjs +41 -29
  70. package/imports.cjs.map +1 -1
  71. package/imports.d.ts +8 -0
  72. package/imports.js +40 -31
  73. package/imports.js.map +1 -1
  74. package/math.cjs +32 -6
  75. package/math.cjs.map +1 -1
  76. package/math.d.ts +16 -0
  77. package/math.js +33 -10
  78. package/math.js.map +1 -1
  79. package/media.cjs +275 -84
  80. package/media.cjs.map +1 -1
  81. package/media.d.ts +188 -2
  82. package/media.js +274 -93
  83. package/media.js.map +1 -1
  84. package/mobx.cjs +353 -193
  85. package/mobx.cjs.map +1 -1
  86. package/mobx.d.ts +7 -0
  87. package/mobx.js +351 -200
  88. package/mobx.js.map +1 -1
  89. package/ms.cjs +21 -10
  90. package/ms.cjs.map +1 -1
  91. package/ms.js +22 -13
  92. package/ms.js.map +1 -1
  93. package/number.cjs +13 -7
  94. package/number.cjs.map +1 -1
  95. package/number.js +14 -9
  96. package/number.js.map +1 -1
  97. package/package.json +10 -2
  98. package/parser.cjs +117 -64
  99. package/parser.cjs.map +1 -1
  100. package/parser.js +111 -64
  101. package/parser.js.map +1 -1
  102. package/price.cjs +24 -18
  103. package/price.cjs.map +1 -1
  104. package/price.d.ts +8 -0
  105. package/price.js +25 -20
  106. package/price.js.map +1 -1
  107. package/random.cjs +79 -13
  108. package/random.cjs.map +1 -1
  109. package/random.d.ts +64 -0
  110. package/random.js +80 -22
  111. package/random.js.map +1 -1
  112. package/react.cjs +673 -214
  113. package/react.cjs.map +1 -1
  114. package/react.d.ts +21 -0
  115. package/react.js +674 -239
  116. package/react.js.map +1 -1
  117. package/sound.cjs +14 -9
  118. package/sound.cjs.map +1 -1
  119. package/sound.js +15 -11
  120. package/sound.js.map +1 -1
  121. package/storage.cjs +49 -50
  122. package/storage.cjs.map +1 -1
  123. package/storage.d.ts +8 -0
  124. package/storage.js +50 -53
  125. package/storage.js.map +1 -1
  126. package/text.cjs +51 -34
  127. package/text.cjs.map +1 -1
  128. package/text.js +52 -37
  129. package/text.js.map +1 -1
  130. package/type-guard.cjs +292 -72
  131. package/type-guard.cjs.map +1 -1
  132. package/type-guard.js +288 -73
  133. package/type-guard.js.map +1 -1
  134. package/types.cjs +0 -2
  135. package/types.global.cjs +0 -2
  136. package/types.global.js +0 -2
  137. package/types.js +0 -2
  138. package/vibrate.cjs +31 -6
  139. package/vibrate.cjs.map +1 -1
  140. package/vibrate.d.ts +23 -1
  141. package/vibrate.js +32 -8
  142. package/vibrate.js.map +1 -1
  143. package/types.cjs.map +0 -1
  144. package/types.global.cjs.map +0 -1
  145. package/types.global.js.map +0 -1
  146. package/types.js.map +0 -1
package/mobx.js CHANGED
@@ -1,208 +1,359 @@
1
- import { makeObservable, createAtom, comparer, observable, runInAction, action, $mobx, onBecomeObserved, onBecomeUnobserved } from "mobx";
2
1
  import { typeGuard } from "yummies/type-guard";
3
- const applyObservable = (context, annotationsArray, useDecorators) => {
4
- if (useDecorators) {
5
- annotationsArray.forEach(([annotation, ...fields]) => {
6
- fields.forEach((field) => {
7
- annotation(context, field);
8
- });
9
- });
10
- makeObservable(context);
11
- } else {
12
- const annotationsObject = {};
13
- annotationsArray.forEach(([annotation, ...fields]) => {
14
- fields.forEach((field) => {
15
- annotationsObject[field] = annotation;
16
- });
17
- });
18
- makeObservable(context, annotationsObject);
19
- }
2
+ import { $mobx, action, comparer, createAtom, makeObservable, observable, onBecomeObserved, onBecomeUnobserved, runInAction } from "mobx";
3
+ //#region src/mobx/apply-observable.ts
4
+ /**
5
+ * Applies a compact list of MobX annotations to an object using either
6
+ * decorator-style invocation or the annotation map form accepted by `makeObservable`.
7
+ *
8
+ * @template T Target object type.
9
+ * @param context Object that should become observable.
10
+ * @param annotationsArray Tuples of annotation followed by annotated field names.
11
+ * @param useDecorators Enables decorator-style application before calling `makeObservable`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * applyObservable(store, [[observable, 'items'], [action, 'setItems']]);
16
+ * ```
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * applyObservable(viewModel, [[computed, 'fullName']], true);
21
+ * ```
22
+ */
23
+ var applyObservable = (context, annotationsArray, useDecorators) => {
24
+ if (useDecorators) {
25
+ annotationsArray.forEach(([annotation, ...fields]) => {
26
+ fields.forEach((field) => {
27
+ annotation(context, field);
28
+ });
29
+ });
30
+ makeObservable(context);
31
+ } else {
32
+ const annotationsObject = {};
33
+ annotationsArray.forEach(([annotation, ...fields]) => {
34
+ fields.forEach((field) => {
35
+ annotationsObject[field] = annotation;
36
+ });
37
+ });
38
+ makeObservable(context, annotationsObject);
39
+ }
20
40
  };
21
- const createEnhancedAtom = (name, onBecomeObservedHandler, onBecomeUnobservedHandler, meta) => {
22
- const atom = createAtom(
23
- name,
24
- onBecomeObservedHandler && (() => onBecomeObservedHandler(atom)),
25
- onBecomeUnobservedHandler && (() => onBecomeUnobservedHandler(atom))
26
- );
27
- atom.meta = meta ?? {};
28
- atom.reportChanged = atom.reportChanged.bind(atom);
29
- atom.reportObserved = atom.reportObserved.bind(atom);
30
- return atom;
41
+ //#endregion
42
+ //#region src/mobx/create-enhanced-atom.ts
43
+ /**
44
+ * Creates a MobX atom extended with metadata and bound reporting methods.
45
+ *
46
+ * @template TMeta Metadata object stored on the atom.
47
+ * @param name Atom name used by MobX for debugging.
48
+ * @param onBecomeObservedHandler Callback fired when the atom becomes observed.
49
+ * @param onBecomeUnobservedHandler Callback fired when the atom is no longer observed.
50
+ * @param meta Optional metadata attached to the atom.
51
+ * @returns Atom instance with `meta`, `reportChanged` and `reportObserved`.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const atom = createEnhancedAtom('user-status');
56
+ * atom.reportChanged();
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const atom = createEnhancedAtom('cache', undefined, undefined, { scope: 'users' });
62
+ * atom.meta.scope;
63
+ * ```
64
+ */
65
+ var createEnhancedAtom = (name, onBecomeObservedHandler, onBecomeUnobservedHandler, meta) => {
66
+ const atom = createAtom(name, onBecomeObservedHandler && (() => onBecomeObservedHandler(atom)), onBecomeUnobservedHandler && (() => onBecomeUnobservedHandler(atom)));
67
+ atom.meta = meta ?? {};
68
+ atom.reportChanged = atom.reportChanged.bind(atom);
69
+ atom.reportObserved = atom.reportObserved.bind(atom);
70
+ return atom;
31
71
  };
32
- const createRef = (cfg) => {
33
- let lastValue;
34
- const comparer$1 = cfg?.comparer ?? comparer.default;
35
- const setValue = (value) => {
36
- const nextValue = value ?? null;
37
- if (comparer$1(ref.current, nextValue)) {
38
- return;
39
- }
40
- runInAction(() => {
41
- const prevLastValue = lastValue;
42
- lastValue = ref.current ?? void 0;
43
- ref.current = nextValue;
44
- let isNextValueIgnored = false;
45
- ref.listeners.forEach((listener) => {
46
- const listenerResult = listener(ref.current, lastValue);
47
- if (listenerResult === false) {
48
- isNextValueIgnored = true;
49
- }
50
- });
51
- if (isNextValueIgnored) {
52
- lastValue = prevLastValue;
53
- ref.current = lastValue ?? null;
54
- } else if (ref.current === null && lastValue !== void 0) {
55
- lastValue = void 0;
56
- }
57
- });
58
- };
59
- const ref = setValue;
60
- ref.set = setValue;
61
- ref.listeners = new Set(cfg?.onChange ? [cfg.onChange] : []);
62
- if (cfg?.onSet || cfg?.onUnset) {
63
- ref.listeners.add((value, prevValue) => {
64
- if (value) {
65
- cfg.onSet?.(value, prevValue);
66
- } else {
67
- cfg.onUnset?.(prevValue);
68
- }
69
- });
70
- }
71
- ref.current = cfg?.initial ?? null;
72
- ref.meta = cfg?.meta ?? {};
73
- makeObservable(ref, {
74
- current: observable.ref,
75
- meta: observable
76
- });
77
- return ref;
72
+ //#endregion
73
+ //#region src/mobx/create-ref.ts
74
+ /**
75
+ * Creates a MobX-aware ref that behaves like a callback ref and exposes
76
+ * observable `current` and `meta` fields.
77
+ *
78
+ * @template T Referenced value type.
79
+ * @template TMeta Additional observable metadata stored on the ref.
80
+ * @param cfg Optional callbacks, initial value and comparer configuration.
81
+ * @returns Observable ref function object.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const inputRef = createRef<HTMLInputElement>();
86
+ * inputRef.set(document.createElement('input'));
87
+ * ```
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * const ref = createRef<number>();
92
+ * ref(3);
93
+ * ref.current; // 3
94
+ * ```
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const nodeRef = createRef({
99
+ * onUnset: () => console.log('detached'),
100
+ * meta: { mounted: false },
101
+ * });
102
+ * ```
103
+ */
104
+ var createRef = (cfg) => {
105
+ let lastValue;
106
+ const comparer$1 = cfg?.comparer ?? comparer.default;
107
+ const setValue = (value) => {
108
+ const nextValue = value ?? null;
109
+ if (comparer$1(ref.current, nextValue)) return;
110
+ runInAction(() => {
111
+ const prevLastValue = lastValue;
112
+ lastValue = ref.current ?? void 0;
113
+ ref.current = nextValue;
114
+ let isNextValueIgnored = false;
115
+ ref.listeners.forEach((listener) => {
116
+ if (listener(ref.current, lastValue) === false) isNextValueIgnored = true;
117
+ });
118
+ if (isNextValueIgnored) {
119
+ lastValue = prevLastValue;
120
+ ref.current = lastValue ?? null;
121
+ } else if (ref.current === null && lastValue !== void 0) lastValue = void 0;
122
+ });
123
+ };
124
+ const ref = setValue;
125
+ ref.set = setValue;
126
+ ref.listeners = new Set(cfg?.onChange ? [cfg.onChange] : []);
127
+ if (cfg?.onSet || cfg?.onUnset) ref.listeners.add((value, prevValue) => {
128
+ if (value) cfg.onSet?.(value, prevValue);
129
+ else cfg.onUnset?.(prevValue);
130
+ });
131
+ ref.current = cfg?.initial ?? null;
132
+ ref.meta = cfg?.meta ?? {};
133
+ makeObservable(ref, {
134
+ current: observable.ref,
135
+ meta: observable
136
+ });
137
+ return ref;
78
138
  };
79
- const isRef = (value) => {
80
- return typeof value === "function" && "current" in value;
139
+ /**
140
+ * Checks whether the provided value is a ref created by `createRef`.
141
+ *
142
+ * @template T Referenced value type.
143
+ * @template TMeta Ref metadata type.
144
+ * @param value Value to inspect.
145
+ * @returns `true` when the value is a ref-like function with `current`.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const ref = createRef<number>();
150
+ * isRef(ref); // true
151
+ * ```
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * isRef({ current: 1 }); // false
156
+ * ```
157
+ */
158
+ var isRef = (value) => {
159
+ return typeof value === "function" && "current" in value;
81
160
  };
82
- const toRef = (value, cfg) => {
83
- return isRef(value) ? value : createRef({ initial: value, ...cfg });
161
+ /**
162
+ * Normalizes a plain value or an existing ref into a `Ref` instance.
163
+ *
164
+ * @template T Referenced value type.
165
+ * @template TMeta Ref metadata type.
166
+ * @param value Existing ref or initial plain value.
167
+ * @param cfg Optional ref configuration applied when a new ref is created.
168
+ * @returns Existing ref or a newly created ref initialized with `value`.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * const ref = toRef(document.body);
173
+ * ref.current === document.body;
174
+ * ```
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * const existingRef = createRef<number>();
179
+ * const sameRef = toRef(existingRef);
180
+ * ```
181
+ */
182
+ var toRef = (value, cfg) => {
183
+ return isRef(value) ? value : createRef({
184
+ initial: value,
185
+ ...cfg
186
+ });
84
187
  };
85
- class DeepObservableStruct {
86
- data;
87
- constructor(data) {
88
- this.data = data;
89
- makeObservable(this, {
90
- data: observable.deep,
91
- set: action
92
- });
93
- }
94
- set(newData) {
95
- const stack = Object.keys(this.data).map((key) => [
96
- key,
97
- this.data,
98
- newData
99
- ]);
100
- let currentIndex = 0;
101
- let stackLength = stack.length;
102
- while (currentIndex < stackLength) {
103
- const [key, currObservableData, newData2] = stack[currentIndex];
104
- const newValue = newData2[key];
105
- const currValue = currObservableData[key];
106
- currentIndex++;
107
- if (key in newData2) {
108
- if (typeGuard.isObject(newValue) && typeGuard.isObject(currValue)) {
109
- const newValueKeys = Object.keys(newValue);
110
- Object.keys(currValue).forEach((childKey) => {
111
- if (!(childKey in newValue)) {
112
- delete currObservableData[key][childKey];
113
- }
114
- });
115
- newValueKeys.forEach((childKey) => {
116
- const length = stack.push([
117
- childKey,
118
- currObservableData[key],
119
- newValue
120
- ]);
121
- stackLength = length;
122
- });
123
- } else if (newValue !== currValue) {
124
- currObservableData[key] = newValue;
125
- }
126
- } else {
127
- delete currObservableData[key];
128
- }
129
- }
130
- Object.keys(newData).forEach((newDataKey) => {
131
- if (!this.data[newDataKey]) {
132
- this.data[newDataKey] = newData[newDataKey];
133
- }
134
- });
135
- }
136
- }
137
- const getMobxAdministration = (context) => context[$mobx];
138
- const lazyObserve = ({
139
- context,
140
- property,
141
- onStart,
142
- onEnd,
143
- endDelay = false
144
- }) => {
145
- let timeoutId;
146
- let metaData;
147
- const observingProps = /* @__PURE__ */ new Set();
148
- const properties = Array.isArray(property) ? property : [property];
149
- const cleanup = () => {
150
- observingProps.clear();
151
- if (endDelay === false) {
152
- onEnd?.(metaData, cleanup);
153
- metaData = void 0;
154
- return;
155
- }
156
- if (timeoutId) {
157
- clearTimeout(timeoutId);
158
- timeoutId = void 0;
159
- }
160
- timeoutId = setTimeout(() => {
161
- onEnd?.(metaData, cleanup);
162
- timeoutId = void 0;
163
- metaData = void 0;
164
- }, endDelay);
165
- };
166
- const start = (property2) => {
167
- const isAlreadyObserving = observingProps.size > 0;
168
- observingProps.add(property2);
169
- if (isAlreadyObserving) {
170
- return;
171
- }
172
- if (timeoutId) {
173
- clearTimeout(timeoutId);
174
- timeoutId = void 0;
175
- }
176
- metaData = onStart?.();
177
- };
178
- const stop = (property2) => {
179
- const isAlreadyNotObserving = !observingProps.size;
180
- observingProps.delete(property2);
181
- const isObserving = observingProps.size > 0;
182
- if (isAlreadyNotObserving || isObserving) {
183
- return;
184
- }
185
- cleanup();
186
- };
187
- properties.forEach((property2) => {
188
- if (context) {
189
- onBecomeObserved(context, property2, () => start(property2));
190
- onBecomeUnobserved(context, property2, () => stop(property2));
191
- } else {
192
- onBecomeObserved(property2, () => start(property2));
193
- onBecomeUnobserved(property2, () => stop(property2));
194
- }
195
- });
196
- return cleanup;
188
+ //#endregion
189
+ //#region src/mobx/deep-observable-struct.ts
190
+ /**
191
+ * Wraps a plain object into a deeply observable structure and allows
192
+ * patch-like updates while preserving nested observable references where possible.
193
+ *
194
+ * @template TData Observable object shape.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * const state = new DeepObservableStruct({ user: { name: 'Ann' } });
199
+ * state.set({ user: { name: 'Bob' } });
200
+ * ```
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * const state = new DeepObservableStruct({ filters: { active: true } });
205
+ * state.set({ filters: { active: false, archived: true } });
206
+ * ```
207
+ */
208
+ var DeepObservableStruct = class {
209
+ data;
210
+ constructor(data) {
211
+ this.data = data;
212
+ makeObservable(this, {
213
+ data: observable.deep,
214
+ set: action
215
+ });
216
+ }
217
+ set(newData) {
218
+ const stack = Object.keys(this.data).map((key) => [
219
+ key,
220
+ this.data,
221
+ newData
222
+ ]);
223
+ let currentIndex = 0;
224
+ let stackLength = stack.length;
225
+ while (currentIndex < stackLength) {
226
+ const [key, currObservableData, newData] = stack[currentIndex];
227
+ const newValue = newData[key];
228
+ const currValue = currObservableData[key];
229
+ currentIndex++;
230
+ if (key in newData) {
231
+ if (typeGuard.isObject(newValue) && typeGuard.isObject(currValue)) {
232
+ const newValueKeys = Object.keys(newValue);
233
+ Object.keys(currValue).forEach((childKey) => {
234
+ if (!(childKey in newValue)) delete currObservableData[key][childKey];
235
+ });
236
+ newValueKeys.forEach((childKey) => {
237
+ stackLength = stack.push([
238
+ childKey,
239
+ currObservableData[key],
240
+ newValue
241
+ ]);
242
+ });
243
+ } else if (newValue !== currValue) currObservableData[key] = newValue;
244
+ } else delete currObservableData[key];
245
+ }
246
+ Object.keys(newData).forEach((newDataKey) => {
247
+ if (!this.data[newDataKey]) this.data[newDataKey] = newData[newDataKey];
248
+ });
249
+ }
197
250
  };
198
- export {
199
- DeepObservableStruct,
200
- applyObservable,
201
- createEnhancedAtom,
202
- createRef,
203
- getMobxAdministration,
204
- isRef,
205
- lazyObserve,
206
- toRef
251
+ //#endregion
252
+ //#region src/mobx/get-mobx-administration.ts
253
+ /**
254
+ * Returns the internal MobX administration object associated with an observable target.
255
+ *
256
+ * @param context Observable object instance.
257
+ * @returns MobX administration internals stored under `$mobx`.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * const admin = getMobxAdministration(store);
262
+ * admin.name_;
263
+ * ```
264
+ *
265
+ * @example
266
+ * ```ts
267
+ * const values = getMobxAdministration(formState).values_;
268
+ * ```
269
+ */
270
+ var getMobxAdministration = (context) => context[$mobx];
271
+ //#endregion
272
+ //#region src/mobx/lazy-observe.ts
273
+ /**
274
+ * Starts side effects only while one or more MobX observables are being observed.
275
+ *
276
+ * When the first property becomes observed, `onStart` is called. When all tracked
277
+ * properties become unobserved, `onEnd` is called with the value returned by
278
+ * `onStart`. Cleanup can be delayed via `endDelay`.
279
+ *
280
+ * It uses MobX `onBecomeObserved` and `onBecomeUnobserved` hooks to perform
281
+ * lazy subscription management.
282
+ *
283
+ * @template TMetaData Data returned from `onStart` and forwarded to `onEnd`.
284
+ * @param config Configuration for tracked properties and lifecycle callbacks.
285
+ * @returns Cleanup function that clears the tracked state and runs `onEnd`.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * const stop = lazyObserve({
290
+ * context: store,
291
+ * property: 'items',
292
+ * onStart: () => api.subscribe(),
293
+ * onEnd: (subscription) => subscription.unsubscribe(),
294
+ * });
295
+ * ```
296
+ *
297
+ * @example
298
+ * ```ts
299
+ * lazyObserve({
300
+ * property: [boxA, boxB],
301
+ * onStart: () => console.log('observed'),
302
+ * endDelay: 300,
303
+ * });
304
+ * ```
305
+ */
306
+ var lazyObserve = ({ context, property, onStart, onEnd, endDelay = false }) => {
307
+ let timeoutId;
308
+ let metaData;
309
+ const observingProps = /* @__PURE__ */ new Set();
310
+ const properties = Array.isArray(property) ? property : [property];
311
+ const cleanup = () => {
312
+ observingProps.clear();
313
+ if (endDelay === false) {
314
+ onEnd?.(metaData, cleanup);
315
+ metaData = void 0;
316
+ return;
317
+ }
318
+ if (timeoutId) {
319
+ clearTimeout(timeoutId);
320
+ timeoutId = void 0;
321
+ }
322
+ timeoutId = setTimeout(() => {
323
+ onEnd?.(metaData, cleanup);
324
+ timeoutId = void 0;
325
+ metaData = void 0;
326
+ }, endDelay);
327
+ };
328
+ const start = (property) => {
329
+ const isAlreadyObserving = observingProps.size > 0;
330
+ observingProps.add(property);
331
+ if (isAlreadyObserving) return;
332
+ if (timeoutId) {
333
+ clearTimeout(timeoutId);
334
+ timeoutId = void 0;
335
+ }
336
+ metaData = onStart?.();
337
+ };
338
+ const stop = (property) => {
339
+ const isAlreadyNotObserving = !observingProps.size;
340
+ observingProps.delete(property);
341
+ const isObserving = observingProps.size > 0;
342
+ if (isAlreadyNotObserving || isObserving) return;
343
+ cleanup();
344
+ };
345
+ properties.forEach((property) => {
346
+ if (context) {
347
+ onBecomeObserved(context, property, () => start(property));
348
+ onBecomeUnobserved(context, property, () => stop(property));
349
+ } else {
350
+ onBecomeObserved(property, () => start(property));
351
+ onBecomeUnobserved(property, () => stop(property));
352
+ }
353
+ });
354
+ return cleanup;
207
355
  };
208
- //# sourceMappingURL=mobx.js.map
356
+ //#endregion
357
+ export { DeepObservableStruct, applyObservable, createEnhancedAtom, createRef, getMobxAdministration, isRef, lazyObserve, toRef };
358
+
359
+ //# sourceMappingURL=mobx.js.map
package/mobx.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mobx.js","sources":["../src/mobx/apply-observable.ts","../src/mobx/create-enhanced-atom.ts","../src/mobx/create-ref.ts","../src/mobx/deep-observable-struct.ts","../src/mobx/get-mobx-administration.ts","../src/mobx/lazy-observe.ts"],"sourcesContent":["import { type AnnotationMapEntry, makeObservable } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\nexport type ObservableAnnotationsArray<T extends AnyObject = AnyObject> = [\n AnnotationMapEntry,\n ...(keyof T | (string & {}))[],\n][];\n\n/**\n * Applies a compact list of MobX annotations to an object using either\n * decorator-style invocation or the annotation map form accepted by `makeObservable`.\n *\n * @template T Target object type.\n * @param context Object that should become observable.\n * @param annotationsArray Tuples of annotation followed by annotated field names.\n * @param useDecorators Enables decorator-style application before calling `makeObservable`.\n *\n * @example\n * ```ts\n * applyObservable(store, [[observable, 'items'], [action, 'setItems']]);\n * ```\n *\n * @example\n * ```ts\n * applyObservable(viewModel, [[computed, 'fullName']], true);\n * ```\n */\nexport const applyObservable = <T extends AnyObject>(\n context: T,\n annotationsArray: ObservableAnnotationsArray<T>,\n useDecorators?: boolean,\n) => {\n if (useDecorators) {\n annotationsArray.forEach(([annotation, ...fields]) => {\n fields.forEach((field) => {\n // @ts-expect-error\n annotation(context, field);\n });\n });\n\n makeObservable(context);\n } else {\n const annotationsObject: AnyObject = {};\n\n annotationsArray.forEach(([annotation, ...fields]) => {\n fields.forEach((field) => {\n annotationsObject[field] = annotation;\n });\n });\n\n makeObservable(context, annotationsObject);\n }\n};\n","import { createAtom, type IAtom } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\nexport interface IEnhancedAtom<TMeta extends AnyObject = AnyObject>\n extends IAtom {\n meta: TMeta;\n}\n\n/**\n * Creates a MobX atom extended with metadata and bound reporting methods.\n *\n * @template TMeta Metadata object stored on the atom.\n * @param name Atom name used by MobX for debugging.\n * @param onBecomeObservedHandler Callback fired when the atom becomes observed.\n * @param onBecomeUnobservedHandler Callback fired when the atom is no longer observed.\n * @param meta Optional metadata attached to the atom.\n * @returns Atom instance with `meta`, `reportChanged` and `reportObserved`.\n *\n * @example\n * ```ts\n * const atom = createEnhancedAtom('user-status');\n * atom.reportChanged();\n * ```\n *\n * @example\n * ```ts\n * const atom = createEnhancedAtom('cache', undefined, undefined, { scope: 'users' });\n * atom.meta.scope;\n * ```\n */\nexport const createEnhancedAtom = <TMeta extends AnyObject>(\n name: string,\n onBecomeObservedHandler?: (atom: IEnhancedAtom<TMeta>) => void,\n onBecomeUnobservedHandler?: (atom: IEnhancedAtom<TMeta>) => void,\n meta?: TMeta,\n): IEnhancedAtom<TMeta> => {\n const atom = createAtom(\n name,\n onBecomeObservedHandler && (() => onBecomeObservedHandler(atom)),\n onBecomeUnobservedHandler && (() => onBecomeUnobservedHandler(atom)),\n ) as IEnhancedAtom<TMeta>;\n atom.meta = meta ?? ({} as TMeta);\n atom.reportChanged = atom.reportChanged.bind(atom);\n atom.reportObserved = atom.reportObserved.bind(atom);\n return atom;\n};\n","import {\n type IEqualsComparer,\n makeObservable,\n comparer as mobxComparer,\n observable,\n runInAction,\n} from 'mobx';\nimport type { AnyObject, Maybe } from 'yummies/types';\n\n/**\n * You can return `false` if you don't want to change the value in this ref\n */\nexport type RefChangeListener<T> = (\n value: T | null,\n prevValue: T | undefined,\n) => void | false;\n\n/**\n * Alternative to React.createRef but works in MobX world.\n * Typically it the should be the same React.LegacyRef (fn style)\n */\nexport interface Ref<T = any, TMeta = AnyObject> {\n /**\n * Setter function\n */\n (value: Maybe<T>): void;\n\n set(value: Maybe<T>): void;\n listeners: Set<RefChangeListener<NoInfer<T>>>;\n current: NoInfer<T> | null;\n meta: TMeta;\n}\n\nexport interface CreateRefConfig<T = any, TMeta = AnyObject> {\n onSet?: (node: T, prevValue: T | undefined) => void;\n onUnset?: (lastValue: T | undefined) => void;\n onChange?: RefChangeListener<T>;\n meta?: TMeta;\n initial?: Maybe<T>;\n comparer?: IEqualsComparer<T | null>;\n}\n\n/**\n * Creates a MobX-aware ref that behaves like a callback ref and exposes\n * observable `current` and `meta` fields.\n *\n * @template T Referenced value type.\n * @template TMeta Additional observable metadata stored on the ref.\n * @param cfg Optional callbacks, initial value and comparer configuration.\n * @returns Observable ref function object.\n *\n * @example\n * ```ts\n * const inputRef = createRef<HTMLInputElement>();\n * inputRef.set(document.createElement('input'));\n * ```\n *\n * @example\n * ```ts\n * const nodeRef = createRef({\n * onUnset: () => console.log('detached'),\n * meta: { mounted: false },\n * });\n * ```\n */\nexport const createRef = <T = any, TMeta = AnyObject>(\n cfg?: CreateRefConfig<T, TMeta>,\n): Ref<T, TMeta> => {\n let lastValue: T | undefined;\n const comparer = cfg?.comparer ?? mobxComparer.default;\n\n const setValue: Ref<T, TMeta>['set'] = (value) => {\n const nextValue = value ?? null;\n\n if (comparer(ref.current, nextValue)) {\n return;\n }\n\n runInAction(() => {\n const prevLastValue = lastValue;\n lastValue = ref.current ?? undefined;\n ref.current = nextValue;\n\n let isNextValueIgnored = false;\n\n ref.listeners.forEach((listener) => {\n const listenerResult = listener(ref.current, lastValue);\n\n if (listenerResult === false) {\n isNextValueIgnored = true;\n }\n });\n\n if (isNextValueIgnored) {\n lastValue = prevLastValue;\n ref.current = lastValue ?? null;\n } else if (ref.current === null && lastValue !== undefined) {\n lastValue = undefined;\n }\n });\n };\n\n const ref = setValue as Ref<T, TMeta>;\n\n ref.set = setValue;\n\n ref.listeners = new Set(cfg?.onChange ? [cfg.onChange] : []);\n\n if (cfg?.onSet || cfg?.onUnset) {\n ref.listeners.add((value, prevValue) => {\n if (value) {\n cfg.onSet?.(value, prevValue);\n } else {\n cfg.onUnset?.(prevValue);\n }\n });\n }\n\n ref.current = cfg?.initial ?? null;\n ref.meta = cfg?.meta ?? ({} as TMeta);\n\n makeObservable(ref, {\n current: observable.ref,\n meta: observable,\n });\n\n return ref;\n};\n\n/**\n * Checks whether the provided value is a ref created by `createRef`.\n *\n * @template T Referenced value type.\n * @template TMeta Ref metadata type.\n * @param value Value to inspect.\n * @returns `true` when the value is a ref-like function with `current`.\n *\n * @example\n * ```ts\n * const ref = createRef<number>();\n * isRef(ref); // true\n * ```\n *\n * @example\n * ```ts\n * isRef({ current: 1 }); // false\n * ```\n */\nexport const isRef = <T, TMeta = any>(\n value: T | Ref<T, TMeta>,\n): value is Ref<T, TMeta> => {\n return typeof value === 'function' && 'current' in value;\n};\n\n/**\n * Normalizes a plain value or an existing ref into a `Ref` instance.\n *\n * @template T Referenced value type.\n * @template TMeta Ref metadata type.\n * @param value Existing ref or initial plain value.\n * @param cfg Optional ref configuration applied when a new ref is created.\n * @returns Existing ref or a newly created ref initialized with `value`.\n *\n * @example\n * ```ts\n * const ref = toRef(document.body);\n * ref.current === document.body;\n * ```\n *\n * @example\n * ```ts\n * const existingRef = createRef<number>();\n * const sameRef = toRef(existingRef);\n * ```\n */\nexport const toRef = <T, TMeta = any>(\n value: T | Ref<T, TMeta>,\n cfg?: Omit<CreateRefConfig<T, TMeta>, 'initial'>,\n): Ref<T, TMeta> => {\n return isRef(value) ? value : createRef({ initial: value, ...cfg });\n};\n","import { action, makeObservable, observable } from 'mobx';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject } from 'yummies/types';\n\n/**\n * Wraps a plain object into a deeply observable structure and allows\n * patch-like updates while preserving nested observable references where possible.\n *\n * @template TData Observable object shape.\n *\n * @example\n * ```ts\n * const state = new DeepObservableStruct({ user: { name: 'Ann' } });\n * state.set({ user: { name: 'Bob' } });\n * ```\n *\n * @example\n * ```ts\n * const state = new DeepObservableStruct({ filters: { active: true } });\n * state.set({ filters: { active: false, archived: true } });\n * ```\n */\nexport class DeepObservableStruct<TData extends AnyObject> {\n data: TData;\n\n constructor(data: TData) {\n this.data = data;\n\n makeObservable(this, {\n data: observable.deep,\n set: action,\n });\n }\n\n set(newData: Partial<TData>) {\n type StackItem = [key: string, currObservable: AnyObject, new: AnyObject];\n\n const stack: StackItem[] = Object.keys(this.data).map((key) => [\n key,\n this.data,\n newData,\n ]);\n\n let currentIndex = 0;\n let stackLength = stack.length;\n\n while (currentIndex < stackLength) {\n const [key, currObservableData, newData] = stack[currentIndex];\n const newValue = newData[key];\n const currValue = currObservableData[key];\n\n currentIndex++;\n\n if (key in newData) {\n if (typeGuard.isObject(newValue) && typeGuard.isObject(currValue)) {\n const newValueKeys = Object.keys(newValue);\n\n Object.keys(currValue).forEach((childKey) => {\n if (!(childKey in newValue)) {\n delete currObservableData[key][childKey];\n }\n });\n\n newValueKeys.forEach((childKey) => {\n const length = stack.push([\n childKey,\n currObservableData[key],\n newValue,\n ]);\n stackLength = length;\n });\n } else if (newValue !== currValue) {\n currObservableData[key] = newValue;\n }\n } else {\n delete currObservableData[key];\n }\n }\n\n Object.keys(newData).forEach((newDataKey) => {\n if (!this.data[newDataKey]) {\n // @ts-expect-error\n this.data[newDataKey] = newData[newDataKey];\n }\n });\n }\n}\n","import { $mobx, type AnnotationMapEntry } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\ntype ObservableObjectAdministration = Parameters<\n Exclude<AnnotationMapEntry, boolean>['make_']\n>[0];\n\n/**\n * Returns the internal MobX administration object associated with an observable target.\n *\n * @param context Observable object instance.\n * @returns MobX administration internals stored under `$mobx`.\n *\n * @example\n * ```ts\n * const admin = getMobxAdministration(store);\n * admin.name_;\n * ```\n *\n * @example\n * ```ts\n * const values = getMobxAdministration(formState).values_;\n * ```\n */\nexport const getMobxAdministration = (\n context: AnyObject,\n): ObservableObjectAdministration => context[$mobx];\n","import { onBecomeObserved, onBecomeUnobserved } from 'mobx';\n\n/**\n * Starts side effects only while one or more MobX observables are being observed.\n *\n * When the first property becomes observed, `onStart` is called. When all tracked\n * properties become unobserved, `onEnd` is called with the value returned by\n * `onStart`. Cleanup can be delayed via `endDelay`.\n *\n * It uses MobX `onBecomeObserved` and `onBecomeUnobserved` hooks to perform\n * lazy subscription management.\n *\n * @template TMetaData Data returned from `onStart` and forwarded to `onEnd`.\n * @param config Configuration for tracked properties and lifecycle callbacks.\n * @returns Cleanup function that clears the tracked state and runs `onEnd`.\n *\n * @example\n * ```ts\n * const stop = lazyObserve({\n * context: store,\n * property: 'items',\n * onStart: () => api.subscribe(),\n * onEnd: (subscription) => subscription.unsubscribe(),\n * });\n * ```\n *\n * @example\n * ```ts\n * lazyObserve({\n * property: [boxA, boxB],\n * onStart: () => console.log('observed'),\n * endDelay: 300,\n * });\n * ```\n */\nexport const lazyObserve = <TMetaData = void>({\n context,\n property,\n onStart,\n onEnd,\n endDelay = false,\n}: {\n context?: any;\n property: any | any[];\n onStart?: () => TMetaData;\n onEnd?: (metaData: TMetaData, cleanupFn: VoidFunction) => void;\n endDelay?: number | false;\n}) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let metaData: TMetaData | undefined;\n const observingProps = new Set<string>();\n const properties = Array.isArray(property) ? property : [property];\n\n const cleanup = () => {\n observingProps.clear();\n\n if (endDelay === false) {\n onEnd?.(metaData!, cleanup);\n metaData = undefined;\n return;\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = undefined;\n }\n\n timeoutId = setTimeout(() => {\n onEnd?.(metaData!, cleanup);\n timeoutId = undefined;\n metaData = undefined;\n }, endDelay);\n };\n\n const start = (property: string) => {\n const isAlreadyObserving = observingProps.size > 0;\n observingProps.add(property);\n\n if (isAlreadyObserving) {\n return;\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = undefined;\n }\n\n metaData = onStart?.();\n };\n\n const stop = (property: string) => {\n const isAlreadyNotObserving = !observingProps.size;\n\n observingProps.delete(property);\n\n const isObserving = observingProps.size > 0;\n\n if (isAlreadyNotObserving || isObserving) {\n return;\n }\n\n cleanup();\n };\n\n properties.forEach((property) => {\n if (context) {\n onBecomeObserved(context, property, () => start(property));\n onBecomeUnobserved(context, property, () => stop(property));\n } else {\n onBecomeObserved(property, () => start(property));\n onBecomeUnobserved(property, () => stop(property));\n }\n });\n\n return cleanup;\n};\n"],"names":["comparer","mobxComparer","newData","property"],"mappings":"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"}
1
+ {"version":3,"file":"mobx.js","names":[],"sources":["../src/mobx/apply-observable.ts","../src/mobx/create-enhanced-atom.ts","../src/mobx/create-ref.ts","../src/mobx/deep-observable-struct.ts","../src/mobx/get-mobx-administration.ts","../src/mobx/lazy-observe.ts"],"sourcesContent":["import { type AnnotationMapEntry, makeObservable } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\nexport type ObservableAnnotationsArray<T extends AnyObject = AnyObject> = [\n AnnotationMapEntry,\n ...(keyof T | (string & {}))[],\n][];\n\n/**\n * Applies a compact list of MobX annotations to an object using either\n * decorator-style invocation or the annotation map form accepted by `makeObservable`.\n *\n * @template T Target object type.\n * @param context Object that should become observable.\n * @param annotationsArray Tuples of annotation followed by annotated field names.\n * @param useDecorators Enables decorator-style application before calling `makeObservable`.\n *\n * @example\n * ```ts\n * applyObservable(store, [[observable, 'items'], [action, 'setItems']]);\n * ```\n *\n * @example\n * ```ts\n * applyObservable(viewModel, [[computed, 'fullName']], true);\n * ```\n */\nexport const applyObservable = <T extends AnyObject>(\n context: T,\n annotationsArray: ObservableAnnotationsArray<T>,\n useDecorators?: boolean,\n) => {\n if (useDecorators) {\n annotationsArray.forEach(([annotation, ...fields]) => {\n fields.forEach((field) => {\n // @ts-expect-error\n annotation(context, field);\n });\n });\n\n makeObservable(context);\n } else {\n const annotationsObject: AnyObject = {};\n\n annotationsArray.forEach(([annotation, ...fields]) => {\n fields.forEach((field) => {\n annotationsObject[field] = annotation;\n });\n });\n\n makeObservable(context, annotationsObject);\n }\n};\n","import { createAtom, type IAtom } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\nexport interface IEnhancedAtom<TMeta extends AnyObject = AnyObject>\n extends IAtom {\n meta: TMeta;\n}\n\n/**\n * Creates a MobX atom extended with metadata and bound reporting methods.\n *\n * @template TMeta Metadata object stored on the atom.\n * @param name Atom name used by MobX for debugging.\n * @param onBecomeObservedHandler Callback fired when the atom becomes observed.\n * @param onBecomeUnobservedHandler Callback fired when the atom is no longer observed.\n * @param meta Optional metadata attached to the atom.\n * @returns Atom instance with `meta`, `reportChanged` and `reportObserved`.\n *\n * @example\n * ```ts\n * const atom = createEnhancedAtom('user-status');\n * atom.reportChanged();\n * ```\n *\n * @example\n * ```ts\n * const atom = createEnhancedAtom('cache', undefined, undefined, { scope: 'users' });\n * atom.meta.scope;\n * ```\n */\nexport const createEnhancedAtom = <TMeta extends AnyObject>(\n name: string,\n onBecomeObservedHandler?: (atom: IEnhancedAtom<TMeta>) => void,\n onBecomeUnobservedHandler?: (atom: IEnhancedAtom<TMeta>) => void,\n meta?: TMeta,\n): IEnhancedAtom<TMeta> => {\n const atom = createAtom(\n name,\n onBecomeObservedHandler && (() => onBecomeObservedHandler(atom)),\n onBecomeUnobservedHandler && (() => onBecomeUnobservedHandler(atom)),\n ) as IEnhancedAtom<TMeta>;\n atom.meta = meta ?? ({} as TMeta);\n atom.reportChanged = atom.reportChanged.bind(atom);\n atom.reportObserved = atom.reportObserved.bind(atom);\n return atom;\n};\n","import {\n type IEqualsComparer,\n makeObservable,\n comparer as mobxComparer,\n observable,\n runInAction,\n} from 'mobx';\nimport type { AnyObject, Maybe } from 'yummies/types';\n\n/**\n * You can return `false` if you don't want to change the value in this ref\n */\nexport type RefChangeListener<T> = (\n value: T | null,\n prevValue: T | undefined,\n) => void | false;\n\n/**\n * Alternative to React.createRef but works in MobX world.\n * Typically it the should be the same React.LegacyRef (fn style)\n */\nexport interface Ref<T = any, TMeta = AnyObject> {\n /**\n * Setter function\n */\n (value: Maybe<T>): void;\n\n set(value: Maybe<T>): void;\n listeners: Set<RefChangeListener<NoInfer<T>>>;\n current: NoInfer<T> | null;\n meta: TMeta;\n}\n\nexport interface CreateRefConfig<T = any, TMeta = AnyObject> {\n onSet?: (node: T, prevValue: T | undefined) => void;\n onUnset?: (lastValue: T | undefined) => void;\n onChange?: RefChangeListener<T>;\n meta?: TMeta;\n initial?: Maybe<T>;\n comparer?: IEqualsComparer<T | null>;\n}\n\n/**\n * Creates a MobX-aware ref that behaves like a callback ref and exposes\n * observable `current` and `meta` fields.\n *\n * @template T Referenced value type.\n * @template TMeta Additional observable metadata stored on the ref.\n * @param cfg Optional callbacks, initial value and comparer configuration.\n * @returns Observable ref function object.\n *\n * @example\n * ```ts\n * const inputRef = createRef<HTMLInputElement>();\n * inputRef.set(document.createElement('input'));\n * ```\n *\n * @example\n * ```ts\n * const ref = createRef<number>();\n * ref(3);\n * ref.current; // 3\n * ```\n *\n * @example\n * ```ts\n * const nodeRef = createRef({\n * onUnset: () => console.log('detached'),\n * meta: { mounted: false },\n * });\n * ```\n */\nexport const createRef = <T = any, TMeta = AnyObject>(\n cfg?: CreateRefConfig<T, TMeta>,\n): Ref<T, TMeta> => {\n let lastValue: T | undefined;\n const comparer = cfg?.comparer ?? mobxComparer.default;\n\n const setValue: Ref<T, TMeta>['set'] = (value) => {\n const nextValue = value ?? null;\n\n if (comparer(ref.current, nextValue)) {\n return;\n }\n\n runInAction(() => {\n const prevLastValue = lastValue;\n lastValue = ref.current ?? undefined;\n ref.current = nextValue;\n\n let isNextValueIgnored = false;\n\n ref.listeners.forEach((listener) => {\n const listenerResult = listener(ref.current, lastValue);\n\n if (listenerResult === false) {\n isNextValueIgnored = true;\n }\n });\n\n if (isNextValueIgnored) {\n lastValue = prevLastValue;\n ref.current = lastValue ?? null;\n } else if (ref.current === null && lastValue !== undefined) {\n lastValue = undefined;\n }\n });\n };\n\n const ref = setValue as Ref<T, TMeta>;\n\n ref.set = setValue;\n\n ref.listeners = new Set(cfg?.onChange ? [cfg.onChange] : []);\n\n if (cfg?.onSet || cfg?.onUnset) {\n ref.listeners.add((value, prevValue) => {\n if (value) {\n cfg.onSet?.(value, prevValue);\n } else {\n cfg.onUnset?.(prevValue);\n }\n });\n }\n\n ref.current = cfg?.initial ?? null;\n ref.meta = cfg?.meta ?? ({} as TMeta);\n\n makeObservable(ref, {\n current: observable.ref,\n meta: observable,\n });\n\n return ref;\n};\n\n/**\n * Checks whether the provided value is a ref created by `createRef`.\n *\n * @template T Referenced value type.\n * @template TMeta Ref metadata type.\n * @param value Value to inspect.\n * @returns `true` when the value is a ref-like function with `current`.\n *\n * @example\n * ```ts\n * const ref = createRef<number>();\n * isRef(ref); // true\n * ```\n *\n * @example\n * ```ts\n * isRef({ current: 1 }); // false\n * ```\n */\nexport const isRef = <T, TMeta = any>(\n value: T | Ref<T, TMeta>,\n): value is Ref<T, TMeta> => {\n return typeof value === 'function' && 'current' in value;\n};\n\n/**\n * Normalizes a plain value or an existing ref into a `Ref` instance.\n *\n * @template T Referenced value type.\n * @template TMeta Ref metadata type.\n * @param value Existing ref or initial plain value.\n * @param cfg Optional ref configuration applied when a new ref is created.\n * @returns Existing ref or a newly created ref initialized with `value`.\n *\n * @example\n * ```ts\n * const ref = toRef(document.body);\n * ref.current === document.body;\n * ```\n *\n * @example\n * ```ts\n * const existingRef = createRef<number>();\n * const sameRef = toRef(existingRef);\n * ```\n */\nexport const toRef = <T, TMeta = any>(\n value: T | Ref<T, TMeta>,\n cfg?: Omit<CreateRefConfig<T, TMeta>, 'initial'>,\n): Ref<T, TMeta> => {\n return isRef(value) ? value : createRef({ initial: value, ...cfg });\n};\n","import { action, makeObservable, observable } from 'mobx';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject } from 'yummies/types';\n\n/**\n * Wraps a plain object into a deeply observable structure and allows\n * patch-like updates while preserving nested observable references where possible.\n *\n * @template TData Observable object shape.\n *\n * @example\n * ```ts\n * const state = new DeepObservableStruct({ user: { name: 'Ann' } });\n * state.set({ user: { name: 'Bob' } });\n * ```\n *\n * @example\n * ```ts\n * const state = new DeepObservableStruct({ filters: { active: true } });\n * state.set({ filters: { active: false, archived: true } });\n * ```\n */\nexport class DeepObservableStruct<TData extends AnyObject> {\n data: TData;\n\n constructor(data: TData) {\n this.data = data;\n\n makeObservable(this, {\n data: observable.deep,\n set: action,\n });\n }\n\n set(newData: Partial<TData>) {\n type StackItem = [key: string, currObservable: AnyObject, new: AnyObject];\n\n const stack: StackItem[] = Object.keys(this.data).map((key) => [\n key,\n this.data,\n newData,\n ]);\n\n let currentIndex = 0;\n let stackLength = stack.length;\n\n while (currentIndex < stackLength) {\n const [key, currObservableData, newData] = stack[currentIndex];\n const newValue = newData[key];\n const currValue = currObservableData[key];\n\n currentIndex++;\n\n if (key in newData) {\n if (typeGuard.isObject(newValue) && typeGuard.isObject(currValue)) {\n const newValueKeys = Object.keys(newValue);\n\n Object.keys(currValue).forEach((childKey) => {\n if (!(childKey in newValue)) {\n delete currObservableData[key][childKey];\n }\n });\n\n newValueKeys.forEach((childKey) => {\n const length = stack.push([\n childKey,\n currObservableData[key],\n newValue,\n ]);\n stackLength = length;\n });\n } else if (newValue !== currValue) {\n currObservableData[key] = newValue;\n }\n } else {\n delete currObservableData[key];\n }\n }\n\n Object.keys(newData).forEach((newDataKey) => {\n if (!this.data[newDataKey]) {\n // @ts-expect-error\n this.data[newDataKey] = newData[newDataKey];\n }\n });\n }\n}\n","import { $mobx, type AnnotationMapEntry } from 'mobx';\nimport type { AnyObject } from 'yummies/types';\n\ntype ObservableObjectAdministration = Parameters<\n Exclude<AnnotationMapEntry, boolean>['make_']\n>[0];\n\n/**\n * Returns the internal MobX administration object associated with an observable target.\n *\n * @param context Observable object instance.\n * @returns MobX administration internals stored under `$mobx`.\n *\n * @example\n * ```ts\n * const admin = getMobxAdministration(store);\n * admin.name_;\n * ```\n *\n * @example\n * ```ts\n * const values = getMobxAdministration(formState).values_;\n * ```\n */\nexport const getMobxAdministration = (\n context: AnyObject,\n): ObservableObjectAdministration => context[$mobx];\n","import { onBecomeObserved, onBecomeUnobserved } from 'mobx';\n\n/**\n * Starts side effects only while one or more MobX observables are being observed.\n *\n * When the first property becomes observed, `onStart` is called. When all tracked\n * properties become unobserved, `onEnd` is called with the value returned by\n * `onStart`. Cleanup can be delayed via `endDelay`.\n *\n * It uses MobX `onBecomeObserved` and `onBecomeUnobserved` hooks to perform\n * lazy subscription management.\n *\n * @template TMetaData Data returned from `onStart` and forwarded to `onEnd`.\n * @param config Configuration for tracked properties and lifecycle callbacks.\n * @returns Cleanup function that clears the tracked state and runs `onEnd`.\n *\n * @example\n * ```ts\n * const stop = lazyObserve({\n * context: store,\n * property: 'items',\n * onStart: () => api.subscribe(),\n * onEnd: (subscription) => subscription.unsubscribe(),\n * });\n * ```\n *\n * @example\n * ```ts\n * lazyObserve({\n * property: [boxA, boxB],\n * onStart: () => console.log('observed'),\n * endDelay: 300,\n * });\n * ```\n */\nexport const lazyObserve = <TMetaData = void>({\n context,\n property,\n onStart,\n onEnd,\n endDelay = false,\n}: {\n context?: any;\n property: any | any[];\n onStart?: () => TMetaData;\n onEnd?: (metaData: TMetaData, cleanupFn: VoidFunction) => void;\n endDelay?: number | false;\n}) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let metaData: TMetaData | undefined;\n const observingProps = new Set<string>();\n const properties = Array.isArray(property) ? property : [property];\n\n const cleanup = () => {\n observingProps.clear();\n\n if (endDelay === false) {\n onEnd?.(metaData!, cleanup);\n metaData = undefined;\n return;\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = undefined;\n }\n\n timeoutId = setTimeout(() => {\n onEnd?.(metaData!, cleanup);\n timeoutId = undefined;\n metaData = undefined;\n }, endDelay);\n };\n\n const start = (property: string) => {\n const isAlreadyObserving = observingProps.size > 0;\n observingProps.add(property);\n\n if (isAlreadyObserving) {\n return;\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = undefined;\n }\n\n metaData = onStart?.();\n };\n\n const stop = (property: string) => {\n const isAlreadyNotObserving = !observingProps.size;\n\n observingProps.delete(property);\n\n const isObserving = observingProps.size > 0;\n\n if (isAlreadyNotObserving || isObserving) {\n return;\n }\n\n cleanup();\n };\n\n properties.forEach((property) => {\n if (context) {\n onBecomeObserved(context, property, () => start(property));\n onBecomeUnobserved(context, property, () => stop(property));\n } else {\n onBecomeObserved(property, () => start(property));\n onBecomeUnobserved(property, () => stop(property));\n }\n });\n\n return cleanup;\n};\n"],"mappings":"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"}