@oscarpalmer/mora 0.27.0 → 0.29.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.
@@ -1,2 +1,20 @@
1
- import { a as BATCH, c as NAME_ALL, d as NAME_EFFECT, f as NAME_MORA, h as PROPERTY_LENGTH, i as ARRAY_THRESHOLD, l as NAME_ARRAY, m as NAME_STORE, n as ARRAY_OFFSET, o as METHODS_AFFECTING_LENGTH, p as NAME_SIGNAL, r as ARRAY_PEEK, s as METHODS_UPDATE, t as ACTIVE, u as NAME_COMPUTED } from "./constants-Cy6_M9Vk.mjs";
1
+ import { Active, Batch } from "./models.mjs";
2
+
3
+ //#region src/constants.d.ts
4
+ declare const ACTIVE: Active;
5
+ declare const ARRAY_THRESHOLD = 100;
6
+ declare const ARRAY_OFFSET = 25;
7
+ declare const ARRAY_PEEK = 10;
8
+ declare const BATCH: Batch;
9
+ declare const METHODS_AFFECTING_LENGTH: Set<string>;
10
+ declare const METHODS_UPDATE: Set<string>;
11
+ declare const NAME_ARRAY = "array";
12
+ declare const NAME_COMPUTED = "computed";
13
+ declare const NAME_EFFECT = "effect";
14
+ declare const NAME_MORA = "$mora";
15
+ declare const NAME_SIGNAL = "signal";
16
+ declare const NAME_STORE = "store";
17
+ declare const NAME_ALL: Set<string>;
18
+ declare const PROPERTY_LENGTH = "length";
19
+ //#endregion
2
20
  export { ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH, METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_SIGNAL, NAME_STORE, PROPERTY_LENGTH };
package/dist/effect.d.mts CHANGED
@@ -1,2 +1,27 @@
1
- import { n as effect, r as runEffect, t as Effect } from "./effect-BkupB1p9.mjs";
1
+ import { GenericCallback } from "@oscarpalmer/atoms/models";
2
+
3
+ //#region src/effect.d.ts
4
+ declare class Effect {
5
+ /**
6
+ * Internal name of the effect
7
+ *
8
+ * @internal
9
+ */
10
+ private readonly $mora;
11
+ /**
12
+ * Internal state of the effect
13
+ *
14
+ * @internal
15
+ */
16
+ private readonly state;
17
+ constructor(callback: GenericCallback);
18
+ }
19
+ declare function runEffect(effect: Effect): void;
20
+ /**
21
+ * Create an effect
22
+ * @param callback Callback for handling signal effects
23
+ * @returns Effect
24
+ */
25
+ declare function effect(callback: GenericCallback): Effect;
26
+ //#endregion
2
27
  export { Effect, effect, runEffect };
@@ -1,5 +1,7 @@
1
- import { t as Effect } from "../effect-BkupB1p9.mjs";
2
- import { d as Signal, h as Reactive, p as Computed } from "../models-QwNga87R.mjs";
1
+ import { Effect } from "../effect.mjs";
2
+ import { Reactive } from "../value/reactive.mjs";
3
+ import { Computed } from "../value/computed.mjs";
4
+ import { Signal } from "../value/signal.mjs";
3
5
  import { ReactiveArray } from "../value/array.mjs";
4
6
  import { Store } from "../value/store.mjs";
5
7
  import { PlainObject } from "@oscarpalmer/atoms/models";
@@ -1,4 +1,5 @@
1
- import { c as ReactiveState, l as SetValueInProxyParameters, p as Computed } from "../models-QwNga87R.mjs";
1
+ import { Computed } from "../value/computed.mjs";
2
+ import { ReactiveState, SetValueInProxyParameters } from "../models.mjs";
2
3
  import { ReactiveArray } from "../value/array.mjs";
3
4
  import { Store } from "../value/store.mjs";
4
5
  import { ArrayOrPlainObject, Key, PlainObject } from "@oscarpalmer/atoms/models";
@@ -8,7 +9,7 @@ declare function emityProxyValues<Value>(state: ReactiveState<Value, Value>, map
8
9
  declare function emityProxyValues<Value>(state: ReactiveState<Value[], Value>, mapped: Map<Key, Computed<unknown>>): void;
9
10
  declare function getReactiveValueInProxy<Value>(array: ReactiveArray<Value>, mapped: Map<Key, Computed<unknown>>, index: number, isArray: true): Computed<unknown>;
10
11
  declare function getReactiveValueInProxy<Value extends PlainObject>(store: Store<Value>, mapped: Map<Key, Computed<unknown>>, key: Key, isArray: false): Computed<unknown>;
11
- declare function setProxyValue(proxy: ArrayOrPlainObject, value: ArrayOrPlainObject): void;
12
+ declare function setProxyValue<Value, Item = Value>(array: boolean, state: ReactiveState<Value, Item>, isObject: (value: unknown) => value is Value | undefined, isProperty: (value: unknown) => boolean, setObject: (state: ReactiveState<Value, Item>, value: Value | undefined) => void, setProperty: (state: ReactiveState<Value, Item>, property: unknown, value: Item) => void, first?: unknown, second?: unknown): void;
12
13
  declare function setValueInProxy<Value extends ArrayOrPlainObject, Equal>(parameters: SetValueInProxyParameters<Value, Equal>): boolean;
13
14
  //#endregion
14
15
  export { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy };
@@ -1,5 +1,4 @@
1
1
  import "../constants.mjs";
2
- import { startBatch, stopBatch } from "../batch.mjs";
3
2
  import { computed } from "../value/computed.mjs";
4
3
  import { emitValue } from "./value.mjs";
5
4
  //#region src/helpers/proxy.ts
@@ -17,21 +16,44 @@ function getReactiveValueInProxy(reactive, mapped, key, isArray) {
17
16
  }
18
17
  return item;
19
18
  }
