@oscarpalmer/mora 0.23.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mora.full.js CHANGED
@@ -3,604 +3,507 @@ const ARRAY_THRESHOLD = 100;
3
3
  const ARRAY_OFFSET = 25;
4
4
  const ARRAY_PEEK = 10;
5
5
  const BATCH = {
6
- depth: 0,
7
- handlers: new Set(),
6
+ depth: 0,
7
+ handlers: /* @__PURE__ */ new Set()
8
8
  };
9
9
  const METHODS_AFFECTING_LENGTH = new Set([
10
- 'pop',
11
- 'push',
12
- 'shift',
13
- 'unshift',
10
+ "pop",
11
+ "push",
12
+ "shift",
13
+ "unshift"
14
14
  ]);
15
15
  const METHODS_UPDATE = new Set([
16
- ...METHODS_AFFECTING_LENGTH,
17
- 'copyWithin',
18
- 'fill',
19
- 'reverse',
20
- 'sort',
21
- 'splice',
16
+ ...METHODS_AFFECTING_LENGTH,
17
+ "copyWithin",
18
+ "fill",
19
+ "reverse",
20
+ "sort",
21
+ "splice"
22
22
  ]);
23
- const NAME_ARRAY = 'array';
24
- const NAME_COMPUTED = 'computed';
25
- const NAME_EFFECT = 'effect';
26
- const NAME_SIGNAL = 'signal';
27
- const NAME_STORE = 'store';
28
- const NAMES = new Set([
29
- NAME_ARRAY,
30
- NAME_COMPUTED,
31
- NAME_SIGNAL,
32
- NAME_STORE,
23
+ const NAME_ARRAY = "array";
24
+ const NAME_COMPUTED = "computed";
25
+ const NAME_EFFECT = "effect";
26
+ const NAME_MORA = "$mora";
27
+ const NAME_SIGNAL = "signal";
28
+ const NAME_STORE = "store";
29
+ const NAME_ALL = new Set([
30
+ NAME_ARRAY,
31
+ NAME_COMPUTED,
32
+ NAME_SIGNAL,
33
+ NAME_STORE
33
34
  ]);
35
+ const PROPERTY_LENGTH = "length";
34
36
 
35
- class Effect {
36
- constructor(callback) {
37
- Object.defineProperty(this, '$mora', {
38
- value: NAME_EFFECT,
39
- });
40
- this.state = {
41
- callback,
42
- };
43
- runEffect(this);
44
- }
45
- }
46
- function runEffect(effect) {
47
- const previousEffect = ACTIVE.effect;
48
- ACTIVE.effect = effect;
49
- try {
50
- effect.state.callback();
51
- }
52
- finally {
53
- ACTIVE.effect = previousEffect;
54
- }
37
+ var Effect = class {
38
+ constructor(callback) {
39
+ Object.defineProperty(this, NAME_MORA, { value: NAME_EFFECT });
40
+ this.state = { callback };
41
+ runEffect(this);
42
+ }
43
+ };
44
+ function runEffect(effect$1) {
45
+ const previousEffect = ACTIVE.effect;
46
+ ACTIVE.effect = effect$1;
47
+ try {
48
+ effect$1.state.callback();
49
+ } finally {
50
+ ACTIVE.effect = previousEffect;
51
+ }
55
52
  }
56
53
  /**
57
- * Create an effect
58
- * @param callback Callback for handling signal effects
59
- * @returns Effect
60
- */
54
+ * Create an effect
55
+ * @param callback Callback for handling signal effects
56
+ * @returns Effect
57
+ */
61
58
  function effect(callback) {
62
- return typeof callback === 'function'
63
- ? new Effect(callback)
64
- : undefined;
59
+ return typeof callback === "function" ? new Effect(callback) : void 0;
65
60
  }
66
61
 
67
62
  /**
68
- * Is the value a reactive array?
69
- * @param value Value to check
70
- * @returns True if value is a {@link ReactiveArray}
71
- */
63
+ * Is the value a reactive array?
64
+ * @param value Value to check
65
+ * @returns True if value is a {@link ReactiveArray}
66
+ */
72
67
  function isArray(value) {
73
- return isMora(value, NAME_ARRAY);
68
+ return isMora(value, NAME_ARRAY);
74
69
  }
75
70
  /**
76
- * Is the value a computed signal?
77
- * @param value Value to check
78
- * @returns True if value is a {@link Computed}
79
- */
71
+ * Is the value a computed signal?
72
+ * @param value Value to check
73
+ * @returns True if value is a {@link Computed}
74
+ */
80
75
  function isComputed(value) {
81
- return isMora(value, NAME_COMPUTED);
76
+ return isMora(value, NAME_COMPUTED);
82
77
  }
83
78
  /**
84
- * Is the value an effect?
85
- * @param value Value to check
86
- * @returns True if value is an {@link Effect}
87
- */
79
+ * Is the value an effect?
80
+ * @param value Value to check
81
+ * @returns True if value is an {@link Effect}
82
+ */
88
83
  function isEffect(value) {
89
- return isMora(value, NAME_EFFECT);
84
+ return isMora(value, NAME_EFFECT);
90
85
  }
91
86
  function isMora(value, name) {
92
- return (typeof value === 'object' &&
93
- value != null &&
94
- '$mora' in value &&
95
- (typeof name === 'string'
96
- ? value.$mora === name
97
- : name.has(value.$mora)));
87
+ return typeof value === "object" && value != null && NAME_MORA in value && (typeof name === "string" ? value[NAME_MORA] === name : name.has(value[NAME_MORA]));
98
88
  }
99
89
  /**
100
- * Is the value reactive?
101
- * @param value Value to check
102
- * @returns True if value is a {@link Reactive}
103
- */
90
+ * Is the value reactive?
91
+ * @param value Value to check
92
+ * @returns True if value is a {@link Reactive}
93
+ */
104
94
  function isReactive(value) {
105
- return isMora(value, NAMES);
95
+ return isMora(value, NAME_ALL);
106
96
  }
107
97
  /**
108
- * Is the value a signal?
109
- * @param value Value to check
110
- * @returns True if value is a {@link Signal}
111
- */
98
+ * Is the value a signal?
99
+ * @param value Value to check
100
+ * @returns True if value is a {@link Signal}
101
+ */
112
102
  function isSignal(value) {
113
- return isMora(value, NAME_SIGNAL);
103
+ return isMora(value, NAME_SIGNAL);
114
104
  }
115
105
 
116
106
  function flushHandlers() {
117
- while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
118
- const handlers = [...BATCH.handlers];
119
- BATCH.handlers.clear();
120
- for (const handler of handlers) {
121
- if (isEffect(handler)) {
122
- runEffect(handler);
123
- }
124
- else {
125
- handler.callback(handler.state.value);
126
- }
127
- }
128
- }
107
+ while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
108
+ const handlers = [...BATCH.handlers];
109
+ BATCH.handlers.clear();
110
+ for (const handler of handlers) if (isEffect(handler)) runEffect(handler);
111
+ else handler.callback(handler.state.value);
112
+ }
129
113
  }
130
114
  /**
131
- * Start batching effects
132
- *
133
- * _(Use {@link stopBatch} to flush and run batched effects)_
134
- */
115
+ * Start batching effects
116
+ *
117
+ * _(Use {@link stopBatch} to flush and run batched effects)_
118
+ */
135
119
  function startBatch() {
136
- BATCH.depth += 1;
120
+ BATCH.depth += 1;
137
121
  }
138
122
  /**
139
- * Stop batching effects and flush _(run)_ them
140
- */
123
+ * Stop batching effects and flush _(run)_ them
124
+ */
141
125
  function stopBatch() {
142
- if (BATCH.depth > 0) {
143
- BATCH.depth -= 1;
144
- }
145
- flushHandlers();
126
+ if (BATCH.depth > 0) BATCH.depth -= 1;
127
+ flushHandlers();
146
128
  }
147
129
 
148
- class Subscription {
149
- callback;
150
- state;
151
- constructor(state, callback) {
152
- this.state = state;
153
- this.callback = callback;
154
- callback(state.value);
155
- }
156
- destroy() {
157
- this.callback = noop;
158
- this.state = undefined;
159
- }
160
- }
161
- function noop() { }
130
+ var Subscription = class {
131
+ callback;
132
+ state;
133
+ constructor(state, callback) {
134
+ this.state = state;
135
+ this.callback = callback;
136
+ callback(state.value);
137
+ }
138
+ destroy() {
139
+ this.callback = noop;
140
+ this.state = void 0;
141
+ }
142
+ };
143
+ function noop() {}
162
144
  function subscribe(state, callback) {
163
- if (typeof callback !== 'function' || state.subscriptions.has(callback)) {
164
- return noop;
165
- }
166
- state.subscriptions.set(callback, new Subscription(state, callback));
167
- return () => {
168
- unsubscribe(state, callback);
169
- };
145
+ if (typeof callback !== "function" || state.subscriptions.has(callback)) return noop;
146
+ state.subscriptions.set(callback, new Subscription(state, callback));
147
+ return () => {
148
+ unsubscribe(state, callback);
149
+ };
170
150
  }
171
151
  function unsubscribe(state, callback) {
172
- state.subscriptions.get(callback)?.destroy();
173
- state.subscriptions.delete(callback);
152
+ state.subscriptions.get(callback)?.destroy();
153
+ state.subscriptions.delete(callback);
174
154
  }
175
155
 
176
- class Reactive {
177
- state = {
178
- computeds: new Set(),
179
- effects: new Set(),
180
- equal: Object.is,
181
- subscriptions: new Map(),
182
- value: undefined,
183
- };
184
- constructor(name, value, options) {
185
- this.state.value = value;
186
- if (typeof options === 'object' && typeof options.equal === 'function') {
187
- this.state.equal = options.equal;
188
- }
189
- Object.defineProperty(this, '$mora', {
190
- value: name,
191
- });
192
- }
193
- /**
194
- * Get the value _(without reactivity)_
195
- * @return Current value
196
- */
197
- peek() {
198
- return this.state.value;
199
- }
200
- /**
201
- * Subscribe to changes
202
- * @param callback Callback for changes
203
- * @return Unsubscribe callback
204
- */
205
- subscribe(callback) {
206
- return subscribe(this.state, callback);
207
- }
208
- /**
209
- * JSON representation of the value
210
- * @return JSON value
211
- */
212
- toJSON() {
213
- return this.get();
214
- }
215
- /**
216
- * String representation of the value
217
- * @return Value as string
218
- */
219
- toString() {
220
- return String(this.get());
221
- }
222
- /**
223
- * Unsubscribe from changes
224
- * @param callback Callback to unsubscribe
225
- */
226
- unsubscribe(callback) {
227
- unsubscribe(this.state, callback);
228
- }
229
- }
156
+ var Reactive = class {
157
+ state = {
158
+ computeds: /* @__PURE__ */ new Set(),
159
+ effects: /* @__PURE__ */ new Set(),
160
+ equal: Object.is,
161
+ subscriptions: /* @__PURE__ */ new Map(),
162
+ value: void 0
163
+ };
164
+ constructor(name, value, options) {
165
+ this.state.value = value;
166
+ if (typeof options === "object" && typeof options.equal === "function") this.state.equal = options.equal;
167
+ Object.defineProperty(this, NAME_MORA, { value: name });
168
+ }
169
+ /**
170
+ * Get the value _(without reactivity)_
171
+ * @return Current value
172
+ */
173
+ peek() {
174
+ return this.state.value;
175
+ }
176
+ /**
177
+ * Subscribe to changes
178
+ * @param callback Callback for changes
179
+ * @return Unsubscribe callback
180
+ */
181
+ subscribe(callback) {
182
+ return subscribe(this.state, callback);
183
+ }
184
+ /**
185
+ * JSON representation of the value
186
+ * @return JSON value
187
+ */
188
+ toJSON() {
189
+ return this.get();
190
+ }
191
+ /**
192
+ * String representation of the value
193
+ * @return Value as string
194
+ */
195
+ toString() {
196
+ return String(this.get());
197
+ }
198
+ /**
199
+ * Unsubscribe from changes
200
+ * @param callback Callback to unsubscribe
201
+ */
202
+ unsubscribe(callback) {
203
+ unsubscribe(this.state, callback);
204
+ }
205
+ };
230
206
 
231
- class Computed extends Reactive {
232
- effect = {
233
- dirty: true,
234
- instance: undefined,
235
- };
236
- constructor(callback, options) {
237
- super(NAME_COMPUTED, undefined, options);
238
- this.effect.instance = effect(() => {
239
- if (!this.effect.dirty) {
240
- return;
241
- }
242
- const previousComputed = ACTIVE.computed;
243
- ACTIVE.computed = this;
244
- const value = callback();
245
- ACTIVE.computed = previousComputed;
246
- if (!this.state.equal(this.state.value, value)) {
247
- this.state.value = value;
248
- for (const computed of this.state.computeds) {
249
- computed.effect.dirty = true;
250
- }
251
- for (const effect of this.state.effects) {
252
- BATCH.handlers.add(effect);
253
- }
254
- for (const [, subscription] of this.state.subscriptions) {
255
- subscription.callback(value);
256
- }
257
- }
258
- this.effect.dirty = false;
259
- });
260
- }
261
- /**
262
- * @inheritdoc
263
- */
264
- get() {
265
- if (ACTIVE.computed != null && this !== ACTIVE.computed) {
266
- this.state.computeds.add(ACTIVE.computed);
267
- }
268
- if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) {
269
- this.state.effects.add(ACTIVE.effect);
270
- }
271
- if (this.effect.dirty && BATCH.depth === 0) {
272
- runEffect(this.effect.instance);
273
- }
274
- return this.state.value;
275
- }
276
- }
207
+ var Computed = class extends Reactive {
208
+ effect = {
209
+ dirty: true,
210
+ instance: void 0
211
+ };
212
+ constructor(callback, options) {
213
+ super(NAME_COMPUTED, void 0, options);
214
+ this.effect.instance = effect(() => {
215
+ if (!this.effect.dirty) return;
216
+ const previousComputed = ACTIVE.computed;
217
+ ACTIVE.computed = this;
218
+ const value = callback();
219
+ ACTIVE.computed = previousComputed;
220
+ if (!this.state.equal(this.state.value, value)) {
221
+ this.state.value = value;
222
+ for (const computed$1 of this.state.computeds) computed$1.effect.dirty = true;
223
+ for (const effect$1 of this.state.effects) BATCH.handlers.add(effect$1);
224
+ for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
225
+ }
226
+ this.effect.dirty = false;
227
+ });
228
+ }
229
+ /**
230
+ * @inheritdoc
231
+ */
232
+ get() {
233
+ if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
234
+ if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
235
+ if (this.effect.dirty && BATCH.depth === 0) runEffect(this.effect.instance);
236
+ return this.state.value;
237
+ }
238
+ };
277
239
  /**
278
- * Create a computed value
279
- */
240
+ * Create a computed value
241
+ * @param callback Callback to compute the value
242
+ * @param options Reactivity options
243
+ * @returns Computed value
244
+ */
280
245
  function computed(callback, options) {
281
- return new Computed(callback, options);
246
+ return new Computed(callback, options);
282
247
  }
