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