@oscarpalmer/mora 0.31.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.d.mts +4 -5
- package/dist/batch.mjs +4 -2
- package/dist/constants.d.mts +31 -19
- package/dist/constants.mjs +19 -2
- package/dist/effect.d.mts +5 -5
- package/dist/effect.mjs +8 -5
- package/dist/helpers/is.d.mts +14 -9
- package/dist/helpers/is.mjs +6 -0
- package/dist/helpers/misc.d.mts +4 -0
- package/dist/helpers/misc.mjs +9 -0
- package/dist/helpers/proxy.d.mts +10 -10
- package/dist/helpers/proxy.mjs +83 -27
- package/dist/helpers/subscription.d.mts +8 -0
- package/dist/helpers/subscription.mjs +30 -0
- package/dist/helpers/value.d.mts +10 -7
- package/dist/helpers/value.mjs +56 -17
- package/dist/index.d.mts +3 -2
- package/dist/models.d.mts +82 -101
- package/dist/models.mjs +1 -0
- package/dist/mora.full.mjs +659 -412
- package/dist/value/array.d.mts +5 -5
- package/dist/value/array.mjs +70 -109
- package/dist/value/computed.d.mts +5 -4
- package/dist/value/computed.mjs +45 -31
- package/dist/value/readonly.d.mts +4 -6
- package/dist/value/readonly.mjs +34 -31
- package/dist/value/signal.d.mts +5 -5
- package/dist/value/signal.mjs +28 -34
- package/dist/value/store.d.mts +5 -5
- package/dist/value/store.mjs +25 -83
- package/package.json +6 -6
- package/src/batch.ts +15 -5
- package/src/constants.ts +36 -2
- package/src/effect.ts +20 -11
- package/src/helpers/is.ts +16 -6
- package/src/helpers/misc.ts +15 -0
- package/src/helpers/proxy.ts +151 -74
- package/src/helpers/subscription.ts +89 -0
- package/src/helpers/value.ts +121 -30
- package/src/index.ts +1 -1
- package/src/models.ts +81 -98
- package/src/value/array.ts +116 -226
- package/src/value/computed.ts +96 -43
- package/src/value/readonly.ts +68 -54
- package/src/value/signal.ts +54 -46
- package/src/value/store.ts +42 -168
- package/types/constants.d.ts +1 -1
- package/types/index.d.ts +1 -1
- package/types/value/array.d.ts +1 -1
- package/types/value/computed.d.ts +0 -3
- package/types/value/signal.d.ts +1 -1
- package/types/value/store.d.ts +1 -1
- package/dist/subscription.d.mts +0 -7
- package/dist/subscription.mjs +0 -27
- package/dist/value/reactive.d.mts +0 -5
- package/dist/value/reactive.mjs +0 -16
- package/src/subscription.ts +0 -45
- package/src/value/reactive.ts +0 -24
package/dist/value/array.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactiveArray, ReactiveOptions } from "../models.mjs";
|
|
2
2
|
//#region src/value/array.d.ts
|
|
3
|
+
declare function ReactiveArray(this: any, value: unknown, options?: ReactiveOptions<unknown>): void;
|
|
3
4
|
/**
|
|
4
5
|
* Create a reactive array from a function result
|
|
5
6
|
*
|
|
@@ -7,7 +8,7 @@ import { ReactiveArray, ReactiveOptions } from "../models.mjs";
|
|
|
7
8
|
* @param options Reactivity options
|
|
8
9
|
* @returns Reactive array
|
|
9
10
|
*/
|
|
10
|
-
declare function array<Item>(value: () => Item[] | Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
11
|
+
export declare function array<Item>(value: () => Item[] | Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
11
12
|
/**
|
|
12
13
|
* Create a reactive array from a promise
|
|
13
14
|
*
|
|
@@ -15,7 +16,7 @@ declare function array<Item>(value: () => Item[] | Promise<Item[]>, options?: Re
|
|
|
15
16
|
* @param options Reactivity options
|
|
16
17
|
* @returns Reactive array
|
|
17
18
|
*/
|
|
18
|
-
declare function array<Item>(value: Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
19
|
+
export declare function array<Item>(value: Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
19
20
|
/**
|
|
20
21
|
* Create a reactive array
|
|
21
22
|
*
|
|
@@ -23,6 +24,5 @@ declare function array<Item>(value: Promise<Item[]>, options?: ReactiveOptions<I
|
|
|
23
24
|
* @param options Reactivity options
|
|
24
25
|
* @returns Reactive array
|
|
25
26
|
*/
|
|
26
|
-
declare function array<Item>(value: Item[], options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
27
|
-
//#endregion
|
|
28
|
-
export { array };
|
|
27
|
+
export declare function array<Item>(value: Item[], options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
28
|
+
//#endregion
|
package/dist/value/array.mjs
CHANGED
|
@@ -1,135 +1,96 @@
|
|
|
1
|
-
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY, NAME_MORA } from "../constants.mjs";
|
|
2
|
-
import { emitValue, equalArrays,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY, NAME_MORA, PROPERTY_LENGTH, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
+
import { emitValue, equalArrays, getStringValue } from "../helpers/value.mjs";
|
|
3
|
+
import { getState } from "../helpers/misc.mjs";
|
|
4
|
+
import { subscribeToProxy } from "../helpers/subscription.mjs";
|
|
5
5
|
import { computed } from "./computed.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { emitProxyValues, getValueInProxy, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue } from "../helpers/proxy.mjs";
|
|
7
7
|
import { getReadonlyInstance } from "./readonly.mjs";
|
|
8
8
|
import { signal } from "./signal.mjs";
|
|
9
9
|
import { select } from "@oscarpalmer/atoms/array";
|
|
10
10
|
import { filter } from "@oscarpalmer/atoms/array/filter";
|
|
11
|
-
import { noop } from "@oscarpalmer/atoms/function";
|
|
12
|
-
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
13
11
|
//#region src/value/array.ts
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
let instance = {};
|
|
20
|
-
state.value = new Proxy([], {
|
|
21
|
-
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, state, length) : Reflect.get(target, property),
|
|
22
|
-
set: (target, property, value) => setValueInProxy({
|
|
23
|
-
length,
|
|
24
|
-
property,
|
|
25
|
-
state,
|
|
26
|
-
target,
|
|
27
|
-
value,
|
|
28
|
-
isArray: true
|
|
29
|
-
})
|
|
30
|
-
});
|
|
31
|
-
function get(value) {
|
|
32
|
-
return getArrayValue(instance, indiced, state, length, value);
|
|
33
|
-
}
|
|
34
|
-
function set(first, second) {
|
|
35
|
-
setProxyValue(true, state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
|
|
36
|
-
}
|
|
37
|
-
const handlers = {
|
|
38
|
-
...rx,
|
|
39
|
-
get: (value) => get(value),
|
|
40
|
-
peek: (first, second) => peekArrayValue(state, length, first, second),
|
|
41
|
-
subscribe: (first, second) => {
|
|
42
|
-
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(instance, indiced, first, true).subscribe(second);
|
|
43
|
-
return typeof first === "function" ? subscribe(state, first) : noop;
|
|
44
|
-
},
|
|
45
|
-
unsubscribe: (first, second) => {
|
|
46
|
-
if (typeof first === "number" && typeof second === "function") getReactiveValueInProxy(instance, indiced, first, true)?.unsubscribe(second);
|
|
47
|
-
else if (typeof first === "function") unsubscribe(state, first);
|
|
48
|
-
}
|
|
12
|
+
function ReactiveArray(value, options) {
|
|
13
|
+
this[SYMBOL_STATE] = {
|
|
14
|
+
...getState(void 0, options),
|
|
15
|
+
isArray: true,
|
|
16
|
+
length: signal(0)
|
|
49
17
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
at: (index) => get(index),
|
|
54
|
-
clear: () => {
|
|
55
|
-
state.value.length = 0;
|
|
56
|
-
},
|
|
57
|
-
filter: (callback) => computed(() => filter(get(), callback)),
|
|
58
|
-
map: (callback) => computed(() => get().map(callback)),
|
|
59
|
-
notify: () => {
|
|
60
|
-
emityProxyValues(state, indiced);
|
|
61
|
-
},
|
|
62
|
-
pop: () => state.value.pop(),
|
|
63
|
-
push: (...items) => state.value.push(...items),
|
|
64
|
-
select: (filter, map) => computed(() => select(get(), filter, map)),
|
|
65
|
-
set: (first, second) => {
|
|
66
|
-
set(first, second);
|
|
67
|
-
},
|
|
68
|
-
shift: () => state.value.shift(),
|
|
69
|
-
splice: (from, to, ...items) => state.value.splice(from, to ?? state.value.length, ...items),
|
|
70
|
-
unshift: (...items) => state.value.unshift(...items),
|
|
71
|
-
update: (callback) => updateArrayValue(instance, state, callback)
|
|
72
|
-
};
|
|
73
|
-
Object.defineProperties(instance, {
|
|
74
|
-
[NAME_MORA]: {
|
|
75
|
-
enumerable: false,
|
|
76
|
-
value: NAME_ARRAY
|
|
77
|
-
},
|
|
78
|
-
length: {
|
|
79
|
-
enumerable: true,
|
|
80
|
-
get: () => length.get(),
|
|
81
|
-
set: (value) => setArrayLength(state, value)
|
|
82
|
-
}
|
|
18
|
+
this[SYMBOL_STATE].value = new Proxy([], {
|
|
19
|
+
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(this, property, target) : Reflect.get(target, property),
|
|
20
|
+
set: (target, property, value) => setValueInProxy(this, target, property, value)
|
|
83
21
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
function isArrayIndex(value) {
|
|
92
|
-
return typeof value === "number";
|
|
22
|
+
Object.defineProperty(this, PROPERTY_LENGTH, {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: () => this[SYMBOL_STATE].length.get(),
|
|
25
|
+
set: (value) => setArrayLength(this[SYMBOL_STATE], value)
|
|
26
|
+
});
|
|
27
|
+
setProxyValue.call(this, value);
|
|
93
28
|
}
|
|
94
|
-
|
|
95
|
-
|
|
29
|
+
ReactiveArray.prototype[NAME_MORA] = NAME_ARRAY;
|
|
30
|
+
ReactiveArray.prototype.asReadonly = getReadonlyInstance;
|
|
31
|
+
ReactiveArray.prototype.at = getArrayValues;
|
|
32
|
+
ReactiveArray.prototype.get = getArrayValues;
|
|
33
|
+
ReactiveArray.prototype.notify = emitProxyValues;
|
|
34
|
+
ReactiveArray.prototype.peek = peekArrayValue;
|
|
35
|
+
ReactiveArray.prototype.set = setProxyValue;
|
|
36
|
+
ReactiveArray.prototype.subscribe = subscribeToProxy;
|
|
37
|
+
ReactiveArray.prototype.toString = getStringValue;
|
|
38
|
+
ReactiveArray.prototype.update = updateProxyValue;
|
|
39
|
+
ReactiveArray.prototype.clear = function() {
|
|
40
|
+
this[SYMBOL_STATE].value.length = 0;
|
|
41
|
+
};
|
|
42
|
+
ReactiveArray.prototype.filter = function(callback) {
|
|
43
|
+
return computed(() => filter(getArrayValues.call(this), callback));
|
|
44
|
+
};
|
|
45
|
+
ReactiveArray.prototype.map = function(callback) {
|
|
46
|
+
return computed(() => getArrayValues.call(this).map(callback));
|
|
47
|
+
};
|
|
48
|
+
ReactiveArray.prototype.pop = function() {
|
|
49
|
+
return this[SYMBOL_STATE].value.pop();
|
|
50
|
+
};
|
|
51
|
+
ReactiveArray.prototype.push = function(...items) {
|
|
52
|
+
return this[SYMBOL_STATE].value.push(...items);
|
|
53
|
+
};
|
|
54
|
+
ReactiveArray.prototype.select = function(filter, map) {
|
|
55
|
+
return computed(() => select(getArrayValues.call(this), filter, map));
|
|
56
|
+
};
|
|
57
|
+
ReactiveArray.prototype.shift = function() {
|
|
58
|
+
return this[SYMBOL_STATE].value.shift();
|
|
59
|
+
};
|
|
60
|
+
ReactiveArray.prototype.splice = function(from, to, ...items) {
|
|
61
|
+
return this[SYMBOL_STATE].value.splice(from, to ?? this[SYMBOL_STATE].value.length, ...items);
|
|
62
|
+
};
|
|
63
|
+
ReactiveArray.prototype.toJSON = function() {
|
|
64
|
+
return this[SYMBOL_STATE].value;
|
|
65
|
+
};
|
|
66
|
+
ReactiveArray.prototype.unshift = function(...items) {
|
|
67
|
+
return this[SYMBOL_STATE].value.unshift(...items);
|
|
68
|
+
};
|
|
69
|
+
function array(value, options) {
|
|
70
|
+
return new ReactiveArray(value, options);
|
|
96
71
|
}
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
let value;
|
|
100
|
-
if (typeof first === "number") value = state.value.at(first);
|
|
101
|
-
else value = state.value;
|
|
102
|
-
if (!(first === true || second === true)) return value;
|
|
103
|
-
if (Array.isArray(value)) return value.slice();
|
|
104
|
-
if (isPlainObject(value)) return { ...value };
|
|
105
|
-
return value;
|
|
72
|
+
function getArrayValues(value) {
|
|
73
|
+
return value === "length" ? this[SYMBOL_STATE].length.get() : getValueInProxy.call(this, value);
|
|
106
74
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
75
|
+
function peekArrayValue(first, second) {
|
|
76
|
+
return first === "length" ? this[SYMBOL_STATE].length.peek() : peekValueInProxy.call(this, first, second);
|
|
109
77
|
}
|
|
110
78
|
function setArrayLength(state, value) {
|
|
111
|
-
if (typeof value === "number" && value >= 0 && value !== state.value.length) state.value.length = value;
|
|
79
|
+
if (typeof value === "number" && !Number.isNaN(value) && value >= 0 && value !== state.value.length) state.value.length = value;
|
|
112
80
|
}
|
|
113
|
-
function
|
|
114
|
-
const
|
|
115
|
-
if (actual > -1) state.value[actual] = value;
|
|
116
|
-
}
|
|
117
|
-
function updateArray(type, array, state, length) {
|
|
81
|
+
function updateArray(instance, type, array) {
|
|
82
|
+
const state = instance[SYMBOL_STATE];
|
|
118
83
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
119
84
|
const previousArray = affectsLength ? [] : array.slice();
|
|
120
85
|
const previousLength = array.length;
|
|
121
86
|
return (...args) => {
|
|
122
87
|
const result = array[type](...args);
|
|
123
88
|
if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
|
|
124
|
-
emitValue(
|
|
125
|
-
length.set(array.length);
|
|
89
|
+
emitValue(instance);
|
|
90
|
+
state.length.set(array.length);
|
|
126
91
|
}
|
|
127
92
|
return result;
|
|
128
93
|
};
|
|
129
94
|
}
|
|
130
|
-
function updateArrayValue(instance, state, callback) {
|
|
131
|
-
const updated = callback(state.value);
|
|
132
|
-
if (updated == null || Array.isArray(updated)) instance.set(updated);
|
|
133
|
-
}
|
|
134
95
|
//#endregion
|
|
135
96
|
export { array };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Computed, ComputedEffect, ReactiveOptions } from "../models.mjs";
|
|
2
|
+
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
2
3
|
//#region src/value/computed.d.ts
|
|
4
|
+
declare function Computed(this: any, callback: GenericCallback, options?: ReactiveOptions<unknown>): void;
|
|
3
5
|
/**
|
|
4
6
|
* Create a computed value
|
|
5
7
|
*
|
|
@@ -7,7 +9,6 @@ import { Computed, ComputedEffect, ReactiveOptions } from "../models.mjs";
|
|
|
7
9
|
* @param options Reactivity options
|
|
8
10
|
* @returns Computed value
|
|
9
11
|
*/
|
|
10
|
-
declare function computed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Computed<Value>;
|
|
11
|
-
declare function internalComputed
|
|
12
|
-
//#endregion
|
|
13
|
-
export { computed, internalComputed };
|
|
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>): [Computed<unknown>, ComputedEffect];
|
|
14
|
+
//#endregion
|
package/dist/value/computed.mjs
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import { ACTIVE, BATCH, NAME_COMPUTED, NAME_MORA } from "../constants.mjs";
|
|
1
|
+
import { ACTIVE, BATCH, NAME_COMPUTED, NAME_MORA, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SYMBOL_EFFECT, SYMBOL_STATE } from "../constants.mjs";
|
|
2
2
|
import { internalEffect, runEffect } from "../effect.mjs";
|
|
3
|
+
import { getStringValue, handleSignalValue, peekSignalValue } from "../helpers/value.mjs";
|
|
3
4
|
import { flushHandlers } from "../batch.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { reactive } from "./reactive.mjs";
|
|
5
|
+
import { getState } from "../helpers/misc.mjs";
|
|
6
|
+
import { subscribeToSignal } from "../helpers/subscription.mjs";
|
|
7
7
|
//#region src/value/computed.ts
|
|
8
|
+
function Computed(callback, options) {
|
|
9
|
+
this[SYMBOL_STATE] = getState(void 0, options);
|
|
10
|
+
this[SYMBOL_EFFECT] = getComputedEffect(this, callback);
|
|
11
|
+
}
|
|
12
|
+
Computed.prototype[NAME_MORA] = NAME_COMPUTED;
|
|
13
|
+
Computed.prototype.get = getComputedValue;
|
|
14
|
+
Computed.prototype.peek = peekSignalValue;
|
|
15
|
+
Computed.prototype.subscribe = subscribeToSignal;
|
|
16
|
+
Computed.prototype.toString = getStringValue;
|
|
17
|
+
Computed.prototype.toJSON = function() {
|
|
18
|
+
return this[SYMBOL_STATE].value;
|
|
19
|
+
};
|
|
8
20
|
/**
|
|
9
21
|
* Create a computed value
|
|
10
22
|
*
|
|
@@ -16,25 +28,11 @@ function computed(callback, options) {
|
|
|
16
28
|
return getComputed(callback, options)[0];
|
|
17
29
|
}
|
|
18
30
|
function getComputed(callback, options) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
...rx,
|
|
23
|
-
get: () => getValue(state, fx),
|
|
24
|
-
peek: () => state.value,
|
|
25
|
-
subscribe: (callback) => subscribe(state, callback),
|
|
26
|
-
unsubscribe: (callback) => {
|
|
27
|
-
state.subscriptions.delete(callback);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
Object.defineProperty(instance, NAME_MORA, {
|
|
31
|
-
enumerable: false,
|
|
32
|
-
value: NAME_COMPUTED
|
|
33
|
-
});
|
|
34
|
-
fx = getComputedEffect(state, callback);
|
|
35
|
-
return [Object.freeze(instance), fx];
|
|
31
|
+
if (typeof callback !== "function") throw new TypeError("Computed callback must be a function");
|
|
32
|
+
const instance = new Computed(callback, options);
|
|
33
|
+
return [instance, instance[SYMBOL_EFFECT]];
|
|
36
34
|
}
|
|
37
|
-
function getComputedEffect(
|
|
35
|
+
function getComputedEffect(instance, callback) {
|
|
38
36
|
const fx = {
|
|
39
37
|
dirty: true,
|
|
40
38
|
instance: void 0
|
|
@@ -43,7 +41,7 @@ function getComputedEffect(state, callback) {
|
|
|
43
41
|
if (fx.dirty) {
|
|
44
42
|
const previousComputed = ACTIVE.computed;
|
|
45
43
|
ACTIVE.computed = fx;
|
|
46
|
-
|
|
44
|
+
handleSignalValue(instance, callback, setAndEmit, () => {
|
|
47
45
|
ACTIVE.computed = previousComputed;
|
|
48
46
|
});
|
|
49
47
|
fx.dirty = false;
|
|
@@ -51,21 +49,37 @@ function getComputedEffect(state, callback) {
|
|
|
51
49
|
});
|
|
52
50
|
return fx;
|
|
53
51
|
}
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
function getComputedValue() {
|
|
53
|
+
const fx = this[SYMBOL_EFFECT];
|
|
54
|
+
const state = this[SYMBOL_STATE];
|
|
55
|
+
if (ACTIVE.computed != null && fx !== ACTIVE.computed) {
|
|
56
|
+
state.computeds ??= /* @__PURE__ */ new Set();
|
|
57
|
+
state.computeds.add(ACTIVE.computed);
|
|
58
|
+
}
|
|
59
|
+
if (ACTIVE.effect != null && ACTIVE.effect !== fx.instance) {
|
|
60
|
+
state.effects ??= /* @__PURE__ */ new Set();
|
|
61
|
+
state.effects.add(ACTIVE.effect);
|
|
62
|
+
}
|
|
57
63
|
if (fx.dirty && BATCH.depth === 0) runEffect(fx.instance);
|
|
58
64
|
return state.value;
|
|
59
65
|
}
|
|
60
66
|
function internalComputed(callback, options) {
|
|
61
67
|
return getComputed(callback, options);
|
|
62
68
|
}
|
|
63
|
-
function setAndEmit(
|
|
64
|
-
|
|
69
|
+
function setAndEmit(instance, value) {
|
|
70
|
+
const state = instance[SYMBOL_STATE];
|
|
71
|
+
if ((state.equal ?? Object.is)(state.value, value)) return;
|
|
65
72
|
state.value = value;
|
|
66
|
-
for (const computed of state.computeds) computed.dirty = true;
|
|
67
|
-
for (const effect of state.effects) BATCH.handlers.
|
|
68
|
-
for (const
|
|
73
|
+
if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
|
|
74
|
+
if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
|
|
75
|
+
for (const type of SUBSCRIPTION_TYPES) {
|
|
76
|
+
if (type === "frozen") continue;
|
|
77
|
+
const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
|
|
78
|
+
if (subscriptions != null && subscriptions.size > 0) {
|
|
79
|
+
const copy = SUBSCRIPTION_TYPES_COPY.has(type);
|
|
80
|
+
for (const [, callback] of subscriptions) callback(peekSignalValue.call(instance, copy));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
69
83
|
flushHandlers();
|
|
70
84
|
}
|
|
71
85
|
//#endregion
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
1
|
+
import { InternalSignal, ReadonlyFrozenSignal, ReadonlySignal, SignalState } from "../models.mjs";
|
|
3
2
|
//#region src/value/readonly.d.ts
|
|
4
|
-
declare function getReadonlyInstance<Value>(
|
|
5
|
-
declare function getReadonlySignal
|
|
6
|
-
//#endregion
|
|
7
|
-
export { getReadonlyInstance, getReadonlySignal };
|
|
3
|
+
export declare function getReadonlyInstance<Value>(this: InternalSignal, frozen?: never): ReadonlySignal<Value>;
|
|
4
|
+
export declare function getReadonlySignal(state: SignalState, frozen: boolean): ReadonlySignal<unknown> | ReadonlyFrozenSignal<unknown>;
|
|
5
|
+
//#endregion
|
package/dist/value/readonly.mjs
CHANGED
|
@@ -1,37 +1,40 @@
|
|
|
1
|
-
import { NAME_MORA, NAME_READONLY } from "../constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { NAME_MORA, NAME_READONLY, SUBSCRIPTION_TYPE_FROZEN, SUBSCRIPTION_TYPE_ORIGINAL, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
+
import { getFrozenValue, getSignalValue, getStringValue, peekSignalValue } from "../helpers/value.mjs";
|
|
3
|
+
import { subscribeToReadonly } from "../helpers/subscription.mjs";
|
|
4
4
|
//#region src/value/readonly.ts
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function getReadonlySignal(state, handlers, frozen) {
|
|
11
|
-
const instance = {
|
|
12
|
-
...handlers,
|
|
13
|
-
get: () => getReadonlyValue(state, false, frozen),
|
|
14
|
-
peek: () => getReadonlyValue(state, true, frozen)
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperties(instance, {
|
|
17
|
-
[NAME_MORA]: {
|
|
18
|
-
enumerable: false,
|
|
19
|
-
value: NAME_READONLY
|
|
20
|
-
},
|
|
21
|
-
frozen: {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
value: frozen
|
|
24
|
-
}
|
|
5
|
+
function Readonly(state, frozen) {
|
|
6
|
+
this[SYMBOL_STATE] = state;
|
|
7
|
+
Object.defineProperty(this, SUBSCRIPTION_TYPE_FROZEN, {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
value: frozen
|
|
25
10
|
});
|
|
26
|
-
return Object.freeze(instance);
|
|
27
11
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
12
|
+
Readonly.prototype[NAME_MORA] = NAME_READONLY;
|
|
13
|
+
Readonly.prototype.subscribe = subscribeToReadonly;
|
|
14
|
+
Readonly.prototype.toString = getStringValue;
|
|
15
|
+
Readonly.prototype.get = function() {
|
|
16
|
+
return getReadonlyValue(this, false, this[SUBSCRIPTION_TYPE_FROZEN]);
|
|
17
|
+
};
|
|
18
|
+
Readonly.prototype.peek = function(copy) {
|
|
19
|
+
return getReadonlyValue(this, true, this[SUBSCRIPTION_TYPE_FROZEN], copy);
|
|
20
|
+
};
|
|
21
|
+
Readonly.prototype.toJSON = function() {
|
|
22
|
+
return this[SYMBOL_STATE].value;
|
|
23
|
+
};
|
|
24
|
+
function getReadonlyInstance(frozen) {
|
|
25
|
+
const key = frozen === true ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_ORIGINAL;
|
|
26
|
+
this[SYMBOL_STATE].readonlies ??= {};
|
|
27
|
+
this[SYMBOL_STATE].readonlies[key] ??= getReadonlySignal(this[SYMBOL_STATE], frozen === true);
|
|
28
|
+
return this[SYMBOL_STATE].readonlies[key];
|
|
29
|
+
}
|
|
30
|
+
function getReadonlySignal(state, frozen) {
|
|
31
|
+
return new Readonly(state, frozen);
|
|
32
|
+
}
|
|
33
|
+
function getReadonlyValue(instance, peek, frozen, copy) {
|
|
34
|
+
let value;
|
|
35
|
+
if (peek) value = peekSignalValue.call(instance, copy === true);
|
|
36
|
+
else value = getSignalValue.call(instance);
|
|
37
|
+
return frozen ? getFrozenValue(value) : value;
|
|
35
38
|
}
|
|
36
39
|
//#endregion
|
|
37
40
|
export { getReadonlyInstance, getReadonlySignal };
|
package/dist/value/signal.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactiveOptions, Signal } from "../models.mjs";
|
|
2
2
|
//#region src/value/signal.d.ts
|
|
3
|
+
declare function Signal(this: any, value: unknown, options?: ReactiveOptions<unknown>): void;
|
|
3
4
|
/**
|
|
4
5
|
* Create a reactive value from a function result
|
|
5
6
|
*
|
|
@@ -7,7 +8,7 @@ import { ReactiveOptions, Signal } from "../models.mjs";
|
|
|
7
8
|
* @param options Reactivity options
|
|
8
9
|
* @returns Reactive value
|
|
9
10
|
*/
|
|
10
|
-
declare function signal<Value>(value: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
11
|
+
export declare function signal<Value>(value: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
11
12
|
/**
|
|
12
13
|
* Create a reactive value from a promise
|
|
13
14
|
*
|
|
@@ -15,7 +16,7 @@ declare function signal<Value>(value: () => Value | Promise<Value>, options?: Re
|
|
|
15
16
|
* @param options Reactivity options
|
|
16
17
|
* @returns Reactive value
|
|
17
18
|
*/
|
|
18
|
-
declare function signal<Value>(value: Promise<Value>, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
19
|
+
export declare function signal<Value>(value: Promise<Value>, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
19
20
|
/**
|
|
20
21
|
* Create a reactive value
|
|
21
22
|
*
|
|
@@ -23,6 +24,5 @@ declare function signal<Value>(value: Promise<Value>, options?: ReactiveOptions<
|
|
|
23
24
|
* @param options Reactivity options
|
|
24
25
|
* @returns Reactive value
|
|
25
26
|
*/
|
|
26
|
-
declare function signal<Value>(value: Value, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
27
|
-
//#endregion
|
|
28
|
-
export { signal };
|
|
27
|
+
export declare function signal<Value>(value: Value, options?: ReactiveOptions<Value>): Signal<Value>;
|
|
28
|
+
//#endregion
|
package/dist/value/signal.mjs
CHANGED
|
@@ -1,43 +1,37 @@
|
|
|
1
|
-
import { NAME_MORA, NAME_SIGNAL } from "../constants.mjs";
|
|
2
|
-
import { emitValue,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { NAME_MORA, NAME_SIGNAL, SYMBOL_STATE } from "../constants.mjs";
|
|
2
|
+
import { emitValue, getSignalValue, getStringValue, handleSignalValue, peekSignalValue, updateSignalValue } from "../helpers/value.mjs";
|
|
3
|
+
import { getState } from "../helpers/misc.mjs";
|
|
4
|
+
import { subscribeToSignal } from "../helpers/subscription.mjs";
|
|
5
5
|
import { getReadonlyInstance } from "./readonly.mjs";
|
|
6
6
|
//#region src/value/signal.ts
|
|
7
|
-
function
|
|
8
|
-
|
|
7
|
+
function Signal(value, options) {
|
|
8
|
+
this[SYMBOL_STATE] = getState(void 0, options);
|
|
9
|
+
handleSignalValue(this, value, setAndEmit);
|
|
10
|
+
}
|
|
11
|
+
Signal.prototype[NAME_MORA] = NAME_SIGNAL;
|
|
12
|
+
Signal.prototype.asReadonly = getReadonlyInstance;
|
|
13
|
+
Signal.prototype.get = getSignalValue;
|
|
14
|
+
Signal.prototype.peek = peekSignalValue;
|
|
15
|
+
Signal.prototype.subscribe = subscribeToSignal;
|
|
16
|
+
Signal.prototype.toString = getStringValue;
|
|
17
|
+
Signal.prototype.set = function(value) {
|
|
18
|
+
return handleSignalValue(this, value, setAndEmit);
|
|
19
|
+
};
|
|
20
|
+
Signal.prototype.toJSON = function() {
|
|
21
|
+
return this[SYMBOL_STATE].value;
|
|
22
|
+
};
|
|
23
|
+
Signal.prototype.update = function(callback) {
|
|
24
|
+
return updateSignalValue(this, callback, setAndEmit);
|
|
25
|
+
};
|
|
26
|
+
function setAndEmit(instance, value) {
|
|
27
|
+
const state = instance[SYMBOL_STATE];
|
|
28
|
+
if (!(state.equal ?? Object.is)(state.value, value)) {
|
|
9
29
|
state.value = value;
|
|
10
|
-
emitValue(
|
|
30
|
+
emitValue(instance);
|
|
11
31
|
}
|
|
12
32
|
}
|
|
13
33
|
function signal(value, options) {
|
|
14
|
-
|
|
15
|
-
const readonlies = {};
|
|
16
|
-
const handlers = {
|
|
17
|
-
...rx,
|
|
18
|
-
subscribe: (callback) => subscribe(state, callback),
|
|
19
|
-
unsubscribe: (callback) => {
|
|
20
|
-
state.subscriptions.delete(callback);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const instance = {
|
|
24
|
-
...handlers,
|
|
25
|
-
asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
|
|
26
|
-
get: () => getSimpleValue(state),
|
|
27
|
-
peek: () => state.value,
|
|
28
|
-
set: (value) => {
|
|
29
|
-
handleSimpleValue(state, value, setAndEmit);
|
|
30
|
-
},
|
|
31
|
-
update: (callback) => {
|
|
32
|
-
handleSimpleValue(state, callback(state.value), setAndEmit);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
Object.defineProperty(instance, NAME_MORA, {
|
|
36
|
-
enumerable: false,
|
|
37
|
-
value: NAME_SIGNAL
|
|
38
|
-
});
|
|
39
|
-
handleSimpleValue(state, value, setAndEmit);
|
|
40
|
-
return Object.freeze(instance);
|
|
34
|
+
return new Signal(value, options);
|
|
41
35
|
}
|
|
42
36
|
//#endregion
|
|
43
37
|
export { signal };
|
package/dist/value/store.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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;
|
|
4
5
|
/**
|
|
5
6
|
* Create a reactive store from a function result
|
|
6
7
|
*
|
|
@@ -8,7 +9,7 @@ import { PlainObject } from "@oscarpalmer/atoms/models";
|
|
|
8
9
|
* @param options Reactivity options
|
|
9
10
|
* @returns Reactive store
|
|
10
11
|
*/
|
|
11
|
-
declare function store<Value extends PlainObject>(value: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
12
|
+
export declare function store<Value extends PlainObject>(value: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
12
13
|
/**
|
|
13
14
|
* Create a reactive store from a promise
|
|
14
15
|
*
|
|
@@ -16,7 +17,7 @@ declare function store<Value extends PlainObject>(value: () => Value | Promise<V
|
|
|
16
17
|
* @param options Reactivity options
|
|
17
18
|
* @returns Reactive store
|
|
18
19
|
*/
|
|
19
|
-
declare function store<Value extends PlainObject>(value: Promise<Value>, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
20
|
+
export declare function store<Value extends PlainObject>(value: Promise<Value>, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
20
21
|
/**
|
|
21
22
|
* Create a reactive store
|
|
22
23
|
*
|
|
@@ -24,6 +25,5 @@ declare function store<Value extends PlainObject>(value: Promise<Value>, options
|
|
|
24
25
|
* @param options Reactivity options
|
|
25
26
|
* @returns Reactive store
|
|
26
27
|
*/
|
|
27
|
-
declare function store<Value extends PlainObject>(value: Value, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
28
|
-
//#endregion
|
|
29
|
-
export { store };
|
|
28
|
+
export declare function store<Value extends PlainObject>(value: Value, options?: ReactiveOptions<Value>): ReactiveStore<Value>;
|
|
29
|
+
//#endregion
|