283
248
 
284
249
  function emitValue(state) {
285
- for (const computed of state.computeds) {
286
- computed.effect.dirty = true;
287
- }
288
- for (const effect of state.effects) {
289
- BATCH.handlers.add(effect);
290
- }
291
- for (const [, subscription] of state.subscriptions) {
292
- BATCH.handlers.add(subscription);
293
- }
294
- if (BATCH.depth === 0) {
295
- flushHandlers();
296
- }
250
+ for (const computed$1 of state.computeds) computed$1.effect.dirty = true;
251
+ for (const effect$1 of state.effects) BATCH.handlers.add(effect$1);
252
+ for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
253
+ if (BATCH.depth === 0) flushHandlers();
297
254
  }
298
255
  function equalArrays(state, first, second) {
299
- let { length } = first;
300
- if (length !== second.length) {
301
- return false;
302
- }
303
- let offset = 0;
304
- if (length >= ARRAY_THRESHOLD) {
305
- offset = Math.round(length / ARRAY_PEEK);
306
- offset = offset > ARRAY_OFFSET ? ARRAY_OFFSET : offset;
307
- for (let index = 0; index < offset; index += 1) {
308
- if (!state.equal(first[index], second[index])) {
309
- return false;
310
- }
311
- }
312
- }
313
- length -= offset;
314
- for (let index = offset; index < length; index += 1) {
315
- if (!state.equal(first[index], second[index])) {
316
- return false;
317
- }
318
- }
319
- return true;
256
+ let { length } = first;
257
+ if (length !== second.length) return false;
258
+ let offset = 0;
259
+ if (length >= ARRAY_THRESHOLD) {
260
+ offset = Math.round(length / ARRAY_PEEK);
261
+ offset = offset > ARRAY_OFFSET ? ARRAY_OFFSET : offset;
262
+ for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
263
+ }
264
+ length -= offset;
265
+ for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
266
+ return true;
320
267
  }
