@oscarpalmer/mora 0.36.0 → 0.37.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/helpers/proxy.d.mts +1 -1
- package/dist/helpers/proxy.mjs +14 -11
- package/dist/helpers/value.d.mts +3 -2
- package/dist/helpers/value.mjs +12 -5
- package/dist/models.d.mts +2 -1
- package/dist/mora.full.mjs +33 -22
- package/dist/value/array.mjs +2 -2
- package/dist/value/computed.d.mts +2 -2
- package/dist/value/computed.mjs +8 -7
- package/dist/value/store.mjs +2 -2
- package/package.json +1 -1
- package/src/helpers/proxy.ts +18 -17
- package/src/helpers/value.ts +25 -5
- package/src/models.ts +2 -1
- package/src/value/array.ts +2 -2
- package/src/value/computed.ts +18 -11
- package/src/value/store.ts +2 -2
package/dist/helpers/proxy.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { InternalArray, InternalComputed, InternalStore } from "../models.mjs";
|
|
2
2
|
import { Key } from "@oscarpalmer/atoms/models";
|
|
3
3
|
//#region src/helpers/proxy.d.ts
|
|
4
|
-
export declare function emitProxyValues(this: InternalArray | InternalStore): void;
|
|
5
4
|
export declare function getReactiveValueInProxy(instance: InternalArray | InternalStore, key: Key): InternalComputed;
|
|
6
5
|
export declare function getValueInProxy(this: InternalArray | InternalStore, first?: unknown): unknown;
|
|
6
|
+
export declare function notifyProxyValue(this: InternalArray | InternalStore): void;
|
|
7
7
|
export declare function peekValueInProxy(this: InternalArray | InternalStore, first?: unknown, second?: boolean): unknown;
|
|
8
8
|
export declare function setProxyValue(this: InternalArray | InternalStore, first?: unknown, second?: unknown): void;
|
|
9
9
|
export declare function setValueInProxy(instance: InternalArray | InternalStore, target: object, property: PropertyKey, value: unknown): boolean;
|
package/dist/helpers/proxy.mjs
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import { SYMBOL_STATE } from "../constants.mjs";
|
|
1
|
+
import { SYMBOL_EFFECT, SYMBOL_STATE } from "../constants.mjs";
|
|
2
2
|
import { emitValue, getSignalValue, peekSignalValue } from "./value.mjs";
|
|
3
3
|
import { startBatch, stopBatch } from "../batch.mjs";
|
|
4
4
|
import { internalComputed } from "../value/computed.mjs";
|
|
5
5
|
import { isKey, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
6
6
|
//#region src/helpers/proxy.ts
|
|
7
|
-
function emitProxyValues() {
|
|
8
|
-
const state = this[SYMBOL_STATE];
|
|
9
|
-
state.mapped ??= /* @__PURE__ */ new Map();
|
|
10
|
-
const values = [...state.mapped.values()];
|
|
11
|
-
const { length } = values;
|
|
12
|
-
for (let index = 0; index < length; index += 1) values[index][1].dirty = true;
|
|
13
|
-
emitValue(this);
|
|
14
|
-
}
|
|
15
7
|
function getReactiveValueInProxy(instance, key) {
|
|
16
8
|
const state = instance[SYMBOL_STATE];
|
|
17
9
|
state.mapped ??= /* @__PURE__ */ new Map();
|
|
@@ -21,7 +13,7 @@ function getReactiveValueInProxy(instance, key) {
|
|
|
21
13
|
item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
|
|
22
14
|
state.mapped.set(mapKey, item);
|
|
23
15
|
}
|
|
24
|
-
return item
|
|
16
|
+
return item;
|
|
25
17
|
}
|
|
26
18
|
function getValueInProxy(first) {
|
|
27
19
|
let signal;
|
|
@@ -34,6 +26,17 @@ function isProxyKey(isArray, value) {
|
|
|
34
26
|
function isProxyObject(isArray, value) {
|
|
35
27
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
36
28
|
}
|
|
29
|
+
function notifyProxyValue() {
|
|
30
|
+
const state = this[SYMBOL_STATE];
|
|
31
|
+
state.mapped ??= /* @__PURE__ */ new Map();
|
|
32
|
+
const values = [...state.mapped.values()];
|
|
33
|
+
const { length } = values;
|
|
34
|
+
for (let index = 0; index < length; index += 1) {
|
|
35
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
36
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
37
|
+
}
|
|
38
|
+
emitValue(this, true);
|
|
39
|
+
}
|
|
37
40
|
function peekValueInProxy(first, second) {
|
|
38
41
|
const state = this[SYMBOL_STATE];
|
|
39
42
|
let value;
|
|
@@ -132,4 +135,4 @@ function updateProxyValue(callback) {
|
|
|
132
135
|
setProxyValue.call(this, callback(this[SYMBOL_STATE].value));
|
|
133
136
|
}
|
|
134
137
|
//#endregion
|
|
135
|
-
export {
|
|
138
|
+
export { getReactiveValueInProxy, getValueInProxy, notifyProxyValue, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue };
|
package/dist/helpers/value.d.mts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { InternalStateful } from "../models.mjs";
|
|
2
2
|
//#region src/helpers/value.d.ts
|
|
3
|
-
|
|
3
|
+
type SetValue = (instance: InternalStateful, value: unknown, notify: boolean) => void;
|
|
4
|
+
export declare function emitValue(instance: InternalStateful, notify?: boolean): void;
|
|
4
5
|
export declare function equalArrays(first: unknown[], second: unknown[], equal?: (first: unknown, second: unknown) => boolean): boolean;
|
|
5
6
|
export declare function getFrozenValue(value: unknown): unknown;
|
|
6
7
|
export declare function getJsonValue(this: InternalStateful): unknown;
|
|
7
8
|
export declare function getSignalValue(this: InternalStateful): unknown;
|
|
8
9
|
export declare function getStringValue(this: InternalStateful, json?: boolean): string;
|
|
9
|
-
export declare function handleSignal(instance: InternalStateful, origin: unknown, setValue:
|
|
10
|
+
export declare function handleSignal(instance: InternalStateful, origin: unknown, setValue: SetValue, onAfter?: () => void, notify?: boolean): void;
|
|
10
11
|
export declare function peekSignalValue(this: InternalStateful | [InternalStateful, unknown], copy?: boolean): unknown;
|
|
11
12
|
export declare function updateSignal(instance: InternalStateful, callback: (value: unknown) => unknown, setValue: (instance: InternalStateful, value: unknown) => void): void;
|
|
12
13
|
//#endregion
|
package/dist/helpers/value.mjs
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { ACTIVE, BATCH, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_FROZEN, SYMBOL_STATE } from "../constants.mjs";
|
|
1
|
+
import { ACTIVE, BATCH, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_FROZEN, SYMBOL_EFFECT, SYMBOL_STATE } from "../constants.mjs";
|
|
2
2
|
import { flushHandlers } from "../batch.mjs";
|
|
3
3
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
4
|
//#region src/helpers/value.ts
|
|
5
|
-
function emitValue(instance) {
|
|
5
|
+
function emitValue(instance, notify) {
|
|
6
6
|
const state = instance[SYMBOL_STATE];
|
|
7
7
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
8
8
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
9
|
+
if (notify ?? false) {
|
|
10
|
+
const mapped = instance[SYMBOL_STATE].mapped;
|
|
11
|
+
for (const [, item] of mapped) {
|
|
12
|
+
const fx = item[SYMBOL_EFFECT];
|
|
13
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
9
16
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
10
17
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
11
18
|
if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
|
|
@@ -56,7 +63,7 @@ function getSignalValue() {
|
|
|
56
63
|
function getStringValue(json) {
|
|
57
64
|
return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
|
|
58
65
|
}
|
|
59
|
-
function handleSignal(instance, origin, setValue, onAfter) {
|
|
66
|
+
function handleSignal(instance, origin, setValue, onAfter, notify) {
|
|
60
67
|
const state = instance[SYMBOL_STATE];
|
|
61
68
|
try {
|
|
62
69
|
let actual = typeof origin === "function" ? origin() : origin;
|
|
@@ -65,12 +72,12 @@ function handleSignal(instance, origin, setValue, onAfter) {
|
|
|
65
72
|
actual.then((value) => {
|
|
66
73
|
if (actual === state.promise) {
|
|
67
74
|
state.promise = void 0;
|
|
68
|
-
setValue(instance, value);
|
|
75
|
+
setValue(instance, value, notify ?? false);
|
|
69
76
|
}
|
|
70
77
|
}).catch(() => {
|
|
71
78
|
if (actual === state.promise) state.promise = void 0;
|
|
72
79
|
});
|
|
73
|
-
} else setValue(instance, actual);
|
|
80
|
+
} else setValue(instance, actual, notify ?? false);
|
|
74
81
|
} catch {} finally {
|
|
75
82
|
onAfter?.();
|
|
76
83
|
}
|
package/dist/models.d.mts
CHANGED
|
@@ -15,6 +15,7 @@ export type Computed<Value> = Reactive<Value>;
|
|
|
15
15
|
export type ComputedEffect = {
|
|
16
16
|
dirty: boolean;
|
|
17
17
|
instance: EffectState;
|
|
18
|
+
notify: boolean;
|
|
18
19
|
};
|
|
19
20
|
export type Effect = {};
|
|
20
21
|
export type EffectState = {
|
|
@@ -266,7 +267,7 @@ export type ReactiveOptions<Value> = {
|
|
|
266
267
|
export type ReactiveProxyState = {
|
|
267
268
|
isArray: boolean;
|
|
268
269
|
length?: Signal<number>;
|
|
269
|
-
mapped?: Map<string,
|
|
270
|
+
mapped?: Map<string, InternalComputed>;
|
|
270
271
|
} & SignalState;
|
|
271
272
|
export type ReactiveState<Value = unknown, Item = Value> = {
|
|
272
273
|
computeds?: Set<ComputedEffect>;
|
package/dist/mora.full.mjs
CHANGED
|
@@ -109,10 +109,17 @@ function isPlainObject(value) {
|
|
|
109
109
|
}
|
|
110
110
|
//#endregion
|
|
111
111
|
//#region src/helpers/value.ts
|
|
112
|
-
function emitValue(instance) {
|
|
112
|
+
function emitValue(instance, notify) {
|
|
113
113
|
const state = instance[SYMBOL_STATE];
|
|
114
114
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
115
115
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
116
|
+
if (notify ?? false) {
|
|
117
|
+
const mapped = instance[SYMBOL_STATE].mapped;
|
|
118
|
+
for (const [, item] of mapped) {
|
|
119
|
+
const fx = item[SYMBOL_EFFECT];
|
|
120
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
116
123
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
117
124
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
118
125
|
if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
|
|
@@ -163,7 +170,7 @@ function getSignalValue() {
|
|
|
163
170
|
function getStringValue(json) {
|
|
164
171
|
return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
|
|
165
172
|
}
|
|
166
|
-
function handleSignal(instance, origin, setValue, onAfter) {
|
|
173
|
+
function handleSignal(instance, origin, setValue, onAfter, notify) {
|
|
167
174
|
const state = instance[SYMBOL_STATE];
|
|
168
175
|
try {
|
|
169
176
|
let actual = typeof origin === "function" ? origin() : origin;
|
|
@@ -172,12 +179,12 @@ function handleSignal(instance, origin, setValue, onAfter) {
|
|
|
172
179
|
actual.then((value) => {
|
|
173
180
|
if (actual === state.promise) {
|
|
174
181
|
state.promise = void 0;
|
|
175
|
-
setValue(instance, value);
|
|
182
|
+
setValue(instance, value, notify ?? false);
|
|
176
183
|
}
|
|
177
184
|
}).catch(() => {
|
|
178
185
|
if (actual === state.promise) state.promise = void 0;
|
|
179
186
|
});
|
|
180
|
-
} else setValue(instance, actual);
|
|
187
|
+
} else setValue(instance, actual, notify ?? false);
|
|
181
188
|
} catch {} finally {
|
|
182
189
|
onAfter?.();
|
|
183
190
|
}
|
|
@@ -701,17 +708,17 @@ Computed.prototype.toString = getStringValue;
|
|
|
701
708
|
* @returns Computed value
|
|
702
709
|
*/
|
|
703
710
|
function computed(callback, options) {
|
|
704
|
-
return getComputed(callback, options)
|
|
711
|
+
return getComputed(callback, options);
|
|
705
712
|
}
|
|
706
713
|
function getComputed(callback, options) {
|
|
707
714
|
if (typeof callback !== "function") throw new TypeError("Computed callback must be a function");
|
|
708
|
-
|
|
709
|
-
return [instance, instance[SYMBOL_EFFECT]];
|
|
715
|
+
return new Computed(callback, options);
|
|
710
716
|
}
|
|
711
717
|
function getComputedEffect(instance, callback) {
|
|
712
718
|
const fx = {
|
|
713
719
|
dirty: true,
|
|
714
|
-
instance: void 0
|
|
720
|
+
instance: void 0,
|
|
721
|
+
notify: false
|
|
715
722
|
};
|
|
716
723
|
fx.instance = internalEffect(() => {
|
|
717
724
|
if (fx.dirty) {
|
|
@@ -719,7 +726,8 @@ function getComputedEffect(instance, callback) {
|
|
|
719
726
|
ACTIVE.computed = fx;
|
|
720
727
|
handleSignal(instance, callback, setAndEmit$1, () => {
|
|
721
728
|
ACTIVE.computed = previousComputed;
|
|
722
|
-
|
|
729
|
+
fx.notify = false;
|
|
730
|
+
}, fx.notify);
|
|
723
731
|
fx.dirty = false;
|
|
724
732
|
}
|
|
725
733
|
});
|
|
@@ -742,9 +750,9 @@ function getComputedValue() {
|
|
|
742
750
|
function internalComputed(callback, options) {
|
|
743
751
|
return getComputed(callback, options);
|
|
744
752
|
}
|
|
745
|
-
function setAndEmit$1(instance, value) {
|
|
753
|
+
function setAndEmit$1(instance, value, notify) {
|
|
746
754
|
const state = instance[SYMBOL_STATE];
|
|
747
|
-
if ((state.equal ?? Object.is)(state.value, value)) return;
|
|
755
|
+
if (!notify && (state.equal ?? Object.is)(state.value, value)) return;
|
|
748
756
|
state.value = value;
|
|
749
757
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
750
758
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
@@ -760,14 +768,6 @@ function setAndEmit$1(instance, value) {
|
|
|
760
768
|
}
|
|
761
769
|
//#endregion
|
|
762
770
|
//#region src/helpers/proxy.ts
|
|
763
|
-
function emitProxyValues() {
|
|
764
|
-
const state = this[SYMBOL_STATE];
|
|
765
|
-
state.mapped ??= /* @__PURE__ */ new Map();
|
|
766
|
-
const values = [...state.mapped.values()];
|
|
767
|
-
const { length } = values;
|
|
768
|
-
for (let index = 0; index < length; index += 1) values[index][1].dirty = true;
|
|
769
|
-
emitValue(this);
|
|
770
|
-
}
|
|
771
771
|
function getReactiveValueInProxy(instance, key) {
|
|
772
772
|
const state = instance[SYMBOL_STATE];
|
|
773
773
|
state.mapped ??= /* @__PURE__ */ new Map();
|
|
@@ -777,7 +777,7 @@ function getReactiveValueInProxy(instance, key) {
|
|
|
777
777
|
item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
|
|
778
778
|
state.mapped.set(mapKey, item);
|
|
779
779
|
}
|
|
780
|
-
return item
|
|
780
|
+
return item;
|
|
781
781
|
}
|
|
782
782
|
function getValueInProxy(first) {
|
|
783
783
|
let signal;
|
|
@@ -790,6 +790,17 @@ function isProxyKey(isArray, value) {
|
|
|
790
790
|
function isProxyObject(isArray, value) {
|
|
791
791
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
792
792
|
}
|
|
793
|
+
function notifyProxyValue() {
|
|
794
|
+
const state = this[SYMBOL_STATE];
|
|
795
|
+
state.mapped ??= /* @__PURE__ */ new Map();
|
|
796
|
+
const values = [...state.mapped.values()];
|
|
797
|
+
const { length } = values;
|
|
798
|
+
for (let index = 0; index < length; index += 1) {
|
|
799
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
800
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
801
|
+
}
|
|
802
|
+
emitValue(this, true);
|
|
803
|
+
}
|
|
793
804
|
function peekValueInProxy(first, second) {
|
|
794
805
|
const state = this[SYMBOL_STATE];
|
|
795
806
|
let value;
|
|
@@ -977,7 +988,7 @@ ReactiveArray.prototype.clear = clearArrayValues;
|
|
|
977
988
|
ReactiveArray.prototype.filter = filterArrayValues;
|
|
978
989
|
ReactiveArray.prototype.get = getArrayValues;
|
|
979
990
|
ReactiveArray.prototype.map = mapArrayValues;
|
|
980
|
-
ReactiveArray.prototype.notify =
|
|
991
|
+
ReactiveArray.prototype.notify = notifyProxyValue;
|
|
981
992
|
ReactiveArray.prototype.peek = peekArrayValue;
|
|
982
993
|
ReactiveArray.prototype.pop = popArrayValue;
|
|
983
994
|
ReactiveArray.prototype.push = pushArrayValues;
|
|
@@ -1061,7 +1072,7 @@ function ReactiveStore(value, options) {
|
|
|
1061
1072
|
ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
|
|
1062
1073
|
ReactiveStore.prototype.asReadonly = getReadonlySignal;
|
|
1063
1074
|
ReactiveStore.prototype.get = getValueInProxy;
|
|
1064
|
-
ReactiveStore.prototype.notify =
|
|
1075
|
+
ReactiveStore.prototype.notify = notifyProxyValue;
|
|
1065
1076
|
ReactiveStore.prototype.peek = peekValueInProxy;
|
|
1066
1077
|
ReactiveStore.prototype.set = setProxyValue;
|
|
1067
1078
|
ReactiveStore.prototype.subscribe = subscribeToProxy;
|
package/dist/value/array.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { emitValue, equalArrays, getJsonValue, getStringValue } from "../helpers
|
|
|
3
3
|
import { getState } from "../helpers/misc.mjs";
|
|
4
4
|
import { subscribeToProxy } from "../helpers/subscription.mjs";
|
|
5
5
|
import { computed } from "./computed.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { getValueInProxy, notifyProxyValue, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue } from "../helpers/proxy.mjs";
|
|
7
7
|
import { getReadonlySignal } from "./readonly.mjs";
|
|
8
8
|
import { signal } from "./signal.mjs";
|
|
9
9
|
import { select } from "@oscarpalmer/atoms/array";
|
|
@@ -33,7 +33,7 @@ ReactiveArray.prototype.clear = clearArrayValues;
|
|
|
33
33
|
ReactiveArray.prototype.filter = filterArrayValues;
|
|
34
34
|
ReactiveArray.prototype.get = getArrayValues;
|
|
35
35
|
ReactiveArray.prototype.map = mapArrayValues;
|
|
36
|
-
ReactiveArray.prototype.notify =
|
|
36
|
+
ReactiveArray.prototype.notify = notifyProxyValue;
|
|
37
37
|
ReactiveArray.prototype.peek = peekArrayValue;
|
|
38
38
|
ReactiveArray.prototype.pop = popArrayValue;
|
|
39
39
|
ReactiveArray.prototype.push = pushArrayValues;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Computed,
|
|
1
|
+
import { Computed, InternalComputed, ReactiveOptions } from "../models.mjs";
|
|
2
2
|
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
3
|
//#region src/value/computed.d.ts
|
|
4
4
|
declare function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>): void;
|
|
@@ -10,5 +10,5 @@ declare function Computed(this: any, callback: GenericCallback, options?: Reacti
|
|
|
10
10
|
* @returns Computed value
|
|
11
11
|
*/
|
|
12
12
|
export declare function computed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Computed<Value>;
|
|
13
|
-
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>):
|
|
13
|
+
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>): InternalComputed;
|
|
14
14
|
//#endregion
|
package/dist/value/computed.mjs
CHANGED
|
@@ -23,17 +23,17 @@ Computed.prototype.toString = getStringValue;
|
|
|
23
23
|
* @returns Computed value
|
|
24
24
|
*/
|
|
25
25
|
function computed(callback, options) {
|
|
26
|
-
return getComputed(callback, options)
|
|
26
|
+
return getComputed(callback, options);
|
|
27
27
|
}
|
|
28
28
|
function getComputed(callback, options) {
|
|
29
29
|
if (typeof callback !== "function") throw new TypeError("Computed callback must be a function");
|
|
30
|
-
|
|
31
|
-
return [instance, instance[SYMBOL_EFFECT]];
|
|
30
|
+
return new Computed(callback, options);
|
|
32
31
|
}
|
|
33
32
|
function getComputedEffect(instance, callback) {
|
|
34
33
|
const fx = {
|
|
35
34
|
dirty: true,
|
|
36
|
-
instance: void 0
|
|
35
|
+
instance: void 0,
|
|
36
|
+
notify: false
|
|
37
37
|
};
|
|
38
38
|
fx.instance = internalEffect(() => {
|
|
39
39
|
if (fx.dirty) {
|
|
@@ -41,7 +41,8 @@ function getComputedEffect(instance, callback) {
|
|
|
41
41
|
ACTIVE.computed = fx;
|
|
42
42
|
handleSignal(instance, callback, setAndEmit, () => {
|
|
43
43
|
ACTIVE.computed = previousComputed;
|
|
44
|
-
|
|
44
|
+
fx.notify = false;
|
|
45
|
+
}, fx.notify);
|
|
45
46
|
fx.dirty = false;
|
|
46
47
|
}
|
|
47
48
|
});
|
|
@@ -64,9 +65,9 @@ function getComputedValue() {
|
|
|
64
65
|
function internalComputed(callback, options) {
|
|
65
66
|
return getComputed(callback, options);
|
|
66
67
|
}
|
|
67
|
-
function setAndEmit(instance, value) {
|
|
68
|
+
function setAndEmit(instance, value, notify) {
|
|
68
69
|
const state = instance[SYMBOL_STATE];
|
|
69
|
-
if ((state.equal ?? Object.is)(state.value, value)) return;
|
|
70
|
+
if (!notify && (state.equal ?? Object.is)(state.value, value)) return;
|
|
70
71
|
state.value = value;
|
|
71
72
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
72
73
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
package/dist/value/store.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { NAME_MORA, NAME_STORE, SYMBOL_STATE } from "../constants.mjs";
|
|
|
2
2
|
import { getJsonValue, getStringValue } from "../helpers/value.mjs";
|
|
3
3
|
import { getState } from "../helpers/misc.mjs";
|
|
4
4
|
import { subscribeToProxy } from "../helpers/subscription.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { getValueInProxy, notifyProxyValue, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue } from "../helpers/proxy.mjs";
|
|
6
6
|
import { getReadonlySignal } from "./readonly.mjs";
|
|
7
7
|
//#region src/value/store.ts
|
|
8
8
|
function ReactiveStore(value, options) {
|
|
@@ -16,7 +16,7 @@ function ReactiveStore(value, options) {
|
|
|
16
16
|
ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
|
|
17
17
|
ReactiveStore.prototype.asReadonly = getReadonlySignal;
|
|
18
18
|
ReactiveStore.prototype.get = getValueInProxy;
|
|
19
|
-
ReactiveStore.prototype.notify =
|
|
19
|
+
ReactiveStore.prototype.notify = notifyProxyValue;
|
|
20
20
|
ReactiveStore.prototype.peek = peekValueInProxy;
|
|
21
21
|
ReactiveStore.prototype.set = setProxyValue;
|
|
22
22
|
ReactiveStore.prototype.subscribe = subscribeToProxy;
|
package/package.json
CHANGED
package/src/helpers/proxy.ts
CHANGED
|
@@ -6,28 +6,13 @@ import type {
|
|
|
6
6
|
PlainObject,
|
|
7
7
|
} from '@oscarpalmer/atoms/models';
|
|
8
8
|
import {startBatch, stopBatch} from '../batch';
|
|
9
|
-
import {PROPERTY_LENGTH, SYMBOL_STATE} from '../constants';
|
|
9
|
+
import {PROPERTY_LENGTH, SYMBOL_EFFECT, SYMBOL_STATE} from '../constants';
|
|
10
10
|
import type {InternalArray, InternalComputed, InternalStore, ReactiveProxyState} from '../models';
|
|
11
11
|
import {internalComputed} from '../value/computed';
|
|
12
12
|
import {emitValue, getSignalValue, peekSignalValue} from './value';
|
|
13
13
|
|
|
14
14
|
// #region Functions
|
|
15
15
|
|
|
16
|
-
export function emitProxyValues(this: InternalArray | InternalStore): void {
|
|
17
|
-
const state = this[SYMBOL_STATE];
|
|
18
|
-
|
|
19
|
-
state.mapped ??= new Map();
|
|
20
|
-
|
|
21
|
-
const values = [...state.mapped.values()];
|
|
22
|
-
const {length} = values;
|
|
23
|
-
|
|
24
|
-
for (let index = 0; index < length; index += 1) {
|
|
25
|
-
values[index][1].dirty = true;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
emitValue(this);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
16
|
export function getReactiveValueInProxy(
|
|
32
17
|
instance: InternalArray | InternalStore,
|
|
33
18
|
key: Key,
|
|
@@ -50,7 +35,7 @@ export function getReactiveValueInProxy(
|
|
|
50
35
|
state.mapped.set(mapKey, item);
|
|
51
36
|
}
|
|
52
37
|
|
|
53
|
-
return item
|
|
38
|
+
return item;
|
|
54
39
|
}
|
|
55
40
|
|
|
56
41
|
export function getValueInProxy(this: InternalArray | InternalStore, first?: unknown): unknown {
|
|
@@ -71,6 +56,22 @@ function isProxyObject(isArray: boolean, value: unknown): value is ArrayOrPlainO
|
|
|
71
56
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
72
57
|
}
|
|
73
58
|
|
|
59
|
+
export function notifyProxyValue(this: InternalArray | InternalStore): void {
|
|
60
|
+
const state = this[SYMBOL_STATE];
|
|
61
|
+
|
|
62
|
+
state.mapped ??= new Map();
|
|
63
|
+
|
|
64
|
+
const values = [...state.mapped.values()];
|
|
65
|
+
const {length} = values;
|
|
66
|
+
|
|
67
|
+
for (let index = 0; index < length; index += 1) {
|
|
68
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
69
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
emitValue(this, true);
|
|
73
|
+
}
|
|
74
|
+
|
|
74
75
|
export function peekValueInProxy(
|
|
75
76
|
this: InternalArray | InternalStore,
|
|
76
77
|
first?: unknown,
|
package/src/helpers/value.ts
CHANGED
|
@@ -9,13 +9,20 @@ import {
|
|
|
9
9
|
SUBSCRIPTION_TYPE_FROZEN,
|
|
10
10
|
SUBSCRIPTION_TYPES,
|
|
11
11
|
SUBSCRIPTION_TYPES_COPY,
|
|
12
|
+
SYMBOL_EFFECT,
|
|
12
13
|
SYMBOL_STATE,
|
|
13
14
|
} from '../constants';
|
|
14
|
-
import type {InternalStateful} from '../models';
|
|
15
|
+
import type {InternalArray, InternalComputed, InternalStateful, InternalStore} from '../models';
|
|
16
|
+
|
|
17
|
+
// #region Types
|
|
18
|
+
|
|
19
|
+
type SetValue = (instance: InternalStateful, value: unknown, notify: boolean) => void;
|
|
20
|
+
|
|
21
|
+
// #endregion
|
|
15
22
|
|
|
16
23
|
// #region Functions
|
|
17
24
|
|
|
18
|
-
export function emitValue(instance: InternalStateful): void {
|
|
25
|
+
export function emitValue(instance: InternalStateful, notify?: boolean): void {
|
|
19
26
|
const state = instance[SYMBOL_STATE];
|
|
20
27
|
|
|
21
28
|
if (state.computeds != null && state.computeds.size > 0) {
|
|
@@ -30,6 +37,18 @@ export function emitValue(instance: InternalStateful): void {
|
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
39
|
|
|
40
|
+
if (notify ?? false) {
|
|
41
|
+
const proxy = instance as InternalArray | InternalStore;
|
|
42
|
+
const state = proxy[SYMBOL_STATE];
|
|
43
|
+
const mapped = state.mapped as Map<unknown, InternalComputed>;
|
|
44
|
+
|
|
45
|
+
for (const [, item] of mapped) {
|
|
46
|
+
const fx = item[SYMBOL_EFFECT];
|
|
47
|
+
|
|
48
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
34
53
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
35
54
|
|
|
@@ -136,8 +155,9 @@ export function getStringValue(this: InternalStateful, json?: boolean): string {
|
|
|
136
155
|
export function handleSignal(
|
|
137
156
|
instance: InternalStateful,
|
|
138
157
|
origin: unknown,
|
|
139
|
-
setValue:
|
|
158
|
+
setValue: SetValue,
|
|
140
159
|
onAfter?: () => void,
|
|
160
|
+
notify?: boolean,
|
|
141
161
|
): void {
|
|
142
162
|
const state = instance[SYMBOL_STATE];
|
|
143
163
|
|
|
@@ -152,7 +172,7 @@ export function handleSignal(
|
|
|
152
172
|
if (actual === state.promise) {
|
|
153
173
|
state.promise = undefined;
|
|
154
174
|
|
|
155
|
-
setValue(instance, value);
|
|
175
|
+
setValue(instance, value, notify ?? false);
|
|
156
176
|
}
|
|
157
177
|
})
|
|
158
178
|
.catch(() => {
|
|
@@ -161,7 +181,7 @@ export function handleSignal(
|
|
|
161
181
|
}
|
|
162
182
|
});
|
|
163
183
|
} else {
|
|
164
|
-
setValue(instance, actual);
|
|
184
|
+
setValue(instance, actual, notify ?? false);
|
|
165
185
|
}
|
|
166
186
|
} catch {
|
|
167
187
|
// ?
|
package/src/models.ts
CHANGED
|
@@ -20,6 +20,7 @@ export type Computed<Value> = Reactive<Value>;
|
|
|
20
20
|
export type ComputedEffect = {
|
|
21
21
|
dirty: boolean;
|
|
22
22
|
instance: EffectState;
|
|
23
|
+
notify: boolean;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
export type Effect = {};
|
|
@@ -324,7 +325,7 @@ export type ReactiveOptions<Value> = {
|
|
|
324
325
|
export type ReactiveProxyState = {
|
|
325
326
|
isArray: boolean;
|
|
326
327
|
length?: Signal<number>;
|
|
327
|
-
mapped?: Map<string,
|
|
328
|
+
mapped?: Map<string, InternalComputed>;
|
|
328
329
|
} & SignalState;
|
|
329
330
|
|
|
330
331
|
export type ReactiveState<Value = unknown, Item = Value> = {
|
package/src/value/array.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '../constants';
|
|
11
11
|
import {getState} from '../helpers/misc';
|
|
12
12
|
import {
|
|
13
|
-
|
|
13
|
+
notifyProxyValue,
|
|
14
14
|
getValueInProxy,
|
|
15
15
|
peekValueInProxy,
|
|
16
16
|
setProxyValue,
|
|
@@ -58,7 +58,7 @@ ReactiveArray.prototype.clear = clearArrayValues;
|
|
|
58
58
|
ReactiveArray.prototype.filter = filterArrayValues;
|
|
59
59
|
ReactiveArray.prototype.get = getArrayValues;
|
|
60
60
|
ReactiveArray.prototype.map = mapArrayValues;
|
|
61
|
-
ReactiveArray.prototype.notify =
|
|
61
|
+
ReactiveArray.prototype.notify = notifyProxyValue;
|
|
62
62
|
ReactiveArray.prototype.peek = peekArrayValue;
|
|
63
63
|
ReactiveArray.prototype.pop = popArrayValue;
|
|
64
64
|
ReactiveArray.prototype.push = pushArrayValues;
|
package/src/value/computed.ts
CHANGED
|
@@ -53,21 +53,19 @@ export function computed<Value>(
|
|
|
53
53
|
callback: () => Value | Promise<Value>,
|
|
54
54
|
options?: ReactiveOptions<Value>,
|
|
55
55
|
): Computed<Value> {
|
|
56
|
-
return getComputed(callback, options)
|
|
56
|
+
return getComputed(callback, options) as Computed<Value>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function getComputed<Value>(
|
|
60
60
|
callback: GenericCallback,
|
|
61
61
|
options?: ReactiveOptions<Value>,
|
|
62
|
-
):
|
|
62
|
+
): InternalComputed {
|
|
63
63
|
if (typeof callback !== 'function') {
|
|
64
64
|
throw new TypeError('Computed callback must be a function');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// @ts-expect-error All good, no worries :-)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return [instance, instance[SYMBOL_EFFECT]];
|
|
68
|
+
return new Computed(callback, options);
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
function getComputedEffect(
|
|
@@ -77,6 +75,7 @@ function getComputedEffect(
|
|
|
77
75
|
const fx: ComputedEffect = {
|
|
78
76
|
dirty: true,
|
|
79
77
|
instance: undefined as never,
|
|
78
|
+
notify: false,
|
|
80
79
|
};
|
|
81
80
|
|
|
82
81
|
fx.instance = internalEffect(() => {
|
|
@@ -85,9 +84,17 @@ function getComputedEffect(
|
|
|
85
84
|
|
|
86
85
|
ACTIVE.computed = fx;
|
|
87
86
|
|
|
88
|
-
handleSignal(
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
handleSignal(
|
|
88
|
+
instance,
|
|
89
|
+
callback,
|
|
90
|
+
setAndEmit,
|
|
91
|
+
() => {
|
|
92
|
+
ACTIVE.computed = previousComputed;
|
|
93
|
+
|
|
94
|
+
fx.notify = false;
|
|
95
|
+
},
|
|
96
|
+
fx.notify,
|
|
97
|
+
);
|
|
91
98
|
|
|
92
99
|
fx.dirty = false;
|
|
93
100
|
}
|
|
@@ -122,14 +129,14 @@ function getComputedValue(this: InternalComputed): unknown {
|
|
|
122
129
|
export function internalComputed(
|
|
123
130
|
callback: GenericCallback,
|
|
124
131
|
options?: ReactiveOptions<unknown>,
|
|
125
|
-
):
|
|
132
|
+
): InternalComputed {
|
|
126
133
|
return getComputed(callback, options);
|
|
127
134
|
}
|
|
128
135
|
|
|
129
|
-
function setAndEmit(instance: InternalStateful, value: unknown): void {
|
|
136
|
+
function setAndEmit(instance: InternalStateful, value: unknown, notify: boolean): void {
|
|
130
137
|
const state = instance[SYMBOL_STATE];
|
|
131
138
|
|
|
132
|
-
if ((state.equal ?? Object.is)(state.value, value)) {
|
|
139
|
+
if (!notify && (state.equal ?? Object.is)(state.value, value)) {
|
|
133
140
|
return;
|
|
134
141
|
}
|
|
135
142
|
|
package/src/value/store.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
|
2
2
|
import {NAME_MORA, NAME_STORE, SYMBOL_STATE} from '../constants';
|
|
3
3
|
import {getState} from '../helpers/misc';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
notifyProxyValue,
|
|
6
6
|
getValueInProxy,
|
|
7
7
|
peekValueInProxy,
|
|
8
8
|
setProxyValue,
|
|
@@ -36,7 +36,7 @@ ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
|
|
|
36
36
|
|
|
37
37
|
ReactiveStore.prototype.asReadonly = getReadonlySignal;
|
|
38
38
|
ReactiveStore.prototype.get = getValueInProxy;
|
|
39
|
-
ReactiveStore.prototype.notify =
|
|
39
|
+
ReactiveStore.prototype.notify = notifyProxyValue;
|
|
40
40
|
ReactiveStore.prototype.peek = peekValueInProxy;
|
|
41
41
|
ReactiveStore.prototype.set = setProxyValue;
|
|
42
42
|
ReactiveStore.prototype.subscribe = subscribeToProxy;
|