@oscarpalmer/mora 0.28.0 → 0.30.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 +15 -6
- package/dist/constants.d.mts +0 -1
- package/dist/constants.mjs +4 -3
- package/dist/effect.d.mts +5 -8
- package/dist/effect.mjs +23 -19
- package/dist/helpers/is.d.mts +9 -9
- package/dist/helpers/is.mjs +6 -0
- package/dist/helpers/proxy.d.mts +5 -9
- package/dist/helpers/proxy.mjs +4 -4
- package/dist/helpers/value.d.mts +3 -3
- package/dist/helpers/value.mjs +21 -3
- package/dist/index.d.mts +7 -8
- package/dist/index.mjs +1 -1
- package/dist/models.d.mts +356 -18
- package/dist/mora.full.mjs +458 -409
- package/dist/subscription.d.mts +1 -9
- package/dist/subscription.mjs +14 -15
- package/dist/value/array.d.mts +5 -133
- package/dist/value/array.mjs +91 -137
- package/dist/value/computed.d.mts +4 -12
- package/dist/value/computed.mjs +54 -50
- package/dist/value/reactive.d.mts +3 -38
- package/dist/value/reactive.mjs +10 -49
- package/dist/value/signal.d.mts +5 -21
- package/dist/value/signal.mjs +27 -49
- package/dist/value/store.d.mts +9 -92
- package/dist/value/store.mjs +42 -49
- package/package.json +8 -8
- package/src/batch.ts +22 -9
- package/src/constants.ts +3 -4
- package/src/effect.ts +31 -26
- package/src/helpers/is.ts +11 -10
- package/src/helpers/proxy.ts +23 -18
- package/src/helpers/value.ts +38 -3
- package/src/index.ts +6 -7
- package/src/models.ts +431 -16
- package/src/subscription.ts +20 -20
- package/src/value/array.ts +183 -265
- package/src/value/computed.ts +80 -74
- package/src/value/reactive.ts +16 -64
- package/src/value/signal.ts +34 -71
- package/src/value/store.ts +84 -177
package/dist/subscription.d.mts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { ReactiveState, Unsubscribe } from "./models.mjs";
|
|
2
|
-
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
|
-
|
|
4
2
|
//#region src/subscription.d.ts
|
|
5
|
-
declare class Subscription {
|
|
6
|
-
callback: GenericCallback;
|
|
7
|
-
state: ReactiveState<unknown, never>;
|
|
8
|
-
constructor(state: ReactiveState<unknown, never>, callback: GenericCallback);
|
|
9
|
-
destroy(): void;
|
|
10
|
-
}
|
|
11
3
|
declare function noop(): void;
|
|
12
4
|
declare function subscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): Unsubscribe;
|
|
13
5
|
declare function unsubscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): void;
|
|
14
6
|
//#endregion
|
|
15
|
-
export {
|
|
7
|
+
export { noop, subscribe, unsubscribe };
|
package/dist/subscription.mjs
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
//#region src/subscription.ts
|
|
2
|
-
var Subscription = class {
|
|
3
|
-
callback;
|
|
4
|
-
state;
|
|
5
|
-
constructor(state, callback) {
|
|
6
|
-
this.state = state;
|
|
7
|
-
this.callback = callback;
|
|
8
|
-
callback(state.value);
|
|
9
|
-
}
|
|
10
|
-
destroy() {
|
|
11
|
-
this.callback = noop;
|
|
12
|
-
this.state = void 0;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
2
|
function noop() {}
|
|
16
3
|
function subscribe(state, callback) {
|
|
17
4
|
if (typeof callback !== "function" || state.subscriptions.has(callback)) return noop;
|
|
18
|
-
state.subscriptions.set(callback,
|
|
5
|
+
state.subscriptions.set(callback, subscription(state, callback));
|
|
19
6
|
return () => {
|
|
20
7
|
unsubscribe(state, callback);
|
|
21
8
|
};
|
|
22
9
|
}
|
|
10
|
+
function subscription(state, callback) {
|
|
11
|
+
const instance = {
|
|
12
|
+
callback,
|
|
13
|
+
state,
|
|
14
|
+
destroy: () => {
|
|
15
|
+
instance.callback = noop;
|
|
16
|
+
instance.state = void 0;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
callback(state.value);
|
|
20
|
+
return instance;
|
|
21
|
+
}
|
|
23
22
|
function unsubscribe(state, callback) {
|
|
24
23
|
state.subscriptions.get(callback)?.destroy();
|
|
25
24
|
state.subscriptions.delete(callback);
|
|
26
25
|
}
|
|
27
26
|
//#endregion
|
|
28
|
-
export {
|
|
27
|
+
export { noop, subscribe, unsubscribe };
|
package/dist/value/array.d.mts
CHANGED
|
@@ -1,138 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Computed } from "./computed.mjs";
|
|
3
|
-
import { ReactiveOptions, Unsubscribe } from "../models.mjs";
|
|
4
|
-
import { PROPERTY_LENGTH } from "../constants.mjs";
|
|
5
|
-
|
|
1
|
+
import { ReactiveArray, ReactiveOptions } from "../models.mjs";
|
|
6
2
|
//#region src/value/array.d.ts
|
|
7
|
-
declare class ReactiveArray<Item> extends Reactive<Item[], Item> {
|
|
8
|
-
#private;
|
|
9
|
-
/**
|
|
10
|
-
* The length of the array
|
|
11
|
-
*/
|
|
12
|
-
get length(): number;
|
|
13
|
-
/**
|
|
14
|
-
* Set the length of the array
|
|
15
|
-
*/
|
|
16
|
-
set length(value: number);
|
|
17
|
-
constructor(value: Item[], options?: ReactiveOptions<Item>);
|
|
18
|
-
/**
|
|
19
|
-
* Clear the array
|
|
20
|
-
*/
|
|
21
|
-
clear(): void;
|
|
22
|
-
/**
|
|
23
|
-
* Create a computed, filtered array
|
|
24
|
-
* @param callback Callback to evaluate each item
|
|
25
|
-
* @return Computed array of filtered items
|
|
26
|
-
*/
|
|
27
|
-
filter(callback: (item: Item, index: number, array: Item[]) => boolean): Computed<Item[]>;
|
|
28
|
-
/**
|
|
29
|
-
* @inheritdoc
|
|
30
|
-
*/
|
|
31
|
-
get(): Item[];
|
|
32
|
-
/**
|
|
33
|
-
* Get the value at an index
|
|
34
|
-
* @param index Index of item to get _(if negative, starts from the end)_
|
|
35
|
-
* @returns Item at index, or `undefined` if it doesn't exist
|
|
36
|
-
*/
|
|
37
|
-
get(index: number): Item | undefined;
|
|
38
|
-
/**
|
|
39
|
-
* Get the length of the array
|
|
40
|
-
* @returns Length of the array
|
|
41
|
-
*/
|
|
42
|
-
get(property: typeof PROPERTY_LENGTH): number;
|
|
43
|
-
/**
|
|
44
|
-
* Create a computed, mapped array
|
|
45
|
-
* @param callback Callback to transform each item
|
|
46
|
-
* @return Computed array of mapped items
|
|
47
|
-
*/
|
|
48
|
-
map<Mapped>(callback: (item: Item, index: number, array: Item[]) => Mapped): Computed<Mapped[]>;
|
|
49
|
-
/**
|
|
50
|
-
* Notify dependents of changes
|
|
51
|
-
*
|
|
52
|
-
* _This bypasses equality checks and will immediately notify dependents.
|
|
53
|
-
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
54
|
-
*/
|
|
55
|
-
notify(): void;
|
|
56
|
-
/**
|
|
57
|
-
* @inheritdoc
|
|
58
|
-
*/
|
|
59
|
-
peek(): Item[];
|
|
60
|
-
/**
|
|
61
|
-
* Get the value at an index _(without reactivity)_
|
|
62
|
-
* @param index Index of item to get _(if negative, starts from the end)_
|
|
63
|
-
* @returns Item at index, or `undefined` if it doesn't exist
|
|
64
|
-
*/
|
|
65
|
-
peek(index: number): Item | undefined;
|
|
66
|
-
/**
|
|
67
|
-
* Get the length of the array _(without reactivity)_
|
|
68
|
-
* @returns Length of the array
|
|
69
|
-
*/
|
|
70
|
-
peek(property: typeof PROPERTY_LENGTH): number;
|
|
71
|
-
/**
|
|
72
|
-
* Remove and return the last item of the array
|
|
73
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
74
|
-
*/
|
|
75
|
-
pop(): Item | undefined;
|
|
76
|
-
/**
|
|
77
|
-
* Add items to the end of the array
|
|
78
|
-
* @param items Items to add
|
|
79
|
-
* @returns New array length
|
|
80
|
-
*/
|
|
81
|
-
push(...items: Item[]): number;
|
|
82
|
-
/**
|
|
83
|
-
* Set the value
|
|
84
|
-
* @param value New array of items _(defaults to an empty array)_
|
|
85
|
-
*/
|
|
86
|
-
set(value?: Item[] | (() => null | undefined | Item[] | Promise<null | undefined | Item[]>) | Promise<null | undefined | Item[]>): void;
|
|
87
|
-
/**
|
|
88
|
-
* Set the value at an index
|
|
89
|
-
* @param index Index of item to set __(if negative, starts from the end)_
|
|
90
|
-
* @param value New item
|
|
91
|
-
*/
|
|
92
|
-
set(index: number, value: Item | (() => Item | Promise<Item>) | Promise<Item>): void;
|
|
93
|
-
/**
|
|
94
|
-
* Set the length of the array
|
|
95
|
-
* @param value New array length
|
|
96
|
-
*/
|
|
97
|
-
set(property: typeof PROPERTY_LENGTH, value: number): void;
|
|
98
|
-
/**
|
|
99
|
-
* Remove and return the first item of the array
|
|
100
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
101
|
-
*/
|
|
102
|
-
shift(): Item | undefined;
|
|
103
|
-
/**
|
|
104
|
-
* Remove and return items from the array _(and optionally add new items)_
|
|
105
|
-
* @param from Index to start removing items from
|
|
106
|
-
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
107
|
-
* @param items Optional items to add
|
|
108
|
-
* @returns Removed items
|
|
109
|
-
*/
|
|
110
|
-
splice(from: number, to?: number, ...items: Item[]): Item[];
|
|
111
|
-
/**
|
|
112
|
-
* @inheritdoc
|
|
113
|
-
*/
|
|
114
|
-
subscribe(callback: (value: Item[]) => void): Unsubscribe;
|
|
115
|
-
/**
|
|
116
|
-
* Subscribe to changes at a specific index
|
|
117
|
-
* @param index Index of item to subscribe to
|
|
118
|
-
* @param callback Callback for changes
|
|
119
|
-
* @returns Unsubscribe callback
|
|
120
|
-
*/
|
|
121
|
-
subscribe(index: number, callback: (value: Item | undefined) => void): Unsubscribe;
|
|
122
|
-
/**
|
|
123
|
-
* Add items to the beginning of the array
|
|
124
|
-
* @param items Items to add
|
|
125
|
-
* @returns New array length
|
|
126
|
-
*/
|
|
127
|
-
unshift(...items: Item[]): number;
|
|
128
|
-
/**
|
|
129
|
-
* Update the value _(based on the current value)_
|
|
130
|
-
* @param callback Callback to update the value
|
|
131
|
-
*/
|
|
132
|
-
update(callback: (value: Item[]) => Item[]): void;
|
|
133
|
-
}
|
|
134
3
|
/**
|
|
135
4
|
* Create a reactive array from a function result
|
|
5
|
+
*
|
|
136
6
|
* @param value Initial array of items
|
|
137
7
|
* @param options Reactivity options
|
|
138
8
|
* @returns Reactive array
|
|
@@ -140,6 +10,7 @@ declare class ReactiveArray<Item> extends Reactive<Item[], Item> {
|
|
|
140
10
|
declare function array<Item>(value: () => Item[] | Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
141
11
|
/**
|
|
142
12
|
* Create a reactive array from a promise
|
|
13
|
+
*
|
|
143
14
|
* @param value Initial array of items
|
|
144
15
|
* @param options Reactivity options
|
|
145
16
|
* @returns Reactive array
|
|
@@ -147,10 +18,11 @@ declare function array<Item>(value: () => Item[] | Promise<Item[]>, options?: Re
|
|
|
147
18
|
declare function array<Item>(value: Promise<Item[]>, options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
148
19
|
/**
|
|
149
20
|
* Create a reactive array
|
|
21
|
+
*
|
|
150
22
|
* @param value Initial array of items
|
|
151
23
|
* @param options Reactivity options
|
|
152
24
|
* @returns Reactive array
|
|
153
25
|
*/
|
|
154
26
|
declare function array<Item>(value: Item[], options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
155
27
|
//#endregion
|
|
156
|
-
export {
|
|
28
|
+
export { array };
|
package/dist/value/array.mjs
CHANGED
|
@@ -1,139 +1,82 @@
|
|
|
1
|
-
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY } from "../constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY, NAME_MORA } from "../constants.mjs";
|
|
2
|
+
import { emitValue, equalArrays, getSimpleValue } from "../helpers/value.mjs";
|
|
3
|
+
import { subscribe, unsubscribe } from "../subscription.mjs";
|
|
4
|
+
import { reactive } from "./reactive.mjs";
|
|
4
5
|
import { computed } from "./computed.mjs";
|
|
5
|
-
import { emitValue, equalArrays, getValue } from "../helpers/value.mjs";
|
|
6
6
|
import { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy } from "../helpers/proxy.mjs";
|
|
7
7
|
import { signal } from "./signal.mjs";
|
|
8
|
+
import { select } from "@oscarpalmer/atoms/array";
|
|
9
|
+
import { filter } from "@oscarpalmer/atoms/array/filter";
|
|
10
|
+
import { noop } from "@oscarpalmer/atoms/function";
|
|
8
11
|
//#region src/value/array.ts
|
|
9
|
-
var ReactiveArray = class extends Reactive {
|
|
10
|
-
#indiced = /* @__PURE__ */ new Map();
|
|
11
|
-
#size = signal(0);
|
|
12
|
-
/**
|
|
13
|
-
* The length of the array
|
|
14
|
-
*/
|
|
15
|
-
get length() {
|
|
16
|
-
return this.#size.get();
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Set the length of the array
|
|
20
|
-
*/
|
|
21
|
-
set length(value) {
|
|
22
|
-
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
|
|
23
|
-
}
|
|
24
|
-
constructor(value, options) {
|
|
25
|
-
super(NAME_ARRAY, new Proxy(value, {
|
|
26
|
-
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
27
|
-
set: (target, property, value) => setValueInProxy({
|
|
28
|
-
property,
|
|
29
|
-
target,
|
|
30
|
-
value,
|
|
31
|
-
isArray: true,
|
|
32
|
-
state: this.state,
|
|
33
|
-
length: this.#size
|
|
34
|
-
})
|
|
35
|
-
}), options);
|
|
36
|
-
this.#size.set(value.length);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Clear the array
|
|
40
|
-
*/
|
|
41
|
-
clear() {
|
|
42
|
-
this.length = 0;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Create a computed, filtered array
|
|
46
|
-
* @param callback Callback to evaluate each item
|
|
47
|
-
* @return Computed array of filtered items
|
|
48
|
-
*/
|
|
49
|
-
filter(callback) {
|
|
50
|
-
return computed(() => this.get().filter(callback));
|
|
51
|
-
}
|
|
52
|
-
get(first) {
|
|
53
|
-
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
54
|
-
return first === "length" ? this.length : getValue(this.state);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Create a computed, mapped array
|
|
58
|
-
* @param callback Callback to transform each item
|
|
59
|
-
* @return Computed array of mapped items
|
|
60
|
-
*/
|
|
61
|
-
map(callback) {
|
|
62
|
-
return computed(() => this.get().map(callback));
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Notify dependents of changes
|
|
66
|
-
*
|
|
67
|
-
* _This bypasses equality checks and will immediately notify dependents.
|
|
68
|
-
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
69
|
-
*/
|
|
70
|
-
notify() {
|
|
71
|
-
emityProxyValues(this.state, this.#indiced);
|
|
72
|
-
}
|
|
73
|
-
peek(value) {
|
|
74
|
-
if (value === "length") return this.#size.peek();
|
|
75
|
-
return typeof value === "number" ? this.state.value.at(value) : this.state.value.slice();
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Remove and return the last item of the array
|
|
79
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
80
|
-
*/
|
|
81
|
-
pop() {
|
|
82
|
-
return this.state.value.pop();
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Add items to the end of the array
|
|
86
|
-
* @param items Items to add
|
|
87
|
-
* @returns New array length
|
|
88
|
-
*/
|
|
89
|
-
push(...items) {
|
|
90
|
-
return this.state.value.push(...items);
|
|
91
|
-
}
|
|
92
|
-
set(first, second) {
|
|
93
|
-
setProxyValue(true, this.state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Remove and return the first item of the array
|
|
97
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
98
|
-
*/
|
|
99
|
-
shift() {
|
|
100
|
-
return this.state.value.shift();
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Remove and return items from the array _(and optionally add new items)_
|
|
104
|
-
* @param from Index to start removing items from
|
|
105
|
-
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
106
|
-
* @param items Optional items to add
|
|
107
|
-
* @returns Removed items
|
|
108
|
-
*/
|
|
109
|
-
splice(from, to, ...items) {
|
|
110
|
-
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
111
|
-
}
|
|
112
|
-
subscribe(first, second) {
|
|
113
|
-
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
114
|
-
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Add items to the beginning of the array
|
|
118
|
-
* @param items Items to add
|
|
119
|
-
* @returns New array length
|
|
120
|
-
*/
|
|
121
|
-
unshift(...items) {
|
|
122
|
-
return this.state.value.unshift(...items);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Update the value _(based on the current value)_
|
|
126
|
-
* @param callback Callback to update the value
|
|
127
|
-
*/
|
|
128
|
-
update(callback) {
|
|
129
|
-
const updated = callback(this.state.value);
|
|
130
|
-
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
12
|
function array(value, options) {
|
|
134
|
-
const
|
|
13
|
+
const [rx, state] = reactive([], options);
|
|
14
|
+
const indiced = /* @__PURE__ */ new Map();
|
|
15
|
+
const length = signal(0);
|
|
16
|
+
state.value = new Proxy([], {
|
|
17
|
+
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, state, length) : Reflect.get(target, property),
|
|
18
|
+
set: (target, property, value) => setValueInProxy({
|
|
19
|
+
length,
|
|
20
|
+
property,
|
|
21
|
+
state,
|
|
22
|
+
target,
|
|
23
|
+
value,
|
|
24
|
+
isArray: true
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
function get(value) {
|
|
28
|
+
return getArrayValue(instance, indiced, state, length, value);
|
|
29
|
+
}
|
|
30
|
+
const instance = {
|
|
31
|
+
...rx,
|
|
32
|
+
length: state.value.length,
|
|
33
|
+
at: (index) => get(index),
|
|
34
|
+
clear: () => {
|
|
35
|
+
state.value.length = 0;
|
|
36
|
+
},
|
|
37
|
+
filter: (callback) => computed(() => filter(get(), callback)),
|
|
38
|
+
get: (value) => get(value),
|
|
39
|
+
map: (callback) => computed(() => get().map(callback)),
|
|
40
|
+
notify: () => {
|
|
41
|
+
emityProxyValues(state, indiced);
|
|
42
|
+
},
|
|
43
|
+
peek: (value) => peekArrayValue(state, length, value),
|
|
44
|
+
pop: () => state.value.pop(),
|
|
45
|
+
push: (...items) => state.value.push(...items),
|
|
46
|
+
select: (filter, map) => computed(() => select(get(), filter, map)),
|
|
47
|
+
set: (first, second) => {
|
|
48
|
+
setProxyValue(true, state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
|
|
49
|
+
},
|
|
50
|
+
shift: () => state.value.shift(),
|
|
51
|
+
splice: (from, to, ...items) => state.value.splice(from, to ?? state.value.length, ...items),
|
|
52
|
+
subscribe: (first, second) => {
|
|
53
|
+
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(instance, indiced, first, true).subscribe(second);
|
|
54
|
+
return typeof first === "function" ? subscribe(state, first) : noop;
|
|
55
|
+
},
|
|
56
|
+
unshift: (...items) => state.value.unshift(...items),
|
|
57
|
+
unsubscribe: (first, second) => {
|
|
58
|
+
if (typeof first === "number" && typeof second === "function") getReactiveValueInProxy(instance, indiced, first, true)?.unsubscribe(second);
|
|
59
|
+
else if (typeof first === "function") unsubscribe(state, first);
|
|
60
|
+
},
|
|
61
|
+
update: (callback) => updateArrayValue(instance, state, callback)
|
|
62
|
+
};
|
|
63
|
+
Object.defineProperties(instance, {
|
|
64
|
+
[NAME_MORA]: {
|
|
65
|
+
enumerable: false,
|
|
66
|
+
value: NAME_ARRAY
|
|
67
|
+
},
|
|
68
|
+
length: {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: () => length.get(),
|
|
71
|
+
set: (value) => setArrayLength(state, value)
|
|
72
|
+
}
|
|
73
|
+
});
|
|
135
74
|
instance.set(value);
|
|
136
|
-
return instance;
|
|
75
|
+
return Object.freeze(instance);
|
|
76
|
+
}
|
|
77
|
+
function getArrayValue(instance, indiced, state, length, first) {
|
|
78
|
+
if (typeof first === "number") return getReactiveValueInProxy(instance, indiced, first, true).get();
|
|
79
|
+
return first === "length" ? length.get() : getSimpleValue(state);
|
|
137
80
|
}
|
|
138
81
|
function isArrayIndex(value) {
|
|
139
82
|
return typeof value === "number";
|
|
@@ -141,6 +84,20 @@ function isArrayIndex(value) {
|
|
|
141
84
|
function isArrayValue(value) {
|
|
142
85
|
return value == null || Array.isArray(value);
|
|
143
86
|
}
|
|
87
|
+
function peekArrayValue(state, length, value) {
|
|
88
|
+
if (value === "length") return length.peek();
|
|
89
|
+
return typeof value === "number" ? state.value.at(value) : state.value.slice();
|
|
90
|
+
}
|
|
91
|
+
function setArray(state, value) {
|
|
92
|
+
state.value.splice(0, state.value.length, ...value ?? []);
|
|
93
|
+
}
|
|
94
|
+
function setArrayLength(state, value) {
|
|
95
|
+
if (typeof value === "number" && value >= 0 && value !== state.value.length) state.value.length = value;
|
|
96
|
+
}
|
|
97
|
+
function setAtIndex(state, index, value) {
|
|
98
|
+
const actual = index < 0 ? state.value.length + index : index;
|
|
99
|
+
if (actual > -1) state.value[actual] = value;
|
|
100
|
+
}
|
|
144
101
|
function updateArray(type, array, state, length) {
|
|
145
102
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
146
103
|
const previousArray = affectsLength ? [] : array.slice();
|
|
@@ -154,12 +111,9 @@ function updateArray(type, array, state, length) {
|
|
|
154
111
|
return result;
|
|
155
112
|
};
|
|
156
113
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
function setAtIndex(state, index, value) {
|
|
161
|
-
const actual = index < 0 ? state.value.length + index : index;
|
|
162
|
-
if (actual > -1) state.value[actual] = value;
|
|
114
|
+
function updateArrayValue(instance, state, callback) {
|
|
115
|
+
const updated = callback(state.value);
|
|
116
|
+
if (updated == null || Array.isArray(updated)) instance.set(updated);
|
|
163
117
|
}
|
|
164
118
|
//#endregion
|
|
165
|
-
export {
|
|
119
|
+
export { array };
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ReactiveOptions } from "../models.mjs";
|
|
3
|
-
|
|
1
|
+
import { Computed, ComputedEffect, ReactiveOptions } from "../models.mjs";
|
|
4
2
|
//#region src/value/computed.d.ts
|
|
5
|
-
declare class Computed<Value> extends Reactive<Value> {
|
|
6
|
-
private readonly effect;
|
|
7
|
-
constructor(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>);
|
|
8
|
-
/**
|
|
9
|
-
* @inheritdoc
|
|
10
|
-
*/
|
|
11
|
-
get(): Value;
|
|
12
|
-
}
|
|
13
3
|
/**
|
|
14
4
|
* Create a computed value
|
|
5
|
+
*
|
|
15
6
|
* @param callback Callback to compute the value
|
|
16
7
|
* @param options Reactivity options
|
|
17
8
|
* @returns Computed value
|
|
18
9
|
*/
|
|
19
10
|
declare function computed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): Computed<Value>;
|
|
11
|
+
declare function internalComputed<Value>(callback: () => Value | Promise<Value>, options?: ReactiveOptions<Value>): [Computed<Value>, ComputedEffect];
|
|
20
12
|
//#endregion
|
|
21
|
-
export {
|
|
13
|
+
export { computed, internalComputed };
|
package/dist/value/computed.mjs
CHANGED
|
@@ -1,68 +1,72 @@
|
|
|
1
|
-
import { ACTIVE, BATCH, NAME_COMPUTED } from "../constants.mjs";
|
|
2
|
-
import {
|
|
1
|
+
import { ACTIVE, BATCH, NAME_COMPUTED, NAME_MORA } from "../constants.mjs";
|
|
2
|
+
import { internalEffect, runEffect } from "../effect.mjs";
|
|
3
3
|
import { flushHandlers } from "../batch.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { handleSimpleValue } from "../helpers/value.mjs";
|
|
5
|
+
import { subscribe } from "../subscription.mjs";
|
|
6
|
+
import { reactive } from "./reactive.mjs";
|
|
5
7
|
//#region src/value/computed.ts
|
|
6
|
-
var Computed = class extends Reactive {
|
|
7
|
-
effect = {
|
|
8
|
-
dirty: true,
|
|
9
|
-
instance: void 0
|
|
10
|
-
};
|
|
11
|
-
constructor(callback, options) {
|
|
12
|
-
super(NAME_COMPUTED, void 0, options);
|
|
13
|
-
this.effect.instance = effect(() => {
|
|
14
|
-
if (this.effect.dirty) {
|
|
15
|
-
setValue(this, this.state, callback);
|
|
16
|
-
this.effect.dirty = false;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* @inheritdoc
|
|
22
|
-
*/
|
|
23
|
-
get() {
|
|
24
|
-
if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
|
|
25
|
-
if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
|
|
26
|
-
if (this.effect.dirty && BATCH.depth === 0) runEffect(this.effect.instance);
|
|
27
|
-
return this.state.value;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
8
|
/**
|
|
31
9
|
* Create a computed value
|
|
10
|
+
*
|
|
32
11
|
* @param callback Callback to compute the value
|
|
33
12
|
* @param options Reactivity options
|
|
34
13
|
* @returns Computed value
|
|
35
14
|
*/
|
|
36
15
|
function computed(callback, options) {
|
|
37
|
-
return
|
|
16
|
+
return getComputed(callback, options)[0];
|
|
17
|
+
}
|
|
18
|
+
function getComputed(callback, options) {
|
|
19
|
+
const [rx, state] = reactive(void 0, options);
|
|
20
|
+
let fx;
|
|
21
|
+
const instance = {
|
|
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];
|
|
36
|
+
}
|
|
37
|
+
function getComputedEffect(state, callback) {
|
|
38
|
+
const fx = {
|
|
39
|
+
dirty: true,
|
|
40
|
+
instance: void 0
|
|
41
|
+
};
|
|
42
|
+
fx.instance = internalEffect(() => {
|
|
43
|
+
if (fx.dirty) {
|
|
44
|
+
const previousComputed = ACTIVE.computed;
|
|
45
|
+
ACTIVE.computed = fx;
|
|
46
|
+
handleSimpleValue(state, callback, setAndEmit, () => {
|
|
47
|
+
ACTIVE.computed = previousComputed;
|
|
48
|
+
});
|
|
49
|
+
fx.dirty = false;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return fx;
|
|
53
|
+
}
|
|
54
|
+
function getValue(state, fx) {
|
|
55
|
+
if (ACTIVE.computed != null && fx !== ACTIVE.computed) state.computeds.add(ACTIVE.computed);
|
|
56
|
+
if (ACTIVE.effect != null && ACTIVE.effect !== fx.instance) state.effects.add(ACTIVE.effect);
|
|
57
|
+
if (fx.dirty && BATCH.depth === 0) runEffect(fx.instance);
|
|
58
|
+
return state.value;
|
|
59
|
+
}
|
|
60
|
+
function internalComputed(callback, options) {
|
|
61
|
+
return getComputed(callback, options);
|
|
38
62
|
}
|
|
39
63
|
function setAndEmit(state, value) {
|
|
40
64
|
if (state.equal(state.value, value)) return;
|
|
41
65
|
state.value = value;
|
|
42
|
-
for (const computed of state.computeds) computed.
|
|
66
|
+
for (const computed of state.computeds) computed.dirty = true;
|
|
43
67
|
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
44
68
|
for (const [, subscription] of state.subscriptions) subscription.callback(value);
|
|
45
69
|
flushHandlers();
|
|
46
70
|
}
|
|
47
|
-
function setValue(instance, state, callback) {
|
|
48
|
-
const previousComputed = ACTIVE.computed;
|
|
49
|
-
ACTIVE.computed = instance;
|
|
50
|
-
try {
|
|
51
|
-
const value = callback();
|
|
52
|
-
if (value instanceof Promise) {
|
|
53
|
-
state.promise = value;
|
|
54
|
-
value.then((resolvedValue) => {
|
|
55
|
-
if (state.promise === value) {
|
|
56
|
-
state.promise = void 0;
|
|
57
|
-
setAndEmit(state, resolvedValue);
|
|
58
|
-
}
|
|
59
|
-
}).catch(() => {
|
|
60
|
-
if (state.promise === value) state.promise = void 0;
|
|
61
|
-
});
|
|
62
|
-
} else setAndEmit(state, value);
|
|
63
|
-
} finally {
|
|
64
|
-
ACTIVE.computed = previousComputed;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
71
|
//#endregion
|
|
68
|
-
export {
|
|
72
|
+
export { computed, internalComputed };
|
|
@@ -1,40 +1,5 @@
|
|
|
1
|
-
import { ReactiveOptions, ReactiveState
|
|
2
|
-
|
|
1
|
+
import { Reactive, ReactiveOptions, ReactiveState } from "../models.mjs";
|
|
3
2
|
//#region src/value/reactive.d.ts
|
|
4
|
-
declare
|
|
5
|
-
protected readonly state: ReactiveState<Value, Equal>;
|
|
6
|
-
constructor(name: string, value: Value, options?: ReactiveOptions<Equal>);
|
|
7
|
-
/**
|
|
8
|
-
* Get the value
|
|
9
|
-
* @return Current value
|
|
10
|
-
*/
|
|
11
|
-
abstract get(): Value;
|
|
12
|
-
/**
|
|
13
|
-
* Get the value _(without reactivity)_
|
|
14
|
-
* @return Current value
|
|
15
|
-
*/
|
|
16
|
-
peek(): Value;
|
|
17
|
-
/**
|
|
18
|
-
* Subscribe to changes
|
|
19
|
-
* @param callback Callback for changes
|
|
20
|
-
* @return Unsubscribe callback
|
|
21
|
-
*/
|
|
22
|
-
subscribe(callback: (value: Value) => void): Unsubscribe;
|
|
23
|
-
/**
|
|
24
|
-
* JSON representation of the value
|
|
25
|
-
* @return JSON value
|
|
26
|
-
*/
|
|
27
|
-
toJSON(): Value;
|
|
28
|
-
/**
|
|
29
|
-
* String representation of the value
|
|
30
|
-
* @return Value as string
|
|
31
|
-
*/
|
|
32
|
-
toString(): string;
|
|
33
|
-
/**
|
|
34
|
-
* Unsubscribe from changes
|
|
35
|
-
* @param callback Callback to unsubscribe
|
|
36
|
-
*/
|
|
37
|
-
unsubscribe(callback: (value: Value) => void): void;
|
|
38
|
-
}
|
|
3
|
+
declare function reactive<Value, Equal = Value>(value: Value, options?: ReactiveOptions<Equal>): [Reactive<Value>, ReactiveState<Value, Equal>];
|
|
39
4
|
//#endregion
|
|
40
|
-
export {
|
|
5
|
+
export { reactive };
|