@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.
- package/dist/batch.mjs +2 -2
- package/dist/constants.d.mts +2 -0
- package/dist/constants.mjs +3 -1
- package/dist/effect.d.mts +1 -0
- package/dist/effect.mjs +8 -5
- package/dist/helpers/is.d.mts +6 -6
- package/dist/helpers/misc.d.mts +4 -0
- package/dist/helpers/misc.mjs +9 -0
- package/dist/helpers/proxy.d.mts +8 -10
- package/dist/helpers/proxy.mjs +71 -33
- package/dist/helpers/subscription.d.mts +4 -4
- package/dist/helpers/subscription.mjs +16 -13
- package/dist/helpers/value.d.mts +8 -7
- package/dist/helpers/value.mjs +35 -22
- package/dist/models.d.mts +47 -24
- package/dist/models.mjs +1 -0
- package/dist/mora.full.mjs +307 -236
- package/dist/value/array.d.mts +1 -0
- package/dist/value/array.mjs +69 -61
- package/dist/value/computed.d.mts +3 -1
- package/dist/value/computed.mjs +39 -25
- package/dist/value/readonly.d.mts +3 -3
- package/dist/value/readonly.mjs +31 -24
- package/dist/value/signal.d.mts +1 -0
- package/dist/value/signal.mjs +27 -20
- package/dist/value/store.d.mts +1 -0
- package/dist/value/store.mjs +23 -41
- package/package.json +1 -1
- package/src/batch.ts +2 -2
- package/src/constants.ts +4 -0
- package/src/effect.ts +16 -11
- package/src/helpers/is.ts +6 -6
- package/src/helpers/misc.ts +15 -0
- package/src/helpers/proxy.ts +116 -89
- package/src/helpers/subscription.ts +46 -35
- package/src/helpers/value.ts +61 -35
- package/src/models.ts +54 -28
- package/src/value/array.ts +103 -124
- package/src/value/computed.ts +70 -40
- package/src/value/readonly.ts +54 -41
- package/src/value/signal.ts +46 -35
- package/src/value/store.ts +36 -83
- package/dist/value/reactive.d.mts +0 -4
- package/dist/value/reactive.mjs +0 -15
- package/src/value/reactive.ts +0 -27
package/dist/mora.full.mjs
CHANGED
|
@@ -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
|
|
65
|
-
|
|
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(
|
|
107
|
-
|
|
108
|
-
for (const
|
|
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
|
-
|
|
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 (!
|
|
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
|
|
130
|
-
for (let index = offset; index <
|
|
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
|
|
140
|
-
if (ACTIVE.computed != null)
|
|
141
|
-
|
|
142
|
-
|
|
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
|
|
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(
|
|
171
|
+
setValue(instance, value);
|
|
153
172
|
}
|
|
154
173
|
}).catch(() => {
|
|
155
174
|
if (actual === state.promise) state.promise = void 0;
|
|
156
175
|
});
|
|
157
|
-
} else setValue(
|
|
176
|
+
} else setValue(instance, actual);
|
|
158
177
|
} catch {} finally {
|
|
159
178
|
onAfter?.();
|
|
160
179
|
}
|
|
161
180
|
}
|
|
162
|
-
function
|
|
163
|
-
let peeked = value;
|
|
164
|
-
if (
|
|
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
|
|
188
|
+
function updateSignalValue(instance, callback, setValue) {
|
|
170
189
|
if (typeof callback !== "function") throw new TypeError("Callback must be a function");
|
|
171
|
-
|
|
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) :
|
|
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(
|
|
622
|
-
if (isKey(first)) return getReactiveValueInProxy(
|
|
623
|
-
return subscribeToSignal(
|
|
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,
|
|
626
|
-
|
|
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] =
|
|
657
|
+
const [subscription, existing] = this[SYMBOL_STATE].subscriptions.create({
|
|
631
658
|
key: type,
|
|
632
|
-
value:
|
|
659
|
+
value: subscriber
|
|
633
660
|
});
|
|
634
|
-
if (!existing)
|
|
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
|
|
638
|
-
return subscribeToReactive(
|
|
664
|
+
function subscribeToReadonly(subscriber) {
|
|
665
|
+
return subscribeToReactive.call(this, this.frozen ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_READONLY, subscriber);
|
|
639
666
|
}
|
|
640
|
-
|
|
641
|
-
|
|
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
|
|
669
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
698
|
-
|
|
699
|
-
|
|
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(
|
|
707
|
-
|
|
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
|
|
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(
|
|
722
|
-
const
|
|
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(
|
|
757
|
+
emitValue(this);
|
|
726
758
|
}
|
|
727
|
-
function getReactiveValueInProxy(
|
|
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 ?
|
|
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(
|
|
737
|
-
if (isArray ? typeof first === "number" : isKey(first)) return getReactiveValueInProxy(
|
|
738
|
-
return
|
|
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(
|
|
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
|
|
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(
|
|
750
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
786
|
-
else if (isProxyObject(isArray, actual))
|
|
851
|
+
} else if (property) setProxyProperty(state, first, actual);
|
|
852
|
+
else if (isProxyObject(state.isArray, actual)) setProxyObject(state, actual);
|
|
787
853
|
}
|
|
788
|
-
function setValueInProxy(
|
|
789
|
-
|
|
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(
|
|
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(
|
|
867
|
+
function updateProxyValue(callback) {
|
|
801
868
|
if (typeof callback !== "function") throw new TypeError("Callback must be a function");
|
|
802
|
-
setProxyValue(
|
|
869
|
+
setProxyValue.call(this, callback(this[SYMBOL_STATE].value));
|
|
803
870
|
}
|
|
804
871
|
//#endregion
|
|
805
872
|
//#region src/value/readonly.ts
|
|
806
|
-
function
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
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
|
-
|
|
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(
|
|
901
|
+
function getReadonlyValue(instance, peek, frozen, copy) {
|
|
828
902
|
let value;
|
|
829
|
-
if (peek) value =
|
|
830
|
-
else value =
|
|
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
|
|
836
|
-
|
|
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(
|
|
932
|
+
emitValue(instance);
|
|
839
933
|
}
|
|
840
934
|
}
|
|
841
935
|
function signal(value, options) {
|
|
842
|
-
|
|
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
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
-
|
|
906
|
-
|
|
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
|
|
909
|
-
return
|
|
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
|
|
915
|
-
|
|
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(
|
|
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
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
-
|
|
974
|
-
|
|
975
|
-
|
|
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 };
|