@oscarpalmer/mora 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/batch.mjs +2 -2
  2. package/dist/constants.d.mts +2 -0
  3. package/dist/constants.mjs +3 -1
  4. package/dist/effect.d.mts +1 -0
  5. package/dist/effect.mjs +8 -5
  6. package/dist/helpers/is.d.mts +6 -6
  7. package/dist/helpers/misc.d.mts +4 -0
  8. package/dist/helpers/misc.mjs +9 -0
  9. package/dist/helpers/proxy.d.mts +8 -10
  10. package/dist/helpers/proxy.mjs +71 -33
  11. package/dist/helpers/subscription.d.mts +4 -4
  12. package/dist/helpers/subscription.mjs +16 -13
  13. package/dist/helpers/value.d.mts +8 -7
  14. package/dist/helpers/value.mjs +35 -22
  15. package/dist/models.d.mts +47 -24
  16. package/dist/models.mjs +1 -0
  17. package/dist/mora.full.mjs +307 -236
  18. package/dist/value/array.d.mts +1 -0
  19. package/dist/value/array.mjs +69 -61
  20. package/dist/value/computed.d.mts +3 -1
  21. package/dist/value/computed.mjs +39 -25
  22. package/dist/value/readonly.d.mts +3 -3
  23. package/dist/value/readonly.mjs +31 -24
  24. package/dist/value/signal.d.mts +1 -0
  25. package/dist/value/signal.mjs +27 -20
  26. package/dist/value/store.d.mts +1 -0
  27. package/dist/value/store.mjs +23 -41
  28. package/package.json +1 -1
  29. package/src/batch.ts +2 -2
  30. package/src/constants.ts +4 -0
  31. package/src/effect.ts +16 -11
  32. package/src/helpers/is.ts +6 -6
  33. package/src/helpers/misc.ts +15 -0
  34. package/src/helpers/proxy.ts +116 -89
  35. package/src/helpers/subscription.ts +46 -35
  36. package/src/helpers/value.ts +61 -35
  37. package/src/models.ts +54 -28
  38. package/src/value/array.ts +103 -124
  39. package/src/value/computed.ts +70 -40
  40. package/src/value/readonly.ts +54 -41
  41. package/src/value/signal.ts +46 -35
  42. package/src/value/store.ts +36 -83
  43. package/dist/value/reactive.d.mts +0 -4
  44. package/dist/value/reactive.mjs +0 -15
  45. package/src/value/reactive.ts +0 -27
@@ -34,6 +34,9 @@ const NAME_ALL = /* @__PURE__ */ new Set([
34
34
  NAME_SIGNAL,
35
35
  NAME_STORE
36
36
  ]);
37
+ const PROPERTY_LENGTH = "length";
38
+ const SYMBOL_EFFECT = Symbol("effect");
39
+ const SYMBOL_STATE = Symbol("state");
37
40
  const SUBSCRIPTION_PROPERTY$1 = {
38
41
  key: NAME_MORA,
39
42
  value: NAME_SUBSCRIPTION
@@ -50,6 +53,11 @@ const SUBSCRIPTION_TYPES = /* @__PURE__ */ new Set([
50
53
  ]);
51
54
  //#endregion
52
55
  //#region src/effect.ts
56
+ function Effect(callback) {
57
+ this[SYMBOL_STATE] = { callback };
58
+ runEffect(this[SYMBOL_STATE]);
59
+ }
60
+ Effect.prototype[NAME_MORA] = NAME_EFFECT;
53
61
  /**
54
62
  * Create an effect
55
63
  *
@@ -61,10 +69,8 @@ function effect(callback) {
61
69
  return getEffect(callback)[0];
62
70
  }
63
71
  function getEffect(callback) {
64
- const state = { callback };
65
- const instance = Object.freeze({ [NAME_MORA]: NAME_EFFECT });
66
- runEffect(state);
67
- return [instance, state];
72
+ const instance = new Effect(callback);
73
+ return [instance, instance[SYMBOL_STATE]];
68
74
  }
69
75
  function internalEffect(callback) {
70
76
  return getEffect(callback)[1];
@@ -103,13 +109,15 @@ function isPlainObject(value) {
103
109
  }
104
110
  //#endregion
105
111
  //#region src/helpers/value.ts
106
- function emitValue(state) {
107
- for (const computed of state.computeds) computed.dirty = true;
108
- for (const effect of state.effects) BATCH.handlers.set(effect, effect);
112
+ function emitValue(instance) {
113
+ const state = instance[SYMBOL_STATE];
114
+ if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
115
+ if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
109
116
  for (const type of SUBSCRIPTION_TYPES) {
110
117
  const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
111
- if (subscriptions != null) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
118
+ if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
112
119
  callback,
120
+ instance,
113
121
  state,
114
122
  frozen: type === SUBSCRIPTION_TYPE_FROZEN,
115
123
  copy: SUBSCRIPTION_TYPES_COPY.has(type)
@@ -118,16 +126,17 @@ function emitValue(state) {
118
126
  if (BATCH.depth === 0) flushHandlers();
119
127
  }
120
128
  function equalArrays(state, first, second) {
121
- let { length } = first;
129
+ const { length } = first;
122
130
  if (length !== second.length) return false;
131
+ const eq = state.equal ?? Object.is;
123
132
  let offset = 0;
124
133
  if (length >= 100) {
125
134
  offset = Math.round(length / 10);
126
135
  offset = offset > 25 ? 25 : offset;
127
- for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
136
+ for (let index = 0; index < offset; index += 1) if (!(eq(first[index], second[index]) && eq(first[length - index - 1], second[length - index - 1]))) return false;
128
137
  }
129
- length -= offset;
130
- for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
138
+ const end = length - offset;
139
+ for (let index = offset; index < end; index += 1) if (!eq(first[index], second[index])) return false;
131
140
  return true;
132
141
  }
133
142
  function getFrozenValue(value) {
@@ -136,12 +145,22 @@ function getFrozenValue(value) {
136
145
  else if (isPlainObject(frozen)) frozen = Object.freeze({ ...frozen });
137
146
  return frozen;
138
147
  }
139
- function getSimpleValue(state) {
140
- if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
141
- if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
142
- return state.value;
148
+ function getSignalValue() {
149
+ if (ACTIVE.computed != null) {
150
+ this[SYMBOL_STATE].computeds ??= /* @__PURE__ */ new Set();
151
+ this[SYMBOL_STATE].computeds.add(ACTIVE.computed);
152
+ }
153
+ if (ACTIVE.effect != null) {
154
+ this[SYMBOL_STATE].effects ??= /* @__PURE__ */ new Set();
155
+ this[SYMBOL_STATE].effects.add(ACTIVE.effect);
156
+ }
157
+ return this[SYMBOL_STATE].value;
143
158
  }