321
268
  function getValue(state) {
322
- if (ACTIVE.computed != null) {
323
- state.computeds.add(ACTIVE.computed);
324
- }
325
- if (ACTIVE.effect != null) {
326
- state.effects.add(ACTIVE.effect);
327
- }
328
- return state.value;
269
+ if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
270
+ if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
271
+ return state.value;
329
272
  }
330
273
 
331
- function getReactiveValueInProxy(reactive, mapped, key, isArray) {
332
- let item = mapped.get(key);
333
- if (item == null) {
334
- item = computed(() => {
335
- const value = reactive.get();
336
- return isArray
337
- ? value.at(key)
338
- : value[key];
339
- });
340
- mapped.set(key, item);
341
- }
342
- return item;
274
+ function emityProxyValues(state, mapped) {
275
+ const values = [...mapped.values()];
276
+ const { length } = values;
277
+ for (let index = 0; index < length; index += 1) values[index].effect.dirty = true;
278
+ emitValue(state);
279
+ }
280
+ function getReactiveValueInProxy(reactive, mapped, key, isArray$1) {
281
+ let item = mapped.get(key);
282
+ if (item == null) {
283
+ item = computed(() => isArray$1 ? reactive.get().at(key) : reactive.get()[key]);
284
+ mapped.set(key, item);
285
+ }
286
+ return item;
343
287
  }
344
288
  function setProxyValue(proxy, value) {
345
- startBatch();
346
- const proxyKeys = Object.keys(proxy);
347
- const valueKeys = Object.keys(value);
348
- let { length } = proxyKeys;
349
- for (let index = 0; index < length; index += 1) {
350
- const key = proxyKeys[index];
351
- proxy[key] = valueKeys.includes(key)
352
- ? value[key]
353
- : undefined;
354
- }
355
- length = valueKeys.length;
356
- for (let index = 0; index < length; index += 1) {
357
- const key = valueKeys[index];
358
- if (!proxyKeys.includes(key)) {
359
- const keyedValue = value[key];
360
- proxy[key] = keyedValue;
361
- }
362
- }
363
- stopBatch();
289
+ startBatch();
290
+ const proxyKeys = Object.keys(proxy);
291
+ const valueKeys = Object.keys(value);
292
+ let { length } = proxyKeys;
293
+ for (let index = 0; index < length; index += 1) {
294
+ const key = proxyKeys[index];
295
+ proxy[key] = valueKeys.includes(key) ? value[key] : void 0;
296
+ }
297
+ length = valueKeys.length;
298
+ for (let index = 0; index < length; index += 1) {
299
+ const key = valueKeys[index];
300
+ if (!proxyKeys.includes(key)) proxy[key] = value[key];
301
+ }
302
+ stopBatch();
364
303
  }
365
304
  function setValueInProxy(parameters) {
366
- const { isArray, length, property, state, target, value } = parameters;
367
- if (isArray) {
368
- const isIndex = !Number.isNaN(Number(property));
369
- const isLength = property === 'length';
370
- if (!(isIndex || isLength)) {
371
- return Reflect.set(target, property, value);
372
- }
373
- }
374
- const previous = Reflect.get(target, property);
375
- if (!state.equal(previous, value)) {
376
- Reflect.set(target, property, value);
377
- emitValue(state);
378
- if (isArray) {
379
- length?.set(target.length);
380
- }
381
- }
382
- return true;
305
+ const { isArray: isArray$1, length, property, state, target, value } = parameters;
306
+ if (isArray$1) {
307
+ if (!(!Number.isNaN(Number(property)) || property === PROPERTY_LENGTH)) return Reflect.set(target, property, value);
308
+ }
309
+ const previous = Reflect.get(target, property);
310
+ if (!state.equal(previous, value)) {
311
+ Reflect.set(target, property, value);
312
+ emitValue(state);
313
+ if (isArray$1) length?.set(target.length);
314
+ }
315
+ return true;
383
316
  }
384
317
 
385
- class Signal extends Reactive {
386
- constructor(value, options) {
387
- super(NAME_SIGNAL, value, options);
388
- }
389
- /**
390
- * @inheritdoc
391
- */
392
- get() {
393
- return getValue(this.state);
394
- }
395
- /**
396
- * Set the value
397
- * @param value New value
398
- */
399
- set(value) {
400
- if (!this.state.equal(this.state.value, value)) {
401
- this.state.value = value;
402
- emitValue(this.state);
403
- }
404
- }
405
- /**
406
- * Update the value _(based on the current value)_
407
- * @param callback Callback to update the value
408
- */
409
- update(callback) {
410
- this.set(callback(this.state.value));
411
- }
412
- }
318
+ var Signal = class extends Reactive {
319
+ constructor(value, options) {
320
+ super(NAME_SIGNAL, value, options);
321
+ }
322
+ /**
323
+ * @inheritdoc
324
+ */
325
+ get() {
326
+ return getValue(this.state);
327
+ }
328
+ /**
329
+ * Set the value
330
+ * @param value New value
331
+ */
332
+ set(value) {
333
+ if (!this.state.equal(this.state.value, value)) {
334
+ this.state.value = value;
335
+ emitValue(this.state);
336
+ }
337
+ }
338
+ /**
339
+ * Update the value _(based on the current value)_
340
+ * @param callback Callback to update the value
341
+ */
342
+ update(callback) {
343
+ this.set(callback(this.state.value));
344
+ }
345
+ };
413
346
  /**
414
- * Create a reactive value
415
- * @param value Initial value
416
- * @param options Optional reactivity options
417
- * @returns Reactive value
418
- */
347
+ * Create a reactive value
348
+ * @param value Initial value
349
+ * @param options Reactivity options
350
+ * @returns Reactive value
351
+ */
419
352
  function signal(value, options) {
420
- return new Signal(value, options);
353
+ return new Signal(value, options);
421
354
  }
422
355
 
423
- class ReactiveArray extends Reactive {
424
- #indiced = new Map();
425
- #size = signal(0);
426
- /**
427
- * The length of the array
428
- */
429
- get length() {
430
- return this.#size.get();
431
- }
432
- /**
433
- * Set the length of the array
434
- */
435
- set length(value) {
436
- if (typeof value === 'number' &&
437
- value >= 0 &&
438
- value !== this.state.value.length) {
439
- this.get().length = value;
440
- }
441
- }
442
- constructor(value, options) {
443
- super(NAME_ARRAY, new Proxy(value, {
444
- get: (target, property) => METHODS_UPDATE.has(property)
445
- ? updateArray(property, target, this.state, this.#size)
446
- : Reflect.get(target, property),
447
- set: (target, property, value) => setValueInProxy({
448
- property,
449
- target,
450
- value,
451
- isArray: true,
452
- state: this.state,
453
- length: this.#size,
454
- }),
455
- }), options);
456
- this.#size.set(value.length);
457
- }
458
- /**
459
- * Clear the array
460
- */
461
- clear() {
462
- this.length = 0;
463
- }
464
- /**
465
- * Create a computed, filtered array
466
- * @param callback Callback to evaluate each item
467
- * @return Computed array of filtered items
468
- */
469
- filter(callback) {
470
- return computed(() => this.get().filter(callback));
471
- }
472
- get(first) {
473
- if (typeof first === 'number') {
474
- return getReactiveValueInProxy(this, this.#indiced, first, true).get();
475
- }
476
- if (first === 'length') {
477
- return this.length;
478
- }
479
- return getValue(this.state);
480
- }
481
- /**
482
- * Create a computed, mapped array
483
- * @param callback Callback to transform each item
484
- * @return Computed array of mapped items
485
- */
486
- map(callback) {
487
- return computed(() => this.get().map(callback));
488
- }
489
- /**
490
- * Notify dependents of changes
491
- *
492
- * _This bypasses equality checks and will immediately notify dependents.
493
- * Use this only if you're modifying nested data that would be ignored by equality checks._
494
- */
495
- notify() {
496
- emitValue(this.state);
497
- }
498
- peek(value) {
499
- if (value === 'length') {
500
- return this.#size.peek();
501
- }
502
- if (typeof value === 'number') {
503
- return this.state.value.at(value);
504
- }
505
- return [...this.state.value];
506
- }
507
- /**
508
- * Remove and return the last item of the array
509
- * @returns Removed item, or `undefined` if the array is empty
510
- */
511
- pop() {
512
- return this.state.value.pop();
513
- }
514
- /**
515
- * Add items to the end of the array
516
- * @param items Items to add
517
- * @returns New array length
518
- */
519
- push(...items) {
520
- return this.state.value.push(...items);
521
- }
522
- set(first, second) {
523
- if (first == null || Array.isArray(first)) {
524
- this.state.value.splice(0, this.state.value.length, ...(first ?? []));
525
- }
526
- else if (first === 'length') {
527
- this.length = second;
528
- }
529
- else if (typeof first === 'number' && !Number.isNaN(first)) {
530
- setAtIndex(this.state.value, first, second);
531
- }
532
- }
533
- /**
534
- * Remove and return the first item of the array
535
- * @returns Removed item, or `undefined` if the array is empty
536
- */
537
- shift() {
538
- return this.state.value.shift();
539
- }
540
- /**
541
- * Remove and return items from the array _(and optionally add new items)_
542
- * @param from Index to start removing items from
543
- * @param to Index to stop removing items at _(defaults to the end of the array)_
544
- * @param items Optional items to add
545
- * @returns Removed items
546
- */
547
- splice(from, to, ...items) {
548
- return this.state.value.splice(from, to ?? this.state.value.length, ...items);
549
- }
550
- subscribe(first, second) {
551
- if (typeof first === 'number' && typeof second === 'function') {
552
- return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
553
- }
554
- return typeof first === 'function' ? subscribe(this.state, first) : noop;
555
- }
556
- /**
557
- * Add items to the beginning of the array
558
- * @param items Items to add
559
- * @returns New array length
560
- */
561
- unshift(...items) {
562
- return this.state.value.unshift(...items);
563
- }
564
- /**
565
- * Update the value _(based on the current value)_
566
- * @param callback Callback to update the value
567
- */
568
- update(callback) {
569
- const updated = callback(this.state.value);
570
- if (updated == null || Array.isArray(updated)) {
571
- this.set(updated);
572
- }
573
- }
574
- }
356
+ var ReactiveArray = class extends Reactive {
357
+ #indiced = /* @__PURE__ */ new Map();
358
+ #size = signal(0);
359
+ /**
360
+ * The length of the array
361
+ */
362
+ get length() {
363
+ return this.#size.get();
364
+ }
365
+ /**
366
+ * Set the length of the array
367
+ */
368
+ set length(value) {
369
+ if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
370
+ }
371
+ constructor(value, options) {
372
+ super(NAME_ARRAY, new Proxy(value, {
373
+ get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
374
+ set: (target, property, value$1) => setValueInProxy({
375
+ property,
376
+ target,
377
+ value: value$1,
378
+ isArray: true,
379
+ state: this.state,
380
+ length: this.#size
381
+ })
382
+ }), options);
383
+ this.#size.set(value.length);
384
+ }
385
+ /**
386
+ * Clear the array
387
+ */
388
+ clear() {
389
+ this.length = 0;
390
+ }
391
+ /**
392
+ * Create a computed, filtered array
393
+ * @param callback Callback to evaluate each item
394
+ * @return Computed array of filtered items
395
+ */
396
+ filter(callback) {
397
+ return computed(() => this.get().filter(callback));
398
+ }
399
+ get(first) {
400
+ if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
401
+ return first === PROPERTY_LENGTH ? this.length : getValue(this.state);
402
+ }
403
+ /**
404
+ * Create a computed, mapped array
405
+ * @param callback Callback to transform each item
406
+ * @return Computed array of mapped items
407
+ */
408
+ map(callback) {
409
+ return computed(() => this.get().map(callback));
410
+ }
411
+ /**
412
+ * Notify dependents of changes
413
+ *
414
+ * _This bypasses equality checks and will immediately notify dependents.
415
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
416
+ */
417
+ notify() {
418
+ emityProxyValues(this.state, this.#indiced);
419
+ }
420
+ peek(value) {
421
+ if (value === "length") return this.#size.peek();
422
+ return typeof value === "number" ? this.state.value.at(value) : [...this.state.value];
423
+ }
424
+ /**
425
+ * Remove and return the last item of the array
426
+ * @returns Removed item, or `undefined` if the array is empty
427
+ */
428
+ pop() {
429
+ return this.state.value.pop();
430
+ }
431
+ /**
432
+ * Add items to the end of the array
433
+ * @param items Items to add
434
+ * @returns New array length
435
+ */
436
+ push(...items) {
437
+ return this.state.value.push(...items);
438
+ }
439
+ set(first, second) {
440
+ if (first == null || Array.isArray(first)) this.state.value.splice(0, this.state.value.length, ...first ?? []);
441
+ else if (first === "length") this.length = second;
442
+ else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
443
+ }
444
+ /**
445
+ * Remove and return the first item of the array
446
+ * @returns Removed item, or `undefined` if the array is empty
447
+ */
448
+ shift() {
449
+ return this.state.value.shift();
450
+ }
451
+ /**
452
+ * Remove and return items from the array _(and optionally add new items)_
453
+ * @param from Index to start removing items from
454
+ * @param to Index to stop removing items at _(defaults to the end of the array)_
455
+ * @param items Optional items to add
456
+ * @returns Removed items
457
+ */
458
+ splice(from, to, ...items) {
459
+ return this.state.value.splice(from, to ?? this.state.value.length, ...items);
460
+ }
461
+ subscribe(first, second) {
462
+ if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
463
+ return typeof first === "function" ? subscribe(this.state, first) : noop;
464
+ }
465
+ /**
466
+ * Add items to the beginning of the array
467
+ * @param items Items to add
468
+ * @returns New array length
469
+ */
470
+ unshift(...items) {
471
+ return this.state.value.unshift(...items);
472
+ }
473
+ /**
474
+ * Update the value _(based on the current value)_
475
+ * @param callback Callback to update the value
476
+ */
477
+ update(callback) {
478
+ const updated = callback(this.state.value);
479
+ if (updated == null || Array.isArray(updated)) this.set(updated);
480
+ }
481
+ };
575
482
  /**
576
- * Create a reactive array
577
- * @param value Initial array of items
578
- * @param options Optional reactivity options
579
- * @returns Reactive array
580
- */
483
+ * Create a reactive array
484
+ * @param value Initial array of items
485
+ * @param options Reactivity options
486
+ * @returns Reactive array
487
+ */
581
488
  function array(value, options) {
582
- return new ReactiveArray(Array.isArray(value) ? value : [], options);
583
- }
584
- function updateArray(type, array, state, length) {
585
- const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
586
- const previousArray = affectsLength ? [] : [...array];
587
- const previousLength = array.length;
588
- return (...args) => {
589
- const result = array[type](...args);
590
- if (affectsLength
591
- ? array.length !== previousLength
592
- : !equalArrays(state, previousArray, array)) {
593
- emitValue(state);
594
- length.set(array.length);
595
- }
596
- return result;
597
- };
598
- }
599
- function setAtIndex(array, index, value) {
600
- const actual = index < 0 ? array.length + index : index;
601
- if (actual > -1) {
602
- array[actual] = value;
603
- }
489
+ return new ReactiveArray(Array.isArray(value) ? value : [], options);
490
+ }
491
+ function updateArray(type, array$1, state, length) {
492
+ const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
493
+ const previousArray = affectsLength ? [] : [...array$1];
494
+ const previousLength = array$1.length;
495
+ return (...args) => {
496
+ const result = array$1[type](...args);
497
+ if (affectsLength ? array$1.length !== previousLength : !equalArrays(state, previousArray, array$1)) {
498
+ emitValue(state);
499
+ length.set(array$1.length);
500
+ }
501
+ return result;
502
+ };
503
+ }
504
+ function setAtIndex(array$1, index, value) {
505
+ const actual = index < 0 ? array$1.length + index : index;
506
+ if (actual > -1) array$1[actual] = value;
604
507
  }
605
508
 
606
509
  function isKey(value) {
@@ -612,61 +515,71 @@ function isPlainObject(value) {
612
515
  const prototype = Object.getPrototypeOf(value);
613
516
  return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
614
517
  }
518
+ var TYPED_ARRAYS = new Set([
519
+ Int8Array,
520
+ Uint8Array,
521
+ Uint8ClampedArray,
522
+ Int16Array,
523
+ Uint16Array,
524
+ Int32Array,
525
+ Uint32Array,
526
+ Float32Array,
527
+ Float64Array,
528
+ BigInt64Array,
529
+ BigUint64Array
530
+ ]);
615
531
 
616
- class Store extends Reactive {
617
- #keyed = new Map();
618
- constructor(value, options) {
619
- super(NAME_STORE, new Proxy(value, {
620
- set: (target, property, value) => setValueInProxy({
621
- target,
622
- property,
623
- value,
624
- isArray: false,
625
- state: this.state,
626
- }),
627
- }), options);
628
- }
629
- get(key) {
630
- return isKey(key)
631
- ? getReactiveValueInProxy(this, this.#keyed, key, false).get()
632
- : getValue(this.state);
633
- }
634
- peek(key) {
635
- return isKey(key) ? this.state.value[key] : { ...this.state.value };
636
- }
637
- set(first, second) {
638
- if (isKey(first)) {
639
- this.state.value[first] = second;
640
- }
641
- else if (first == null || isPlainObject(first)) {
642
- setProxyValue(this.state.value, first ?? {});
643
- }
644
- }
645
- subscribe(first, second) {
646
- if (isKey(first) && typeof second === 'function') {
647
- return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
648
- }
649
- return typeof first === 'function' ? subscribe(this.state, first) : noop;
650
- }
651
- /**
652
- * Update the value _(based on the current value)_
653
- * @param callback Callback to update the value
654
- */
655
- update(callback) {
656
- const updated = callback({ ...this.state.value });
657
- if (updated == null || isPlainObject(updated)) {
658
- setProxyValue(this.state.value, updated ?? {});
659
- }
660
- }
661
- }
532
+ var Store = class extends Reactive {
533
+ #keyed = /* @__PURE__ */ new Map();
534
+ constructor(value, options) {
535
+ super(NAME_STORE, new Proxy(value, { set: (target, property, value$1) => setValueInProxy({
536
+ target,
537
+ property,
538
+ value: value$1,
539
+ isArray: false,
540
+ state: this.state
541
+ }) }), options);
542
+ }
543
+ get(key) {
544
+ return isKey(key) ? getReactiveValueInProxy(this, this.#keyed, key, false).get() : getValue(this.state);
545
+ }
546
+ /**
547
+ * Notify dependents of changes
548
+ *
549
+ * _This bypasses equality checks and will immediately notify dependents.
550
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
551
+ */
552
+ notify() {
553
+ emityProxyValues(this.state, this.#keyed);
554
+ }
555
+ peek(key) {
556
+ return isKey(key) ? this.state.value[key] : { ...this.state.value };
557
+ }
558
+ set(first, second) {
559
+ if (isKey(first)) this.state.value[first] = second;
560
+ else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
561
+ }
562
+ subscribe(first, second) {
563
+ if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
564
+ return typeof first === "function" ? subscribe(this.state, first) : noop;
565
+ }
566
+ /**
567
+ * Update the value _(based on the current value)_
568
+ * @param callback Callback to update the value
569
+ */
570
+ update(callback) {
571
+ const updated = callback({ ...this.state.value });
572
+ if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
573
+ }
574
+ };
662
575
  /**
663
- * Create a reactive store
664
- * @param value Initial object value
665
- * @param options Optional reactivity options
666
- * @returns Reactive store
667
- */
576
+ * Create a reactive store
577
+ * @param value Initial object value
578
+ * @param options Reactivity options
579
+ * @returns Reactive store
580
+ */
668
581
  function store(value, options) {
669
- return new Store((isPlainObject(value) ? value : {}), options);
582
+ return new Store(isPlainObject(value) ? value : {}, options);
670
583
  }
671
584
 
672
- export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
585
+ export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };