mutts 1.0.8 → 1.0.10

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 (195) hide show
  1. package/README.md +77 -35
  2. package/dist/browser.cjs +2144 -5355
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +2 -1655
  5. package/dist/browser.dev.cjs +110 -0
  6. package/dist/browser.dev.cjs.map +1 -0
  7. package/dist/browser.dev.d.ts +2 -0
  8. package/dist/browser.dev.esm.js +5 -0
  9. package/dist/browser.dev.esm.js.map +1 -0
  10. package/dist/browser.esm.js +20 -107
  11. package/dist/browser.esm.js.map +1 -1
  12. package/dist/chunks/{async-browser-CA0jPWIi.cjs → async-browser-BU_IfxYD.cjs} +19 -107
  13. package/dist/chunks/async-browser-BU_IfxYD.cjs.map +1 -0
  14. package/dist/chunks/{async-core-UqHzvJ-S.cjs → async-core-CRLKP3l-.cjs} +8 -4
  15. package/dist/chunks/async-core-CRLKP3l-.cjs.map +1 -0
  16. package/dist/chunks/{async-node-BYHuGTni.cjs → async-node-3PrbVAbB.cjs} +7 -12
  17. package/dist/chunks/async-node-3PrbVAbB.cjs.map +1 -0
  18. package/dist/chunks/index-CaaQQlPJ.esm.js +3174 -0
  19. package/dist/chunks/index-CaaQQlPJ.esm.js.map +1 -0
  20. package/dist/chunks/node-nKJBk8iJ.esm.js +96 -0
  21. package/dist/chunks/node-nKJBk8iJ.esm.js.map +1 -0
  22. package/dist/chunks/proxy-Dtg-bJ3T.cjs +3763 -0
  23. package/dist/chunks/proxy-Dtg-bJ3T.cjs.map +1 -0
  24. package/dist/chunks/proxy-r7lARftl.esm.js +3701 -0
  25. package/dist/chunks/proxy-r7lARftl.esm.js.map +1 -0
  26. package/dist/debug.cjs +980 -0
  27. package/dist/debug.cjs.map +1 -0
  28. package/dist/debug.d.ts +208 -0
  29. package/dist/debug.esm.js +950 -0
  30. package/dist/debug.esm.js.map +1 -0
  31. package/dist/devtools/manifest.json +1 -1
  32. package/dist/devtools/panel.html +1 -1
  33. package/dist/devtools/panel.js +107 -94
  34. package/dist/devtools/panel.js.map +1 -1
  35. package/dist/index.d.ts +1447 -13
  36. package/dist/mutts.umd.js +7167 -1
  37. package/dist/mutts.umd.js.map +1 -1
  38. package/dist/mutts.umd.min.js +1 -1
  39. package/dist/mutts.umd.min.js.map +1 -1
  40. package/dist/node.cjs +70 -66
  41. package/dist/node.cjs.map +1 -1
  42. package/dist/node.d.ts +2 -1
  43. package/dist/node.dev.cjs +110 -0
  44. package/dist/node.dev.cjs.map +1 -0
  45. package/dist/node.dev.d.ts +2 -0
  46. package/dist/node.dev.esm.js +6 -0
  47. package/dist/node.dev.esm.js.map +1 -0
  48. package/dist/node.esm.js +4 -103
  49. package/dist/node.esm.js.map +1 -1
  50. package/dist/{reactive/types.d.ts → types-W5vD6m2n.d.ts} +186 -93
  51. package/docs/ai/api-reference.md +12 -19
  52. package/docs/ai/manual.md +521 -17
  53. package/docs/events.md +57 -2
  54. package/docs/flavored.md +210 -0
  55. package/docs/reactive/advanced.md +314 -5
  56. package/docs/reactive/attend.md +142 -0
  57. package/docs/reactive/collections.md +76 -39
  58. package/docs/reactive/core.md +100 -14
  59. package/docs/reactive/debugging.md +123 -18
  60. package/docs/reactive/error-handling.md +121 -0
  61. package/docs/reactive/resource.md +125 -0
  62. package/docs/reactive/scan.md +247 -1
  63. package/docs/reactive.md +4 -1
  64. package/docs/std-decorators.md +102 -51
  65. package/docs/utils.md +70 -0
  66. package/docs/zone.md +3 -7
  67. package/package.json +64 -30
  68. package/dist/async/browser.d.ts +0 -2
  69. package/dist/async/browser.d.ts.map +0 -1
  70. package/dist/async/index.d.ts +0 -18
  71. package/dist/async/index.d.ts.map +0 -1
  72. package/dist/async/node.d.ts +0 -2
  73. package/dist/async/node.d.ts.map +0 -1
  74. package/dist/chunks/async-browser-CA0jPWIi.cjs.map +0 -1
  75. package/dist/chunks/async-core-UqHzvJ-S.cjs.map +0 -1
  76. package/dist/chunks/async-node-BYHuGTni.cjs.map +0 -1
  77. package/dist/chunks/index-DhaOVusv.esm.js +0 -6411
  78. package/dist/chunks/index-DhaOVusv.esm.js.map +0 -1
  79. package/dist/decorator.d.ts +0 -106
  80. package/dist/decorator.d.ts.map +0 -1
  81. package/dist/destroyable.d.ts +0 -87
  82. package/dist/destroyable.d.ts.map +0 -1
  83. package/dist/entry-browser.d.ts +0 -3
  84. package/dist/entry-browser.d.ts.map +0 -1
  85. package/dist/entry-node.d.ts +0 -3
  86. package/dist/entry-node.d.ts.map +0 -1
  87. package/dist/eventful.d.ts +0 -18
  88. package/dist/eventful.d.ts.map +0 -1
  89. package/dist/index.d.ts.map +0 -1
  90. package/dist/indexable.d.ts +0 -243
  91. package/dist/indexable.d.ts.map +0 -1
  92. package/dist/introspection.d.ts +0 -27
  93. package/dist/introspection.d.ts.map +0 -1
  94. package/dist/iterableWeak.d.ts +0 -53
  95. package/dist/iterableWeak.d.ts.map +0 -1
  96. package/dist/mixins.d.ts +0 -25
  97. package/dist/mixins.d.ts.map +0 -1
  98. package/dist/promiseChain.d.ts +0 -20
  99. package/dist/promiseChain.d.ts.map +0 -1
  100. package/dist/reactive/array.d.ts +0 -49
  101. package/dist/reactive/array.d.ts.map +0 -1
  102. package/dist/reactive/buffer.d.ts +0 -44
  103. package/dist/reactive/buffer.d.ts.map +0 -1
  104. package/dist/reactive/change.d.ts +0 -29
  105. package/dist/reactive/change.d.ts.map +0 -1
  106. package/dist/reactive/debug.d.ts +0 -111
  107. package/dist/reactive/debug.d.ts.map +0 -1
  108. package/dist/reactive/deep-touch.d.ts +0 -28
  109. package/dist/reactive/deep-touch.d.ts.map +0 -1
  110. package/dist/reactive/deep-watch-state.d.ts +0 -25
  111. package/dist/reactive/deep-watch-state.d.ts.map +0 -1
  112. package/dist/reactive/deep-watch.d.ts +0 -19
  113. package/dist/reactive/deep-watch.d.ts.map +0 -1
  114. package/dist/reactive/effect-context.d.ts +0 -7
  115. package/dist/reactive/effect-context.d.ts.map +0 -1
  116. package/dist/reactive/effects.d.ts +0 -151
  117. package/dist/reactive/effects.d.ts.map +0 -1
  118. package/dist/reactive/index.d.ts +0 -20
  119. package/dist/reactive/index.d.ts.map +0 -1
  120. package/dist/reactive/interface.d.ts +0 -64
  121. package/dist/reactive/interface.d.ts.map +0 -1
  122. package/dist/reactive/map.d.ts +0 -30
  123. package/dist/reactive/map.d.ts.map +0 -1
  124. package/dist/reactive/memoize.d.ts +0 -5
  125. package/dist/reactive/memoize.d.ts.map +0 -1
  126. package/dist/reactive/non-reactive-state.d.ts +0 -9
  127. package/dist/reactive/non-reactive-state.d.ts.map +0 -1
  128. package/dist/reactive/non-reactive.d.ts +0 -11
  129. package/dist/reactive/non-reactive.d.ts.map +0 -1
  130. package/dist/reactive/project.d.ts +0 -41
  131. package/dist/reactive/project.d.ts.map +0 -1
  132. package/dist/reactive/proxy-state.d.ts +0 -8
  133. package/dist/reactive/proxy-state.d.ts.map +0 -1
  134. package/dist/reactive/proxy.d.ts +0 -23
  135. package/dist/reactive/proxy.d.ts.map +0 -1
  136. package/dist/reactive/record.d.ts +0 -116
  137. package/dist/reactive/record.d.ts.map +0 -1
  138. package/dist/reactive/register.d.ts +0 -64
  139. package/dist/reactive/register.d.ts.map +0 -1
  140. package/dist/reactive/registry.d.ts +0 -20
  141. package/dist/reactive/registry.d.ts.map +0 -1
  142. package/dist/reactive/set.d.ts +0 -28
  143. package/dist/reactive/set.d.ts.map +0 -1
  144. package/dist/reactive/tracking.d.ts +0 -7
  145. package/dist/reactive/tracking.d.ts.map +0 -1
  146. package/dist/reactive/types.d.ts.map +0 -1
  147. package/dist/std-decorators.d.ts +0 -50
  148. package/dist/std-decorators.d.ts.map +0 -1
  149. package/dist/utils.d.ts +0 -49
  150. package/dist/utils.d.ts.map +0 -1
  151. package/dist/zone.d.ts +0 -40
  152. package/dist/zone.d.ts.map +0 -1
  153. package/docs/reactive/project.md +0 -93
  154. package/src/async/browser.ts +0 -319
  155. package/src/async/index.ts +0 -23
  156. package/src/async/node.ts +0 -104
  157. package/src/decorator.ts +0 -272
  158. package/src/destroyable.ts +0 -199
  159. package/src/entry-browser.ts +0 -5
  160. package/src/entry-node.ts +0 -5
  161. package/src/eventful.ts +0 -77
  162. package/src/index.d.ts +0 -12
  163. package/src/index.ts +0 -64
  164. package/src/indexable.ts +0 -526
  165. package/src/introspection.ts +0 -59
  166. package/src/iterableWeak.ts +0 -233
  167. package/src/mixins.ts +0 -123
  168. package/src/promiseChain.ts +0 -110
  169. package/src/reactive/array.ts +0 -507
  170. package/src/reactive/buffer.ts +0 -168
  171. package/src/reactive/change.ts +0 -138
  172. package/src/reactive/debug.ts +0 -517
  173. package/src/reactive/deep-touch.ts +0 -268
  174. package/src/reactive/deep-watch-state.ts +0 -82
  175. package/src/reactive/deep-watch.ts +0 -168
  176. package/src/reactive/effect-context.ts +0 -18
  177. package/src/reactive/effects.ts +0 -1382
  178. package/src/reactive/index.ts +0 -75
  179. package/src/reactive/interface.ts +0 -210
  180. package/src/reactive/map.ts +0 -158
  181. package/src/reactive/memoize.ts +0 -163
  182. package/src/reactive/non-reactive-state.ts +0 -49
  183. package/src/reactive/non-reactive.ts +0 -43
  184. package/src/reactive/project.ts +0 -453
  185. package/src/reactive/proxy-state.ts +0 -27
  186. package/src/reactive/proxy.ts +0 -264
  187. package/src/reactive/record.ts +0 -196
  188. package/src/reactive/register.ts +0 -419
  189. package/src/reactive/registry.ts +0 -59
  190. package/src/reactive/set.ts +0 -130
  191. package/src/reactive/tracking.ts +0 -44
  192. package/src/reactive/types.ts +0 -440
  193. package/src/std-decorators.ts +0 -217
  194. package/src/utils.ts +0 -301
  195. package/src/zone.ts +0 -138
@@ -0,0 +1,3174 @@
1
+ import { r as decorator, x as flavored, a3 as markWithRoot, O as named, a4 as rootFunctionSymbol, S as proxyToObject, a5 as getRoot, a6 as dependant, U as options, a0 as untracked, s as deepCompare, a7 as optionCall, W as root, u as effect, $ as touched1, K as isReactive, T as reactive, _ as touched, o as cleanedBy, C as getState, a8 as keysOf, a9 as __runInitializers, aa as __esDecorate, ab as FoolProof, ac as objectsWithDeepWatchers, ad as effectToDeepWatchedObjects, ae as deepWatchers, H as isNonReactive, a1 as unwrap, af as registerDeepWatcher, w as flavorOptions, X as stopped, ag as nonReactiveClass, ah as unreactiveProps, ai as addUnreactiveProps, aj as nonReactiveObjects, ak as __setFunctionName, al as __classPrivateFieldGet, am as __classPrivateFieldSet, l as atomic, an as contentRef, ao as notifyPropertyChange, ap as metaProtos, aq as wrapProtos, ar as objectParents, as as watchers, at as effectToReactiveObjects, P as objectToProxy } from './proxy-r7lARftl.esm.js';
2
+
3
+ // Integrated with `using` statement via Symbol.dispose
4
+ const fr = new FinalizationRegistry((f) => f());
5
+ /**
6
+ * Symbol for marking destructor methods
7
+ */
8
+ const destructor = Symbol('destructor');
9
+ /**
10
+ * Symbol for accessing allocated values in destroyable objects
11
+ */
12
+ const allocatedValues = Symbol('allocated');
13
+ /**
14
+ * Error thrown when attempting to access a destroyed object
15
+ */
16
+ class DestructionError extends Error {
17
+ static throw(msg) {
18
+ return () => {
19
+ throw new DestructionError(msg);
20
+ };
21
+ }
22
+ constructor(msg) {
23
+ super(`Object is destroyed. ${msg}`);
24
+ this.name = 'DestroyedAccessError';
25
+ }
26
+ }
27
+ const destroyedHandler = {
28
+ [Symbol.toStringTag]: 'MutTs Destroyable',
29
+ get: DestructionError.throw('Cannot access destroyed object'),
30
+ set: DestructionError.throw('Cannot access destroyed object'),
31
+ };
32
+ function Destroyable(base, destructorObj) {
33
+ var _a;
34
+ if (base && typeof base !== 'function') {
35
+ destructorObj = base;
36
+ base = undefined;
37
+ }
38
+ if (!base) {
39
+ base = class {
40
+ };
41
+ }
42
+ return _a = class Destroyable extends base {
43
+ static destroy(obj) {
44
+ const destructor = _a.destructors.get(obj);
45
+ if (!destructor)
46
+ return false;
47
+ fr.unregister(obj[allocatedValues]);
48
+ _a.destructors.delete(obj);
49
+ Object.setPrototypeOf(obj, new Proxy({}, destroyedHandler));
50
+ // Clear all own properties
51
+ for (const key of Object.getOwnPropertyNames(obj)) {
52
+ delete obj[key];
53
+ }
54
+ destructor();
55
+ return true;
56
+ }
57
+ static isDestroyable(obj) {
58
+ return _a.destructors.has(obj);
59
+ }
60
+ constructor(...args) {
61
+ super(...args);
62
+ const allocated = {};
63
+ this[allocatedValues] = allocated;
64
+ // @ts-expect-error `this` is an AbstractDestroyable
65
+ const myDestructor = destructorObj?.destructor ?? this[destructor];
66
+ if (!myDestructor) {
67
+ throw new DestructionError('Destructor is not defined');
68
+ }
69
+ function destruction() {
70
+ myDestructor(allocated);
71
+ }
72
+ _a.destructors.set(this, destruction);
73
+ fr.register(this, destruction, allocated);
74
+ }
75
+ },
76
+ _a.destructors = new WeakMap(),
77
+ _a;
78
+ }
79
+ /**
80
+ * Decorator that marks properties to be stored in the allocated object and passed to the destructor
81
+ * Use with accessor properties or explicit get/set pairs
82
+ */
83
+ const allocated = decorator({
84
+ setter(original, _target, propertyKey) {
85
+ return function (value) {
86
+ this[allocatedValues][propertyKey] = value;
87
+ return original.call(this, value);
88
+ };
89
+ },
90
+ });
91
+ /**
92
+ * Registers a callback to be called when an object is garbage collected
93
+ * @param cb - The callback function to execute on garbage collection
94
+ * @returns The object whose reference can be collected
95
+ */
96
+ function callOnGC(cb) {
97
+ let called = false;
98
+ const forward = () => {
99
+ if (called)
100
+ return;
101
+ called = true;
102
+ cb();
103
+ };
104
+ fr.register(forward, cb, cb);
105
+ return forward;
106
+ }
107
+
108
+ /** Max edit distance before bailing out to a single "replace all" patch */
109
+ const BAILOUT_D = 256;
110
+ /**
111
+ * Myers' diff producing grouped patches: `{indexA, indexB, sliceA, sliceB}[]`.
112
+ * - O(N) for identical or prefix/suffix-only differences
113
+ * - O(ND) for small D, with a hard bailout at D=BAILOUT_D → single replacement patch
114
+ */
115
+ function arrayDiff(A, B) {
116
+ let start = 0;
117
+ let endA = A.length;
118
+ let endB = B.length;
119
+ // Trim common prefix
120
+ while (start < endA && start < endB && A[start] === B[start])
121
+ start++;
122
+ // Trim common suffix
123
+ while (endA > start && endB > start && A[endA - 1] === B[endB - 1]) {
124
+ endA--;
125
+ endB--;
126
+ }
127
+ const lenA = endA - start;
128
+ const lenB = endB - start;
129
+ if (lenA === 0 && lenB === 0)
130
+ return [];
131
+ if (lenA === 0)
132
+ return [{ indexA: start, indexB: start, sliceA: [], sliceB: B.slice(start, endB) }];
133
+ if (lenB === 0)
134
+ return [{ indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: [] }];
135
+ // Myers with bailout
136
+ const maxD = Math.min(lenA + lenB, BAILOUT_D);
137
+ const vSize = 2 * maxD + 1;
138
+ const vOffset = maxD;
139
+ const V = new Int32Array(vSize);
140
+ V[vOffset + 1] = 0;
141
+ const history = [];
142
+ for (let d = 0; d <= maxD; d++) {
143
+ for (let k = -d; k <= d; k += 2) {
144
+ let x;
145
+ if (k === -d || (k !== d && V[vOffset + k - 1] < V[vOffset + k + 1])) {
146
+ x = V[vOffset + k + 1];
147
+ }
148
+ else {
149
+ x = V[vOffset + k - 1] + 1;
150
+ }
151
+ let y = x - k;
152
+ while (x < lenA && y < lenB && A[start + x] === B[start + y]) {
153
+ x++;
154
+ y++;
155
+ }
156
+ V[vOffset + k] = x;
157
+ if (x >= lenA && y >= lenB)
158
+ return buildPatches(history, A, B, start, x, y, d, k, vOffset);
159
+ }
160
+ history.push(new Int32Array(V));
161
+ }
162
+ // Bailout: too many differences
163
+ return [
164
+ { indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: B.slice(start, endB) },
165
+ ];
166
+ }
167
+ function buildPatches(history, A, B, offset, finalX, finalY, finalD, finalK, vOffset) {
168
+ // Backtrack from (finalX, finalY) at step finalD to step 0, collecting ops in reverse
169
+ const ops = []; // 0=eq, 1=ins, 2=del
170
+ let x = finalX;
171
+ let y = finalY;
172
+ let k = finalK;
173
+ for (let d = finalD; d > 0; d--) {
174
+ const prev = history[d - 1];
175
+ let prevK;
176
+ let down;
177
+ if (k === -d) {
178
+ prevK = k + 1;
179
+ down = true;
180
+ }
181
+ else if (k === d) {
182
+ prevK = k - 1;
183
+ down = false;
184
+ }
185
+ else if (prev[vOffset + k - 1] < prev[vOffset + k + 1]) {
186
+ prevK = k + 1;
187
+ down = true;
188
+ }
189
+ else {
190
+ prevK = k - 1;
191
+ down = false;
192
+ }
193
+ const prevXEnd = prev[vOffset + prevK];
194
+ const prevYEnd = prevXEnd - prevK;
195
+ const xStart = down ? prevXEnd : prevXEnd + 1;
196
+ const yStart = down ? prevYEnd + 1 : prevXEnd + 1 - k;
197
+ // Diagonal matches (pushed in reverse)
198
+ while (x > xStart && y > yStart) {
199
+ ops.push(0);
200
+ x--;
201
+ y--;
202
+ }
203
+ // The edit step
204
+ if (down) {
205
+ ops.push(1); // ins
206
+ y--;
207
+ }
208
+ else {
209
+ ops.push(2); // del
210
+ x--;
211
+ }
212
+ k = prevK;
213
+ }
214
+ // Walk ops forward (they were pushed in reverse), grouping contiguous edits
215
+ const patches = [];
216
+ let currA = offset;
217
+ let currB = offset;
218
+ let sliceA = [];
219
+ let sliceB = [];
220
+ let patchA = -1;
221
+ let patchB = -1;
222
+ const flush = () => {
223
+ if (patchA !== -1) {
224
+ patches.push({ indexA: patchA, indexB: patchB, sliceA, sliceB });
225
+ sliceA = [];
226
+ sliceB = [];
227
+ patchA = -1;
228
+ }
229
+ };
230
+ for (let i = ops.length - 1; i >= 0; i--) {
231
+ const op = ops[i];
232
+ if (op === 0) {
233
+ flush();
234
+ currA++;
235
+ currB++;
236
+ }
237
+ else if (op === 1) {
238
+ if (patchA === -1) {
239
+ patchA = currA;
240
+ patchB = currB;
241
+ }
242
+ sliceB.push(B[currB++]);
243
+ }
244
+ else {
245
+ if (patchA === -1) {
246
+ patchA = currA;
247
+ patchB = currB;
248
+ }
249
+ sliceA.push(A[currA++]);
250
+ }
251
+ }
252
+ flush();
253
+ return patches;
254
+ }
255
+
256
+ var _a, _b;
257
+ const events = Symbol('events');
258
+ const hooks = Symbol('hooks');
259
+ const eventBehavior = {
260
+ on(eventOrEvents, cb) {
261
+ if (typeof eventOrEvents === 'object') {
262
+ for (const e of Object.keys(eventOrEvents)) {
263
+ this.on(e, eventOrEvents[e]);
264
+ }
265
+ }
266
+ else if (cb !== undefined) {
267
+ const callbacks = this[events].get(eventOrEvents) ?? new Set();
268
+ if (!callbacks.has(cb))
269
+ callbacks.add(cb);
270
+ this[events].set(eventOrEvents, callbacks);
271
+ }
272
+ return () => this.off(eventOrEvents, cb);
273
+ },
274
+ off(eventOrEvents, cb) {
275
+ if (typeof eventOrEvents === 'object') {
276
+ for (const e of Object.keys(eventOrEvents)) {
277
+ this.off(e, eventOrEvents[e]);
278
+ }
279
+ }
280
+ else if (cb !== null && cb !== undefined) {
281
+ const callbacks = this[events].get(eventOrEvents);
282
+ if (callbacks) {
283
+ callbacks.delete(cb);
284
+ if (!callbacks.size)
285
+ this[events].delete(eventOrEvents);
286
+ }
287
+ }
288
+ else {
289
+ // Remove all listeners for this event
290
+ this[events].delete(eventOrEvents);
291
+ }
292
+ },
293
+ emit(event, ...args) {
294
+ const callbacks = this[events].get(event);
295
+ if (callbacks)
296
+ for (const cb of callbacks)
297
+ cb.apply(this, args);
298
+ for (const cb of this[hooks])
299
+ cb.call(this, event, ...args);
300
+ },
301
+ };
302
+ function perEvent(eventful, fct, use) {
303
+ const cache = new Map();
304
+ return new Proxy(fct, {
305
+ get(target, prop) {
306
+ if (typeof prop !== 'string')
307
+ return target[prop];
308
+ if (use && !eventful[events].has(prop) && !eventful[hooks].size)
309
+ return () => { };
310
+ // Return cached function or create and cache
311
+ let cached = cache.get(prop);
312
+ if (!cached) {
313
+ cached = (...args) => fct.apply(eventful, [prop, ...args]);
314
+ cache.set(prop, cached);
315
+ }
316
+ return cached;
317
+ },
318
+ });
319
+ }
320
+ /**
321
+ * A type-safe event system that provides a clean API for event handling
322
+ * @template Events - The event map defining event names and their handler signatures
323
+ */
324
+ class Eventful {
325
+ constructor() {
326
+ this[_a] = new Map();
327
+ this[_b] = new Set();
328
+ this.on = perEvent(this, eventBehavior.on);
329
+ this.off = perEvent(this, eventBehavior.off);
330
+ this.emit = perEvent(this, eventBehavior.emit, 'use');
331
+ }
332
+ hook(cb) {
333
+ this[hooks].add(cb);
334
+ return () => {
335
+ this[hooks].delete(cb);
336
+ };
337
+ }
338
+ }
339
+ _a = events, _b = hooks;
340
+
341
+ /**
342
+ * Symbol for defining custom getter logic for numeric index access
343
+ */
344
+ const getAt = Symbol('getAt');
345
+ /**
346
+ * Symbol for defining custom setter logic for numeric index access
347
+ */
348
+ const setAt = Symbol('setAt');
349
+ function Indexable(base, accessor) {
350
+ if (base && typeof base !== 'function') {
351
+ accessor = base;
352
+ base = undefined;
353
+ }
354
+ if (!base) {
355
+ //@ts-expect-error
356
+ base = class {
357
+ };
358
+ }
359
+ if (!accessor) {
360
+ accessor = {
361
+ get(index) {
362
+ if (typeof this[getAt] !== 'function') {
363
+ throw new Error('Indexable class must have an [getAt] method');
364
+ }
365
+ return this[getAt](index);
366
+ },
367
+ set(index, value) {
368
+ if (typeof this[setAt] !== 'function') {
369
+ throw new Error('Indexable class has read-only numeric index access');
370
+ }
371
+ this[setAt](index, value);
372
+ },
373
+ };
374
+ }
375
+ class Indexable extends base {
376
+ }
377
+ Object.setPrototypeOf(Indexable.prototype, new Proxy(base.prototype, {
378
+ //@ts-expect-error
379
+ [Symbol.toStringTag]: 'MutTs Indexable',
380
+ get(target, prop, receiver) {
381
+ if (prop in target) {
382
+ const getter = Object.getOwnPropertyDescriptor(target, prop)?.get;
383
+ return getter ? getter.call(receiver) : target[prop];
384
+ }
385
+ if (typeof prop === 'string') {
386
+ if (prop === 'length' && accessor.getLength)
387
+ return accessor.getLength.call(receiver);
388
+ const numProp = Number(prop);
389
+ if (!Number.isNaN(numProp)) {
390
+ return accessor.get.call(receiver, numProp);
391
+ }
392
+ }
393
+ return undefined;
394
+ },
395
+ set(target, prop, value, receiver) {
396
+ if (prop in target) {
397
+ const setter = Object.getOwnPropertyDescriptor(target, prop)?.set;
398
+ if (setter)
399
+ setter.call(receiver, value);
400
+ else
401
+ target[prop] = value;
402
+ return true;
403
+ }
404
+ if (typeof prop === 'string') {
405
+ if (prop === 'length' && accessor.setLength) {
406
+ accessor.setLength.call(receiver, value);
407
+ return true;
408
+ }
409
+ const numProp = Number(prop);
410
+ if (!Number.isNaN(numProp)) {
411
+ if (!accessor.set)
412
+ throw new Error('Indexable class has read-only numeric index access');
413
+ accessor.set.call(receiver, numProp, value);
414
+ return true;
415
+ }
416
+ }
417
+ Object.defineProperty(receiver, prop, {
418
+ value,
419
+ writable: true,
420
+ enumerable: true,
421
+ configurable: true,
422
+ });
423
+ return true;
424
+ },
425
+ has(target, prop) {
426
+ if (prop in target)
427
+ return true;
428
+ if (typeof prop === 'string') {
429
+ if (prop === 'length' && accessor.getLength)
430
+ return true;
431
+ const numProp = Number(prop);
432
+ if (!Number.isNaN(numProp))
433
+ return true;
434
+ }
435
+ return false;
436
+ },
437
+ ownKeys(target) {
438
+ const keys = Reflect.ownKeys(target);
439
+ if (accessor.getLength) {
440
+ keys.push('length');
441
+ const len = accessor.getLength.call(this);
442
+ for (let i = 0; i < len; i++)
443
+ keys.push(String(i));
444
+ }
445
+ return keys;
446
+ },
447
+ getOwnPropertyDescriptor(target, prop) {
448
+ if (prop in target)
449
+ return Object.getOwnPropertyDescriptor(target, prop);
450
+ if (typeof prop === 'string') {
451
+ if (prop === 'length' && accessor.getLength) {
452
+ return {
453
+ enumerable: false,
454
+ configurable: true,
455
+ get: () => accessor.getLength.call(this),
456
+ };
457
+ }
458
+ const numProp = Number(prop);
459
+ if (!Number.isNaN(numProp)) {
460
+ return {
461
+ enumerable: true,
462
+ configurable: true,
463
+ get: () => accessor.get.call(this, numProp),
464
+ set: accessor.set
465
+ ? (v) => accessor.set.call(this, numProp, v)
466
+ : undefined,
467
+ };
468
+ }
469
+ }
470
+ return undefined;
471
+ },
472
+ }));
473
+ return Indexable;
474
+ }
475
+ /**
476
+ * Symbol for accessing the forwarded array in ArrayReadForward
477
+ */
478
+ const forwardArray = Symbol('forwardArray');
479
+ /**
480
+ * A read-only array forwarder that implements all reading/iterating methods of Array
481
+ * but does not implement modification methods.
482
+ *
483
+ * The constructor takes a callback that returns an array, and all methods forward
484
+ * their behavior to the result of that callback.
485
+ */
486
+ class ArrayReadForward {
487
+ get [forwardArray]() {
488
+ throw new Error('ArrayReadForward is not implemented');
489
+ }
490
+ /**
491
+ * Get the length of the array
492
+ */
493
+ get length() {
494
+ return this[forwardArray].length;
495
+ }
496
+ /**
497
+ * Iterator protocol support
498
+ */
499
+ [Symbol.iterator]() {
500
+ return this[forwardArray][Symbol.iterator]();
501
+ }
502
+ // Reading/Iterating methods
503
+ /**
504
+ * Creates a new array with the results of calling a provided function on every element
505
+ */
506
+ map(callbackfn, thisArg) {
507
+ return this[forwardArray].map(callbackfn, thisArg);
508
+ }
509
+ filter(predicate, thisArg) {
510
+ return this[forwardArray].filter(predicate, thisArg);
511
+ }
512
+ reduce(callbackfn, initialValue) {
513
+ return initialValue !== undefined
514
+ ? this[forwardArray].reduce(callbackfn, initialValue)
515
+ : this[forwardArray].reduce(callbackfn);
516
+ }
517
+ reduceRight(callbackfn, initialValue) {
518
+ return initialValue !== undefined
519
+ ? this[forwardArray].reduceRight(callbackfn, initialValue)
520
+ : this[forwardArray].reduceRight(callbackfn);
521
+ }
522
+ /**
523
+ * Executes a provided function once for each array element
524
+ */
525
+ forEach(callbackfn, thisArg) {
526
+ this[forwardArray].forEach(callbackfn, thisArg);
527
+ }
528
+ find(predicate, thisArg) {
529
+ return this[forwardArray].find(predicate, thisArg);
530
+ }
531
+ /**
532
+ * Returns the index of the first element in the array that satisfies the provided testing function
533
+ */
534
+ findIndex(predicate, thisArg) {
535
+ return this[forwardArray].findIndex(predicate, thisArg);
536
+ }
537
+ findLast(predicate, thisArg) {
538
+ return this[forwardArray].findLast(predicate, thisArg);
539
+ }
540
+ /**
541
+ * Returns the index of the last element in the array that satisfies the provided testing function
542
+ */
543
+ findLastIndex(predicate, thisArg) {
544
+ return this[forwardArray].findLastIndex(predicate, thisArg);
545
+ }
546
+ /**
547
+ * Determines whether an array includes a certain value among its entries
548
+ */
549
+ includes(searchElement, fromIndex) {
550
+ return this[forwardArray].includes(searchElement, fromIndex);
551
+ }
552
+ /**
553
+ * Returns the first index at which a given element can be found in the array
554
+ */
555
+ indexOf(searchElement, fromIndex) {
556
+ return this[forwardArray].indexOf(searchElement, fromIndex);
557
+ }
558
+ /**
559
+ * Returns the last index at which a given element can be found in the array
560
+ */
561
+ lastIndexOf(searchElement, fromIndex) {
562
+ return this[forwardArray].lastIndexOf(searchElement, fromIndex);
563
+ }
564
+ /**
565
+ * Returns a shallow copy of a portion of an array into a new array object
566
+ */
567
+ slice(start, end) {
568
+ return this[forwardArray].slice(start, end);
569
+ }
570
+ concat(...items) {
571
+ return this[forwardArray].concat(...items);
572
+ }
573
+ /**
574
+ * Tests whether all elements in the array pass the test implemented by the provided function
575
+ */
576
+ every(predicate, thisArg) {
577
+ return this[forwardArray].every(predicate, thisArg);
578
+ }
579
+ /**
580
+ * Tests whether at least one element in the array passes the test implemented by the provided function
581
+ */
582
+ some(predicate, thisArg) {
583
+ return this[forwardArray].some(predicate, thisArg);
584
+ }
585
+ /**
586
+ * Joins all elements of an array into a string
587
+ */
588
+ join(separator) {
589
+ return this[forwardArray].join(separator);
590
+ }
591
+ /**
592
+ * Returns a new array iterator that contains the keys for each index in the array
593
+ */
594
+ keys() {
595
+ return this[forwardArray].keys();
596
+ }
597
+ /**
598
+ * Returns a new array iterator that contains the values for each index in the array
599
+ */
600
+ values() {
601
+ return this[forwardArray].values();
602
+ }
603
+ /**
604
+ * Returns a new array iterator that contains the key/value pairs for each index in the array
605
+ */
606
+ entries() {
607
+ return this[forwardArray].entries();
608
+ }
609
+ /**
610
+ * Returns a string representation of the array
611
+ */
612
+ toString() {
613
+ return this[forwardArray].toString();
614
+ }
615
+ /**
616
+ * Returns a localized string representing the array
617
+ */
618
+ toLocaleString(locales, options) {
619
+ return this[forwardArray].toLocaleString(locales, options);
620
+ }
621
+ /**
622
+ * Returns the element at the specified index, or undefined if the index is out of bounds
623
+ */
624
+ at(index) {
625
+ return this[forwardArray].at(index);
626
+ }
627
+ /**
628
+ * Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth
629
+ */
630
+ flat(depth) {
631
+ return this[forwardArray].flat(depth);
632
+ }
633
+ /**
634
+ * Returns a new array formed by applying a given callback function to each element of the array,
635
+ * and then flattening the result by one level
636
+ */
637
+ flatMap(callback, thisArg) {
638
+ return this[forwardArray].flatMap(callback, thisArg);
639
+ }
640
+ /**
641
+ * Returns a new array with elements in reversed order (ES2023)
642
+ */
643
+ toReversed() {
644
+ return this[forwardArray].toReversed?.() ?? [...this[forwardArray]].reverse();
645
+ }
646
+ /**
647
+ * Returns a new array with elements sorted (ES2023)
648
+ */
649
+ toSorted(compareFn) {
650
+ return this[forwardArray].toSorted?.(compareFn) ?? [...this[forwardArray]].sort(compareFn);
651
+ }
652
+ /**
653
+ * Returns a new array with some elements removed and/or replaced at a given index (ES2023)
654
+ */
655
+ toSpliced(start, deleteCount, ...items) {
656
+ if (deleteCount === undefined)
657
+ return this[forwardArray].toSpliced(start);
658
+ return this[forwardArray].toSpliced(start, deleteCount, ...items);
659
+ }
660
+ /**
661
+ * Returns a new array with the element at the given index replaced with the given value (ES2023)
662
+ */
663
+ with(index, value) {
664
+ return this[forwardArray].with(index, value);
665
+ }
666
+ get [Symbol.unscopables]() {
667
+ return this[forwardArray][Symbol.unscopables];
668
+ }
669
+ }
670
+
671
+ const forward = (name, target) => (...args) => {
672
+ return target[name](...args);
673
+ };
674
+ const alreadyChained = new WeakMap();
675
+ const originals = new WeakMap();
676
+ function cache$1(target, rv) {
677
+ originals.set(rv, target);
678
+ alreadyChained.set(target, rv);
679
+ }
680
+ const promiseProxyHandler = {
681
+ //@ts-expect-error
682
+ [Symbol.toStringTag]: 'MutTs PromiseChain function',
683
+ get(target, prop) {
684
+ if (prop === Symbol.toStringTag)
685
+ return 'PromiseProxy';
686
+ if (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))
687
+ return target[prop];
688
+ return chainPromise(target.then((r) => r[prop]));
689
+ },
690
+ };
691
+ const promiseForward = (target) => ({
692
+ // biome-ignore lint/suspicious/noThenProperty: This one is the whole point
693
+ then: forward('then', target),
694
+ catch: forward('catch', target),
695
+ finally: forward('finally', target),
696
+ });
697
+ const objectProxyHandler = {
698
+ //@ts-expect-error
699
+ [Symbol.toStringTag]: 'MutTs PromiseChain object',
700
+ get(target, prop, receiver) {
701
+ const getter = Object.getOwnPropertyDescriptor(target, prop)?.get;
702
+ const rv = getter ? getter.call(receiver) : target[prop];
703
+ // Allows fct.call or fct.apply to bypass the chain system
704
+ if (typeof target === 'function')
705
+ return rv;
706
+ return chainPromise(rv);
707
+ },
708
+ apply(target, thisArg, args) {
709
+ return chainPromise(target.apply(thisArg, args));
710
+ },
711
+ };
712
+ function chainObject(given) {
713
+ const rv = new Proxy(given, objectProxyHandler);
714
+ cache$1(given, rv);
715
+ return rv;
716
+ }
717
+ function chainable(x) {
718
+ return x && ['function', 'object'].includes(typeof x);
719
+ }
720
+ /**
721
+ * Transforms a promise or value into a chainable object
722
+ * Allows calling methods directly on promise results without awaiting them first
723
+ * @param given - The promise or value to make chainable
724
+ * @returns A chainable version of the input
725
+ */
726
+ function chainPromise(given) {
727
+ if (!chainable(given))
728
+ return given;
729
+ if (alreadyChained.has(given))
730
+ return alreadyChained.get(given);
731
+ if (!(given instanceof Promise))
732
+ return chainObject(given);
733
+ // @ts-expect-error It's ok as we check if it's an object above
734
+ given = given.then((r) => (chainable(r) ? chainObject(r) : r));
735
+ const target = Object.assign(function (...args) {
736
+ return chainPromise(given.then((r) => {
737
+ return this?.then
738
+ ? this.then((t) => r.apply(t, args))
739
+ : r.apply(this, args);
740
+ }));
741
+ }, promiseForward(given));
742
+ const chained = new Proxy(target, promiseProxyHandler);
743
+ cache$1(given, chained);
744
+ return chained;
745
+ }
746
+
747
+ const memoizedRegistry = new WeakMap();
748
+ const wrapperRegistry = new WeakMap();
749
+ function getBranch(tree, key) {
750
+ tree.branches ?? (tree.branches = new WeakMap());
751
+ let branch = tree.branches.get(key);
752
+ if (!branch) {
753
+ branch = {};
754
+ tree.branches.set(key, branch);
755
+ }
756
+ return branch;
757
+ }
758
+ function memoizeFunction(fn, opts) {
759
+ const fnRoot = getRoot(fn);
760
+ const existing = memoizedRegistry.get(fnRoot);
761
+ if (existing)
762
+ return existing;
763
+ const cacheRoot = {};
764
+ const memoized = markWithRoot(function memoized(...args) {
765
+ if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
766
+ if (opts?.lenient)
767
+ return fn.apply(this, args);
768
+ throw new Error('memoize expects non-null object arguments');
769
+ }
770
+ let node = cacheRoot;
771
+ // Note: decorators add `this` as first argument
772
+ for (const arg of args) {
773
+ node = getBranch(node, arg);
774
+ }
775
+ dependant(node, 'memoize');
776
+ if ('result' in node) {
777
+ if (options.onMemoizationDiscrepancy) {
778
+ const wasVerification = options.isVerificationRun;
779
+ options.isVerificationRun = true;
780
+ try {
781
+ const fresh = untracked(() => fn.apply(this, args));
782
+ if (!deepCompare(node.result, fresh)) {
783
+ optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
784
+ }
785
+ }
786
+ finally {
787
+ options.isVerificationRun = wasVerification;
788
+ }
789
+ }
790
+ return node.result;
791
+ }
792
+ // Create memoize internal effect to track dependencies and invalidate cache
793
+ // Use untracked to prevent the effect creation from being affected by parent effects
794
+ node.cleanup = root(() => effect.named('memoize')(() => {
795
+ // Execute the function and track its dependencies
796
+ // The function execution will automatically track dependencies on reactive objects
797
+ node.result = fn.apply(this, args);
798
+ return (reason) => {
799
+ // When dependencies change, clear the cache and notify consumers
800
+ delete node.result;
801
+ touched1(node, { type: 'invalidate', prop: args }, 'memoize');
802
+ // Lazy memoization: stop the effect so it doesn't re-run immediately.
803
+ // It will be re-created on next access.
804
+ if (node.cleanup) {
805
+ node.cleanup({ type: 'invalidate', cause: reason });
806
+ node.cleanup = undefined;
807
+ }
808
+ };
809
+ }, { opaque: true }));
810
+ if (options.onMemoizationDiscrepancy) {
811
+ const wasVerification = options.isVerificationRun;
812
+ options.isVerificationRun = true;
813
+ try {
814
+ const fresh = untracked(() => fn.apply(this, args));
815
+ if (!deepCompare(node.result, fresh)) {
816
+ optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
817
+ }
818
+ }
819
+ finally {
820
+ options.isVerificationRun = wasVerification;
821
+ }
822
+ }
823
+ return node.result;
824
+ }, fn);
825
+ memoizedRegistry.set(fnRoot, memoized);
826
+ memoizedRegistry.set(memoized, memoized);
827
+ return memoized;
828
+ }
829
+ function memoizeObject(target, opts) {
830
+ const existing = memoizedRegistry.get(target);
831
+ if (existing)
832
+ return existing;
833
+ const proxy = new Proxy(target, {
834
+ get(source, prop, receiver) {
835
+ // 1. Walk prototype chain to find descriptor
836
+ let current = source;
837
+ let desc;
838
+ while (current) {
839
+ desc = Object.getOwnPropertyDescriptor(current, prop);
840
+ if (desc)
841
+ break;
842
+ current = Object.getPrototypeOf(current);
843
+ }
844
+ if (!desc)
845
+ return Reflect.get(source, prop, receiver);
846
+ // 2. If getter, memoize
847
+ if (desc.get) {
848
+ const originalGetter = desc.get;
849
+ let wrapper = wrapperRegistry.get(originalGetter);
850
+ if (!wrapper) {
851
+ wrapper = markWithRoot(named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
852
+ return originalGetter.call(that);
853
+ }), {
854
+ propertyKey: prop,
855
+ });
856
+ const origRoot = originalGetter[rootFunctionSymbol];
857
+ if (origRoot)
858
+ wrapper[rootFunctionSymbol] = origRoot;
859
+ wrapperRegistry.set(originalGetter, wrapper);
860
+ }
861
+ const memoized = memoizeFunction(wrapper, opts);
862
+ return memoized(receiver);
863
+ }
864
+ // 3. Otherwise forward
865
+ return Reflect.get(source, prop, receiver);
866
+ },
867
+ // Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
868
+ set(source, prop, value, _receiver) {
869
+ // By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
870
+ // it recognizes itself and triggers change notifications.
871
+ return Reflect.set(source, prop, value, source);
872
+ },
873
+ });
874
+ proxyToObject.set(proxy, target);
875
+ memoizedRegistry.set(target, proxy);
876
+ return proxy;
877
+ }
878
+ /**
879
+ * Decorator and function wrapper for memoizing computed values based on reactive dependencies.
880
+ *
881
+ * When used as a decorator on getters or methods, it caches the result and automatically
882
+ * invalidates the cache when reactive dependencies change.
883
+ *
884
+ * When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
885
+ *
886
+ * @example
887
+ * ```typescript
888
+ * class User {
889
+ * @memoize
890
+ * get fullName() {
891
+ * return `${this.firstName} ${this.lastName}`
892
+ * }
893
+ * }
894
+ *
895
+ * // Or as a function wrapper
896
+ * const expensive = memoize((obj: SomeObject) => {
897
+ * return heavyComputation(obj)
898
+ * })
899
+ * ```
900
+ */
901
+ function makeMemoizeDecorator(memoizeOpts) {
902
+ return decorator({
903
+ getter(original, target, propertyKey) {
904
+ return function () {
905
+ let wrapper = wrapperRegistry.get(original);
906
+ if (!wrapper) {
907
+ wrapper = markWithRoot(named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
908
+ return original.call(that);
909
+ }), {
910
+ method: original,
911
+ propertyKey,
912
+ });
913
+ const origRoot = original[rootFunctionSymbol];
914
+ if (origRoot)
915
+ wrapper[rootFunctionSymbol] = origRoot;
916
+ wrapperRegistry.set(original, wrapper);
917
+ }
918
+ const memoized = memoizeFunction(wrapper, memoizeOpts);
919
+ return memoized(this);
920
+ };
921
+ },
922
+ method(original, target, name) {
923
+ return function (...args) {
924
+ let wrapper = wrapperRegistry.get(original);
925
+ if (!wrapper) {
926
+ wrapper = markWithRoot(named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
927
+ return original.call(that, ...args);
928
+ }), {
929
+ method: original,
930
+ propertyKey: name,
931
+ });
932
+ const origRoot = original[rootFunctionSymbol];
933
+ if (origRoot)
934
+ wrapper[rootFunctionSymbol] = origRoot;
935
+ wrapperRegistry.set(original, wrapper);
936
+ }
937
+ const memoized = memoizeFunction(wrapper, memoizeOpts);
938
+ return memoized(this, ...args);
939
+ };
940
+ },
941
+ default: (target) => typeof target === 'object'
942
+ ? memoizeObject(target, memoizeOpts)
943
+ : memoizeFunction(target, memoizeOpts),
944
+ });
945
+ }
946
+ const memoize = flavored(makeMemoizeDecorator(), {
947
+ get lenient() {
948
+ return makeMemoizeDecorator({ lenient: true });
949
+ },
950
+ });
951
+
952
+ function attend(source, callback) {
953
+ const enumerate = typeof source === 'function'
954
+ ? source
955
+ : Array.isArray(source)
956
+ ? () => Array.from({ length: source.length }, (_, i) => i)
957
+ : source instanceof Map
958
+ ? () => source.keys()
959
+ : source instanceof Set
960
+ ? () => source.values()
961
+ : () => Object.keys(source);
962
+ const keyEffects = new Map();
963
+ const outer = effect(({ ascend }) => {
964
+ const keys = new Set();
965
+ for (const key of enumerate())
966
+ keys.add(key);
967
+ for (const key of keys) {
968
+ if (keyEffects.has(key))
969
+ continue;
970
+ keyEffects.set(key, ascend(() => effect(() => callback(key))));
971
+ }
972
+ for (const key of Array.from(keyEffects.keys())) {
973
+ if (!keys.has(key)) {
974
+ keyEffects.get(key)();
975
+ keyEffects.delete(key);
976
+ }
977
+ }
978
+ });
979
+ return (reason) => {
980
+ outer(reason);
981
+ for (const stop of keyEffects.values())
982
+ stop(reason);
983
+ keyEffects.clear();
984
+ };
985
+ }
986
+ /**
987
+ * Perform a reactive scan over an array of items.
988
+ *
989
+ * This implementation is highly optimized for performance and fine-grained reactivity:
990
+ * - **Incremental Updates**: Changes to an item only trigger re-computation from that
991
+ * point onwards in the result chain.
992
+ * - **Move Optimization**: If items are moved within the array, their accumulated
993
+ * values are reused as long as their predecessor remains the same.
994
+ * - **Duplicate Support**: Correctly handles multiple occurrences of the same object
995
+ * instance using an internal occurrence tracking mechanism.
996
+ * - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
997
+ * automatically cleared when source items are garbage collected.
998
+ *
999
+ * @example
1000
+ * ```typescript
1001
+ * const source = reactive([{ val: 1 }, { val: 2 }, { val: 3 }])
1002
+ * const sum = scan(source, (acc, item) => acc + item.val, 0)
1003
+ *
1004
+ * expect([...sum]).toEqual([1, 3, 6])
1005
+ *
1006
+ * // Modifying an item only re-computes subsequent sums
1007
+ * source[1].val = 10
1008
+ * expect([...sum]).toEqual([1, 11, 14])
1009
+ * ```
1010
+ *
1011
+ * @param source The source array of objects (will be made reactive)
1012
+ * @param callback The accumulator function called with (accumulator, currentItem)
1013
+ * @param initialValue The starting value for the accumulation
1014
+ * @returns A reactive array of accumulated values, with a [cleanup] property to stop the tracking
1015
+ */
1016
+ function scan(source, callback, initialValue) {
1017
+ const observedSource = reactive(source);
1018
+ const rawResult = [];
1019
+ const result = reactive(rawResult);
1020
+ // Track effects for each index to dispose them when the array shrinks
1021
+ const indexEffects = new Map();
1022
+ // Mapping from index to its current intermediate object
1023
+ const indexToIntermediate = reactive([]);
1024
+ const intermediaries = new WeakMap();
1025
+ let Intermediate = (() => {
1026
+ var _a;
1027
+ let _instanceExtraInitializers = [];
1028
+ let _get_acc_decorators;
1029
+ return _a = class Intermediate {
1030
+ constructor(val, prev) {
1031
+ this.val = (__runInitializers(this, _instanceExtraInitializers), val);
1032
+ this.prev = prev;
1033
+ }
1034
+ get acc() {
1035
+ const prevAcc = this.prev ? this.prev.acc : initialValue;
1036
+ return callback(prevAcc, this.val);
1037
+ }
1038
+ },
1039
+ (() => {
1040
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
1041
+ _get_acc_decorators = [memoize];
1042
+ __esDecorate(_a, null, _get_acc_decorators, { kind: "getter", name: "acc", static: false, private: false, access: { has: obj => "acc" in obj, get: obj => obj.acc }, metadata: _metadata }, null, _instanceExtraInitializers);
1043
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1044
+ })(),
1045
+ _a;
1046
+ })();
1047
+ function disposeIndex(index) {
1048
+ const stop = indexEffects.get(index);
1049
+ if (stop) {
1050
+ stop();
1051
+ indexEffects.delete(index);
1052
+ Reflect.deleteProperty(indexToIntermediate, index);
1053
+ Reflect.deleteProperty(result, index);
1054
+ }
1055
+ }
1056
+ const mainEffect = effect(function scanMainEffect({ ascend }) {
1057
+ const length = observedSource.length;
1058
+ const occurrenceCount = new Map();
1059
+ let prev;
1060
+ for (let i = 0; i < length; i++)
1061
+ if (i in observedSource) {
1062
+ const val = observedSource[i];
1063
+ if (!(val &&
1064
+ (typeof val === 'object' || typeof val === 'function' || typeof val === 'symbol'))) {
1065
+ throw new Error('scan: items must be objects (WeakKey) for intermediate caching');
1066
+ }
1067
+ const count = occurrenceCount.get(val) ?? 0;
1068
+ occurrenceCount.set(val, count + 1);
1069
+ let list = intermediaries.get(val);
1070
+ if (!list) {
1071
+ list = [];
1072
+ intermediaries.set(val, list);
1073
+ }
1074
+ let intermediate = list[count];
1075
+ if (!intermediate) {
1076
+ intermediate = reactive(new Intermediate(val, prev));
1077
+ list[count] = intermediate;
1078
+ }
1079
+ else {
1080
+ // Update the link.
1081
+ if (untracked(() => intermediate.prev) !== prev) {
1082
+ intermediate.prev = prev;
1083
+ }
1084
+ }
1085
+ // Update the reactive mapping for this index
1086
+ if (indexToIntermediate[i] !== intermediate) {
1087
+ indexToIntermediate[i] = intermediate;
1088
+ }
1089
+ // If we don't have an effect for this index yet, create one
1090
+ if (!indexEffects.has(i)) {
1091
+ ascend(() => {
1092
+ const index = i;
1093
+ const stop = effect(function scanIndexSyncEffect() {
1094
+ const inter = indexToIntermediate[index];
1095
+ if (inter) {
1096
+ const accValue = inter.acc;
1097
+ result[index] = accValue;
1098
+ }
1099
+ });
1100
+ indexEffects.set(index, stop);
1101
+ });
1102
+ }
1103
+ prev = intermediate;
1104
+ }
1105
+ // Cleanup trailing indices
1106
+ for (const index of Array.from(indexEffects.keys())) {
1107
+ if (index >= length)
1108
+ disposeIndex(index);
1109
+ }
1110
+ // Ensure result length matches source length
1111
+ if (rawResult.length !== length) {
1112
+ FoolProof.set(result, 'length', length, result);
1113
+ }
1114
+ });
1115
+ return cleanedBy(result, ((reason) => {
1116
+ mainEffect(reason);
1117
+ for (const stop of indexEffects.values())
1118
+ stop(reason);
1119
+ indexEffects.clear();
1120
+ }));
1121
+ }
1122
+ function lift(cb) {
1123
+ let result;
1124
+ let rawResult;
1125
+ const liftCleanup = effect.named('lift')(markWithRoot((access) => {
1126
+ const source = cb(access);
1127
+ if (!source || typeof source !== 'object')
1128
+ throw new Error('lift callback must return an array or object');
1129
+ const sourceProto = Object.getPrototypeOf(source);
1130
+ if (!result) {
1131
+ rawResult = Array.isArray(source) ? [] : Object.create(sourceProto);
1132
+ result = reactive(rawResult);
1133
+ }
1134
+ if (sourceProto !== Object.getPrototypeOf(result))
1135
+ throw new Error('lift callback must return the same type as the previous result');
1136
+ if (Array.isArray(source)) {
1137
+ const res = result;
1138
+ const patches = arrayDiff(res, source);
1139
+ for (let i = patches.length - 1; i >= 0; i--) {
1140
+ const { indexA, sliceA, sliceB } = patches[i];
1141
+ res.splice(indexA, sliceA.length, ...sliceB);
1142
+ }
1143
+ }
1144
+ else {
1145
+ for (const key of Object.keys(source)) {
1146
+ const had = key in rawResult;
1147
+ const newDesc = Object.getOwnPropertyDescriptor(source, key);
1148
+ if (had) {
1149
+ const oldDesc = Object.getOwnPropertyDescriptor(rawResult, key);
1150
+ const sameAccessor = oldDesc && newDesc.get && oldDesc.get === newDesc.get;
1151
+ Object.defineProperty(rawResult, key, newDesc);
1152
+ if (!sameAccessor &&
1153
+ rawResult[key] !==
1154
+ (oldDesc ? (oldDesc.get ? oldDesc.get() : oldDesc.value) : undefined))
1155
+ touched1(rawResult, { type: 'set', prop: key }, key);
1156
+ }
1157
+ else {
1158
+ Object.defineProperty(rawResult, key, newDesc);
1159
+ touched1(rawResult, { type: 'add', prop: key }, key);
1160
+ }
1161
+ }
1162
+ for (const key of Object.keys(rawResult))
1163
+ if (!(key in source)) {
1164
+ delete rawResult[key];
1165
+ touched1(rawResult, { type: 'del', prop: key }, key);
1166
+ }
1167
+ }
1168
+ }, cb));
1169
+ return cleanedBy(result, liftCleanup);
1170
+ }
1171
+ /**
1172
+ * Reactively maps an array source through `fn`, producing a lazy reactive output array.
1173
+ *
1174
+ * Each source item gets its own isolated effect (via `root()`) so that changes to one item
1175
+ * only recompute that item's projection. Structural changes (push, splice, reorder) are detected
1176
+ * via `arrayDiff` and surgically applied to the output cache.
1177
+ *
1178
+ * The source can be a reactive array or a function returning an array. When a function is provided,
1179
+ * the function is re-evaluated inside an effect whenever its dependencies change.
1180
+ *
1181
+ * Output elements are computed lazily — accessing `result[i]` triggers computation if not yet cached.
1182
+ *
1183
+ * @param source - A reactive array or a function returning an array
1184
+ * @param fn - Mapping function applied to each element
1185
+ * @param options - Optional purity hints to skip per-item effects
1186
+ * @returns A readonly reactive array with a `[cleanup]` method to dispose all effects
1187
+ */
1188
+ function morphArray(source, fn, options) {
1189
+ if (typeof source !== 'function' && !isReactive(source) && options?.pure === true) {
1190
+ return source.map(fn);
1191
+ }
1192
+ let track;
1193
+ const itemEffects = new Map();
1194
+ const cache = [];
1195
+ let input = [];
1196
+ function stopItem(key) {
1197
+ const entry = itemEffects.get(key);
1198
+ if (entry) {
1199
+ entry.stop({ type: 'stopped' });
1200
+ itemEffects.delete(key);
1201
+ }
1202
+ }
1203
+ function computeItem(key, input) {
1204
+ const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(input));
1205
+ if (isPure) {
1206
+ track(() => {
1207
+ cache[key] = fn(input);
1208
+ });
1209
+ }
1210
+ else {
1211
+ const indexRef = { value: key };
1212
+ let stop;
1213
+ track(() => {
1214
+ stop = effect.opaque(() => {
1215
+ cache[indexRef.value] = fn(input);
1216
+ return (reason) => {
1217
+ delete cache[indexRef.value];
1218
+ touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1219
+ stop({ type: 'invalidate', cause: reason });
1220
+ };
1221
+ });
1222
+ });
1223
+ itemEffects.set(key, { stop, index: indexRef });
1224
+ }
1225
+ }
1226
+ const proxy = reactive(cache, {
1227
+ get(cache, prop) {
1228
+ const n = typeof prop === 'string' ? Number(prop) : NaN;
1229
+ if (Number.isNaN(n))
1230
+ return cache[prop];
1231
+ if (!(n in cache))
1232
+ computeItem(n, input[n]);
1233
+ return cache[n];
1234
+ },
1235
+ has(_cache, prop) {
1236
+ return Reflect.has(input, prop);
1237
+ },
1238
+ });
1239
+ const stopMain = effect.named('morph:array')(({ ascend }) => {
1240
+ track = ascend;
1241
+ const newInput = [...(typeof source === 'function' ? source() : source)];
1242
+ const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
1243
+ if (diffs.length > 0) {
1244
+ for (const diff of diffs) {
1245
+ // Stop items in removed range
1246
+ for (let i = diff.indexA; i < diff.indexA + diff.sliceA.length; i++)
1247
+ stopItem(i);
1248
+ // Shift existing itemEffects in the Map to match the new indices
1249
+ const shift = diff.sliceB.length - diff.sliceA.length;
1250
+ if (shift !== 0) {
1251
+ // We need to move entries in the Map.
1252
+ const entries = Array.from(itemEffects.entries()).sort((a, b) => a[0] - b[0]);
1253
+ // Remove entries that will be shifted
1254
+ for (const [idx, entry] of entries) {
1255
+ if (idx >= diff.indexA + diff.sliceA.length) {
1256
+ itemEffects.delete(idx);
1257
+ }
1258
+ }
1259
+ // Re-add them with shifted indices
1260
+ for (const [idx, entry] of entries) {
1261
+ if (idx >= diff.indexA + diff.sliceA.length) {
1262
+ const newIdx = idx + shift;
1263
+ entry.index.value = newIdx;
1264
+ itemEffects.set(newIdx, entry);
1265
+ }
1266
+ }
1267
+ }
1268
+ // Splice the cache
1269
+ cache.splice(diff.indexA, diff.sliceA.length, ...new Array(diff.sliceB.length).fill(undefined));
1270
+ // Make holes for lazy computation
1271
+ for (let i = diff.indexA; i < diff.indexA + diff.sliceB.length; i++)
1272
+ delete cache[i];
1273
+ }
1274
+ const invalidates = new Set([keysOf]);
1275
+ if (input.length !== newInput.length)
1276
+ invalidates.add('length');
1277
+ for (const diff of diffs) {
1278
+ const max = Math.max(diff.sliceA.length, diff.sliceB.length);
1279
+ for (let i = 0; i < max; i++)
1280
+ invalidates.add(String(diff.indexA + i));
1281
+ }
1282
+ touched(cache, { type: 'bunch', method: 'morph-input' }, invalidates);
1283
+ }
1284
+ input = newInput;
1285
+ });
1286
+ return cleanedBy(proxy, (reason) => {
1287
+ stopMain(reason);
1288
+ for (const entry of itemEffects.values())
1289
+ entry.stop(reason);
1290
+ itemEffects.clear();
1291
+ });
1292
+ }
1293
+ /**
1294
+ * Reactively maps a `Map` source through `fn`, producing a reactive output Map.
1295
+ *
1296
+ * Each key gets its own isolated effect so that value changes for one key only recompute
1297
+ * that key's projection. Key additions and removals are tracked via `keysOf` dependency.
1298
+ *
1299
+ * @param source - A reactive Map
1300
+ * @param fn - Mapping function applied to each value
1301
+ * @param options - Optional purity hints to skip per-key effects
1302
+ * @returns A reactive Map with a `[cleanup]` method to dispose all effects
1303
+ */
1304
+ function morphMap(source, fn, options) {
1305
+ if (!isReactive(source) && options?.pure === true) {
1306
+ const res = new Map();
1307
+ for (const [k, v] of source)
1308
+ res.set(k, fn(v));
1309
+ return res;
1310
+ }
1311
+ let track;
1312
+ const itemEffects = new Map();
1313
+ const cache = new Map();
1314
+ Object.defineProperty(cache, 'constructor', { value: Object, enumerable: false });
1315
+ function stopItem(key) {
1316
+ const stop = itemEffects.get(key);
1317
+ if (stop) {
1318
+ stop({ type: 'stopped' });
1319
+ itemEffects.delete(key);
1320
+ }
1321
+ }
1322
+ function computeItem(key, val) {
1323
+ const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1324
+ if (isPure) {
1325
+ cache.set(key, track(() => fn(val)));
1326
+ }
1327
+ else {
1328
+ const stop = track(() => effect.opaque(() => {
1329
+ cache.set(key, fn(source.get(key)));
1330
+ return (reason) => {
1331
+ cache.delete(key);
1332
+ touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1333
+ stop({ type: 'invalidate', cause: reason });
1334
+ };
1335
+ }));
1336
+ itemEffects.set(key, stop);
1337
+ }
1338
+ }
1339
+ const proxy = reactive(cache, {
1340
+ get(cache, prop) {
1341
+ if (prop === 'get')
1342
+ return (key) => {
1343
+ if (!cache.has(key) && source.has(key))
1344
+ computeItem(key, source.get(key));
1345
+ return cache.get(key);
1346
+ };
1347
+ if (prop === 'has')
1348
+ return (key) => {
1349
+ return source.has(key);
1350
+ };
1351
+ if (prop === 'keys')
1352
+ return () => {
1353
+ return source.keys();
1354
+ };
1355
+ if (prop === 'values')
1356
+ return function* () {
1357
+ for (const key of source.keys()) {
1358
+ yield proxy.get(key);
1359
+ }
1360
+ };
1361
+ if (prop === 'entries')
1362
+ return function* () {
1363
+ for (const key of source.keys()) {
1364
+ yield [key, proxy.get(key)];
1365
+ }
1366
+ };
1367
+ if (prop === Symbol.iterator)
1368
+ return function* () {
1369
+ for (const key of source.keys()) {
1370
+ yield [key, proxy.get(key)];
1371
+ }
1372
+ };
1373
+ return cache[prop];
1374
+ },
1375
+ });
1376
+ let stateSnapshot = getState(source);
1377
+ const stopMain = effect.named('morph:map')(({ ascend }) => {
1378
+ track = ascend;
1379
+ dependant(source, keysOf);
1380
+ while ('evolution' in stateSnapshot) {
1381
+ const { evolution } = stateSnapshot;
1382
+ stateSnapshot = stateSnapshot.next;
1383
+ if (evolution.type === 'add') {
1384
+ touched1(cache, evolution, evolution.prop);
1385
+ }
1386
+ else if (evolution.type === 'del') {
1387
+ stopItem(evolution.prop);
1388
+ cache.delete(evolution.prop);
1389
+ touched1(cache, evolution, evolution.prop);
1390
+ }
1391
+ }
1392
+ });
1393
+ return cleanedBy(proxy, (reason) => {
1394
+ stopMain(reason);
1395
+ for (const stop of itemEffects.values())
1396
+ stop(reason);
1397
+ itemEffects.clear();
1398
+ });
1399
+ }
1400
+ /**
1401
+ * Reactively maps a record/object source through `fn`, producing a reactive output record.
1402
+ *
1403
+ * Each key gets its own isolated effect so that value changes for one key only recompute
1404
+ * that key's projection. Key additions and removals are tracked automatically.
1405
+ *
1406
+ * @param source - A reactive record
1407
+ * @param fn - Mapping function applied to each value
1408
+ * @param options - Optional purity hints to skip per-key effects
1409
+ * @returns A reactive record with a `[cleanup]` method to dispose all effects
1410
+ */
1411
+ function morphRecord(source, fn, options) {
1412
+ if (!isReactive(source) && options?.pure === true) {
1413
+ const res = {};
1414
+ for (const k of Object.keys(source))
1415
+ res[k] = fn(source[k]);
1416
+ return res;
1417
+ }
1418
+ let track;
1419
+ const itemEffects = new Map();
1420
+ const cache = {};
1421
+ function stopItem(key) {
1422
+ const stop = itemEffects.get(key);
1423
+ if (stop) {
1424
+ stop({ type: 'stopped' });
1425
+ itemEffects.delete(key);
1426
+ }
1427
+ }
1428
+ function computeItem(key, val) {
1429
+ const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1430
+ if (isPure) {
1431
+ cache[key] = track(() => fn(val));
1432
+ }
1433
+ else {
1434
+ const stop = track(() => effect.opaque(() => {
1435
+ cache[key] = fn(source[key]);
1436
+ return (reason) => {
1437
+ delete cache[key];
1438
+ touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1439
+ stop({ type: 'invalidate', cause: reason });
1440
+ };
1441
+ }));
1442
+ itemEffects.set(key, stop);
1443
+ }
1444
+ }
1445
+ function get(prop) {
1446
+ if (!(prop in cache) && prop in source)
1447
+ computeItem(prop, source[prop]);
1448
+ return cache[prop];
1449
+ }
1450
+ const proxy = reactive(cache, {
1451
+ get(_, prop) {
1452
+ return get(prop);
1453
+ },
1454
+ has(_, prop) {
1455
+ return prop in source;
1456
+ },
1457
+ ownKeys() {
1458
+ return Reflect.ownKeys(source);
1459
+ },
1460
+ getOwnPropertyDescriptor(_cache, prop) {
1461
+ if (prop in source)
1462
+ return { configurable: true, enumerable: true, get: () => get(prop) };
1463
+ },
1464
+ });
1465
+ let stateSnapshot = getState(source);
1466
+ const stopMain = effect.named('morph:record')(({ ascend }) => {
1467
+ track = ascend;
1468
+ // Track only structural changes on source
1469
+ dependant(source, keysOf);
1470
+ while ('evolution' in stateSnapshot) {
1471
+ const { evolution } = stateSnapshot;
1472
+ stateSnapshot = stateSnapshot.next;
1473
+ if (evolution.type === 'add') {
1474
+ touched1(cache, evolution, evolution.prop);
1475
+ }
1476
+ else if (evolution.type === 'del') {
1477
+ stopItem(evolution.prop);
1478
+ delete cache[evolution.prop];
1479
+ touched1(cache, evolution, evolution.prop);
1480
+ }
1481
+ }
1482
+ });
1483
+ return cleanedBy(proxy, (reason) => {
1484
+ stopMain(reason);
1485
+ for (const stop of itemEffects.values())
1486
+ stop(reason);
1487
+ itemEffects.clear();
1488
+ });
1489
+ }
1490
+ /**
1491
+ * Reactively maps a collection (array, Map, or record) through a per-entry function.
1492
+ *
1493
+ * Each entry in the source gets its own reactive context — when only one entry's dependencies
1494
+ * change, only that entry's projection recomputes. Structural changes (additions, removals,
1495
+ * reorders) are detected via diffing and applied surgically.
1496
+ *
1497
+ * Use `morph.pure(source, fn)` when `fn` has no reactive reads (skips per-item effects).
1498
+ *
1499
+ * @example
1500
+ * ```ts
1501
+ * const users = reactive([{ name: 'John' }, { name: 'Jane' }])
1502
+ * const names = morph(users, u => u.name.toUpperCase())
1503
+ * // names[0] = 'JOHN', names[1] = 'JANE'
1504
+ * // Changing users[0].name only recomputes names[0]
1505
+ * ```
1506
+ */
1507
+ const morph = flavored(function morph(source, fn, options) {
1508
+ if (Array.isArray(source) || typeof source === 'function')
1509
+ return morphArray(source, fn, options);
1510
+ if (source instanceof Map)
1511
+ return morphMap(source, fn, options);
1512
+ return morphRecord(source, fn, options);
1513
+ }, {
1514
+ get pure() {
1515
+ return (source, fn, _opt) => this(source, fn, { pure: true });
1516
+ },
1517
+ });
1518
+
1519
+ /**
1520
+ * Deep watch an object and all its nested properties
1521
+ * @param target - The object to watch deeply
1522
+ * @param callback - The callback to call when any nested property changes
1523
+ * @param options - Options for the deep watch
1524
+ * @returns A cleanup function to stop watching
1525
+ */
1526
+ /**
1527
+ * Sets up deep watching for an object, tracking all nested property changes
1528
+ * @param target - The object to watch
1529
+ * @param callback - The callback to call when changes occur
1530
+ * @param options - Options for deep watching
1531
+ * @returns A cleanup function to stop deep watching
1532
+ */
1533
+ function deepWatch(target, callback, { immediate = false } = {}) {
1534
+ if (target === null || target === undefined)
1535
+ return undefined;
1536
+ if (typeof target !== 'object')
1537
+ throw new Error('Target of deep watching must be an object');
1538
+ // Create a wrapper callback that matches EffectTrigger signature
1539
+ const wrappedCallback = markWithRoot((() => callback(target)), callback);
1540
+ registerDeepWatcher();
1541
+ // Use the existing effect system to register dependencies
1542
+ return effect(() => {
1543
+ // Mark the target object as having deep watchers
1544
+ objectsWithDeepWatchers.add(target);
1545
+ // Track which objects this effect is watching for cleanup
1546
+ let effectObjects = effectToDeepWatchedObjects.get(wrappedCallback);
1547
+ if (!effectObjects) {
1548
+ effectObjects = new Set();
1549
+ effectToDeepWatchedObjects.set(wrappedCallback, effectObjects);
1550
+ }
1551
+ effectObjects.add(target);
1552
+ // Traverse the object graph and register dependencies
1553
+ // This will re-run every time the effect runs, ensuring we catch all changes
1554
+ const visited = new WeakSet();
1555
+ function traverseAndTrack(obj, depth = 0) {
1556
+ // Prevent infinite recursion and excessive depth
1557
+ if (!obj || visited.has(obj) || typeof obj !== 'object' || depth > options.maxDeepWatchDepth)
1558
+ return;
1559
+ // Do not traverse into unreactive objects
1560
+ if (isNonReactive(obj))
1561
+ return;
1562
+ visited.add(obj);
1563
+ // Mark this object as having deep watchers
1564
+ objectsWithDeepWatchers.add(obj);
1565
+ effectObjects.add(obj);
1566
+ // Traverse all properties to register dependencies
1567
+ // unwrap to avoid kicking dependency
1568
+ for (const key in unwrap(obj)) {
1569
+ if (Object.hasOwn(obj, key)) {
1570
+ // Access the property to register dependency
1571
+ const value = obj[key];
1572
+ // Make the value reactive if it's an object
1573
+ const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
1574
+ traverseAndTrack(reactiveValue, depth + 1);
1575
+ }
1576
+ }
1577
+ // Also handle array indices and length
1578
+ // biome-ignore lint/suspicious/useIsArray: Check for both native arrays and reactive arrays
1579
+ if (Array.isArray(obj) || obj instanceof Array) {
1580
+ // Access array length to register dependency on length changes
1581
+ const length = obj.length;
1582
+ // Access all current array elements to register dependencies
1583
+ for (let i = 0; i < length; i++) {
1584
+ // Access the array element to register dependency
1585
+ const value = obj[i];
1586
+ // Make the value reactive if it's an object
1587
+ const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
1588
+ traverseAndTrack(reactiveValue, depth + 1);
1589
+ }
1590
+ }
1591
+ // Handle Set values (deep watch values only, not keys since Sets don't have separate keys)
1592
+ else if (obj instanceof Set) {
1593
+ // Access all Set values to register dependencies
1594
+ for (const value of obj) {
1595
+ // Make the value reactive if it's an object
1596
+ const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
1597
+ traverseAndTrack(reactiveValue, depth + 1);
1598
+ }
1599
+ }
1600
+ // Handle Map values (deep watch values only, not keys)
1601
+ else if (obj instanceof Map) {
1602
+ // Access all Map values to register dependencies
1603
+ for (const [_key, value] of obj) {
1604
+ // Make the value reactive if it's an object
1605
+ const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
1606
+ traverseAndTrack(reactiveValue, depth + 1);
1607
+ }
1608
+ }
1609
+ // Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
1610
+ // They will only trigger when the collection itself is replaced
1611
+ }
1612
+ // Traverse the target object to register all dependencies
1613
+ // This will register dependencies on all current properties and array elements
1614
+ traverseAndTrack(target);
1615
+ // Only call the callback if immediate is true or if it's not the first run
1616
+ if (immediate) {
1617
+ untracked(() => callback(target));
1618
+ }
1619
+ immediate = true;
1620
+ // Return a cleanup function that properly removes deep watcher tracking
1621
+ return () => {
1622
+ // Get the objects this effect was watching
1623
+ const effectObjects = effectToDeepWatchedObjects.get(wrappedCallback);
1624
+ if (effectObjects) {
1625
+ // Remove deep watcher tracking from all objects this effect was watching
1626
+ for (const obj of effectObjects) {
1627
+ // Check if this object still has other deep watchers
1628
+ const watchers = deepWatchers.get(obj);
1629
+ if (watchers) {
1630
+ // Remove this effect's callback from the watchers
1631
+ watchers.delete(wrappedCallback);
1632
+ // If no more watchers, remove the object from deep watchers tracking
1633
+ if (watchers.size === 0) {
1634
+ deepWatchers.delete(obj);
1635
+ objectsWithDeepWatchers.delete(obj);
1636
+ }
1637
+ }
1638
+ else {
1639
+ // No watchers found, remove from deep watchers tracking
1640
+ objectsWithDeepWatchers.delete(obj);
1641
+ }
1642
+ }
1643
+ // Clean up the tracking data
1644
+ effectToDeepWatchedObjects.delete(wrappedCallback);
1645
+ }
1646
+ };
1647
+ });
1648
+ }
1649
+
1650
+ /**
1651
+ * Organizes a source object's properties into a target object using a callback function.
1652
+ * This creates a reactive mapping between source properties and a target object,
1653
+ * automatically handling property additions, updates, and removals.
1654
+ *
1655
+ * @template Source - The type of the source object
1656
+ * @template Target - The type of the target object (defaults to Record<PropertyKey, any>)
1657
+ *
1658
+ * @param {Source} source - The source object to organize
1659
+ * @param {OrganizedCallback<Source, Target>} apply - Callback function that defines how each source property is mapped to the target
1660
+ * @param {Target} [baseTarget={}] - Optional base target object to use (will be made reactive if not already)
1661
+ *
1662
+ * @returns {OrganizedResult<Target>} The target object with cleanup capability
1663
+ *
1664
+ * @example
1665
+ * // Organize user permissions into role-based access
1666
+ * const user = reactive({ isAdmin: true, canEdit: false });
1667
+ * const permissions = organized(
1668
+ * user,
1669
+ * (access, target) => {
1670
+ * if (access.key === 'isAdmin') {
1671
+ * target.hasFullAccess = access.value;
1672
+ * }
1673
+ * target[`can${access.key.charAt(0).toUpperCase() + access.key.slice(1)}`] = access.value;
1674
+ * }
1675
+ * );
1676
+ *
1677
+ * @example
1678
+ * // Transform object structure with cleanup
1679
+ * const source = reactive({ firstName: 'John', lastName: 'Doe' });
1680
+ * const formatted = organized(
1681
+ * source,
1682
+ * (access, target) => {
1683
+ * if (access.key === 'firstName' || access.key === 'lastName') {
1684
+ * target.fullName = `${source.firstName} ${source.lastName}`.trim();
1685
+ * }
1686
+ * }
1687
+ * );
1688
+ *
1689
+ * @example
1690
+ * // Using with cleanup in a component
1691
+ * effect(() => {
1692
+ * const data = fetchData();
1693
+ * const organizedData = organized(data, (access, target) => {
1694
+ * // Transform data
1695
+ * });
1696
+ *
1697
+ * // The cleanup will be called automatically when the effect is disposed
1698
+ * return () => organizedData[cleanup]();
1699
+ * });
1700
+ */
1701
+ function organized(source, apply, baseTarget = {}) {
1702
+ const observedSource = reactive(source);
1703
+ const target = reactive(baseTarget);
1704
+ const stop = attend(() => {
1705
+ const keys = [];
1706
+ for (const key in observedSource)
1707
+ keys.push(key);
1708
+ return keys;
1709
+ }, (key) => {
1710
+ const sourceKey = key;
1711
+ const accessBase = {
1712
+ key: sourceKey,
1713
+ get: () => FoolProof.get(observedSource, sourceKey, observedSource),
1714
+ set: (value) => FoolProof.set(observedSource, sourceKey, value, observedSource),
1715
+ };
1716
+ Object.defineProperty(accessBase, 'value', {
1717
+ get: accessBase.get,
1718
+ set: accessBase.set,
1719
+ configurable: true,
1720
+ enumerable: true,
1721
+ });
1722
+ return apply(accessBase, target);
1723
+ });
1724
+ return cleanedBy(target, (reason) => stop(reason));
1725
+ }
1726
+ /**
1727
+ * Organizes a property on a target object
1728
+ * Shortcut for defineProperty/delete with touched signal
1729
+ * @param target - The target object
1730
+ * @param property - The property to organize
1731
+ * @param access - The access object
1732
+ * @returns The property descriptor
1733
+ */
1734
+ function organize(target, property, access) {
1735
+ Object.defineProperty(target, property, {
1736
+ get: access.get,
1737
+ set: access.set,
1738
+ configurable: true,
1739
+ enumerable: true,
1740
+ });
1741
+ touched1(target, { type: 'set', prop: property }, property);
1742
+ return () => delete target[property];
1743
+ }
1744
+
1745
+ //#region watch
1746
+ const unsetYet = Symbol('unset-yet');
1747
+ const watch = flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
1748
+ changed, options = {}) {
1749
+ return typeof value === 'function'
1750
+ ? watchCallBack(value, changed, options)
1751
+ : typeof value === 'object' && value !== null
1752
+ ? watchObject(value, changed, options)
1753
+ : (() => {
1754
+ throw new Error('watch: value must be a function or an object');
1755
+ })();
1756
+ }, {
1757
+ get deep() {
1758
+ return flavorOptions(this, { deep: true });
1759
+ },
1760
+ get immediate() {
1761
+ return flavorOptions(this, { immediate: true });
1762
+ },
1763
+ });
1764
+ function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1765
+ if (deep)
1766
+ return deepWatch(value, changed, { immediate });
1767
+ return effect(function watchObjectEffect() {
1768
+ dependant(value);
1769
+ if (immediate)
1770
+ changed(value);
1771
+ immediate = true;
1772
+ });
1773
+ }
1774
+ function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
1775
+ let oldValue = unsetYet;
1776
+ let deepCleanup;
1777
+ const cbCleanup = effect(markWithRoot(function watchCallBackEffect(access) {
1778
+ const newValue = value(access);
1779
+ if (oldValue !== newValue) {
1780
+ const old = oldValue;
1781
+ if (old === unsetYet) {
1782
+ if (immediate)
1783
+ untracked(() => changed(newValue));
1784
+ }
1785
+ else
1786
+ untracked(() => changed(newValue, old));
1787
+ }
1788
+ oldValue = newValue;
1789
+ if (deep) {
1790
+ if (deepCleanup)
1791
+ deepCleanup();
1792
+ deepCleanup = deepWatch(newValue, (value) => changed(value, value));
1793
+ }
1794
+ }, value));
1795
+ return Object.defineProperties(() => {
1796
+ cbCleanup();
1797
+ if (deepCleanup)
1798
+ deepCleanup();
1799
+ }, {
1800
+ [stopped]: { get: () => cbCleanup[stopped] },
1801
+ });
1802
+ }
1803
+ //#endregion
1804
+ //#region when
1805
+ /**
1806
+ * Returns a promise that resolves when the predicate returns a truthy value.
1807
+ * The predicate is evaluated reactively — it re-runs whenever its dependencies change.
1808
+ * @param predicate - Reactive function that returns a value; resolves when truthy
1809
+ * @param timeout - Optional timeout in milliseconds — rejects if condition is not met within this duration
1810
+ * @returns Promise that resolves with the first truthy return value
1811
+ */
1812
+ function when(predicate, timeout) {
1813
+ return new Promise((resolve, reject) => {
1814
+ let timer;
1815
+ const stop = effect(function whenEffect(access) {
1816
+ try {
1817
+ const value = predicate(access);
1818
+ if (value) {
1819
+ if (timer !== undefined)
1820
+ clearTimeout(timer);
1821
+ timer = undefined;
1822
+ queueMicrotask(() => stop());
1823
+ resolve(value);
1824
+ }
1825
+ }
1826
+ catch (error) {
1827
+ if (timer !== undefined)
1828
+ clearTimeout(timer);
1829
+ timer = undefined;
1830
+ reject(error);
1831
+ }
1832
+ });
1833
+ if (timeout !== undefined) {
1834
+ timer = setTimeout(() => {
1835
+ stop();
1836
+ timer = undefined;
1837
+ reject(new Error(`when: timed out after ${timeout}ms`));
1838
+ }, timeout);
1839
+ }
1840
+ });
1841
+ }
1842
+ //#endregion
1843
+ //#region nonReactive
1844
+ /**
1845
+ * Mark an object as non-reactive. This object and all its properties will never be made reactive.
1846
+ * @param obj - The object to mark as non-reactive
1847
+ */
1848
+ function shallowNonReactive(obj) {
1849
+ obj = unwrap(obj);
1850
+ if (isNonReactive(obj))
1851
+ return obj;
1852
+ nonReactiveObjects.add(obj);
1853
+ return obj;
1854
+ }
1855
+ function unreactiveApplication(arg1, ...args) {
1856
+ return typeof arg1 === 'object'
1857
+ ? shallowNonReactive(arg1)
1858
+ : ((original) => {
1859
+ // Copy the parent's unreactive properties if they exist
1860
+ const parentSet = unreactiveProps.get(original.prototype);
1861
+ const set = new Set(parentSet || []);
1862
+ // Add all arguments (including the first one)
1863
+ set.add(arg1);
1864
+ for (const arg of args)
1865
+ set.add(arg);
1866
+ addUnreactiveProps(original.prototype, set);
1867
+ return original; // Return the class
1868
+ });
1869
+ }
1870
+ /**
1871
+ * Decorator that marks classes or properties as non-reactive
1872
+ * Prevents objects from being made reactive
1873
+ */
1874
+ const unreactive = decorator({
1875
+ class(original) {
1876
+ // Called without arguments, mark entire class as non-reactive
1877
+ nonReactiveClass(original);
1878
+ },
1879
+ default: unreactiveApplication,
1880
+ });
1881
+ /**
1882
+ * Creates a reactive resource that automatically tracks async state.
1883
+ * @param fetcher - Async function that returns the value. Reactive dependencies are tracked.
1884
+ * @param options - Resource options (initialValue)
1885
+ * @returns Reactive Resource object with value, loading, error, latest properties
1886
+ */
1887
+ function resource(fetcher, options = {}) {
1888
+ const state = reactive({
1889
+ value: options.initialValue,
1890
+ loading: true,
1891
+ error: undefined,
1892
+ latest: options.initialValue,
1893
+ reload: () => {
1894
+ reloadSignal.value++;
1895
+ },
1896
+ });
1897
+ const reloadSignal = reactive({ value: 0 });
1898
+ let counter = 0;
1899
+ const stop = effect(function resourceEffect(access) {
1900
+ // Track reload signal to enable manual reloading
1901
+ if (reloadSignal.value) ;
1902
+ const id = ++counter;
1903
+ state.loading = true;
1904
+ state.error = undefined;
1905
+ try {
1906
+ const result = fetcher(access);
1907
+ if (result instanceof Promise) {
1908
+ result.then((val) => {
1909
+ if (id === counter) {
1910
+ state.value = val;
1911
+ state.latest = val;
1912
+ state.loading = false;
1913
+ }
1914
+ }, (err) => {
1915
+ if (id === counter) {
1916
+ state.error = err;
1917
+ state.loading = false;
1918
+ }
1919
+ });
1920
+ }
1921
+ else {
1922
+ state.value = result;
1923
+ state.latest = result;
1924
+ state.loading = false;
1925
+ }
1926
+ }
1927
+ catch (err) {
1928
+ state.error = err;
1929
+ state.loading = false;
1930
+ }
1931
+ });
1932
+ state.stop = stop;
1933
+ return state;
1934
+ }
1935
+ //#endregion
1936
+
1937
+ // Helper to work around TypeScript limitation: base class expressions cannot reference class type parameters
1938
+ function getRegisterBase() {
1939
+ class RegisterBase extends Indexable(ArrayReadForward, {
1940
+ get(index) {
1941
+ return this[getAt](index);
1942
+ },
1943
+ set(index, value) {
1944
+ this[setAt](index, value);
1945
+ },
1946
+ getLength() {
1947
+ return this.length;
1948
+ },
1949
+ setLength(value) {
1950
+ this.length = value;
1951
+ },
1952
+ }) {
1953
+ toArray() {
1954
+ return Array.from(this);
1955
+ }
1956
+ }
1957
+ return RegisterBase;
1958
+ }
1959
+ let RegisterClass = (() => {
1960
+ var _RegisterClass_instances, _RegisterClass_keyFn, _RegisterClass_keys, _RegisterClass_values, _RegisterClass_usage, _RegisterClass_valueInfo, _RegisterClass_keyEffects, _RegisterClass_ascend, _RegisterClass_events, _RegisterClass_rekeyValue;
1961
+ let _classDecorators = [unreactive];
1962
+ let _classDescriptor;
1963
+ let _classExtraInitializers = [];
1964
+ let _classThis;
1965
+ let _classSuper = getRegisterBase();
1966
+ _classThis = class extends _classSuper {
1967
+ get [(_RegisterClass_keyFn = new WeakMap(), _RegisterClass_keys = new WeakMap(), _RegisterClass_values = new WeakMap(), _RegisterClass_usage = new WeakMap(), _RegisterClass_valueInfo = new WeakMap(), _RegisterClass_keyEffects = new WeakMap(), _RegisterClass_ascend = new WeakMap(), _RegisterClass_events = new WeakMap(), _RegisterClass_instances = new WeakSet(), forwardArray)]() {
1968
+ return this.toArray();
1969
+ }
1970
+ on(eventOrEvents, cb) {
1971
+ // @ts-expect-error Delegate to Eventful
1972
+ return __classPrivateFieldGet(this, _RegisterClass_events, "f").on(eventOrEvents, cb);
1973
+ }
1974
+ off(eventOrEvents, cb) {
1975
+ // @ts-expect-error Delegate to Eventful
1976
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").off(eventOrEvents, cb);
1977
+ }
1978
+ /**
1979
+ * Register a global hook that receives all events
1980
+ */
1981
+ hook(cb) {
1982
+ return __classPrivateFieldGet(this, _RegisterClass_events, "f").hook(cb);
1983
+ }
1984
+ constructor(keyFn, initial) {
1985
+ super();
1986
+ _RegisterClass_instances.add(this);
1987
+ _RegisterClass_keyFn.set(this, void 0);
1988
+ _RegisterClass_keys.set(this, void 0);
1989
+ _RegisterClass_values.set(this, void 0);
1990
+ _RegisterClass_usage.set(this, new Map());
1991
+ _RegisterClass_valueInfo.set(this, new Map());
1992
+ _RegisterClass_keyEffects.set(this, new Set());
1993
+ _RegisterClass_ascend.set(this, void 0);
1994
+ _RegisterClass_events.set(this, new Eventful()
1995
+ /**
1996
+ * Register event listeners for CRUD operations
1997
+ */
1998
+ );
1999
+ /* Moved below initialization */
2000
+ let ascendGet;
2001
+ effect(({ ascend }) => {
2002
+ ascendGet = ascend;
2003
+ });
2004
+ __classPrivateFieldSet(this, _RegisterClass_ascend, ascendGet, "f");
2005
+ if (typeof keyFn !== 'function')
2006
+ throw new Error('Register requires a key function');
2007
+ __classPrivateFieldSet(this, _RegisterClass_keyFn, keyFn, "f");
2008
+ __classPrivateFieldSet(this, _RegisterClass_keys, reactive([]), "f");
2009
+ __classPrivateFieldSet(this, _RegisterClass_values, reactive(new Map()), "f");
2010
+ if (initial)
2011
+ this.push(...initial);
2012
+ }
2013
+ ensureKey(value) {
2014
+ let info = __classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2015
+ if (info)
2016
+ return info.key;
2017
+ info = { key: undefined };
2018
+ __classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").set(value, info);
2019
+ __classPrivateFieldGet(this, _RegisterClass_ascend, "f").call(this, () => {
2020
+ const stop = effect(({ reaction }) => {
2021
+ const nextKey = __classPrivateFieldGet(this, _RegisterClass_keyFn, "f").call(this, value);
2022
+ this.assertValidKey(nextKey);
2023
+ const previousKey = info.key;
2024
+ if (reaction && previousKey !== undefined && !Object.is(nextKey, previousKey))
2025
+ __classPrivateFieldGet(this, _RegisterClass_instances, "m", _RegisterClass_rekeyValue).call(this, value, previousKey, nextKey);
2026
+ info.key = nextKey;
2027
+ });
2028
+ info.stop = stop;
2029
+ __classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").add(stop);
2030
+ });
2031
+ if (info.key === undefined)
2032
+ throw new Error('Register key function must return a property key');
2033
+ return info.key;
2034
+ }
2035
+ assertValidKey(key) {
2036
+ const type = typeof key;
2037
+ if (type !== 'string' && type !== 'number' && type !== 'symbol')
2038
+ throw new Error('Register key function must return a property key');
2039
+ }
2040
+ setKeyValue(key, value, index) {
2041
+ const existing = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2042
+ if (existing !== undefined && existing !== value) {
2043
+ this.cleanupValue(existing);
2044
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2045
+ if (index !== undefined) {
2046
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', existing, value, key, index);
2047
+ }
2048
+ }
2049
+ else {
2050
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2051
+ }
2052
+ }
2053
+ cleanupValue(value) {
2054
+ const info = __classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2055
+ if (!info)
2056
+ return;
2057
+ const stop = info.stop;
2058
+ if (stop) {
2059
+ info.stop = undefined;
2060
+ __classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").delete(stop);
2061
+ stop();
2062
+ }
2063
+ __classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").delete(value);
2064
+ }
2065
+ disposeKeyEffects() {
2066
+ for (const value of Array.from(__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").keys()))
2067
+ this.cleanupValue(value);
2068
+ __classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").clear();
2069
+ }
2070
+ incrementUsage(key) {
2071
+ const count = __classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key) ?? 0;
2072
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count + 1);
2073
+ }
2074
+ decrementUsage(key, index) {
2075
+ const count = __classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key);
2076
+ if (!count)
2077
+ return;
2078
+ if (count <= 1) {
2079
+ const value = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2080
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(key);
2081
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").delete(key);
2082
+ if (value !== undefined) {
2083
+ this.cleanupValue(value);
2084
+ const idx = index ?? __classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2085
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('delete', value, key, idx);
2086
+ }
2087
+ }
2088
+ else {
2089
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count - 1);
2090
+ }
2091
+ }
2092
+ normalizeIndex(index, allowEnd = false) {
2093
+ const length = this.length;
2094
+ let resolved = index;
2095
+ if (resolved < 0)
2096
+ resolved = Math.max(length + resolved, 0);
2097
+ if (resolved > length) {
2098
+ if (allowEnd)
2099
+ resolved = length;
2100
+ else
2101
+ throw new RangeError('Index out of bounds');
2102
+ }
2103
+ if (!allowEnd && resolved === length)
2104
+ throw new RangeError('Index out of bounds');
2105
+ return resolved;
2106
+ }
2107
+ assignAt(index, key, value) {
2108
+ const oldKey = __classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
2109
+ if (oldKey !== undefined && Object.is(oldKey, key)) {
2110
+ const oldValue = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2111
+ this.setKeyValue(key, value);
2112
+ if (oldValue !== undefined && oldValue !== value) {
2113
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', oldValue, value, key, index);
2114
+ }
2115
+ return;
2116
+ }
2117
+ if (oldKey !== undefined)
2118
+ this.decrementUsage(oldKey);
2119
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f")[index] = key;
2120
+ this.incrementUsage(key);
2121
+ this.setKeyValue(key, value);
2122
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
2123
+ }
2124
+ insertKeyValue(index, key, value) {
2125
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 0, key);
2126
+ this.incrementUsage(key);
2127
+ this.setKeyValue(key, value);
2128
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
2129
+ }
2130
+ rebuildFrom(values) {
2131
+ this.disposeKeyEffects();
2132
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(0, __classPrivateFieldGet(this, _RegisterClass_keys, "f").length);
2133
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
2134
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
2135
+ for (const value of values) {
2136
+ const key = this.ensureKey(value);
2137
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").push(key);
2138
+ this.incrementUsage(key);
2139
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2140
+ }
2141
+ }
2142
+ get length() {
2143
+ return __classPrivateFieldGet(this, _RegisterClass_keys, "f").length;
2144
+ }
2145
+ [(_RegisterClass_rekeyValue = function _RegisterClass_rekeyValue(value, oldKey, newKey) {
2146
+ if (Object.is(oldKey, newKey))
2147
+ return;
2148
+ const existingValue = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(newKey);
2149
+ if (existingValue !== undefined && existingValue !== value)
2150
+ throw new Error(`Register key collision for key ${String(newKey)}`);
2151
+ const count = __classPrivateFieldGet(this, _RegisterClass_usage, "f").get(oldKey);
2152
+ if (!count)
2153
+ return;
2154
+ const existingCount = __classPrivateFieldGet(this, _RegisterClass_usage, "f").get(newKey) ?? 0;
2155
+ this.setKeyValue(newKey, value);
2156
+ let index = -1;
2157
+ for (let i = 0; i < __classPrivateFieldGet(this, _RegisterClass_keys, "f").length; i++)
2158
+ if (Object.is(__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i], oldKey)) {
2159
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f")[i] = newKey;
2160
+ if (index === -1)
2161
+ index = i;
2162
+ }
2163
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").set(newKey, existingCount + count);
2164
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(oldKey);
2165
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").delete(oldKey);
2166
+ const updatedInfo = __classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2167
+ if (updatedInfo)
2168
+ updatedInfo.key = newKey;
2169
+ if (index !== -1) {
2170
+ __classPrivateFieldGet(this, _RegisterClass_events, "f").emit('rekey', value, oldKey, newKey, index);
2171
+ }
2172
+ }, getAt)](index) {
2173
+ const key = __classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
2174
+ return key === undefined ? undefined : __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2175
+ }
2176
+ [setAt](index, value) {
2177
+ const key = this.ensureKey(value);
2178
+ if (index === this.length) {
2179
+ this.insertKeyValue(index, key, value);
2180
+ return;
2181
+ }
2182
+ const normalized = this.normalizeIndex(index);
2183
+ this.assignAt(normalized, key, value);
2184
+ }
2185
+ push(...items) {
2186
+ for (const item of items) {
2187
+ const key = this.ensureKey(item);
2188
+ this.insertKeyValue(this.length, key, item);
2189
+ }
2190
+ return this.length;
2191
+ }
2192
+ pop() {
2193
+ if (!this.length)
2194
+ return undefined;
2195
+ return this.removeAt(this.length - 1);
2196
+ }
2197
+ shift() {
2198
+ if (!this.length)
2199
+ return undefined;
2200
+ return this.removeAt(0);
2201
+ }
2202
+ unshift(...items) {
2203
+ let index = 0;
2204
+ for (const item of items) {
2205
+ const key = this.ensureKey(item);
2206
+ this.insertKeyValue(index++, key, item);
2207
+ }
2208
+ return this.length;
2209
+ }
2210
+ splice(start, deleteCount, ...items) {
2211
+ const normalizedStart = this.normalizeIndex(start, true);
2212
+ const maxDeletions = this.length - normalizedStart;
2213
+ const actualDelete = Math.min(deleteCount === undefined ? maxDeletions : Math.max(deleteCount, 0), maxDeletions);
2214
+ const keysToInsert = [];
2215
+ for (const item of items)
2216
+ keysToInsert.push(this.ensureKey(item));
2217
+ const removedKeys = __classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(normalizedStart, actualDelete, ...keysToInsert);
2218
+ const removedValues = [];
2219
+ for (let i = 0; i < removedKeys.length; i++) {
2220
+ const key = removedKeys[i];
2221
+ if (key === undefined)
2222
+ continue;
2223
+ const value = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2224
+ this.decrementUsage(key, normalizedStart + i);
2225
+ removedValues.push(value);
2226
+ }
2227
+ for (let i = 0; i < keysToInsert.length; i++) {
2228
+ const key = keysToInsert[i];
2229
+ const value = items[i];
2230
+ this.incrementUsage(key);
2231
+ this.setKeyValue(key, value);
2232
+ }
2233
+ return removedValues;
2234
+ }
2235
+ clear() {
2236
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").length = 0;
2237
+ __classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
2238
+ __classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
2239
+ this.disposeKeyEffects();
2240
+ }
2241
+ get(key) {
2242
+ return __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2243
+ }
2244
+ set(key, value) {
2245
+ if (__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
2246
+ this.setKeyValue(key, value);
2247
+ }
2248
+ remove(key) {
2249
+ let index = this.indexOfKey(key);
2250
+ while (index !== -1) {
2251
+ this.removeAt(index);
2252
+ index = this.indexOfKey(key);
2253
+ }
2254
+ }
2255
+ removeAt(index) {
2256
+ const [key] = __classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 1);
2257
+ if (key === undefined)
2258
+ return undefined;
2259
+ const value = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2260
+ this.decrementUsage(key, index);
2261
+ return value;
2262
+ }
2263
+ /**
2264
+ * Keep only the items for which the predicate returns true.
2265
+ * Items for which the predicate returns false are removed.
2266
+ *
2267
+ * The predicate is evaluated once per distinct key; duplicate keys
2268
+ * will follow the same keep/remove decision.
2269
+ */
2270
+ keep(predicate) {
2271
+ const decisions = new Map();
2272
+ for (const [index, key] of __classPrivateFieldGet(this, _RegisterClass_keys, "f").entries()) {
2273
+ if (decisions.has(key)) {
2274
+ if (!decisions.get(key))
2275
+ this.removeAt(index);
2276
+ continue;
2277
+ }
2278
+ const value = __classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2279
+ const shouldKeep = predicate(value);
2280
+ decisions.set(key, shouldKeep);
2281
+ if (!shouldKeep)
2282
+ this.removeAt(index);
2283
+ }
2284
+ }
2285
+ hasKey(key) {
2286
+ return __classPrivateFieldGet(this, _RegisterClass_usage, "f").has(key);
2287
+ }
2288
+ indexOfKey(key) {
2289
+ return __classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2290
+ }
2291
+ mapKeys() {
2292
+ return __classPrivateFieldGet(this, _RegisterClass_values, "f").keys();
2293
+ }
2294
+ update(...values) {
2295
+ for (const value of values) {
2296
+ const key = this.ensureKey(value);
2297
+ if (__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key)) {
2298
+ const index = __classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2299
+ this.setKeyValue(key, value, index);
2300
+ }
2301
+ }
2302
+ }
2303
+ upsert(insert, ...values) {
2304
+ for (const value of values) {
2305
+ const key = this.ensureKey(value);
2306
+ if (__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
2307
+ this.setKeyValue(key, value);
2308
+ else
2309
+ insert(value);
2310
+ }
2311
+ }
2312
+ entries() {
2313
+ const self = this;
2314
+ function* iterator() {
2315
+ for (let i = 0; i < __classPrivateFieldGet(self, _RegisterClass_keys, "f").length; i++) {
2316
+ const val = __classPrivateFieldGet(self, _RegisterClass_values, "f").get(__classPrivateFieldGet(self, _RegisterClass_keys, "f")[i]);
2317
+ if (val !== undefined)
2318
+ yield [i, val];
2319
+ }
2320
+ }
2321
+ return iterator();
2322
+ }
2323
+ [Symbol.iterator]() {
2324
+ const self = this;
2325
+ function* iterator() {
2326
+ for (const key of __classPrivateFieldGet(self, _RegisterClass_keys, "f")) {
2327
+ const value = __classPrivateFieldGet(self, _RegisterClass_values, "f").get(key);
2328
+ if (value !== undefined)
2329
+ yield value;
2330
+ }
2331
+ }
2332
+ return iterator();
2333
+ }
2334
+ toString() {
2335
+ return `[Register length=${this.length}]`;
2336
+ }
2337
+ at(index) {
2338
+ const resolved = index < 0 ? this.length + index : index;
2339
+ if (resolved < 0 || resolved >= this.length)
2340
+ return undefined;
2341
+ return this[getAt](resolved);
2342
+ }
2343
+ reverse() {
2344
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").reverse();
2345
+ return this;
2346
+ }
2347
+ sort(compareFn) {
2348
+ const fwdCompareFn = compareFn
2349
+ ? (a, b) => compareFn(__classPrivateFieldGet(this, _RegisterClass_values, "f").get(a), __classPrivateFieldGet(this, _RegisterClass_values, "f").get(b))
2350
+ : undefined;
2351
+ __classPrivateFieldGet(this, _RegisterClass_keys, "f").sort(fwdCompareFn);
2352
+ return this;
2353
+ }
2354
+ fill(value, start = 0, end = this.length) {
2355
+ const values = this.toArray();
2356
+ values.fill(value, start, end);
2357
+ this.rebuildFrom(values);
2358
+ return this;
2359
+ }
2360
+ copyWithin(target, start, end) {
2361
+ const values = this.toArray();
2362
+ values.copyWithin(target, start, end);
2363
+ this.rebuildFrom(values);
2364
+ return this;
2365
+ }
2366
+ };
2367
+ __setFunctionName(_classThis, "RegisterClass");
2368
+ (() => {
2369
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2370
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
2371
+ _classThis = _classDescriptor.value;
2372
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
2373
+ __runInitializers(_classThis, _classExtraInitializers);
2374
+ })();
2375
+ return _classThis;
2376
+ })();
2377
+ const Register = RegisterClass;
2378
+ /**
2379
+ * Creates a reactive Register - an ordered, array-like collection with stable key-based identity.
2380
+ *
2381
+ * Register combines array semantics (indexable access, ordering, iteration) with Map-like
2382
+ * key-based lookups. Items with the same key share the same value instance, making it ideal
2383
+ * for UI lists keyed by IDs or when you need to preserve identity across reorders.
2384
+ *
2385
+ * @param keyFn - Function that extracts the key from each item
2386
+ * @param initial - Optional initial items to populate the register
2387
+ * @returns A reactive Register instance
2388
+ *
2389
+ * @example
2390
+ * ```typescript
2391
+ * const users = register(
2392
+ * (user: User) => user.id,
2393
+ * [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
2394
+ * )
2395
+ *
2396
+ * users.push({ id: 3, name: 'Charlie' })
2397
+ * const bob = users.get(2) // Get by key
2398
+ * ```
2399
+ */
2400
+ function register(keyFn, initial) {
2401
+ return new RegisterClass(keyFn, initial);
2402
+ }
2403
+
2404
+ /**
2405
+ * Converts an iterator to a generator that yields reactive values
2406
+ */
2407
+ function* makeReactiveIterator(iterator) {
2408
+ let result = iterator.next();
2409
+ while (!result.done) {
2410
+ yield reactive(result.value);
2411
+ result = iterator.next();
2412
+ }
2413
+ }
2414
+ /**
2415
+ * Converts an iterator of key-value pairs to a generator that yields reactive key-value pairs
2416
+ */
2417
+ function* makeReactiveEntriesIterator(iterator) {
2418
+ let result = iterator.next();
2419
+ while (!result.done) {
2420
+ const [key, value] = result.value;
2421
+ yield [reactive(key), reactive(value)];
2422
+ result = iterator.next();
2423
+ }
2424
+ }
2425
+
2426
+ function* index(i, { length = true } = {}) {
2427
+ if (length)
2428
+ yield 'length';
2429
+ yield i;
2430
+ }
2431
+ class Indexer extends Array {
2432
+ get(i) {
2433
+ dependant(this, i);
2434
+ return reactive(this[i]);
2435
+ }
2436
+ // Returns undefined intentionally: signals the proxy handler that notifications
2437
+ // were already dispatched via touched(), preventing double notification
2438
+ set(i, value) {
2439
+ const added = i >= this.length;
2440
+ this[i] = value;
2441
+ touched(this, { type: 'set', prop: i }, index(i, { length: added }));
2442
+ }
2443
+ }
2444
+ const indexLess = { get: FoolProof.get, set: FoolProof.set };
2445
+ // Fast numeric-string check: first char is a digit (0-9)
2446
+ function asIndex(prop) {
2447
+ const c = prop.charCodeAt(0);
2448
+ if (c < 48 || c > 57)
2449
+ return -1; // not 0-9
2450
+ const n = +prop; // coerce — faster than parseInt, handles "0", "12", etc.
2451
+ return n === (n | 0) && n >= 0 ? n : -1;
2452
+ }
2453
+ Object.assign(FoolProof, {
2454
+ get(obj, prop, receiver) {
2455
+ if (Array.isArray(obj) && typeof prop === 'string') {
2456
+ const i = asIndex(prop);
2457
+ if (i >= 0)
2458
+ return Indexer.prototype.get.call(obj, i);
2459
+ }
2460
+ return indexLess.get(obj, prop, receiver);
2461
+ },
2462
+ set(obj, prop, value, receiver) {
2463
+ if (Array.isArray(obj) && typeof prop === 'string') {
2464
+ const i = asIndex(prop);
2465
+ if (i >= 0)
2466
+ return Indexer.prototype.set.call(obj, i, value);
2467
+ }
2468
+ return indexLess.set(obj, prop, value, receiver);
2469
+ },
2470
+ });
2471
+ class ReactiveArray extends Array {
2472
+ toJSON() {
2473
+ return this;
2474
+ }
2475
+ }
2476
+ /**
2477
+ * This is a wrapper class for Array that adds reactive behavior.
2478
+ * It extends Array and overrides methods to add reactive behavior, while making sure that the internal representation is not reactive.
2479
+ */
2480
+ let ReactiveArrayWrapper = (() => {
2481
+ var _a;
2482
+ let _classSuper = Array;
2483
+ let _instanceExtraInitializers = [];
2484
+ let _fill_decorators;
2485
+ let _pop_decorators;
2486
+ let _push_decorators;
2487
+ let _reverse_decorators;
2488
+ let _shift_decorators;
2489
+ let _sort_decorators;
2490
+ let _splice_decorators;
2491
+ let _unshift_decorators;
2492
+ return _a = class ReactiveArrayWrapper extends _classSuper {
2493
+ at(index) {
2494
+ return reactive(super.at(index));
2495
+ }
2496
+ concat(...items) {
2497
+ return reactive(super.concat(...items.map(unwrap)));
2498
+ }
2499
+ entries() {
2500
+ dependant(this, keysOf);
2501
+ return makeReactiveEntriesIterator(super.entries());
2502
+ }
2503
+ every(predicate, thisArg) {
2504
+ return super.every((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg);
2505
+ }
2506
+ fill(value, start, end) {
2507
+ return super.fill(unwrap(value), start, end);
2508
+ }
2509
+ filter(predicate, thisArg) {
2510
+ return reactive(super.filter((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg));
2511
+ }
2512
+ find(predicate, thisArg) {
2513
+ return reactive(super.find((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg));
2514
+ }
2515
+ findIndex(predicate, thisArg) {
2516
+ return super.findIndex((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg);
2517
+ }
2518
+ findLast(predicate, thisArg) {
2519
+ return reactive(super.findLast((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg));
2520
+ }
2521
+ findLastIndex(predicate, thisArg) {
2522
+ return super.findLastIndex((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg);
2523
+ }
2524
+ flat(depth) {
2525
+ return reactive(super.flat(depth));
2526
+ }
2527
+ flatMap(callbackfn, thisArg) {
2528
+ return reactive(super.flatMap((v, i, a) => unwrap(callbackfn.call(thisArg, reactive(v), i, a)), thisArg));
2529
+ }
2530
+ forEach(callbackfn, thisArg) {
2531
+ super.forEach((v, i, a) => {
2532
+ callbackfn.call(thisArg, reactive(v), i, a);
2533
+ }, thisArg);
2534
+ }
2535
+ includes(searchElement, fromIndex) {
2536
+ return arguments.length > 1
2537
+ ? super.includes(unwrap(searchElement), fromIndex)
2538
+ : super.includes(unwrap(searchElement));
2539
+ }
2540
+ indexOf(searchElement, fromIndex) {
2541
+ return arguments.length > 1
2542
+ ? super.indexOf(unwrap(searchElement), fromIndex)
2543
+ : super.indexOf(unwrap(searchElement));
2544
+ }
2545
+ join(separator) {
2546
+ return super.join(separator);
2547
+ }
2548
+ keys() {
2549
+ dependant(this, 'length');
2550
+ return super.keys();
2551
+ }
2552
+ lastIndexOf(searchElement, fromIndex) {
2553
+ return arguments.length > 1
2554
+ ? super.lastIndexOf(unwrap(searchElement), fromIndex)
2555
+ : super.lastIndexOf(unwrap(searchElement));
2556
+ }
2557
+ map(callbackfn, thisArg) {
2558
+ return reactive(super.map((v, i, a) => unwrap(callbackfn.call(thisArg, reactive(v), i, a)), thisArg));
2559
+ }
2560
+ pop() {
2561
+ return reactive(super.pop());
2562
+ }
2563
+ push(...items) {
2564
+ return super.push(...items.map(unwrap));
2565
+ }
2566
+ reduce(callbackfn, initialValue) {
2567
+ return reactive(arguments.length > 1
2568
+ ? super.reduce((acc, v, i, a) => unwrap(callbackfn(acc, reactive(v), i, a)), initialValue)
2569
+ : super.reduce((acc, v, i, a) => unwrap(callbackfn(acc, reactive(v), i, a))));
2570
+ }
2571
+ reduceRight(callbackfn, initialValue) {
2572
+ return reactive(arguments.length > 1
2573
+ ? super.reduceRight((acc, v, i, a) => unwrap(callbackfn(acc, reactive(v), i, a)), initialValue)
2574
+ : super.reduceRight((acc, v, i, a) => unwrap(callbackfn(acc, reactive(v), i, a))));
2575
+ }
2576
+ reverse() {
2577
+ return reactive(super.reverse());
2578
+ }
2579
+ shift() {
2580
+ return reactive(super.shift());
2581
+ }
2582
+ slice(start, end) {
2583
+ return reactive(super.slice(start, end));
2584
+ }
2585
+ some(predicate, thisArg) {
2586
+ return super.some((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg);
2587
+ }
2588
+ sort(compareFn) {
2589
+ const wrappedCompare = compareFn
2590
+ ? (a, b) => compareFn(reactive(a), reactive(b))
2591
+ : undefined;
2592
+ return super.sort(wrappedCompare);
2593
+ }
2594
+ splice(start, deleteCount, ...items) {
2595
+ if (arguments.length > 2)
2596
+ return reactive(super.splice(start, deleteCount, ...items.map(unwrap)));
2597
+ if (arguments.length === 2)
2598
+ return reactive(super.splice(start, deleteCount));
2599
+ if (arguments.length === 1)
2600
+ return reactive(super.splice(start));
2601
+ return reactive([]);
2602
+ }
2603
+ unshift(...items) {
2604
+ return super.unshift(...items.map(unwrap));
2605
+ }
2606
+ values() {
2607
+ dependant(this, keysOf);
2608
+ return makeReactiveIterator(super.values());
2609
+ }
2610
+ [(_fill_decorators = [atomic], _pop_decorators = [atomic], _push_decorators = [atomic], _reverse_decorators = [atomic], _shift_decorators = [atomic], _sort_decorators = [atomic], _splice_decorators = [atomic], _unshift_decorators = [atomic], Symbol.iterator)]() {
2611
+ dependant(this, keysOf);
2612
+ return makeReactiveIterator(super[Symbol.iterator]());
2613
+ }
2614
+ toReversed() {
2615
+ return reactive(super.toReversed());
2616
+ }
2617
+ toSorted(compareFn) {
2618
+ const wrappedCompare = compareFn
2619
+ ? (a, b) => compareFn(reactive(a), reactive(b))
2620
+ : undefined;
2621
+ return reactive(super.toSorted(wrappedCompare));
2622
+ }
2623
+ // biome-ignore lint/complexity/noArguments: Needed to distinguish fn() from fn(undefined)
2624
+ toSpliced(start, deleteCount, ...items) {
2625
+ if (arguments.length > 2)
2626
+ return reactive(super.toSpliced(start, deleteCount, ...items.map(unwrap)));
2627
+ if (arguments.length === 2)
2628
+ return reactive(super.toSpliced(start, deleteCount));
2629
+ if (arguments.length === 1)
2630
+ return reactive(super.toSpliced(start));
2631
+ return reactive([...this]);
2632
+ }
2633
+ with(index, value) {
2634
+ return reactive(super.with(index, unwrap(value)));
2635
+ }
2636
+ constructor() {
2637
+ super(...arguments);
2638
+ __runInitializers(this, _instanceExtraInitializers);
2639
+ }
2640
+ },
2641
+ (() => {
2642
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2643
+ __esDecorate(_a, null, _fill_decorators, { kind: "method", name: "fill", static: false, private: false, access: { has: obj => "fill" in obj, get: obj => obj.fill }, metadata: _metadata }, null, _instanceExtraInitializers);
2644
+ __esDecorate(_a, null, _pop_decorators, { kind: "method", name: "pop", static: false, private: false, access: { has: obj => "pop" in obj, get: obj => obj.pop }, metadata: _metadata }, null, _instanceExtraInitializers);
2645
+ __esDecorate(_a, null, _push_decorators, { kind: "method", name: "push", static: false, private: false, access: { has: obj => "push" in obj, get: obj => obj.push }, metadata: _metadata }, null, _instanceExtraInitializers);
2646
+ __esDecorate(_a, null, _reverse_decorators, { kind: "method", name: "reverse", static: false, private: false, access: { has: obj => "reverse" in obj, get: obj => obj.reverse }, metadata: _metadata }, null, _instanceExtraInitializers);
2647
+ __esDecorate(_a, null, _shift_decorators, { kind: "method", name: "shift", static: false, private: false, access: { has: obj => "shift" in obj, get: obj => obj.shift }, metadata: _metadata }, null, _instanceExtraInitializers);
2648
+ __esDecorate(_a, null, _sort_decorators, { kind: "method", name: "sort", static: false, private: false, access: { has: obj => "sort" in obj, get: obj => obj.sort }, metadata: _metadata }, null, _instanceExtraInitializers);
2649
+ __esDecorate(_a, null, _splice_decorators, { kind: "method", name: "splice", static: false, private: false, access: { has: obj => "splice" in obj, get: obj => obj.splice }, metadata: _metadata }, null, _instanceExtraInitializers);
2650
+ __esDecorate(_a, null, _unshift_decorators, { kind: "method", name: "unshift", static: false, private: false, access: { has: obj => "unshift" in obj, get: obj => obj.unshift }, metadata: _metadata }, null, _instanceExtraInitializers);
2651
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
2652
+ })(),
2653
+ _a;
2654
+ })();
2655
+
2656
+ /**
2657
+ * Reactive wrapper around JavaScript's WeakMap class
2658
+ * Only tracks individual key operations, no size tracking (WeakMap limitation)
2659
+ */
2660
+ class ReactiveWeakMap extends WeakMap {
2661
+ // Implement WeakMap interface methods with reactivity
2662
+ delete(key) {
2663
+ const hadKey = this.has(key);
2664
+ const result = this.delete(key);
2665
+ if (hadKey)
2666
+ touched1(contentRef(this), { type: 'del', prop: key }, key);
2667
+ return result;
2668
+ }
2669
+ get(key) {
2670
+ dependant(contentRef(this), key);
2671
+ return reactive(this.get(key));
2672
+ }
2673
+ has(key) {
2674
+ dependant(contentRef(this), key);
2675
+ return this.has(key);
2676
+ }
2677
+ set(key, value) {
2678
+ const hadKey = this.has(key);
2679
+ const oldValue = this.get(key);
2680
+ const reactiveValue = reactive(value);
2681
+ this.set(key, reactiveValue);
2682
+ if (!hadKey || oldValue !== reactiveValue) {
2683
+ notifyPropertyChange(contentRef(this), key, oldValue, reactiveValue, hadKey);
2684
+ }
2685
+ return this;
2686
+ }
2687
+ }
2688
+ /**
2689
+ * Reactive wrapper around JavaScript's Map class
2690
+ * Tracks size changes, individual key operations, and collection-wide operations
2691
+ */
2692
+ class ReactiveMap extends Map {
2693
+ // Implement Map interface methods with reactivity
2694
+ get size() {
2695
+ dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
2696
+ return this.size;
2697
+ }
2698
+ clear() {
2699
+ const hadEntries = this.size > 0;
2700
+ this.clear();
2701
+ if (hadEntries) {
2702
+ const evolution = { type: 'bunch', method: 'clear' };
2703
+ // Clear triggers all effects since all keys are affected
2704
+ touched1(this, evolution, 'size');
2705
+ touched(contentRef(this), evolution);
2706
+ }
2707
+ }
2708
+ entries() {
2709
+ dependant(contentRef(this));
2710
+ return makeReactiveEntriesIterator(this.entries());
2711
+ }
2712
+ forEach(callbackfn, thisArg) {
2713
+ dependant(contentRef(this));
2714
+ this.forEach(callbackfn, thisArg);
2715
+ }
2716
+ keys() {
2717
+ dependant(contentRef(this), keysOf);
2718
+ return this.keys();
2719
+ }
2720
+ values() {
2721
+ dependant(contentRef(this));
2722
+ return makeReactiveIterator(this.values());
2723
+ }
2724
+ [Symbol.iterator]() {
2725
+ dependant(contentRef(this));
2726
+ const it = Map.prototype[Symbol.iterator].call(this);
2727
+ const nativeNext = it.next.bind(it);
2728
+ it.next = () => {
2729
+ const result = nativeNext();
2730
+ if (result.done)
2731
+ return result;
2732
+ const [key, value] = result.value;
2733
+ return { value: [reactive(key), reactive(value)], done: false };
2734
+ };
2735
+ return it;
2736
+ }
2737
+ // Implement Map methods with reactivity
2738
+ delete(key) {
2739
+ const hadKey = this.has(key);
2740
+ const result = this.delete(key);
2741
+ if (hadKey) {
2742
+ const evolution = { type: 'del', prop: key };
2743
+ touched1(contentRef(this), evolution, key);
2744
+ touched1(this, evolution, 'size');
2745
+ }
2746
+ return result;
2747
+ }
2748
+ get(key) {
2749
+ dependant(contentRef(this), key);
2750
+ return reactive(this.get(key));
2751
+ }
2752
+ has(key) {
2753
+ dependant(contentRef(this), key);
2754
+ return this.has(key);
2755
+ }
2756
+ set(key, value) {
2757
+ const hadKey = this.has(key);
2758
+ const oldValue = this.get(key);
2759
+ const reactiveValue = reactive(value);
2760
+ this.set(key, reactiveValue);
2761
+ if (!hadKey || oldValue !== reactiveValue) {
2762
+ notifyPropertyChange(contentRef(this), key, oldValue, reactiveValue, hadKey);
2763
+ // Also notify size change for Map (WeakMap doesn't track size)
2764
+ const evolution = { type: hadKey ? 'set' : 'add', prop: key };
2765
+ touched1(this, evolution, 'size');
2766
+ }
2767
+ return this;
2768
+ }
2769
+ }
2770
+
2771
+ /**
2772
+ * Reactive wrapper around JavaScript's WeakSet class
2773
+ * Only tracks individual value operations, no size tracking (WeakSet limitation)
2774
+ */
2775
+ class ReactiveWeakSet extends WeakSet {
2776
+ add(value) {
2777
+ const had = this.has(value);
2778
+ this.add(value);
2779
+ if (!had) {
2780
+ // touch the specific value and the collection view
2781
+ touched1(contentRef(this), { type: 'add', prop: value }, value);
2782
+ // no size/allProps for WeakSet
2783
+ }
2784
+ return this;
2785
+ }
2786
+ delete(value) {
2787
+ const had = this.has(value);
2788
+ const res = this.delete(value);
2789
+ if (had)
2790
+ touched1(contentRef(this), { type: 'del', prop: value }, value);
2791
+ return res;
2792
+ }
2793
+ has(value) {
2794
+ dependant(contentRef(this), value);
2795
+ return this.has(value);
2796
+ }
2797
+ }
2798
+ /**
2799
+ * Reactive wrapper around JavaScript's Set class
2800
+ * Tracks size changes, individual value operations, and collection-wide operations
2801
+ */
2802
+ class ReactiveSet extends Set {
2803
+ get size() {
2804
+ // size depends on the wrapper instance, like Map counterpart
2805
+ dependant(this, 'size');
2806
+ return this.size;
2807
+ }
2808
+ add(value) {
2809
+ const had = this.has(value);
2810
+ const reactiveValue = reactive(value);
2811
+ this.add(reactiveValue);
2812
+ if (!had) {
2813
+ const evolution = { type: 'add', prop: reactiveValue };
2814
+ // touch for value-specific and aggregate dependencies
2815
+ touched1(contentRef(this), evolution, reactiveValue);
2816
+ touched1(this, evolution, 'size');
2817
+ }
2818
+ return this;
2819
+ }
2820
+ clear() {
2821
+ const hadEntries = this.size > 0;
2822
+ this.clear();
2823
+ if (hadEntries) {
2824
+ const evolution = { type: 'bunch', method: 'clear' };
2825
+ touched1(this, evolution, 'size');
2826
+ touched(contentRef(this), evolution);
2827
+ }
2828
+ }
2829
+ delete(value) {
2830
+ const had = this.has(value);
2831
+ const res = this.delete(value);
2832
+ if (had) {
2833
+ const evolution = { type: 'del', prop: value };
2834
+ touched1(contentRef(this), evolution, value);
2835
+ touched1(this, evolution, 'size');
2836
+ }
2837
+ return res;
2838
+ }
2839
+ has(value) {
2840
+ dependant(contentRef(this), value);
2841
+ return this.has(value);
2842
+ }
2843
+ entries() {
2844
+ dependant(contentRef(this));
2845
+ return makeReactiveEntriesIterator(this.entries());
2846
+ }
2847
+ forEach(callbackfn, thisArg) {
2848
+ dependant(contentRef(this));
2849
+ this.forEach(callbackfn, thisArg);
2850
+ }
2851
+ keys() {
2852
+ dependant(contentRef(this));
2853
+ return makeReactiveIterator(this.keys());
2854
+ }
2855
+ values() {
2856
+ dependant(contentRef(this));
2857
+ return makeReactiveIterator(this.values());
2858
+ }
2859
+ [Symbol.iterator]() {
2860
+ dependant(contentRef(this));
2861
+ const it = Set.prototype[Symbol.iterator].call(this);
2862
+ const nativeNext = it.next.bind(it);
2863
+ it.next = () => {
2864
+ const result = nativeNext();
2865
+ if (result.done)
2866
+ return result;
2867
+ return { value: reactive(result.value), done: false };
2868
+ };
2869
+ return it;
2870
+ }
2871
+ }
2872
+
2873
+ // Register native collection types to use specialized reactive wrappers
2874
+ console.time('mutts-reactive-init');
2875
+ metaProtos.set(Array, ReactiveArray.prototype);
2876
+ metaProtos.set(Set, ReactiveSet.prototype);
2877
+ metaProtos.set(WeakSet, ReactiveWeakSet.prototype);
2878
+ metaProtos.set(Map, ReactiveMap.prototype);
2879
+ metaProtos.set(WeakMap, ReactiveWeakMap.prototype);
2880
+ wrapProtos.set(Array, ReactiveArrayWrapper.prototype);
2881
+ console.timeEnd('mutts-reactive-init');
2882
+ /**
2883
+ * Object containing internal reactive system state for debugging and profiling
2884
+ */
2885
+ const profileInfo = {
2886
+ objectToProxy,
2887
+ proxyToObject,
2888
+ effectToReactiveObjects,
2889
+ watchers,
2890
+ objectParents,
2891
+ objectsWithDeepWatchers,
2892
+ deepWatchers,
2893
+ effectToDeepWatchedObjects,
2894
+ nonReactiveObjects,
2895
+ };
2896
+
2897
+ // In order to avoid async re-entrance, we could use zone.js or something like that.
2898
+ const syncCalculating = [];
2899
+ /**
2900
+ * Decorator that caches the result of a getter method and only recomputes when dependencies change
2901
+ * Prevents circular dependencies and provides automatic cache invalidation
2902
+ */
2903
+ const cached = decorator({
2904
+ getter(original, _target, propertyKey) {
2905
+ return function () {
2906
+ const alreadyCalculating = syncCalculating.findIndex((c) => c.object === this && c.prop === propertyKey);
2907
+ if (alreadyCalculating > -1)
2908
+ throw new Error(`Circular dependency detected: ${syncCalculating
2909
+ .slice(alreadyCalculating)
2910
+ .map((c) => `${c.object.constructor.name}.${String(c.prop)}`)
2911
+ .join(' -> ')} -> again`);
2912
+ syncCalculating.push({ object: this, prop: propertyKey });
2913
+ try {
2914
+ const rv = original.call(this);
2915
+ cache(this, propertyKey, rv);
2916
+ return rv;
2917
+ }
2918
+ finally {
2919
+ syncCalculating.pop();
2920
+ }
2921
+ };
2922
+ },
2923
+ });
2924
+ /**
2925
+ * Checks if a property is cached (has a cached value)
2926
+ * @param object - The object to check
2927
+ * @param propertyKey - The property key to check
2928
+ * @returns True if the property has a cached value
2929
+ */
2930
+ function isCached(object, propertyKey) {
2931
+ return !!Object.getOwnPropertyDescriptor(object, propertyKey);
2932
+ }
2933
+ /**
2934
+ * Caches a value for a property on an object
2935
+ * @param object - The object to cache the value on
2936
+ * @param propertyKey - The property key to cache
2937
+ * @param value - The value to cache
2938
+ */
2939
+ function cache(object, propertyKey, value) {
2940
+ Object.defineProperty(object, propertyKey, { value });
2941
+ }
2942
+ /**
2943
+ * Creates a decorator that modifies property descriptors for specified properties
2944
+ * @param descriptor - The descriptor properties to apply
2945
+ * @returns A class decorator that applies the descriptor to specified properties
2946
+ */
2947
+ const descriptor = flavored(function descriptor(descriptor) {
2948
+ return (...properties) => (Base) => {
2949
+ return class extends Base {
2950
+ constructor(...args) {
2951
+ super(...args);
2952
+ for (const key of properties) {
2953
+ const existing = Object.getOwnPropertyDescriptor(this, key);
2954
+ Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
2955
+ }
2956
+ }
2957
+ };
2958
+ };
2959
+ }, {
2960
+ /**
2961
+ * enumerable: true
2962
+ */
2963
+ get enumerable() {
2964
+ return descriptor({ enumerable: true });
2965
+ },
2966
+ /**
2967
+ * enumerable: false
2968
+ */
2969
+ get hidden() {
2970
+ return descriptor({ enumerable: false });
2971
+ },
2972
+ /**
2973
+ * configurable: true
2974
+ */
2975
+ get configurable() {
2976
+ return descriptor({ configurable: true });
2977
+ },
2978
+ /**
2979
+ * configurable: false
2980
+ */
2981
+ get frozen() {
2982
+ return descriptor({ configurable: false });
2983
+ },
2984
+ /**
2985
+ * writable: true
2986
+ */
2987
+ get writable() {
2988
+ return descriptor({ writable: true });
2989
+ },
2990
+ /**
2991
+ * writable: false
2992
+ */
2993
+ get readonly() {
2994
+ return descriptor({ writable: false });
2995
+ },
2996
+ });
2997
+ /**
2998
+ * Decorator that marks methods, properties, or classes as deprecated
2999
+ * Provides warning messages when deprecated items are used
3000
+ */
3001
+ const deprecated = Object.assign(decorator({
3002
+ method(original, _target, propertyKey) {
3003
+ return function (...args) {
3004
+ deprecated.warn(this, propertyKey);
3005
+ return original.apply(this, args);
3006
+ };
3007
+ },
3008
+ getter(original, _target, propertyKey) {
3009
+ return function () {
3010
+ deprecated.warn(this, propertyKey);
3011
+ return original.call(this);
3012
+ };
3013
+ },
3014
+ setter(original, _target, propertyKey) {
3015
+ return function (value) {
3016
+ deprecated.warn(this, propertyKey);
3017
+ return original.call(this, value);
3018
+ };
3019
+ },
3020
+ class(original) {
3021
+ return class extends original {
3022
+ constructor(...args) {
3023
+ super(...args);
3024
+ deprecated.warn(this, 'constructor');
3025
+ }
3026
+ };
3027
+ },
3028
+ default(message) {
3029
+ return decorator({
3030
+ method(original, _target, propertyKey) {
3031
+ return function (...args) {
3032
+ deprecated.warn(this, propertyKey, message);
3033
+ return original.apply(this, args);
3034
+ };
3035
+ },
3036
+ getter(original, _target, propertyKey) {
3037
+ return function () {
3038
+ deprecated.warn(this, propertyKey, message);
3039
+ return original.call(this);
3040
+ };
3041
+ },
3042
+ setter(original, _target, propertyKey) {
3043
+ return function (value) {
3044
+ deprecated.warn(this, propertyKey, message);
3045
+ return original.call(this, value);
3046
+ };
3047
+ },
3048
+ class(original) {
3049
+ return class extends original {
3050
+ constructor(...args) {
3051
+ super(...args);
3052
+ deprecated.warn(this, 'constructor', message);
3053
+ }
3054
+ };
3055
+ },
3056
+ });
3057
+ },
3058
+ }), {
3059
+ warn: (target, propertyKey, message) => {
3060
+ // biome-ignore lint/suspicious/noConsole: To be overridden
3061
+ console.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
3062
+ },
3063
+ });
3064
+ /**
3065
+ * Creates a debounced method decorator that delays execution until after the delay period has passed
3066
+ * @param delay - The delay in milliseconds
3067
+ * @returns A method decorator that debounces method calls
3068
+ */
3069
+ function debounce(delay) {
3070
+ return decorator({
3071
+ method(original, _target, _propertyKey) {
3072
+ let timeoutId = null;
3073
+ return function (...args) {
3074
+ // Clear existing timeout
3075
+ if (timeoutId) {
3076
+ clearTimeout(timeoutId);
3077
+ }
3078
+ // Set new timeout
3079
+ timeoutId = setTimeout(() => {
3080
+ original.apply(this, args);
3081
+ timeoutId = null;
3082
+ }, delay);
3083
+ };
3084
+ },
3085
+ });
3086
+ }
3087
+ /**
3088
+ * Creates a throttled method decorator that limits execution to once per delay period
3089
+ * @param delay - The delay in milliseconds
3090
+ * @returns A method decorator that throttles method calls
3091
+ */
3092
+ function throttle(delay) {
3093
+ return decorator({
3094
+ method(original, _target, _propertyKey) {
3095
+ let lastCallTime = 0;
3096
+ let timeoutId = null;
3097
+ return function (...args) {
3098
+ const now = Date.now();
3099
+ // If enough time has passed since last call, execute immediately
3100
+ if (now - lastCallTime >= delay) {
3101
+ // Clear any pending timeout since we're executing now
3102
+ if (timeoutId) {
3103
+ clearTimeout(timeoutId);
3104
+ timeoutId = null;
3105
+ }
3106
+ lastCallTime = now;
3107
+ return original.apply(this, args);
3108
+ }
3109
+ // Otherwise, schedule execution for when the delay period ends
3110
+ if (!timeoutId) {
3111
+ const remainingTime = delay - (now - lastCallTime);
3112
+ const scheduledArgs = [...args]; // Capture args at scheduling time
3113
+ timeoutId = setTimeout(() => {
3114
+ lastCallTime = Date.now();
3115
+ original.apply(this, scheduledArgs);
3116
+ timeoutId = null;
3117
+ }, remainingTime);
3118
+ }
3119
+ };
3120
+ },
3121
+ });
3122
+ }
3123
+
3124
+ var version$1 = "1.0.10";
3125
+ var pkg = {
3126
+ version: version$1};
3127
+
3128
+ const { version } = pkg;
3129
+ // Singleton verification
3130
+ const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
3131
+ const globalScope = (typeof globalThis !== 'undefined'
3132
+ ? globalThis
3133
+ : typeof window !== 'undefined'
3134
+ ? window
3135
+ : typeof global !== 'undefined'
3136
+ ? global
3137
+ : false);
3138
+ if (globalScope) {
3139
+ // Detect the source of this instance safely across different environments
3140
+ let source = 'mutts/index';
3141
+ // biome-ignore lint/security/noGlobalEval: Intentional eval for cross-env import.meta detection
3142
+ const viteEval = eval;
3143
+ try {
3144
+ if (typeof __filename !== 'undefined')
3145
+ source = __filename;
3146
+ else {
3147
+ // Using eval to avoid SyntaxError in CJS environments where import.meta is not allowed
3148
+ const meta = viteEval('import.meta');
3149
+ if (meta && meta.url)
3150
+ source = meta.url;
3151
+ }
3152
+ }
3153
+ catch (e) {
3154
+ // Fallback for environments where neither is available or accessible
3155
+ }
3156
+ const currentSourceInfo = {
3157
+ version,
3158
+ source,
3159
+ timestamp: Date.now(),
3160
+ };
3161
+ if (globalScope[GLOBAL_MUTTS_KEY]) {
3162
+ const existing = globalScope[GLOBAL_MUTTS_KEY];
3163
+ throw new Error(`[Mutts] Multiple instances detected!\n` +
3164
+ `Existing instance: ${JSON.stringify(existing, null, 2)}\n` +
3165
+ `New instance: ${JSON.stringify(currentSourceInfo, null, 2)}\n` +
3166
+ `This usually happens when 'mutts' is both installed as a dependency and bundled, ` +
3167
+ `or when different versions are loaded. ` +
3168
+ `Please check your build configuration (aliases, externals) to ensure a single source of truth.`);
3169
+ }
3170
+ globalScope[GLOBAL_MUTTS_KEY] = currentSourceInfo;
3171
+ }
3172
+
3173
+ export { ArrayReadForward as A, setAt as B, throttle as C, Destroyable as D, Eventful as E, unreactive as F, watch as G, when as H, Indexable as I, Register as R, DestructionError as a, allocated as b, allocatedValues as c, arrayDiff as d, attend as e, cache as f, cached as g, callOnGC as h, chainPromise as i, debounce as j, deepWatch as k, deprecated as l, descriptor as m, destructor as n, forwardArray as o, getAt as p, isCached as q, lift as r, memoize as s, morph as t, organize as u, organized as v, profileInfo as w, register as x, resource as y, scan as z };
3174
+ //# sourceMappingURL=index-CaaQQlPJ.esm.js.map