144
- function handleSimpleValue(state, origin, setValue, onAfter) {
159
+ function getStringValue(json) {
160
+ return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
161
+ }
162
+ function handleSignalValue(instance, origin, setValue, onAfter) {
163
+ const state = instance[SYMBOL_STATE];
145
164
  try {
146
165
  let actual = typeof origin === "function" ? origin() : origin;
147
166
  if (actual instanceof Promise) {
@@ -149,26 +168,26 @@ function handleSimpleValue(state, origin, setValue, onAfter) {
149
168
  actual.then((value) => {
150
169
  if (actual === state.promise) {
151
170
  state.promise = void 0;
152
- setValue(state, value);
171
+ setValue(instance, value);
153
172
  }
154
173
  }).catch(() => {
155
174
  if (actual === state.promise) state.promise = void 0;
156
175
  });
157
- } else setValue(state, actual);
176
+ } else setValue(instance, actual);
158
177
  } catch {} finally {
159
178
  onAfter?.();
160
179
  }
161
180
  }
162
- function peekSimpleValue(value, copy) {
163
- let peeked = value;
164
- if (!copy) return peeked;
181
+ function peekSignalValue(copy) {
182
+ let peeked = Array.isArray(this) ? this[1] : this[SYMBOL_STATE].value;
183
+ if (copy !== true) return peeked;
165
184
  if (Array.isArray(peeked)) peeked = peeked.slice();
166
185
  else if (isPlainObject(peeked)) peeked = { ...peeked };
167
186
  return peeked;
168
187
  }
169
- function updateSimpleValue(state, callback, setValue) {
188
+ function updateSignalValue(instance, callback, setValue) {
170
189
  if (typeof callback !== "function") throw new TypeError("Callback must be a function");
171
- handleSimpleValue(state, callback(state.value), setValue);
190
+ handleSignalValue(instance, callback(instance[SYMBOL_STATE].value), setValue);
172
191
  }
173
192
  //#endregion
174
193
  //#region src/batch.ts
@@ -183,7 +202,7 @@ function flushHandlers() {
183
202
  for (let index = 0; index < length; index += 1) {
184
203
  const [, handler] = handlers[index];
185
204
  const subscription = handler;
186
- if (typeof subscription.frozen === "boolean") subscription.callback(subscription.frozen ? getFrozenValue(subscription.state.value) : peekSimpleValue(subscription.state.value, subscription.copy));
205
+ if (typeof subscription.frozen === "boolean") subscription.callback(subscription.frozen ? getFrozenValue(subscription.state.value) : peekSignalValue.call(subscription.instance, subscription.copy));
187
206
  else runEffect(handler);
188
207
  }
189
208
  }
@@ -423,6 +442,14 @@ function filter(array, ...parameters) {
423
442
  filter.remove = exclude;
424
443
  Object.defineProperty(filter, "remove", { value: exclude });
425
444
  //#endregion
445
+ //#region src/helpers/misc.ts
446
+ function getState(value, options) {
447
+ return {
448
+ value,
449
+ equal: typeof options === "object" && typeof options?.equal === "function" ? options.equal : void 0
450
+ };
451
+ }
452
+ //#endregion
426
453
  //#region node_modules/@oscarpalmer/atoms/dist/internal/abort.mjs
427
454
  function createAborter(value, onAbort) {
428
455
  if (!(value instanceof AbortSignal)) return;
@@ -618,41 +645,42 @@ const SUBSCRIPTION_PROPERTY = "$subscriptions";
618
645
  const SUBSCRIPTION_STORE = "subscriptions";
619
646
  //#endregion
620
647
  //#region src/helpers/subscription.ts
621
- function subscribeToProxy(isArray, instance, state, mapped, first, second, third) {
622
- if (isKey(first)) return getReactiveValueInProxy(instance, mapped, first, isArray).subscribe(second, third);
623
- return subscribeToSignal(state, first, second === true);
648
+ function subscribeToProxy(first, second, third) {
649
+ if (isKey(first)) return getReactiveValueInProxy(this, first).subscribe(second, third);
650
+ return subscribeToSignal.call(this, first, second);
624
651
  }
625
- function subscribeToReactive(type, state, callback) {
626
- state.subscriptions ??= subscriptions({
652
+ function subscribeToReactive(type, subscriber) {
653
+ this[SYMBOL_STATE].subscriptions ??= subscriptions({
627
654
  keys: SUBSCRIPTION_TYPES,
628
655
  property: SUBSCRIPTION_PROPERTY$1
629
656
  });
630
- const [subscription, existing] = state.subscriptions.create({
657
+ const [subscription, existing] = this[SYMBOL_STATE].subscriptions.create({
631
658
  key: type,
632
- value: callback
659
+ value: subscriber
633
660
  });
634
- if (!existing) callback(type === "frozen" ? getFrozenValue(state.value) : peekSimpleValue(state.value, SUBSCRIPTION_TYPES_COPY.has(type)));
661
+ if (!existing) subscriber(type === "frozen" ? getFrozenValue(this[SYMBOL_STATE].value) : peekSignalValue.call(this, SUBSCRIPTION_TYPES_COPY.has(type)), subscription);
635
662
  return subscription;
636
663
  }
637
- function subscribeToSignal(state, callback, copy) {
638
- return subscribeToReactive(copy ? SUBSCRIPTION_TYPE_COPY : SUBSCRIPTION_TYPE_ORIGINAL, state, callback);
664
+ function subscribeToReadonly(subscriber) {
665
+ return subscribeToReactive.call(this, this.frozen ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_READONLY, subscriber);
639
666
  }
640
- //#endregion
641
- //#region src/value/reactive.ts
642
- function reactive(value, options) {
643
- const state = {
644
- computeds: /* @__PURE__ */ new Set(),
645
- effects: /* @__PURE__ */ new Set(),
646
- equal: typeof options === "object" && typeof options?.equal === "function" ? options.equal : Object.is,
647
- value
648
- };
649
- return [{
650
- toJSON: () => state.value,
651
- toString: () => String(state.value)
652
- }, state];
667
+ function subscribeToSignal(subscriber, copy) {
668
+ return subscribeToReactive.call(this, copy === true ? SUBSCRIPTION_TYPE_COPY : SUBSCRIPTION_TYPE_ORIGINAL, subscriber);
653
669
  }
654
670
  //#endregion
655
671
  //#region src/value/computed.ts
672
+ function Computed(callback, options) {
673
+ this[SYMBOL_STATE] = getState(void 0, options);
674
+ this[SYMBOL_EFFECT] = getComputedEffect(this, callback);
675
+ }
676
+ Computed.prototype[NAME_MORA] = NAME_COMPUTED;
677
+ Computed.prototype.get = getComputedValue;
678
+ Computed.prototype.peek = peekSignalValue;
679
+ Computed.prototype.subscribe = subscribeToSignal;
680
+ Computed.prototype.toString = getStringValue;
681
+ Computed.prototype.toJSON = function() {
682
+ return this[SYMBOL_STATE].value;
683
+ };
656
684
  /**
657
685
  * Create a computed value
658
686
  *
@@ -665,19 +693,10 @@ function computed(callback, options) {
665
693
  }
666
694
  function getComputed(callback, options) {
667
695
  if (typeof callback !== "function") throw new TypeError("Computed callback must be a function");
668
- const [rx, state] = reactive(void 0, options);
669
- let fx;
670
- const instance = {
671
- ...rx,
672
- get: () => getValue(state, fx),
673
- peek: (copy) => peekSimpleValue(state.value, copy === true),
674
- subscribe: (callback, copy) => subscribeToSignal(state, callback, copy === true)
675
- };
676
- Object.defineProperty(instance, NAME_MORA, { value: NAME_COMPUTED });
677
- fx = getComputedEffect(state, callback);
678
- return [Object.freeze(instance), fx];
696
+ const instance = new Computed(callback, options);
697
+ return [instance, instance[SYMBOL_EFFECT]];
679
698
  }
680
- function getComputedEffect(state, callback) {
699
+ function getComputedEffect(instance, callback) {
681
700
  const fx = {
682
701
  dirty: true,
683
702
  instance: void 0
@@ -686,7 +705,7 @@ function getComputedEffect(state, callback) {
686
705
  if (fx.dirty) {
687
706
  const previousComputed = ACTIVE.computed;
688
707
  ACTIVE.computed = fx;
689
- handleSimpleValue(state, callback, setAndEmit$1, () => {
708
+ handleSignalValue(instance, callback, setAndEmit$1, () => {
690
709
  ACTIVE.computed = previousComputed;
691
710
  });
692
711
  fx.dirty = false;
@@ -694,69 +713,116 @@ function getComputedEffect(state, callback) {
694
713
  });
695
714
  return fx;
696
715
  }
697
- function getValue(state, fx) {
698
- if (ACTIVE.computed != null && fx !== ACTIVE.computed) state.computeds.add(ACTIVE.computed);
699
- if (ACTIVE.effect != null && ACTIVE.effect !== fx.instance) state.effects.add(ACTIVE.effect);
716
+ function getComputedValue() {
717
+ const fx = this[SYMBOL_EFFECT];
718
+ const state = this[SYMBOL_STATE];
719
+ if (ACTIVE.computed != null && fx !== ACTIVE.computed) {
720
+ state.computeds ??= /* @__PURE__ */ new Set();
721
+ state.computeds.add(ACTIVE.computed);
722
+ }
723
+ if (ACTIVE.effect != null && ACTIVE.effect !== fx.instance) {
724
+ state.effects ??= /* @__PURE__ */ new Set();
725
+ state.effects.add(ACTIVE.effect);
726
+ }
700
727
  if (fx.dirty && BATCH.depth === 0) runEffect(fx.instance);
701
728
  return state.value;
702
729
  }
703
730
  function internalComputed(callback, options) {
704
731
  return getComputed(callback, options);
705
732
  }
706
- function setAndEmit$1(state, value) {
707
- if (state.equal(state.value, value)) return;
733
+ function setAndEmit$1(instance, value) {
734
+ const state = instance[SYMBOL_STATE];
735
+ if ((state.equal ?? Object.is)(state.value, value)) return;
708
736
  state.value = value;
709
- for (const computed of state.computeds) computed.dirty = true;
710
- for (const effect of state.effects) BATCH.handlers.set(effect, effect);
737
+ if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
738
+ if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
711
739
  for (const type of SUBSCRIPTION_TYPES) {
712
740
  if (type === "frozen") continue;
713
- const copy = SUBSCRIPTION_TYPES_COPY.has(type);
714
741
  const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
715
- if (subscriptions != null) for (const [, callback] of subscriptions) callback(peekSimpleValue(state.value, copy));
742
+ if (subscriptions != null && subscriptions.size > 0) {
743
+ const copy = SUBSCRIPTION_TYPES_COPY.has(type);
744
+ for (const [, callback] of subscriptions) callback(peekSignalValue.call(instance, copy));
745
+ }
716
746
  }
717
747
  flushHandlers();
718
748
  }
719
749
  //#endregion
720
750
  //#region src/helpers/proxy.ts
721
- function emitProxyValues(state, mapped) {
722
- const values = [...mapped.values()];
751
+ function emitProxyValues() {
752
+ const state = this[SYMBOL_STATE];
753
+ state.mapped ??= /* @__PURE__ */ new Map();
754
+ const values = [...state.mapped.values()];
723
755
  const { length } = values;
724
756
  for (let index = 0; index < length; index += 1) values[index][1].dirty = true;
725
- emitValue(state);
757
+ emitValue(this);
726
758
  }
727
- function getReactiveValueInProxy(reactive, mapped, key, isArray) {
759
+ function getReactiveValueInProxy(instance, key) {
760
+ const state = instance[SYMBOL_STATE];
761
+ state.mapped ??= /* @__PURE__ */ new Map();
728
762
  const mapKey = String(key);
729
- let item = mapped.get(mapKey);
763
+ let item = state.mapped.get(mapKey);
730
764
  if (item == null) {
731
- item = internalComputed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
732
- mapped.set(mapKey, item);
765
+ item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
766
+ state.mapped.set(mapKey, item);
733
767
  }
734
768
  return item[0];
735
769
  }
736
- function getValueInProxy(isArray, instance, state, mapped, first) {
737
- if (isArray ? typeof first === "number" : isKey(first)) return getReactiveValueInProxy(instance, mapped, first, isArray).get();
738
- return getSimpleValue(state);
770
+ function getValueInProxy(first) {
771
+ if (this[SYMBOL_STATE].isArray ? typeof first === "number" : isKey(first)) return getReactiveValueInProxy(this, first).get();
772
+ return getSignalValue.call(this);
739
773
  }
740
774
  function isProxyObject(isArray, value) {
741
775
  return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
742
776
  }
743
- function peekValueInProxy(isArray, state, first, second) {
777
+ function peekValueInProxy(first, second) {
778
+ const state = this[SYMBOL_STATE];
744
779
  let value;
745
- if (isArray ? typeof first === "number" : isKey(first)) value = isArray ? state.value.at(first) : state.value[first];
780
+ if (state.isArray ? typeof first === "number" : isKey(first)) value = state.isArray ? state.value.at(first) : state.value[first];
746
781
  else value = state.value;
747
- return peekSimpleValue(value, first === true || second === true);
782
+ return peekSignalValue.call([this, value], first === true || second === true);
783
+ }
784
+ function setProxyObject(state, value) {
785
+ if (state.isArray) {
786
+ state.value.splice(0, state.value.length, ...value ?? []);
787
+ return;
788
+ }
789
+ startBatch();
790
+ const actual = value ?? {};
791
+ const proxy = state.value;
792
+ const proxyKeys = Object.keys(proxy);
793
+ const actualKeys = Object.keys(actual);
794
+ let { length } = proxyKeys;
795
+ for (let index = 0; index < length; index += 1) {
796
+ const key = proxyKeys[index];
797
+ proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
798
+ }
799
+ length = actualKeys.length;
800
+ for (let index = 0; index < length; index += 1) {
801
+ const key = actualKeys[index];
802
+ if (!proxyKeys.includes(key)) proxy[key] = actual[key];
803
+ }
804
+ stopBatch();
805
+ }
806
+ function setProxyProperty(state, property, value) {
807
+ if (!state.isArray) {
808
+ state.value[property] = value;
809
+ return;
810
+ }
811
+ const actual = property < 0 ? state.value.length + property : property;
812
+ if (actual > -1) state.value[actual] = value;
748
813
  }
749
- function setProxyValue(isArray, state, setObject, setProperty, first, second) {
750
- if (isArray && first === "length") {
814
+ function setProxyValue(first, second) {
815
+ const state = this[SYMBOL_STATE];
816
+ if (state.isArray && first === "length") {
751
817
  state.value.length = second;
752
818
  return;
753
819
  }
754
- if (isProxyObject(isArray, first)) {
755
- setObject(state, first);
820
+ if (isProxyObject(state.isArray, first)) {
821
+ setProxyObject(state, first);
756
822
  return;
757
823
  }
758
- const property = isArray ? typeof first === "number" : isKey(first);
759
- if (isArray && property && Number.isNaN(first)) return;
824
+ const property = state.isArray ? typeof first === "number" : isKey(first);
825
+ if (state.isArray && property && Number.isNaN(first)) return;
760
826
  let actual = property ? second : first;
761
827
  if (typeof actual === "function") try {
762
828
  actual = actual();
@@ -771,208 +837,213 @@ function setProxyValue(isArray, state, setObject, setProperty, first, second) {
771
837
  actual.then((value) => {
772
838
  if (property && state.promises.get(first) === actual) {
773
839
  state.promises.delete(first);
774
- setProperty(state, first, value);
840
+ setProxyProperty(state, first, value);
775
841
  return;
776
842
  }
777
- if (!property && isProxyObject(isArray, value) && state.promise === actual) {
843
+ if (!property && isProxyObject(state.isArray, value) && state.promise === actual) {
778
844
  state.promise = void 0;
779
- setObject(state, value);
845
+ setProxyObject(state, value);
780
846
  }
781
847
  }).catch(() => {
782
848
  if (property && state.promises.get(first) === actual) state.promises.delete(first);
783
849
  else if (!property && state.promise === actual) state.promise = void 0;
784
850
  });
785
- } else if (property) setProperty(state, first, actual);
786
- else if (isProxyObject(isArray, actual)) setObject(state, actual);
851
+ } else if (property) setProxyProperty(state, first, actual);
852
+ else if (isProxyObject(state.isArray, actual)) setProxyObject(state, actual);
787
853
  }
788
- function setValueInProxy(isArray, state, target, property, value, length) {
789
- if (isArray) {
854
+ function setValueInProxy(instance, target, property, value) {
855
+ const state = instance[SYMBOL_STATE];
856
+ if (state.isArray) {
790
857
  if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
791
858
  }
792
859
  const previous = Reflect.get(target, property);
793
- if (!state.equal(previous, value)) {
860
+ if (!(state.equal ?? Object.is)(previous, value)) {
794
861
  Reflect.set(target, property, value);
795
- emitValue(state);
796
- if (isArray) length?.set(target.length);
862
+ emitValue(instance);
863
+ if (state.isArray) state.length?.set(target.length);
797
864
  }
798
865
  return true;
799
866
  }
800
- function updateProxyValue(isArray, state, setObject, setProperty, callback) {
867
+ function updateProxyValue(callback) {
801
868
  if (typeof callback !== "function") throw new TypeError("Callback must be a function");
802
- setProxyValue(isArray, state, setObject, setProperty, callback(state.value));
869
+ setProxyValue.call(this, callback(this[SYMBOL_STATE].value));
803
870
  }
804
871
  //#endregion
805
872
  //#region src/value/readonly.ts
806
- function getReadonlyInstance(state, instances, frozen) {
807
- const key = frozen ? "frozen" : "original";
808
- instances[key] ??= getReadonlySignal(state, frozen);
809
- return instances[key];
873
+ function Readonly(state, frozen) {
874
+ this[SYMBOL_STATE] = state;
875
+ Object.defineProperty(this, SUBSCRIPTION_TYPE_FROZEN, {
876
+ enumerable: true,
877
+ value: frozen
878
+ });
879
+ }
880
+ Readonly.prototype[NAME_MORA] = NAME_READONLY;
881
+ Readonly.prototype.subscribe = subscribeToReadonly;
882
+ Readonly.prototype.toString = getStringValue;
883
+ Readonly.prototype.get = function() {
884
+ return getReadonlyValue(this, false, this[SUBSCRIPTION_TYPE_FROZEN]);
885
+ };
886
+ Readonly.prototype.peek = function(copy) {
887
+ return getReadonlyValue(this, true, this[SUBSCRIPTION_TYPE_FROZEN], copy);
888
+ };
889
+ Readonly.prototype.toJSON = function() {
890
+ return this[SYMBOL_STATE].value;
891
+ };
892
+ function getReadonlyInstance(frozen) {
893
+ const key = frozen === true ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_ORIGINAL;
894
+ this[SYMBOL_STATE].readonlies ??= {};
895
+ this[SYMBOL_STATE].readonlies[key] ??= getReadonlySignal(this[SYMBOL_STATE], frozen === true);
896
+ return this[SYMBOL_STATE].readonlies[key];
810
897
  }
811
898
  function getReadonlySignal(state, frozen) {
812
- const type = frozen ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_READONLY;
813
- const instance = {
814
- get: () => getReadonlyValue(state, false, frozen),
815
- peek: (copy) => getReadonlyValue(state, true, frozen, copy),
816
- subscribe: (callback) => subscribeToReactive(type, state, callback)
817
- };
818
- Object.defineProperties(instance, {
819
- [NAME_MORA]: { value: NAME_READONLY },
820
- frozen: {
821
- enumerable: true,
822
- value: frozen
823
- }
824
- });
825
- return Object.freeze(instance);
899
+ return new Readonly(state, frozen);
826
900
  }
827
- function getReadonlyValue(state, peek, frozen, copy) {
901
+ function getReadonlyValue(instance, peek, frozen, copy) {
828
902
  let value;
829
- if (peek) value = peekSimpleValue(state.value, copy === true);
830
- else value = getSimpleValue(state);
903
+ if (peek) value = peekSignalValue.call(instance, copy === true);
904
+ else value = getSignalValue.call(instance);
831
905
  return frozen ? getFrozenValue(value) : value;
832
906
  }
833
907
  //#endregion
834
908
  //#region src/value/signal.ts
835
- function setAndEmit(state, value) {
836
- if (!state.equal(state.value, value)) {
909
+ function Signal(value, options) {
910
+ this[SYMBOL_STATE] = getState(void 0, options);
911
+ handleSignalValue(this, value, setAndEmit);
912
+ }
913
+ Signal.prototype[NAME_MORA] = NAME_SIGNAL;
914
+ Signal.prototype.asReadonly = getReadonlyInstance;
915
+ Signal.prototype.get = getSignalValue;
916
+ Signal.prototype.peek = peekSignalValue;
917
+ Signal.prototype.subscribe = subscribeToSignal;
918
+ Signal.prototype.toString = getStringValue;
919
+ Signal.prototype.set = function(value) {
920
+ return handleSignalValue(this, value, setAndEmit);
921
+ };
922
+ Signal.prototype.toJSON = function() {
923
+ return this[SYMBOL_STATE].value;
924
+ };
925
+ Signal.prototype.update = function(callback) {
926
+ return updateSignalValue(this, callback, setAndEmit);
927
+ };
928
+ function setAndEmit(instance, value) {
929
+ const state = instance[SYMBOL_STATE];
930
+ if (!(state.equal ?? Object.is)(state.value, value)) {
837
931
  state.value = value;
838
- emitValue(state);
932
+ emitValue(instance);
839
933
  }
840
934
  }
841
935
  function signal(value, options) {
842
- const [rx, state] = reactive(void 0, options);
843
- const readonlies = {};
844
- const instance = {
845
- ...rx,
846
- asReadonly: (frozen) => getReadonlyInstance(state, readonlies, frozen === true),
847
- get: () => getSimpleValue(state),
848
- peek: (copy) => peekSimpleValue(state.value, copy === true),
849
- set: (value) => handleSimpleValue(state, value, setAndEmit),
850
- subscribe: (callback, copy) => subscribeToSignal(state, callback, copy === true),
851
- update: (callback) => updateSimpleValue(state, callback, setAndEmit)
852
- };
853
- Object.defineProperty(instance, NAME_MORA, { value: NAME_SIGNAL });
854
- handleSimpleValue(state, value, setAndEmit);
855
- return Object.freeze(instance);
936
+ return new Signal(value, options);
856
937
  }
857
938
  //#endregion
858
939
  //#region src/value/array.ts
859
- function array(value, options) {
860
- const [rx, state] = reactive([], options);
861
- const isArray = true;
862
- const length = signal(0);
863
- const mapped = /* @__PURE__ */ new Map();
864
- const readonlies = {};
865
- state.value = new Proxy([], {
866
- get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, state, length) : Reflect.get(target, property),
867
- set: (target, property, value) => setValueInProxy(isArray, state, target, property, value, length)
868
- });
869
- function get(value) {
870
- return value === "length" ? length.get() : getValueInProxy(isArray, instance, state, mapped, value);
871
- }
872
- function set(first, second) {
873
- setProxyValue(true, state, setArrayValue, setAtIndex, first, second);
874
- }
875
- const instance = {
876
- ...rx,
877
- asReadonly: (frozen) => getReadonlyInstance(state, readonlies, frozen === true),
878
- at: (index) => get(index),
879
- clear: () => {
880
- state.value.length = 0;
881
- },
882
- filter: (callback) => computed(() => filter(get(), callback)),
883
- get: (value) => get(value),
884
- map: (callback) => computed(() => get().map(callback)),
885
- notify: () => emitProxyValues(state, mapped),
886
- peek: (first, second) => peekArrayValue(state, length, first, second),
887
- pop: () => state.value.pop(),
888
- push: (...items) => state.value.push(...items),
889
- select: (filter, map) => computed(() => select(get(), filter, map)),
890
- set: (first, second) => set(first, second),
891
- shift: () => state.value.shift(),
892
- splice: (from, to, ...items) => state.value.splice(from, to ?? state.value.length, ...items),
893
- subscribe: (first, second, third) => subscribeToProxy(isArray, instance, state, mapped, first, second, third),
894
- unshift: (...items) => state.value.unshift(...items),
895
- update: (callback) => updateProxyValue(true, state, setArrayValue, setAtIndex, callback)
940
+ function ReactiveArray(value, options) {
941
+ this[SYMBOL_STATE] = {
942
+ ...getState(void 0, options),
943
+ isArray: true,
944
+ length: signal(0)
896
945
  };
897
- Object.defineProperties(instance, {
898
- [NAME_MORA]: { value: NAME_ARRAY },
899
- length: {
900
- enumerable: true,
901
- get: () => length.get(),
902
- set: (value) => setArrayLength(state, value)
903
- }
946
+ this[SYMBOL_STATE].value = new Proxy([], {
947
+ get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(this, property, target) : Reflect.get(target, property),
948
+ set: (target, property, value) => setValueInProxy(this, target, property, value)
904
949
  });
905
- set(value);
906
- return Object.freeze(instance);
950
+ Object.defineProperty(this, PROPERTY_LENGTH, {
951
+ enumerable: true,
952
+ get: () => this[SYMBOL_STATE].length.get(),
953
+ set: (value) => setArrayLength(this[SYMBOL_STATE], value)
954
+ });
955
+ setProxyValue.call(this, value);
956
+ }
957
+ ReactiveArray.prototype[NAME_MORA] = NAME_ARRAY;
958
+ ReactiveArray.prototype.asReadonly = getReadonlyInstance;
959
+ ReactiveArray.prototype.at = getArrayValues;
960
+ ReactiveArray.prototype.get = getArrayValues;
961
+ ReactiveArray.prototype.notify = emitProxyValues;
962
+ ReactiveArray.prototype.peek = peekArrayValue;
963
+ ReactiveArray.prototype.set = setProxyValue;
964
+ ReactiveArray.prototype.subscribe = subscribeToProxy;
965
+ ReactiveArray.prototype.toString = getStringValue;
966
+ ReactiveArray.prototype.update = updateProxyValue;
967
+ ReactiveArray.prototype.clear = function() {
968
+ this[SYMBOL_STATE].value.length = 0;
969
+ };
970
+ ReactiveArray.prototype.filter = function(callback) {
971
+ return computed(() => filter(getArrayValues.call(this), callback));
972
+ };
973
+ ReactiveArray.prototype.map = function(callback) {
974
+ return computed(() => getArrayValues.call(this).map(callback));
975
+ };
976
+ ReactiveArray.prototype.pop = function() {
977
+ return this[SYMBOL_STATE].value.pop();
978
+ };
979
+ ReactiveArray.prototype.push = function(...items) {
980
+ return this[SYMBOL_STATE].value.push(...items);
981
+ };
982
+ ReactiveArray.prototype.select = function(filter, map) {
983
+ return computed(() => select(getArrayValues.call(this), filter, map));
984
+ };
985
+ ReactiveArray.prototype.shift = function() {
986
+ return this[SYMBOL_STATE].value.shift();
987
+ };
988
+ ReactiveArray.prototype.splice = function(from, to, ...items) {
989
+ return this[SYMBOL_STATE].value.splice(from, to ?? this[SYMBOL_STATE].value.length, ...items);
990
+ };
991
+ ReactiveArray.prototype.toJSON = function() {
992
+ return this[SYMBOL_STATE].value;
993
+ };
994
+ ReactiveArray.prototype.unshift = function(...items) {
995
+ return this[SYMBOL_STATE].value.unshift(...items);
996
+ };
997
+ function array(value, options) {
998
+ return new ReactiveArray(value, options);
907
999
  }
908
- function peekArrayValue(state, length, first, second) {
909
- return first === "length" ? length.peek() : peekValueInProxy(true, state, first, second);
1000
+ function getArrayValues(value) {
1001
+ return value === "length" ? this[SYMBOL_STATE].length.get() : getValueInProxy.call(this, value);
1002
+ }
1003
+ function peekArrayValue(first, second) {
1004
+ return first === "length" ? this[SYMBOL_STATE].length.peek() : peekValueInProxy.call(this, first, second);
910
1005
  }
911
1006
  function setArrayLength(state, value) {
912
1007
  if (typeof value === "number" && !Number.isNaN(value) && value >= 0 && value !== state.value.length) state.value.length = value;
913
1008
  }
914
- function setArrayValue(state, value) {
915
- state.value.splice(0, state.value.length, ...value ?? []);
916
- }
917
- function setAtIndex(state, index, value) {
918
- const actual = index < 0 ? state.value.length + index : index;
919
- if (actual > -1) state.value[actual] = value;
920
- }
921
- function updateArray(type, array, state, length) {
1009
+ function updateArray(instance, type, array) {
1010
+ const state = instance[SYMBOL_STATE];
922
1011
  const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
923
1012
  const previousArray = affectsLength ? [] : array.slice();
924
1013
  const previousLength = array.length;
925
1014
  return (...args) => {
926
1015
  const result = array[type](...args);
927
1016
  if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
928
- emitValue(state);
929
- length.set(array.length);
1017
+ emitValue(instance);
1018
+ state.length.set(array.length);
930
1019
  }
931
1020
  return result;
932
1021
  };
933
1022
  }
934
1023
  //#endregion
935
1024
  //#region src/value/store.ts
936
- function setPropertyValue(state, key, value) {
937
- state.value[key] = value;
938
- }
939
- function setStoreValue(state, value) {
940
- startBatch();
941
- const actual = value ?? {};
942
- const proxy = state.value;
943
- const proxyKeys = Object.keys(proxy);
944
- const actualKeys = Object.keys(actual);
945
- let { length } = proxyKeys;
946
- for (let index = 0; index < length; index += 1) {
947
- const key = proxyKeys[index];
948
- proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
949
- }
950
- length = actualKeys.length;
951
- for (let index = 0; index < length; index += 1) {
952
- const key = actualKeys[index];
953
- if (!proxyKeys.includes(key)) proxy[key] = actual[key];
954
- }
955
- stopBatch();
956
- }
957
- function store(value, options) {
958
- const [rx, state] = reactive(void 0, options);
959
- const isArray = false;
960
- const keyed = /* @__PURE__ */ new Map();
961
- const readonlies = {};
962
- state.value = new Proxy({}, { set: (target, property, value) => setValueInProxy(isArray, state, target, property, value) });
963
- const instance = {
964
- ...rx,
965
- asReadonly: (frozen) => getReadonlyInstance(state, readonlies, frozen === true),
966
- get: (value) => getValueInProxy(isArray, instance, state, keyed, value),
967
- notify: () => emitProxyValues(state, keyed),
968
- peek: (first, second) => peekValueInProxy(isArray, state, first, second),
969
- set: (first, second) => setProxyValue(isArray, state, setStoreValue, setPropertyValue, first, second),
970
- subscribe: (first, second, third) => subscribeToProxy(isArray, instance, state, keyed, first, second, third),
971
- update: (callback) => updateProxyValue(isArray, state, setStoreValue, setPropertyValue, callback)
1025
+ function ReactiveStore(value, options) {
1026
+ this[SYMBOL_STATE] = {
1027
+ ...getState(void 0, options),
1028
+ isArray: false
972
1029
  };
973
- Object.defineProperty(instance, NAME_MORA, { value: NAME_STORE });
974
- instance.set(value);
975
- return Object.freeze(instance);
1030
+ this[SYMBOL_STATE].value = new Proxy({}, { set: (target, property, value) => setValueInProxy(this, target, property, value) });
1031
+ setProxyValue.call(this, value);
1032
+ }
1033
+ ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
1034
+ ReactiveStore.prototype.asReadonly = getReadonlyInstance;
1035
+ ReactiveStore.prototype.get = getValueInProxy;
1036
+ ReactiveStore.prototype.notify = emitProxyValues;
1037
+ ReactiveStore.prototype.peek = peekValueInProxy;
1038
+ ReactiveStore.prototype.set = setProxyValue;
1039
+ ReactiveStore.prototype.subscribe = subscribeToProxy;
1040
+ ReactiveStore.prototype.toString = getStringValue;
1041
+ ReactiveStore.prototype.update = updateProxyValue;
1042
+ ReactiveStore.prototype.toJSON = function() {
1043
+ return this[SYMBOL_STATE].value;
1044
+ };
1045
+ function store(value, options) {
1046
+ return new ReactiveStore(value, options);
976
1047
  }
977
1048
  //#endregion
978
1049
  export { array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };