@oscarpalmer/mora 0.36.0 → 0.38.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 +1 -0
- package/dist/constants.d.mts +4 -6
- package/dist/effect.d.mts +0 -1
- package/dist/effect.mjs +1 -0
- package/dist/helpers/proxy.d.mts +1 -1
- package/dist/helpers/proxy.mjs +15 -11
- package/dist/helpers/value.d.mts +3 -2
- package/dist/helpers/value.mjs +15 -6
- package/dist/models.d.mts +4 -4
- package/dist/mora.full.mjs +158 -95
- package/dist/value/array.d.mts +0 -1
- package/dist/value/array.mjs +3 -3
- package/dist/value/computed.d.mts +2 -3
- package/dist/value/computed.mjs +8 -7
- package/dist/value/signal.d.mts +0 -1
- package/dist/value/store.d.mts +0 -1
- package/dist/value/store.mjs +2 -2
- package/package.json +12 -8
- package/src/batch.ts +1 -0
- package/src/constants.ts +8 -7
- package/src/effect.ts +2 -1
- package/src/helpers/proxy.ts +19 -17
- package/src/helpers/value.ts +28 -6
- package/src/models.ts +4 -3
- package/src/value/array.ts +4 -4
- package/src/value/computed.ts +19 -12
- package/src/value/readonly.ts +1 -1
- package/src/value/signal.ts +1 -1
- package/src/value/store.ts +3 -3
package/dist/batch.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BATCH } from "./constants.mjs";
|
|
2
2
|
import { runEffect } from "./effect.mjs";
|
|
3
3
|
import { getFrozenValue, peekSignalValue } from "./helpers/value.mjs";
|
|
4
|
+
import "@oscarpalmer/atoms/result";
|
|
4
5
|
//#region src/batch.ts
|
|
5
6
|
function flushHandlers() {
|
|
6
7
|
if (BATCH.flushing) return;
|
package/dist/constants.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Active, Batch, SubscriptionType } from "./models.mjs";
|
|
2
|
+
import { SubscriptionProperty } from "@oscarpalmer/atoms/subscription";
|
|
2
3
|
//#region src/constants.d.ts
|
|
3
4
|
export declare const ACTIVE: Active;
|
|
4
5
|
export declare const ARRAY_THRESHOLD = 100;
|
|
@@ -17,12 +18,9 @@ export declare const NAME_STORE = "store";
|
|
|
17
18
|
export declare const NAME_SUBSCRIPTION = "subscription";
|
|
18
19
|
export declare const NAME_ALL: Set<string>;
|
|
19
20
|
export declare const PROPERTY_LENGTH = "length";
|
|
20
|
-
export declare const SYMBOL_EFFECT:
|
|
21
|
-
export declare const SYMBOL_STATE:
|
|
22
|
-
export declare const SUBSCRIPTION_PROPERTY:
|
|
23
|
-
key: string;
|
|
24
|
-
value: string;
|
|
25
|
-
};
|
|
21
|
+
export declare const SYMBOL_EFFECT: symbol;
|
|
22
|
+
export declare const SYMBOL_STATE: symbol;
|
|
23
|
+
export declare const SUBSCRIPTION_PROPERTY: SubscriptionProperty;
|
|
26
24
|
export declare const SUBSCRIPTION_TYPE_COPY: SubscriptionType;
|
|
27
25
|
export declare const SUBSCRIPTION_TYPE_FROZEN: SubscriptionType;
|
|
28
26
|
export declare const SUBSCRIPTION_TYPE_ORIGINAL: SubscriptionType;
|
package/dist/effect.d.mts
CHANGED
package/dist/effect.mjs
CHANGED
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,10 @@
|
|
|
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
|
+
import "@oscarpalmer/atoms/result";
|
|
5
6
|
import { isKey, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
6
7
|
//#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
8
|
function getReactiveValueInProxy(instance, key) {
|
|
16
9
|
const state = instance[SYMBOL_STATE];
|
|
17
10
|
state.mapped ??= /* @__PURE__ */ new Map();
|
|
@@ -21,7 +14,7 @@ function getReactiveValueInProxy(instance, key) {
|
|
|
21
14
|
item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
|
|
22
15
|
state.mapped.set(mapKey, item);
|
|
23
16
|
}
|
|
24
|
-
return item
|
|
17
|
+
return item;
|
|
25
18
|
}
|
|
26
19
|
function getValueInProxy(first) {
|
|
27
20
|
let signal;
|
|
@@ -34,6 +27,17 @@ function isProxyKey(isArray, value) {
|
|
|
34
27
|
function isProxyObject(isArray, value) {
|
|
35
28
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
36
29
|
}
|
|
30
|
+
function notifyProxyValue() {
|
|
31
|
+
const state = this[SYMBOL_STATE];
|
|
32
|
+
state.mapped ??= /* @__PURE__ */ new Map();
|
|
33
|
+
const values = [...state.mapped.values()];
|
|
34
|
+
const { length } = values;
|
|
35
|
+
for (let index = 0; index < length; index += 1) {
|
|
36
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
37
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
38
|
+
}
|
|
39
|
+
emitValue(this, true);
|
|
40
|
+
}
|
|
37
41
|
function peekValueInProxy(first, second) {
|
|
38
42
|
const state = this[SYMBOL_STATE];
|
|
39
43
|
let value;
|
|
@@ -132,4 +136,4 @@ function updateProxyValue(callback) {
|
|
|
132
136
|
setProxyValue.call(this, callback(this[SYMBOL_STATE].value));
|
|
133
137
|
}
|
|
134
138
|
//#endregion
|
|
135
|
-
export {
|
|
139
|
+
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,20 @@
|
|
|
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
|
+
import "@oscarpalmer/atoms/result";
|
|
3
4
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
5
|
+
import { round } from "@oscarpalmer/atoms/math";
|
|
4
6
|
//#region src/helpers/value.ts
|
|
5
|
-
function emitValue(instance) {
|
|
7
|
+
function emitValue(instance, notify) {
|
|
6
8
|
const state = instance[SYMBOL_STATE];
|
|
7
9
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
8
10
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
11
|
+
if (notify ?? false) {
|
|
12
|
+
const mapped = instance[SYMBOL_STATE].mapped;
|
|
13
|
+
for (const [, item] of mapped) {
|
|
14
|
+
const fx = item[SYMBOL_EFFECT];
|
|
15
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
9
18
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
10
19
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
11
20
|
if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
|
|
@@ -24,7 +33,7 @@ function equalArrays(first, second, equal) {
|
|
|
24
33
|
const eq = equal ?? Object.is;
|
|
25
34
|
let offset = 0;
|
|
26
35
|
if (length >= 100) {
|
|
27
|
-
offset =
|
|
36
|
+
offset = round(length / 10);
|
|
28
37
|
offset = offset > 25 ? 25 : offset;
|
|
29
38
|
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;
|
|
30
39
|
}
|
|
@@ -56,7 +65,7 @@ function getSignalValue() {
|
|
|
56
65
|
function getStringValue(json) {
|
|
57
66
|
return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
|
|
58
67
|
}
|
|
59
|
-
function handleSignal(instance, origin, setValue, onAfter) {
|
|
68
|
+
function handleSignal(instance, origin, setValue, onAfter, notify) {
|
|
60
69
|
const state = instance[SYMBOL_STATE];
|
|
61
70
|
try {
|
|
62
71
|
let actual = typeof origin === "function" ? origin() : origin;
|
|
@@ -65,12 +74,12 @@ function handleSignal(instance, origin, setValue, onAfter) {
|
|
|
65
74
|
actual.then((value) => {
|
|
66
75
|
if (actual === state.promise) {
|
|
67
76
|
state.promise = void 0;
|
|
68
|
-
setValue(instance, value);
|
|
77
|
+
setValue(instance, value, notify ?? false);
|
|
69
78
|
}
|
|
70
79
|
}).catch(() => {
|
|
71
80
|
if (actual === state.promise) state.promise = void 0;
|
|
72
81
|
});
|
|
73
|
-
} else setValue(instance, actual);
|
|
82
|
+
} else setValue(instance, actual, notify ?? false);
|
|
74
83
|
} catch {} finally {
|
|
75
84
|
onAfter?.();
|
|
76
85
|
}
|
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 = {
|
|
@@ -25,8 +26,7 @@ export type InternalArray = {
|
|
|
25
26
|
} & ReactiveArray<unknown>;
|
|
26
27
|
export type InternalComputed = {
|
|
27
28
|
[SYMBOL_EFFECT]: ComputedEffect;
|
|
28
|
-
|
|
29
|
-
} & Computed<unknown>;
|
|
29
|
+
} & Computed<unknown> & InternalStateful;
|
|
30
30
|
export type InternalReadonly = {
|
|
31
31
|
frozen: boolean;
|
|
32
32
|
} & InternalStateful & ReadonlySignal<unknown>;
|
|
@@ -266,7 +266,7 @@ export type ReactiveOptions<Value> = {
|
|
|
266
266
|
export type ReactiveProxyState = {
|
|
267
267
|
isArray: boolean;
|
|
268
268
|
length?: Signal<number>;
|
|
269
|
-
mapped?: Map<string,
|
|
269
|
+
mapped?: Map<string, InternalComputed>;
|
|
270
270
|
} & SignalState;
|
|
271
271
|
export type ReactiveState<Value = unknown, Item = Value> = {
|
|
272
272
|
computeds?: Set<ComputedEffect>;
|
|
@@ -446,5 +446,5 @@ export type StoredSubscription = {
|
|
|
446
446
|
state: SignalState;
|
|
447
447
|
};
|
|
448
448
|
export type Subscriber<Value> = (value: Value, subscription: Subscription) => void;
|
|
449
|
-
export type SubscriptionType =
|
|
449
|
+
export type SubscriptionType = "copy" | "frozen" | "original" | "readonly";
|
|
450
450
|
//#endregion
|
package/dist/mora.full.mjs
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
2
|
+
/**
|
|
3
|
+
* Is the value a _Key_?
|
|
4
|
+
*
|
|
5
|
+
* @param value Value to check
|
|
6
|
+
* @returns `true` if the value is a _Key_ _(`number` or `string`)_, otherwise `false`
|
|
7
|
+
*/
|
|
8
|
+
function isKey(value) {
|
|
9
|
+
return typeof value === "number" || typeof value === "string";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Is the value a plain object?
|
|
13
|
+
*
|
|
14
|
+
* @param value Value to check
|
|
15
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
16
|
+
*/
|
|
17
|
+
function isPlainObject(value) {
|
|
18
|
+
if (value === null || typeof value !== "object") return false;
|
|
19
|
+
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
20
|
+
const prototype = Object.getPrototypeOf(value);
|
|
21
|
+
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/result/misc.mjs
|
|
25
|
+
function error(value, original) {
|
|
26
|
+
return getError(value, original);
|
|
27
|
+
}
|
|
28
|
+
function getError(value, original) {
|
|
29
|
+
const errorResult = {
|
|
30
|
+
error: value,
|
|
31
|
+
ok: false
|
|
32
|
+
};
|
|
33
|
+
if (original instanceof Error) errorResult.original = original;
|
|
34
|
+
return errorResult;
|
|
35
|
+
}
|
|
36
|
+
function isError(value, extended) {
|
|
37
|
+
return isResultValue(value, false) && (extended === true ? value.original instanceof Error : true);
|
|
38
|
+
}
|
|
39
|
+
function isOk(value) {
|
|
40
|
+
return isResultValue(value, true);
|
|
41
|
+
}
|
|
42
|
+
function isResultValue(value, okValue) {
|
|
43
|
+
return isPlainObject(value) && value.ok === okValue && (okValue ? RESULT_PROPERTY_VALUE : RESULT_PROPERTY_ERROR) in value;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates an ok result
|
|
47
|
+
*
|
|
48
|
+
* @param value Value
|
|
49
|
+
* @returns Ok result
|
|
50
|
+
*/
|
|
51
|
+
function ok(value) {
|
|
52
|
+
return {
|
|
53
|
+
ok: true,
|
|
54
|
+
value
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const RESULT_PROPERTY_ERROR = "error";
|
|
58
|
+
const RESULT_PROPERTY_VALUE = "value";
|
|
59
|
+
error.is = isError;
|
|
60
|
+
ok.is = isOk;
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region node_modules/@oscarpalmer/atoms/dist/result/index.mjs
|
|
63
|
+
async function asyncAttempt(value, err) {
|
|
64
|
+
try {
|
|
65
|
+
let result;
|
|
66
|
+
if (typeof value === "function") result = value();
|
|
67
|
+
else result = value;
|
|
68
|
+
if (result instanceof Promise) result = await result;
|
|
69
|
+
return ok(result);
|
|
70
|
+
} catch (thrown) {
|
|
71
|
+
return getError(err ?? thrown, err == null ? void 0 : thrown);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function attempt(callback, err) {
|
|
75
|
+
try {
|
|
76
|
+
return ok(callback());
|
|
77
|
+
} catch (thrown) {
|
|
78
|
+
return getError(err ?? thrown, err == null ? void 0 : thrown);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
attempt.async = asyncAttempt;
|
|
82
|
+
//#endregion
|
|
1
83
|
//#region src/constants.ts
|
|
2
84
|
const ACTIVE = {};
|
|
3
85
|
const BATCH = {
|
|
@@ -84,35 +166,55 @@ function runEffect(state) {
|
|
|
84
166
|
ACTIVE.effect = previousEffect;
|
|
85
167
|
}
|
|
86
168
|
}
|
|
169
|
+
function getAbsoluteValue(condition, aggregation, value, notNumber, item) {
|
|
170
|
+
if (notNumber || condition(aggregation, value)) {
|
|
171
|
+
if (aggregation.array) {
|
|
172
|
+
aggregation.items ??= {};
|
|
173
|
+
aggregation.items[value] ??= [];
|
|
174
|
+
aggregation.items[value].push(item);
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
return aggregation.value;
|
|
179
|
+
}
|
|
180
|
+
function isMaxValue(aggregation, value) {
|
|
181
|
+
return aggregation.array ? value >= aggregation.value : value > aggregation.value;
|
|
182
|
+
}
|
|
183
|
+
function isMinValue(aggregation, value) {
|
|
184
|
+
return aggregation.array ? value <= aggregation.value : value < aggregation.value;
|
|
185
|
+
}
|
|
186
|
+
getAbsoluteValue.bind(void 0, isMaxValue), getAbsoluteValue.bind(void 0, isMinValue);
|
|
87
187
|
//#endregion
|
|
88
|
-
//#region node_modules/@oscarpalmer/atoms/dist/internal/
|
|
188
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/math/misc.mjs
|
|
89
189
|
/**
|
|
90
|
-
*
|
|
190
|
+
* Round a number
|
|
91
191
|
*
|
|
92
|
-
* @param value
|
|
93
|
-
* @
|
|
192
|
+
* @param value Number to round
|
|
193
|
+
* @param decimals Number of decimal places to round to _(defaults to `0`)_
|
|
194
|
+
* @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
|
|
94
195
|
*/
|
|
95
|
-
function
|
|
96
|
-
return
|
|
196
|
+
function round(value, decimals) {
|
|
197
|
+
return roundNumber(Math.round, value, decimals);
|
|
97
198
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
*/
|
|
104
|
-
function isPlainObject(value) {
|
|
105
|
-
if (value === null || typeof value !== "object") return false;
|
|
106
|
-
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
107
|
-
const prototype = Object.getPrototypeOf(value);
|
|
108
|
-
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
199
|
+
function roundNumber(callback, value, decimals) {
|
|
200
|
+
if (typeof value !== "number") return NaN;
|
|
201
|
+
if (typeof decimals !== "number" || decimals < 1) return callback(value);
|
|
202
|
+
const mod = 10 ** decimals;
|
|
203
|
+
return callback((value + Number.EPSILON) * mod) / mod;
|
|
109
204
|
}
|
|
110
205
|
//#endregion
|
|
111
206
|
//#region src/helpers/value.ts
|
|
112
|
-
function emitValue(instance) {
|
|
207
|
+
function emitValue(instance, notify) {
|
|
113
208
|
const state = instance[SYMBOL_STATE];
|
|
114
209
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
115
210
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
211
|
+
if (notify ?? false) {
|
|
212
|
+
const mapped = instance[SYMBOL_STATE].mapped;
|
|
213
|
+
for (const [, item] of mapped) {
|
|
214
|
+
const fx = item[SYMBOL_EFFECT];
|
|
215
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
116
218
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
117
219
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
118
220
|
if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
|
|
@@ -131,7 +233,7 @@ function equalArrays(first, second, equal) {
|
|
|
131
233
|
const eq = equal ?? Object.is;
|
|
132
234
|
let offset = 0;
|
|
133
235
|
if (length >= 100) {
|
|
134
|
-
offset =
|
|
236
|
+
offset = round(length / 10);
|
|
135
237
|
offset = offset > 25 ? 25 : offset;
|
|
136
238
|
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;
|
|
137
239
|
}
|
|
@@ -163,7 +265,7 @@ function getSignalValue() {
|
|
|
163
265
|
function getStringValue(json) {
|
|
164
266
|
return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
|
|
165
267
|
}
|
|
166
|
-
function handleSignal(instance, origin, setValue, onAfter) {
|
|
268
|
+
function handleSignal(instance, origin, setValue, onAfter, notify) {
|
|
167
269
|
const state = instance[SYMBOL_STATE];
|
|
168
270
|
try {
|
|
169
271
|
let actual = typeof origin === "function" ? origin() : origin;
|
|
@@ -172,12 +274,12 @@ function handleSignal(instance, origin, setValue, onAfter) {
|
|
|
172
274
|
actual.then((value) => {
|
|
173
275
|
if (actual === state.promise) {
|
|
174
276
|
state.promise = void 0;
|
|
175
|
-
setValue(instance, value);
|
|
277
|
+
setValue(instance, value, notify ?? false);
|
|
176
278
|
}
|
|
177
279
|
}).catch(() => {
|
|
178
280
|
if (actual === state.promise) state.promise = void 0;
|
|
179
281
|
});
|
|
180
|
-
} else setValue(instance, actual);
|
|
282
|
+
} else setValue(instance, actual, notify ?? false);
|
|
181
283
|
} catch {} finally {
|
|
182
284
|
onAfter?.();
|
|
183
285
|
}
|
|
@@ -324,29 +426,6 @@ function createFindParameters(original) {
|
|
|
324
426
|
value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
|
|
325
427
|
};
|
|
326
428
|
}
|
|
327
|
-
function findValue(type, array, parameters, reversed) {
|
|
328
|
-
const findIndex = type === FIND_VALUE_INDEX;
|
|
329
|
-
if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
|
|
330
|
-
const { bool, key, value } = createFindParameters(parameters);
|
|
331
|
-
const callbacks = getArrayCallbacks(bool, key);
|
|
332
|
-
if (callbacks?.bool == null && callbacks?.keyed == null) {
|
|
333
|
-
if (findIndex) return reversed ? array.lastIndexOf(value) : array.indexOf(value);
|
|
334
|
-
return reversed ? array.findLast((item) => Object.is(item, value)) : array.find((item) => Object.is(item, value));
|
|
335
|
-
}
|
|
336
|
-
if (callbacks.bool != null) {
|
|
337
|
-
const index = reversed ? array.findLastIndex(callbacks.bool) : array.findIndex(callbacks.bool);
|
|
338
|
-
return findIndex ? index : array[index];
|
|
339
|
-
}
|
|
340
|
-
return findValueInArray(array, callbacks.keyed, value, findIndex, reversed);
|
|
341
|
-
}
|
|
342
|
-
function findValueInArray(array, callback, value, findIndex, reversed) {
|
|
343
|
-
const { length } = array;
|
|
344
|
-
for (let index = 0; index < length; index += 1) {
|
|
345
|
-
const item = reversed ? array.at(-(index + 1)) : array[index];
|
|
346
|
-
if (Object.is(callback?.(item, index, array), value)) return findIndex ? index : item;
|
|
347
|
-
}
|
|
348
|
-
return findIndex ? -1 : void 0;
|
|
349
|
-
}
|
|
350
429
|
function findValues(type, array, parameters, mapper) {
|
|
351
430
|
const result = {
|
|
352
431
|
matched: [],
|
|
@@ -393,54 +472,34 @@ function findValues(type, array, parameters, mapper) {
|
|
|
393
472
|
}
|
|
394
473
|
return result;
|
|
395
474
|
}
|
|
396
|
-
const FIND_VALUE_INDEX = "index";
|
|
397
|
-
const FIND_VALUE_ITEM = "item";
|
|
398
475
|
const FIND_UNIQUE_THRESHOLD = 100;
|
|
399
476
|
//#endregion
|
|
400
|
-
//#region node_modules/@oscarpalmer/atoms/dist/
|
|
401
|
-
function
|
|
402
|
-
return
|
|
403
|
-
}
|
|
404
|
-
function lastIndexOf(array, ...parameters) {
|
|
405
|
-
return findValue(FIND_VALUE_INDEX, array, parameters, true);
|
|
406
|
-
}
|
|
407
|
-
indexOf.last = lastIndexOf;
|
|
408
|
-
//#endregion
|
|
409
|
-
//#region node_modules/@oscarpalmer/atoms/dist/array/find.mjs
|
|
410
|
-
function find(array, ...parameters) {
|
|
411
|
-
return findValue(FIND_VALUE_ITEM, array, parameters, false);
|
|
477
|
+
//#region node_modules/@oscarpalmer/atoms/dist/array/filter.mjs
|
|
478
|
+
function exclude(array, ...parameters) {
|
|
479
|
+
return findValues("all", array, parameters).notMatched;
|
|
412
480
|
}
|
|
413
|
-
function
|
|
414
|
-
return
|
|
481
|
+
function filter(array, ...parameters) {
|
|
482
|
+
return findValues("all", array, parameters).matched;
|
|
415
483
|
}
|
|
416
|
-
|
|
484
|
+
filter.remove = exclude;
|
|
417
485
|
//#endregion
|
|
418
486
|
//#region node_modules/@oscarpalmer/atoms/dist/array/select.mjs
|
|
419
|
-
function
|
|
487
|
+
function filterAndMap(array, ...parameters) {
|
|
488
|
+
return selectValues(array, parameters);
|
|
489
|
+
}
|
|
490
|
+
function mapAndFilter(array, ...parameters) {
|
|
420
491
|
return findValues("all", array, parameters, {
|
|
421
492
|
callback: parameters.shift(),
|
|
422
493
|
reverse: true
|
|
423
494
|
}).matched;
|
|
424
495
|
}
|
|
425
|
-
function select(array, ...parameters) {
|
|
426
|
-
return selectValues(array, parameters);
|
|
427
|
-
}
|
|
428
496
|
function selectValues(array, parameters) {
|
|
429
497
|
return findValues("all", array, parameters, {
|
|
430
498
|
callback: parameters.pop(),
|
|
431
499
|
reverse: false
|
|
432
500
|
}).matched;
|
|
433
501
|
}
|
|
434
|
-
|
|
435
|
-
//#endregion
|
|
436
|
-
//#region node_modules/@oscarpalmer/atoms/dist/array/filter.mjs
|
|
437
|
-
function exclude(array, ...parameters) {
|
|
438
|
-
return findValues("all", array, parameters).notMatched;
|
|
439
|
-
}
|
|
440
|
-
function filter(array, ...parameters) {
|
|
441
|
-
return findValues("all", array, parameters).matched;
|
|
442
|
-
}
|
|
443
|
-
filter.remove = exclude;
|
|
502
|
+
filterAndMap.reverse = mapAndFilter;
|
|
444
503
|
//#endregion
|
|
445
504
|
//#region src/helpers/misc.ts
|
|
446
505
|
function getState(value, options) {
|
|
@@ -701,17 +760,17 @@ Computed.prototype.toString = getStringValue;
|
|
|
701
760
|
* @returns Computed value
|
|
702
761
|
*/
|
|
703
762
|
function computed(callback, options) {
|
|
704
|
-
return getComputed(callback, options)
|
|
763
|
+
return getComputed(callback, options);
|
|
705
764
|
}
|
|
706
765
|
function getComputed(callback, options) {
|
|
707
766
|
if (typeof callback !== "function") throw new TypeError("Computed callback must be a function");
|
|
708
|
-
|
|
709
|
-
return [instance, instance[SYMBOL_EFFECT]];
|
|
767
|
+
return new Computed(callback, options);
|
|
710
768
|
}
|
|
711
769
|
function getComputedEffect(instance, callback) {
|
|
712
770
|
const fx = {
|
|
713
771
|
dirty: true,
|
|
714
|
-
instance: void 0
|
|
772
|
+
instance: void 0,
|
|
773
|
+
notify: false
|
|
715
774
|
};
|
|
716
775
|
fx.instance = internalEffect(() => {
|
|
717
776
|
if (fx.dirty) {
|
|
@@ -719,7 +778,8 @@ function getComputedEffect(instance, callback) {
|
|
|
719
778
|
ACTIVE.computed = fx;
|
|
720
779
|
handleSignal(instance, callback, setAndEmit$1, () => {
|
|
721
780
|
ACTIVE.computed = previousComputed;
|
|
722
|
-
|
|
781
|
+
fx.notify = false;
|
|
782
|
+
}, fx.notify);
|
|
723
783
|
fx.dirty = false;
|
|
724
784
|
}
|
|
725
785
|
});
|
|
@@ -742,9 +802,9 @@ function getComputedValue() {
|
|
|
742
802
|
function internalComputed(callback, options) {
|
|
743
803
|
return getComputed(callback, options);
|
|
744
804
|
}
|
|
745
|
-
function setAndEmit$1(instance, value) {
|
|
805
|
+
function setAndEmit$1(instance, value, notify) {
|
|
746
806
|
const state = instance[SYMBOL_STATE];
|
|
747
|
-
if ((state.equal ?? Object.is)(state.value, value)) return;
|
|
807
|
+
if (!notify && (state.equal ?? Object.is)(state.value, value)) return;
|
|
748
808
|
state.value = value;
|
|
749
809
|
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
750
810
|
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
@@ -760,14 +820,6 @@ function setAndEmit$1(instance, value) {
|
|
|
760
820
|
}
|
|
761
821
|
//#endregion
|
|
762
822
|
//#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
823
|
function getReactiveValueInProxy(instance, key) {
|
|
772
824
|
const state = instance[SYMBOL_STATE];
|
|
773
825
|
state.mapped ??= /* @__PURE__ */ new Map();
|
|
@@ -777,7 +829,7 @@ function getReactiveValueInProxy(instance, key) {
|
|
|
777
829
|
item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
|
|
778
830
|
state.mapped.set(mapKey, item);
|
|
779
831
|
}
|
|
780
|
-
return item
|
|
832
|
+
return item;
|
|
781
833
|
}
|
|
782
834
|
function getValueInProxy(first) {
|
|
783
835
|
let signal;
|
|
@@ -790,6 +842,17 @@ function isProxyKey(isArray, value) {
|
|
|
790
842
|
function isProxyObject(isArray, value) {
|
|
791
843
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
792
844
|
}
|
|
845
|
+
function notifyProxyValue() {
|
|
846
|
+
const state = this[SYMBOL_STATE];
|
|
847
|
+
state.mapped ??= /* @__PURE__ */ new Map();
|
|
848
|
+
const values = [...state.mapped.values()];
|
|
849
|
+
const { length } = values;
|
|
850
|
+
for (let index = 0; index < length; index += 1) {
|
|
851
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
852
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
853
|
+
}
|
|
854
|
+
emitValue(this, true);
|
|
855
|
+
}
|
|
793
856
|
function peekValueInProxy(first, second) {
|
|
794
857
|
const state = this[SYMBOL_STATE];
|
|
795
858
|
let value;
|
|
@@ -977,7 +1040,7 @@ ReactiveArray.prototype.clear = clearArrayValues;
|
|
|
977
1040
|
ReactiveArray.prototype.filter = filterArrayValues;
|
|
978
1041
|
ReactiveArray.prototype.get = getArrayValues;
|
|
979
1042
|
ReactiveArray.prototype.map = mapArrayValues;
|
|
980
|
-
ReactiveArray.prototype.notify =
|
|
1043
|
+
ReactiveArray.prototype.notify = notifyProxyValue;
|
|
981
1044
|
ReactiveArray.prototype.peek = peekArrayValue;
|
|
982
1045
|
ReactiveArray.prototype.pop = popArrayValue;
|
|
983
1046
|
ReactiveArray.prototype.push = pushArrayValues;
|
|
@@ -1018,7 +1081,7 @@ function pushArrayValues(...items) {
|
|
|
1018
1081
|
return this[SYMBOL_STATE].value.push(...items);
|
|
1019
1082
|
}
|
|
1020
1083
|
function selectArrayValues(filter, map) {
|
|
1021
|
-
return computed(() =>
|
|
1084
|
+
return computed(() => filterAndMap(getArrayValues.call(this), filter, map));
|
|
1022
1085
|
}
|
|
1023
1086
|
function setArrayLength(value) {
|
|
1024
1087
|
const values = this[SYMBOL_STATE].value;
|
|
@@ -1061,7 +1124,7 @@ function ReactiveStore(value, options) {
|
|
|
1061
1124
|
ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
|
|
1062
1125
|
ReactiveStore.prototype.asReadonly = getReadonlySignal;
|
|
1063
1126
|
ReactiveStore.prototype.get = getValueInProxy;
|
|
1064
|
-
ReactiveStore.prototype.notify =
|
|
1127
|
+
ReactiveStore.prototype.notify = notifyProxyValue;
|
|
1065
1128
|
ReactiveStore.prototype.peek = peekValueInProxy;
|
|
1066
1129
|
ReactiveStore.prototype.set = setProxyValue;
|
|
1067
1130
|
ReactiveStore.prototype.subscribe = subscribeToProxy;
|
package/dist/value/array.d.mts
CHANGED
package/dist/value/array.mjs
CHANGED
|
@@ -3,11 +3,11 @@ 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
|
-
import { select } from "@oscarpalmer/atoms/array";
|
|
10
9
|
import { filter } from "@oscarpalmer/atoms/array/filter";
|
|
10
|
+
import { select } from "@oscarpalmer/atoms/array/select";
|
|
11
11
|
//#region src/value/array.ts
|
|
12
12
|
function ReactiveArray(value, options) {
|
|
13
13
|
this[SYMBOL_STATE] = {
|
|
@@ -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,7 +1,6 @@
|
|
|
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
|
-
declare function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>): void;
|
|
5
4
|
/**
|
|
6
5
|
* Create a computed value
|
|
7
6
|
*
|
|
@@ -10,5 +9,5 @@ declare function Computed(this: any, callback: GenericCallback, options?: Reacti
|
|
|
10
9
|
* @returns Computed value
|
|
11
10
|
*/
|
|
12
11
|
export declare function computed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Computed<Value>;
|
|
13
|
-
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>):
|
|
12
|
+
export declare function internalComputed(callback: GenericCallback, options?: ReactiveOptions<unknown>): InternalComputed;
|
|
14
13
|
//#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/signal.d.mts
CHANGED
package/dist/value/store.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ReactiveOptions, ReactiveStore } from "../models.mjs";
|
|
2
2
|
import { PlainObject } from "@oscarpalmer/atoms/models";
|
|
3
3
|
//#region src/value/store.d.ts
|
|
4
|
-
declare function ReactiveStore(this: any, value: never, options?: ReactiveOptions<unknown>): void;
|
|
5
4
|
/**
|
|
6
5
|
* Create a reactive store from a function result
|
|
7
6
|
*
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/mora",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Signals and stuff…",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reactive",
|
|
@@ -39,17 +39,21 @@
|
|
|
39
39
|
"test:leak": "vpx vp test run --detect-async-leaks --coverage"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@oscarpalmer/atoms": "^0.
|
|
42
|
+
"@oscarpalmer/atoms": "^0.205"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@types/node": "^26.
|
|
46
|
-
"@vitest/coverage-istanbul": "
|
|
45
|
+
"@types/node": "^26.6",
|
|
46
|
+
"@vitest/coverage-istanbul": "5.0.1",
|
|
47
47
|
"jsdom": "^30.1",
|
|
48
48
|
"tsdown": "^0.23",
|
|
49
|
-
"typescript": "^
|
|
50
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@
|
|
51
|
-
"vite-plus": "
|
|
52
|
-
"vitest": "
|
|
49
|
+
"typescript": "^7",
|
|
50
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
|
|
51
|
+
"vite-plus": "1.0.0",
|
|
52
|
+
"vitest": "5.0.1"
|
|
53
|
+
},
|
|
54
|
+
"overrides": {
|
|
55
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
|
|
56
|
+
"vitest": "5.0.1"
|
|
53
57
|
},
|
|
54
58
|
"packageManager": "npm@11.19.0"
|
|
55
59
|
}
|
package/src/batch.ts
CHANGED
package/src/constants.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {SubscriptionProperty} from '@oscarpalmer/atoms/subscription';
|
|
1
2
|
import type {Active, Batch, SubscriptionType} from './models';
|
|
2
3
|
|
|
3
4
|
// #region Variables
|
|
@@ -16,14 +17,14 @@ export const BATCH: Batch = {
|
|
|
16
17
|
handlers: new Map(),
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
export const METHODS_AFFECTING_LENGTH
|
|
20
|
+
export const METHODS_AFFECTING_LENGTH: Set<string | symbol> = new Set([
|
|
20
21
|
'pop',
|
|
21
22
|
'push',
|
|
22
23
|
'shift',
|
|
23
24
|
'unshift',
|
|
24
25
|
]);
|
|
25
26
|
|
|
26
|
-
export const METHODS_UPDATE
|
|
27
|
+
export const METHODS_UPDATE: Set<string | symbol> = new Set([
|
|
27
28
|
...METHODS_AFFECTING_LENGTH,
|
|
28
29
|
'copyWithin',
|
|
29
30
|
'fill',
|
|
@@ -48,7 +49,7 @@ export const NAME_STORE = 'store';
|
|
|
48
49
|
|
|
49
50
|
export const NAME_SUBSCRIPTION = 'subscription';
|
|
50
51
|
|
|
51
|
-
export const NAME_ALL = new Set([
|
|
52
|
+
export const NAME_ALL: Set<string> = new Set([
|
|
52
53
|
NAME_ARRAY,
|
|
53
54
|
NAME_COMPUTED,
|
|
54
55
|
NAME_READONLY,
|
|
@@ -58,11 +59,11 @@ export const NAME_ALL = new Set([
|
|
|
58
59
|
|
|
59
60
|
export const PROPERTY_LENGTH = 'length';
|
|
60
61
|
|
|
61
|
-
export const SYMBOL_EFFECT = Symbol('effect');
|
|
62
|
+
export const SYMBOL_EFFECT: symbol = Symbol('effect');
|
|
62
63
|
|
|
63
|
-
export const SYMBOL_STATE = Symbol('state');
|
|
64
|
+
export const SYMBOL_STATE: symbol = Symbol('state');
|
|
64
65
|
|
|
65
|
-
export const SUBSCRIPTION_PROPERTY = {
|
|
66
|
+
export const SUBSCRIPTION_PROPERTY: SubscriptionProperty = {
|
|
66
67
|
key: NAME_MORA,
|
|
67
68
|
value: NAME_SUBSCRIPTION,
|
|
68
69
|
};
|
|
@@ -75,7 +76,7 @@ export const SUBSCRIPTION_TYPE_ORIGINAL: SubscriptionType = 'original';
|
|
|
75
76
|
|
|
76
77
|
export const SUBSCRIPTION_TYPE_READONLY: SubscriptionType = 'readonly';
|
|
77
78
|
|
|
78
|
-
export const SUBSCRIPTION_TYPES_COPY = new Set
|
|
79
|
+
export const SUBSCRIPTION_TYPES_COPY: Set<SubscriptionType> = new Set([
|
|
79
80
|
SUBSCRIPTION_TYPE_COPY,
|
|
80
81
|
SUBSCRIPTION_TYPE_READONLY,
|
|
81
82
|
]);
|
package/src/effect.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
+
import {attempt} from '@oscarpalmer/atoms/result';
|
|
2
3
|
import {ACTIVE, NAME_EFFECT, NAME_MORA, SYMBOL_STATE} from './constants';
|
|
3
4
|
import type {Effect, EffectState} from './models';
|
|
4
5
|
|
|
5
6
|
// #region Instance
|
|
6
7
|
|
|
7
|
-
function Effect(this: any, callback: GenericCallback) {
|
|
8
|
+
function Effect(this: any, callback: GenericCallback): void {
|
|
8
9
|
this[SYMBOL_STATE] = {callback};
|
|
9
10
|
|
|
10
11
|
runEffect(this[SYMBOL_STATE]);
|
package/src/helpers/proxy.ts
CHANGED
|
@@ -5,29 +5,15 @@ import type {
|
|
|
5
5
|
Key,
|
|
6
6
|
PlainObject,
|
|
7
7
|
} from '@oscarpalmer/atoms/models';
|
|
8
|
+
import {attempt} from '@oscarpalmer/atoms/result';
|
|
8
9
|
import {startBatch, stopBatch} from '../batch';
|
|
9
|
-
import {PROPERTY_LENGTH, SYMBOL_STATE} from '../constants';
|
|
10
|
+
import {PROPERTY_LENGTH, SYMBOL_EFFECT, SYMBOL_STATE} from '../constants';
|
|
10
11
|
import type {InternalArray, InternalComputed, InternalStore, ReactiveProxyState} from '../models';
|
|
11
12
|
import {internalComputed} from '../value/computed';
|
|
12
13
|
import {emitValue, getSignalValue, peekSignalValue} from './value';
|
|
13
14
|
|
|
14
15
|
// #region Functions
|
|
15
16
|
|
|
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
17
|
export function getReactiveValueInProxy(
|
|
32
18
|
instance: InternalArray | InternalStore,
|
|
33
19
|
key: Key,
|
|
@@ -50,7 +36,7 @@ export function getReactiveValueInProxy(
|
|
|
50
36
|
state.mapped.set(mapKey, item);
|
|
51
37
|
}
|
|
52
38
|
|
|
53
|
-
return item
|
|
39
|
+
return item;
|
|
54
40
|
}
|
|
55
41
|
|
|
56
42
|
export function getValueInProxy(this: InternalArray | InternalStore, first?: unknown): unknown {
|
|
@@ -71,6 +57,22 @@ function isProxyObject(isArray: boolean, value: unknown): value is ArrayOrPlainO
|
|
|
71
57
|
return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
|
|
72
58
|
}
|
|
73
59
|
|
|
60
|
+
export function notifyProxyValue(this: InternalArray | InternalStore): void {
|
|
61
|
+
const state = this[SYMBOL_STATE];
|
|
62
|
+
|
|
63
|
+
state.mapped ??= new Map();
|
|
64
|
+
|
|
65
|
+
const values = [...state.mapped.values()];
|
|
66
|
+
const {length} = values;
|
|
67
|
+
|
|
68
|
+
for (let index = 0; index < length; index += 1) {
|
|
69
|
+
values[index][SYMBOL_EFFECT].dirty = true;
|
|
70
|
+
values[index][SYMBOL_EFFECT].notify = true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
emitValue(this, true);
|
|
74
|
+
}
|
|
75
|
+
|
|
74
76
|
export function peekValueInProxy(
|
|
75
77
|
this: InternalArray | InternalStore,
|
|
76
78
|
first?: unknown,
|
package/src/helpers/value.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import {round} from '@oscarpalmer/atoms/math';
|
|
3
|
+
import {attempt} from '@oscarpalmer/atoms/result';
|
|
2
4
|
import {flushHandlers} from '../batch';
|
|
3
5
|
import {
|
|
4
6
|
ACTIVE,
|
|
@@ -9,13 +11,20 @@ import {
|
|
|
9
11
|
SUBSCRIPTION_TYPE_FROZEN,
|
|
10
12
|
SUBSCRIPTION_TYPES,
|
|
11
13
|
SUBSCRIPTION_TYPES_COPY,
|
|
14
|
+
SYMBOL_EFFECT,
|
|
12
15
|
SYMBOL_STATE,
|
|
13
16
|
} from '../constants';
|
|
14
|
-
import type {InternalStateful} from '../models';
|
|
17
|
+
import type {InternalArray, InternalComputed, InternalStateful, InternalStore} from '../models';
|
|
18
|
+
|
|
19
|
+
// #region Types
|
|
20
|
+
|
|
21
|
+
type SetValue = (instance: InternalStateful, value: unknown, notify: boolean) => void;
|
|
22
|
+
|
|
23
|
+
// #endregion
|
|
15
24
|
|
|
16
25
|
// #region Functions
|
|
17
26
|
|
|
18
|
-
export function emitValue(instance: InternalStateful): void {
|
|
27
|
+
export function emitValue(instance: InternalStateful, notify?: boolean): void {
|
|
19
28
|
const state = instance[SYMBOL_STATE];
|
|
20
29
|
|
|
21
30
|
if (state.computeds != null && state.computeds.size > 0) {
|
|
@@ -30,6 +39,18 @@ export function emitValue(instance: InternalStateful): void {
|
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
if (notify ?? false) {
|
|
43
|
+
const proxy = instance as InternalArray | InternalStore;
|
|
44
|
+
const state = proxy[SYMBOL_STATE];
|
|
45
|
+
const mapped = state.mapped as Map<unknown, InternalComputed>;
|
|
46
|
+
|
|
47
|
+
for (const [, item] of mapped) {
|
|
48
|
+
const fx = item[SYMBOL_EFFECT];
|
|
49
|
+
|
|
50
|
+
BATCH.handlers.set(fx.instance, fx.instance);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
for (const type of SUBSCRIPTION_TYPES) {
|
|
34
55
|
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
35
56
|
|
|
@@ -67,7 +88,7 @@ export function equalArrays(
|
|
|
67
88
|
let offset = 0;
|
|
68
89
|
|
|
69
90
|
if (length >= ARRAY_THRESHOLD) {
|
|
70
|
-
offset =
|
|
91
|
+
offset = round(length / ARRAY_PEEK);
|
|
71
92
|
offset = offset > ARRAY_OFFSET ? ARRAY_OFFSET : offset;
|
|
72
93
|
|
|
73
94
|
for (let index = 0; index < offset; index += 1) {
|
|
@@ -136,8 +157,9 @@ export function getStringValue(this: InternalStateful, json?: boolean): string {
|
|
|
136
157
|
export function handleSignal(
|
|
137
158
|
instance: InternalStateful,
|
|
138
159
|
origin: unknown,
|
|
139
|
-
setValue:
|
|
160
|
+
setValue: SetValue,
|
|
140
161
|
onAfter?: () => void,
|
|
162
|
+
notify?: boolean,
|
|
141
163
|
): void {
|
|
142
164
|
const state = instance[SYMBOL_STATE];
|
|
143
165
|
|
|
@@ -152,7 +174,7 @@ export function handleSignal(
|
|
|
152
174
|
if (actual === state.promise) {
|
|
153
175
|
state.promise = undefined;
|
|
154
176
|
|
|
155
|
-
setValue(instance, value);
|
|
177
|
+
setValue(instance, value, notify ?? false);
|
|
156
178
|
}
|
|
157
179
|
})
|
|
158
180
|
.catch(() => {
|
|
@@ -161,7 +183,7 @@ export function handleSignal(
|
|
|
161
183
|
}
|
|
162
184
|
});
|
|
163
185
|
} else {
|
|
164
|
-
setValue(instance, actual);
|
|
186
|
+
setValue(instance, actual, notify ?? false);
|
|
165
187
|
}
|
|
166
188
|
} catch {
|
|
167
189
|
// ?
|
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 = {};
|
|
@@ -34,8 +35,8 @@ export type InternalArray = {
|
|
|
34
35
|
|
|
35
36
|
export type InternalComputed = {
|
|
36
37
|
[SYMBOL_EFFECT]: ComputedEffect;
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
} & Computed<unknown> &
|
|
39
|
+
InternalStateful;
|
|
39
40
|
|
|
40
41
|
export type InternalReadonly = {
|
|
41
42
|
frozen: boolean;
|
|
@@ -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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {select} from '@oscarpalmer/atoms/array';
|
|
2
1
|
import {filter} from '@oscarpalmer/atoms/array/filter';
|
|
2
|
+
import {select} from '@oscarpalmer/atoms/array/select';
|
|
3
3
|
import {
|
|
4
4
|
METHODS_AFFECTING_LENGTH,
|
|
5
5
|
METHODS_UPDATE,
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
} from '../constants';
|
|
11
11
|
import {getState} from '../helpers/misc';
|
|
12
12
|
import {
|
|
13
|
-
emitProxyValues,
|
|
14
13
|
getValueInProxy,
|
|
14
|
+
notifyProxyValue,
|
|
15
15
|
peekValueInProxy,
|
|
16
16
|
setProxyValue,
|
|
17
17
|
setValueInProxy,
|
|
@@ -26,7 +26,7 @@ import {signal} from './signal';
|
|
|
26
26
|
|
|
27
27
|
// #region Instance
|
|
28
28
|
|
|
29
|
-
function ReactiveArray(this: any, value: unknown, options?: ReactiveOptions<unknown>) {
|
|
29
|
+
function ReactiveArray(this: any, value: unknown, options?: ReactiveOptions<unknown>): void {
|
|
30
30
|
this[SYMBOL_STATE] = {
|
|
31
31
|
...getState(undefined, options),
|
|
32
32
|
isArray: true,
|
|
@@ -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
|
@@ -25,7 +25,7 @@ import type {
|
|
|
25
25
|
|
|
26
26
|
// #region Instance
|
|
27
27
|
|
|
28
|
-
function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>) {
|
|
28
|
+
function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>): void {
|
|
29
29
|
this[SYMBOL_STATE] = getState(undefined, options);
|
|
30
30
|
this[SYMBOL_EFFECT] = getComputedEffect(this, callback);
|
|
31
31
|
}
|
|
@@ -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/readonly.ts
CHANGED
|
@@ -25,7 +25,7 @@ type InternalReadonly = {
|
|
|
25
25
|
|
|
26
26
|
// #region Instance
|
|
27
27
|
|
|
28
|
-
function Readonly(this: any, state: SignalState, frozen: boolean) {
|
|
28
|
+
function Readonly(this: any, state: SignalState, frozen: boolean): void {
|
|
29
29
|
this[SUBSCRIPTION_TYPE_FROZEN] = frozen;
|
|
30
30
|
this[SYMBOL_STATE] = state;
|
|
31
31
|
}
|
package/src/value/signal.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {getReadonlySignal} from './readonly';
|
|
|
15
15
|
|
|
16
16
|
// #region Instance
|
|
17
17
|
|
|
18
|
-
function Signal(this: any, value: unknown, options?: ReactiveOptions<unknown>) {
|
|
18
|
+
function Signal(this: any, value: unknown, options?: ReactiveOptions<unknown>): void {
|
|
19
19
|
this[SYMBOL_STATE] = getState(undefined, options);
|
|
20
20
|
|
|
21
21
|
handleSignal(this, value, setAndEmit);
|
package/src/value/store.ts
CHANGED
|
@@ -2,8 +2,8 @@ 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
|
-
emitProxyValues,
|
|
6
5
|
getValueInProxy,
|
|
6
|
+
notifyProxyValue,
|
|
7
7
|
peekValueInProxy,
|
|
8
8
|
setProxyValue,
|
|
9
9
|
setValueInProxy,
|
|
@@ -16,7 +16,7 @@ import {getReadonlySignal} from './readonly';
|
|
|
16
16
|
|
|
17
17
|
// #region Instance
|
|
18
18
|
|
|
19
|
-
function ReactiveStore(this: any, value: never, options?: ReactiveOptions<unknown>) {
|
|
19
|
+
function ReactiveStore(this: any, value: never, options?: ReactiveOptions<unknown>): void {
|
|
20
20
|
this[SYMBOL_STATE] = {
|
|
21
21
|
...getState(undefined, options),
|
|
22
22
|
isArray: false,
|
|
@@ -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;
|