20
- function setProxyValue(proxy, value) {
21
- startBatch();
22
- const proxyKeys = Object.keys(proxy);
23
- const valueKeys = Object.keys(value);
24
- let { length } = proxyKeys;
25
- for (let index = 0; index < length; index += 1) {
26
- const key = proxyKeys[index];
27
- proxy[key] = valueKeys.includes(key) ? value[key] : void 0;
19
+ function setProxyValue(array, state, isObject, isProperty, setObject, setProperty, first, second) {
20
+ if (array && first === "length") {
21
+ state.value.length = second;
22
+ return;
28
23
  }
29
- length = valueKeys.length;
30
- for (let index = 0; index < length; index += 1) {
31
- const key = valueKeys[index];
32
- if (!proxyKeys.includes(key)) proxy[key] = value[key];
24
+ if (isObject(first)) {
25
+ setObject(state, first);
26
+ return;
33
27
  }
34
- stopBatch();
28
+ const property = isProperty(first);
29
+ if (array && property && Number.isNaN(first)) return;
30
+ let actual = property ? second : first;
31
+ if (typeof actual === "function") try {
32
+ actual = actual();
33
+ } catch {
34
+ return;
35
+ }
36
+ if (actual instanceof Promise) {
37
+ if (property) {
38
+ state.promises ??= /* @__PURE__ */ new Map();
39
+ state.promises.set(first, actual);
40
+ } else state.promise = actual;
41
+ actual.then((value) => {
42
+ if (property && state.promises.get(first) === actual) {
43
+ state.promises.delete(first);
44
+ setProperty(state, first, value);
45
+ return;
46
+ }
47
+ if (!property && isObject(value) && state.promise === actual) {
48
+ state.promise = void 0;
49
+ setObject(state, value);
50
+ }
51
+ }).catch(() => {
52
+ if (property && state.promises.get(first) === actual) state.promises.delete(first);
53
+ else if (!property && state.promise === actual) state.promise = void 0;
54
+ });
55
+ } else if (property) setProperty(state, first, actual);
56
+ else if (isObject(actual)) setObject(state, actual);
35
57
  }
36
58
  function setValueInProxy(parameters) {
37
59
  const { isArray, length, property, state, target, value } = parameters;
@@ -1,4 +1,4 @@
1
- import { c as ReactiveState } from "../models-QwNga87R.mjs";
1
+ import { ReactiveState } from "../models.mjs";
2
2
 
3
3
  //#region src/helpers/value.d.ts
4
4
  declare function emitValue<Value>(state: ReactiveState<Value, never>): void;
@@ -1,5 +1,6 @@
1
1
  import { ACTIVE, BATCH } from "../constants.mjs";
2
2
  import { flushHandlers } from "../batch.mjs";
3
+ import { round } from "@oscarpalmer/atoms/math";
3
4
  //#region src/helpers/value.ts
4
5
  function emitValue(state) {
5
6
  for (const computed of state.computeds) computed.effect.dirty = true;
@@ -12,7 +13,7 @@ function equalArrays(state, first, second) {
12
13
  if (length !== second.length) return false;
13
14
  let offset = 0;
14
15
  if (length >= 100) {
15
- offset = Math.round(length / 10);
16
+ offset = round(length / 10);
16
17
  offset = offset > 25 ? 25 : offset;
17
18
  for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
18
19
  }
package/dist/index.d.mts CHANGED
@@ -1,6 +1,9 @@
1
1
  import { startBatch, stopBatch } from "./batch.mjs";
2
- import { n as effect, t as Effect } from "./effect-BkupB1p9.mjs";
3
- import { d as Signal, f as signal, h as Reactive, m as computed, p as Computed, u as Unsubscribe } from "./models-QwNga87R.mjs";
2
+ import { Effect, effect } from "./effect.mjs";
3
+ import { Reactive } from "./value/reactive.mjs";
4
+ import { Computed, computed } from "./value/computed.mjs";
5
+ import { Signal, signal } from "./value/signal.mjs";
6
+ import { Unsubscribe } from "./models.mjs";
4
7
  import { ReactiveArray, array } from "./value/array.mjs";
5
8
  import { Store, store } from "./value/store.mjs";
6
9
  import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
package/dist/models.d.mts CHANGED
@@ -1,2 +1,62 @@
1
- import { a as InternalComputed, c as ReactiveState, i as EffectState, l as SetValueInProxyParameters, n as Batch, o as InternalEffect, r as ComputedEffect, s as ReactiveOptions, t as Active, u as Unsubscribe } from "./models-QwNga87R.mjs";
1
+ import { Effect } from "./effect.mjs";
2
+ import { Subscription } from "./subscription.mjs";
3
+ import { Computed } from "./value/computed.mjs";
4
+ import { Signal } from "./value/signal.mjs";
5
+ import { GenericCallback, Key } from "@oscarpalmer/atoms/models";
6
+
7
+ //#region src/models.d.ts
8
+ type Active = {
9
+ computed?: Computed<unknown>;
10
+ effect?: Effect;
11
+ };
12
+ type Batch = {
13
+ depth: number;
14
+ handlers: Set<Effect | Subscription>;
15
+ };
16
+ type ComputedEffect = {
17
+ dirty: boolean;
18
+ instance: Effect;
19
+ };
20
+ type EffectState = {
21
+ callback: GenericCallback;
22
+ };
23
+ type InternalComputed = {
24
+ readonly effect: ComputedEffect;
25
+ readonly state: ReactiveState<unknown, unknown>;
26
+ };
27
+ type InternalEffect = {
28
+ state: EffectState;
29
+ };
30
+ type ReactiveOptions<Value> = {
31
+ /**
32
+ * Method for comparing values for equality
33
+ * @param first First value
34
+ * @param second Second value
35
+ * @returns Are the values equal?
36
+ * @default Object.is
37
+ */
38
+ equal?: (first: Value, second: Value) => boolean;
39
+ };
40
+ type ReactiveState<Value, Equal> = {
41
+ computeds: Set<Computed<unknown>>;
42
+ effects: Set<Effect>;
43
+ equal: (first: Equal, second: Equal) => boolean;
44
+ promise?: Promise<Value>;
45
+ promises?: Map<Key, Promise<never>>;
46
+ subscriptions: Map<GenericCallback, Subscription>;
47
+ value: Value;
48
+ };
49
+ type SetValueInProxyParameters<Value, Equal> = {
50
+ target: Value;
51
+ property: PropertyKey;
52
+ value: unknown;
53
+ state: ReactiveState<Value, Equal>;
54
+ isArray: boolean;
55
+ length?: Signal<number>;
56
+ };
57
+ /**
58
+ * Unsubscribe from changes
59
+ */
60
+ type Unsubscribe = () => void;
61
+ //#endregion
2
62
  export { Active, Batch, ComputedEffect, EffectState, InternalComputed, InternalEffect, ReactiveOptions, ReactiveState, SetValueInProxyParameters, Unsubscribe };
@@ -156,6 +156,11 @@ function unsubscribe(state, callback) {
156
156
  //#endregion
157
157
  //#region src/value/reactive.ts
158
158
  var Reactive = class {
159
+ /**
160
+ * Internal state of the reactive value
161
+ *
162
+ * @internal
163
+ */
159
164
  state = {
160
165
  computeds: /* @__PURE__ */ new Set(),
161
166
  effects: /* @__PURE__ */ new Set(),
@@ -215,18 +220,10 @@ var Computed = class extends Reactive {
215
220
  constructor(callback, options) {
216
221
  super(NAME_COMPUTED, void 0, options);
217
222
  this.effect.instance = effect(() => {
218
- if (!this.effect.dirty) return;
219
- const previousComputed = ACTIVE.computed;
220
- ACTIVE.computed = this;
221
- const value = callback();
222
- ACTIVE.computed = previousComputed;
223
- if (!this.state.equal(this.state.value, value)) {
224
- this.state.value = value;
225
- for (const computed of this.state.computeds) computed.effect.dirty = true;
226
- for (const effect of this.state.effects) BATCH.handlers.add(effect);
227
- for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
223
+ if (this.effect.dirty) {
224
+ setValue$1(this, this.state, callback);
225
+ this.effect.dirty = false;
228
226
  }
229
- this.effect.dirty = false;
230
227
  });
231
228
  }
232
229
  /**
@@ -248,6 +245,72 @@ var Computed = class extends Reactive {
248
245
  function computed(callback, options) {
249
246
  return new Computed(callback, options);
250
247
  }
248
+ function setAndEmit$1(state, value) {
249
+ if (state.equal(state.value, value)) return;
250
+ state.value = value;
251
+ for (const computed of state.computeds) computed.effect.dirty = true;
252
+ for (const effect of state.effects) BATCH.handlers.add(effect);
253
+ for (const [, subscription] of state.subscriptions) subscription.callback(value);
254
+ flushHandlers();
255
+ }
256
+ function setValue$1(instance, state, callback) {
257
+ const previousComputed = ACTIVE.computed;
258
+ ACTIVE.computed = instance;
259
+ try {
260
+ const value = callback();
261
+ if (value instanceof Promise) {
262
+ state.promise = value;
263
+ value.then((resolvedValue) => {
264
+ if (state.promise === value) {
265
+ state.promise = void 0;
266
+ setAndEmit$1(state, resolvedValue);
267
+ }
268
+ }).catch(() => {
269
+ if (state.promise === value) state.promise = void 0;
270
+ });
271
+ } else setAndEmit$1(state, value);
272
+ } finally {
273
+ ACTIVE.computed = previousComputed;
274
+ }
275
+ }
276
+ //#endregion
277
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
278
+ /**
279
+ * Is the value a key?
280
+ * @param value Value to check
281
+ * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
282
+ */
283
+ function isKey(value) {
284
+ return typeof value === "number" || typeof value === "string";
285
+ }
286
+ /**
287
+ * Is the value a plain object?
288
+ * @param value Value to check
289
+ * @returns `true` if the value is a plain object, otherwise `false`
290
+ */
291
+ function isPlainObject(value) {
292
+ if (value === null || typeof value !== "object") return false;
293
+ if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
294
+ const prototype = Object.getPrototypeOf(value);
295
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
296
+ }
297
+ //#endregion
298
+ //#region node_modules/@oscarpalmer/atoms/dist/math.mjs
299
+ /**
300
+ * Round a number
301
+ * @param value Number to round
302
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
303
+ * @returns Rounded number, or `NaN` if the value if unable to be rounded
304
+ */
305
+ function round(value, decimals) {
306
+ return roundNumber(Math.round, value, decimals);
307
+ }
308
+ function roundNumber(callback, value, decimals) {
309
+ if (typeof value !== "number") return NaN;
310
+ if (typeof decimals !== "number" || decimals < 1) return callback(value);
311
+ const mod = 10 ** decimals;
312
+ return callback((value + Number.EPSILON) * mod) / mod;
313
+ }
251
314
  //#endregion
252
315
  //#region src/helpers/value.ts
253
316
  function emitValue(state) {
@@ -261,7 +324,7 @@ function equalArrays(state, first, second) {
261
324
  if (length !== second.length) return false;
262
325
  let offset = 0;
263
326
  if (length >= 100) {
264
- offset = Math.round(length / 10);
327
+ offset = round(length / 10);
265
328
  offset = offset > 25 ? 25 : offset;
266
329
  for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
267
330
  }
@@ -290,21 +353,44 @@ function getReactiveValueInProxy(reactive, mapped, key, isArray) {
290
353
  }
291
354
  return item;
292
355
  }
293
- function setProxyValue(proxy, value) {
294
- startBatch();
295
- const proxyKeys = Object.keys(proxy);
296
- const valueKeys = Object.keys(value);
297
- let { length } = proxyKeys;
298
- for (let index = 0; index < length; index += 1) {
299
- const key = proxyKeys[index];
300
- proxy[key] = valueKeys.includes(key) ? value[key] : void 0;
301
- }
302
- length = valueKeys.length;
303
- for (let index = 0; index < length; index += 1) {
304
- const key = valueKeys[index];
305
- if (!proxyKeys.includes(key)) proxy[key] = value[key];
306
- }
307
- stopBatch();
356
+ function setProxyValue(array, state, isObject, isProperty, setObject, setProperty, first, second) {
357
+ if (array && first === "length") {
358
+ state.value.length = second;
359
+ return;
360
+ }
361
+ if (isObject(first)) {
362
+ setObject(state, first);
363
+ return;
364
+ }
365
+ const property = isProperty(first);
366
+ if (array && property && Number.isNaN(first)) return;
367
+ let actual = property ? second : first;
368
+ if (typeof actual === "function") try {
369
+ actual = actual();
370
+ } catch {
371
+ return;
372
+ }
373
+ if (actual instanceof Promise) {
374
+ if (property) {
375
+ state.promises ??= /* @__PURE__ */ new Map();
376
+ state.promises.set(first, actual);
377
+ } else state.promise = actual;
378
+ actual.then((value) => {
379
+ if (property && state.promises.get(first) === actual) {
380
+ state.promises.delete(first);
381
+ setProperty(state, first, value);
382
+ return;
383
+ }
384
+ if (!property && isObject(value) && state.promise === actual) {
385
+ state.promise = void 0;
386
+ setObject(state, value);
387
+ }
388
+ }).catch(() => {
389
+ if (property && state.promises.get(first) === actual) state.promises.delete(first);
390
+ else if (!property && state.promise === actual) state.promise = void 0;
391
+ });
392
+ } else if (property) setProperty(state, first, actual);
393
+ else if (isObject(actual)) setObject(state, actual);
308
394
  }
309
395
  function setValueInProxy(parameters) {
310
396
  const { isArray, length, property, state, target, value } = parameters;
@@ -336,10 +422,7 @@ var Signal = class extends Reactive {
336
422
  * @param value New value
337
423
  */
338
424
  set(value) {
339
- if (!this.state.equal(this.state.value, value)) {
340
- this.state.value = value;
341
- emitValue(this.state);
342
- }
425
+ setValue(this.state, value);
343
426
  }
344
427
  /**
345
428
  * Update the value _(based on the current value)_
@@ -349,14 +432,33 @@ var Signal = class extends Reactive {
349
432
  this.set(callback(this.state.value));
350
433
  }
351
434
  };
352
- /**
353
- * Create a reactive value
354
- * @param value Initial value
355
- * @param options Reactivity options
356
- * @returns Reactive value
357
- */
435
+ function setAndEmit(state, value) {
436
+ if (!state.equal(state.value, value)) {
437
+ state.value = value;
438
+ emitValue(state);
439
+ }
440
+ }
441
+ function setValue(state, value) {
442
+ try {
443
+ let actual = value;
444
+ if (typeof value === "function") actual = value();
445
+ if (actual instanceof Promise) {
446
+ state.promise = actual;
447
+ actual.then((value) => {
448
+ if (actual === state.promise) {
449
+ state.promise = void 0;
450
+ setAndEmit(state, value);
451
+ }
452
+ }).catch(() => {
453
+ if (actual === state.promise) state.promise = void 0;
454
+ });
455
+ } else setAndEmit(state, actual);
456
+ } catch {}
457
+ }
358
458
  function signal(value, options) {
359
- return new Signal(value, options);
459
+ const instance = new Signal(void 0, options);
460
+ instance.set(value);
461
+ return instance;
360
462
  }
361
463
  //#endregion
362
464
  //#region src/value/array.ts
@@ -426,7 +528,7 @@ var ReactiveArray = class extends Reactive {
426
528
  }
427
529
  peek(value) {
428
530
  if (value === "length") return this.#size.peek();
429
- return typeof value === "number" ? this.state.value.at(value) : [...this.state.value];
531
+ return typeof value === "number" ? this.state.value.at(value) : this.state.value.slice();
430
532
  }
431
533
  /**
432
534
  * Remove and return the last item of the array
@@ -444,9 +546,7 @@ var ReactiveArray = class extends Reactive {
444
546
  return this.state.value.push(...items);
445
547
  }
446
548
  set(first, second) {
447
- if (first == null || Array.isArray(first)) this.state.value.splice(0, this.state.value.length, ...first ?? []);
448
- else if (first === "length") this.length = second;
449
- else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
549
+ setProxyValue(true, this.state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
450
550
  }
451
551
  /**
452
552
  * Remove and return the first item of the array
@@ -486,18 +586,20 @@ var ReactiveArray = class extends Reactive {
486
586
  if (updated == null || Array.isArray(updated)) this.set(updated);
487
587
  }
488
588
  };
489
- /**
490
- * Create a reactive array
491
- * @param value Initial array of items
492
- * @param options Reactivity options
493
- * @returns Reactive array
494
- */
495
589
  function array(value, options) {
496
- return new ReactiveArray(Array.isArray(value) ? value : [], options);
590
+ const instance = new ReactiveArray([], options);
591
+ instance.set(value);
592
+ return instance;
593
+ }
594
+ function isArrayIndex(value) {
595
+ return typeof value === "number";
596
+ }
597
+ function isArrayValue(value) {
598
+ return value == null || Array.isArray(value);
497
599
  }
498
600
  function updateArray(type, array, state, length) {
499
601
  const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
500
- const previousArray = affectsLength ? [] : [...array];
602
+ const previousArray = affectsLength ? [] : array.slice();
501
603
  const previousLength = array.length;
502
604
  return (...args) => {
503
605
  const result = array[type](...args);
@@ -508,30 +610,12 @@ function updateArray(type, array, state, length) {
508
610
  return result;
509
611
  };
510
612
  }
511
- function setAtIndex(array, index, value) {
512
- const actual = index < 0 ? array.length + index : index;
513
- if (actual > -1) array[actual] = value;
613
+ function setArray(state, value) {
614
+ state.value.splice(0, state.value.length, ...value ?? []);
514
615
  }
515
- //#endregion
516
- //#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
517
- /**
518
- * Is the value a key?
519
- * @param value Value to check
520
- * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
521
- */
522
- function isKey(value) {
523
- return typeof value === "number" || typeof value === "string";
524
- }
525
- /**
526
- * Is the value a plain object?
527
- * @param value Value to check
528
- * @returns `true` if the value is a plain object, otherwise `false`
529
- */
530
- function isPlainObject(value) {
531
- if (value === null || typeof value !== "object") return false;
532
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
533
- const prototype = Object.getPrototypeOf(value);
534
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
616
+ function setAtIndex(state, index, value) {
617
+ const actual = index < 0 ? state.value.length + index : index;
618
+ if (actual > -1) state.value[actual] = value;
535
619
  }
536
620
  //#endregion
537
621
  //#region src/value/store.ts
@@ -562,8 +646,7 @@ var Store = class extends Reactive {
562
646
  return isKey(key) ? this.state.value[key] : { ...this.state.value };
563
647
  }
564
648
  set(first, second) {
565
- if (isKey(first)) this.state.value[first] = second;
566
- else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
649
+ setProxyValue(false, this.state, isStoreObject, isKey, setObject, setProperty, first, second);
567
650
  }
568
651
  subscribe(first, second) {
569
652
  if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
@@ -574,18 +657,38 @@ var Store = class extends Reactive {
574
657
  * @param callback Callback to update the value
575
658
  */
576
659
  update(callback) {
577
- const updated = callback({ ...this.state.value });
578
- if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
660
+ const updated = callback(this.state.value);
661
+ if (updated == null || isPlainObject(updated)) setObject(this.state, updated);
579
662
  }
580
663
  };
581
- /**
582
- * Create a reactive store
583
- * @param value Initial object value
584
- * @param options Reactivity options
585
- * @returns Reactive store
586
- */
664
+ function isStoreObject(value) {
665
+ return value == null || isPlainObject(value);
666
+ }
667
+ function setObject(state, value) {
668
+ startBatch();
669
+ const actual = value ?? {};
670
+ const proxy = state.value;
671
+ const proxyKeys = Object.keys(proxy);
672
+ const actualKeys = Object.keys(actual);
673
+ let { length } = proxyKeys;
674
+ for (let index = 0; index < length; index += 1) {
675
+ const key = proxyKeys[index];
676
+ proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
677
+ }
678
+ length = actualKeys.length;
679
+ for (let index = 0; index < length; index += 1) {
680
+ const key = actualKeys[index];
681
+ if (!proxyKeys.includes(key)) proxy[key] = actual[key];
682
+ }
683
+ stopBatch();
684
+ }
685
+ function setProperty(state, key, value) {
686
+ state.value[key] = value;
687
+ }
587
688
  function store(value, options) {
588
- return new Store(isPlainObject(value) ? value : {}, options);
689
+ const instance = new Store({}, options);
690
+ instance.set(value);
691
+ return instance;
589
692
  }
590
693
  //#endregion
591
694
  export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
@@ -1,2 +1,15 @@
1
- import { _ as noop, g as Subscription, v as subscribe, y as unsubscribe } from "./models-QwNga87R.mjs";
1
+ import { ReactiveState, Unsubscribe } from "./models.mjs";
2
+ import { GenericCallback } from "@oscarpalmer/atoms/models";
3
+
4
+ //#region src/subscription.d.ts
5
+ declare class Subscription {
6
+ callback: GenericCallback;
7
+ state: ReactiveState<unknown, never>;
8
+ constructor(state: ReactiveState<unknown, never>, callback: GenericCallback);
9
+ destroy(): void;
10
+ }
11
+ declare function noop(): void;
12
+ declare function subscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): Unsubscribe;
13
+ declare function unsubscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): void;
14
+ //#endregion
2
15
  export { Subscription, noop, subscribe, unsubscribe };