@oscarpalmer/mora 0.29.0 → 0.31.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 +2 -2
- package/dist/constants.mjs +7 -4
- package/dist/effect.d.mts +5 -18
- package/dist/effect.mjs +23 -19
- package/dist/helpers/is.d.mts +17 -16
- package/dist/helpers/is.mjs +20 -11
- 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 +22 -5
- package/dist/index.d.mts +8 -9
- package/dist/index.mjs +2 -2
- package/dist/models.d.mts +423 -19
- package/dist/mora.full.mjs +532 -424
- 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 +108 -138
- package/dist/value/computed.d.mts +4 -12
- package/dist/value/computed.mjs +54 -50
- package/dist/value/reactive.d.mts +3 -49
- package/dist/value/reactive.mjs +10 -54
- package/dist/value/readonly.d.mts +7 -0
- package/dist/value/readonly.mjs +37 -0
- package/dist/value/signal.d.mts +5 -21
- package/dist/value/signal.mjs +33 -49
- package/dist/value/store.d.mts +9 -92
- package/dist/value/store.mjs +58 -49
- package/package.json +7 -8
- package/src/batch.ts +22 -9
- package/src/constants.ts +12 -5
- package/src/effect.ts +35 -40
- package/src/helpers/is.ts +36 -20
- package/src/helpers/proxy.ts +23 -18
- package/src/helpers/value.ts +39 -5
- package/src/index.ts +23 -8
- package/src/models.ts +520 -17
- package/src/subscription.ts +20 -20
- package/src/value/array.ts +220 -266
- package/src/value/computed.ts +80 -74
- package/src/value/reactive.ts +16 -77
- package/src/value/readonly.ts +71 -0
- package/src/value/signal.ts +43 -71
- package/src/value/store.ts +130 -177
- 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 +3 -0
- package/types/value/signal.d.ts +1 -1
- package/types/value/store.d.ts +1 -1
package/src/value/array.ts
CHANGED
|
@@ -1,268 +1,40 @@
|
|
|
1
|
+
import {select} from '@oscarpalmer/atoms/array';
|
|
2
|
+
import {filter} from '@oscarpalmer/atoms/array/filter';
|
|
3
|
+
import {noop} from '@oscarpalmer/atoms/function';
|
|
4
|
+
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
1
5
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
METHODS_AFFECTING_LENGTH,
|
|
8
|
+
METHODS_UPDATE,
|
|
9
|
+
NAME_ARRAY,
|
|
10
|
+
NAME_MORA,
|
|
11
|
+
PROPERTY_LENGTH,
|
|
12
|
+
} from '../constants';
|
|
3
13
|
import {
|
|
4
14
|
emityProxyValues,
|
|
5
15
|
getReactiveValueInProxy,
|
|
6
16
|
setProxyValue,
|
|
7
17
|
setValueInProxy,
|
|
8
18
|
} from '../helpers/proxy';
|
|
9
|
-
import {emitValue, equalArrays,
|
|
10
|
-
import type {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
get length(): number {
|
|
25
|
-
return this.#size.get();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Set the length of the array
|
|
30
|
-
*/
|
|
31
|
-
set length(value: number) {
|
|
32
|
-
if (typeof value === 'number' && value >= 0 && value !== this.state.value.length) {
|
|
33
|
-
this.get().length = value;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
constructor(value: Item[], options?: ReactiveOptions<Item>) {
|
|
38
|
-
super(
|
|
39
|
-
NAME_ARRAY,
|
|
40
|
-
new Proxy(value, {
|
|
41
|
-
get: (target: Item[], property: PropertyKey) =>
|
|
42
|
-
METHODS_UPDATE.has(property as string)
|
|
43
|
-
? updateArray(property as string, target, this.state, this.#size)
|
|
44
|
-
: Reflect.get(target, property),
|
|
45
|
-
set: (target: Item[], property: PropertyKey, value: Item) =>
|
|
46
|
-
setValueInProxy({
|
|
47
|
-
property,
|
|
48
|
-
target,
|
|
49
|
-
value,
|
|
50
|
-
isArray: true,
|
|
51
|
-
state: this.state,
|
|
52
|
-
length: this.#size,
|
|
53
|
-
}),
|
|
54
|
-
}),
|
|
55
|
-
options,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
this.#size.set(value.length);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Clear the array
|
|
63
|
-
*/
|
|
64
|
-
clear(): void {
|
|
65
|
-
this.length = 0;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Create a computed, filtered array
|
|
70
|
-
* @param callback Callback to evaluate each item
|
|
71
|
-
* @return Computed array of filtered items
|
|
72
|
-
*/
|
|
73
|
-
filter(callback: (item: Item, index: number, array: Item[]) => boolean): Computed<Item[]> {
|
|
74
|
-
return computed(() => this.get().filter(callback));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @inheritdoc
|
|
79
|
-
*/
|
|
80
|
-
get(): Item[];
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Get the value at an index
|
|
84
|
-
* @param index Index of item to get _(if negative, starts from the end)_
|
|
85
|
-
* @returns Item at index, or `undefined` if it doesn't exist
|
|
86
|
-
*/
|
|
87
|
-
get(index: number): Item | undefined;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Get the length of the array
|
|
91
|
-
* @returns Length of the array
|
|
92
|
-
*/
|
|
93
|
-
get(property: typeof PROPERTY_LENGTH): number;
|
|
94
|
-
|
|
95
|
-
get(first?: unknown): unknown {
|
|
96
|
-
if (typeof first === 'number') {
|
|
97
|
-
return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return first === PROPERTY_LENGTH ? this.length : getValue(this.state);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create a computed, mapped array
|
|
105
|
-
* @param callback Callback to transform each item
|
|
106
|
-
* @return Computed array of mapped items
|
|
107
|
-
*/
|
|
108
|
-
map<Mapped>(callback: (item: Item, index: number, array: Item[]) => Mapped): Computed<Mapped[]> {
|
|
109
|
-
return computed(() => this.get().map(callback));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Notify dependents of changes
|
|
114
|
-
*
|
|
115
|
-
* _This bypasses equality checks and will immediately notify dependents.
|
|
116
|
-
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
117
|
-
*/
|
|
118
|
-
notify(): void {
|
|
119
|
-
emityProxyValues(this.state, this.#indiced);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @inheritdoc
|
|
124
|
-
*/
|
|
125
|
-
override peek(): Item[];
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Get the value at an index _(without reactivity)_
|
|
129
|
-
* @param index Index of item to get _(if negative, starts from the end)_
|
|
130
|
-
* @returns Item at index, or `undefined` if it doesn't exist
|
|
131
|
-
*/
|
|
132
|
-
override peek(index: number): Item | undefined;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Get the length of the array _(without reactivity)_
|
|
136
|
-
* @returns Length of the array
|
|
137
|
-
*/
|
|
138
|
-
override peek(property: typeof PROPERTY_LENGTH): number;
|
|
139
|
-
|
|
140
|
-
override peek(value?: unknown): unknown {
|
|
141
|
-
if (value === PROPERTY_LENGTH) {
|
|
142
|
-
return this.#size.peek();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return typeof value === 'number' ? this.state.value.at(value) : this.state.value.slice();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Remove and return the last item of the array
|
|
150
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
151
|
-
*/
|
|
152
|
-
pop(): Item | undefined {
|
|
153
|
-
return this.state.value.pop();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Add items to the end of the array
|
|
158
|
-
* @param items Items to add
|
|
159
|
-
* @returns New array length
|
|
160
|
-
*/
|
|
161
|
-
push(...items: Item[]): number {
|
|
162
|
-
return this.state.value.push(...items);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Set the value
|
|
167
|
-
* @param value New array of items _(defaults to an empty array)_
|
|
168
|
-
*/
|
|
169
|
-
set(
|
|
170
|
-
value?:
|
|
171
|
-
| Item[]
|
|
172
|
-
| (() => null | undefined | Item[] | Promise<null | undefined | Item[]>)
|
|
173
|
-
| Promise<null | undefined | Item[]>,
|
|
174
|
-
): void;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Set the value at an index
|
|
178
|
-
* @param index Index of item to set __(if negative, starts from the end)_
|
|
179
|
-
* @param value New item
|
|
180
|
-
*/
|
|
181
|
-
set(index: number, value: Item | (() => Item | Promise<Item>) | Promise<Item>): void;
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Set the length of the array
|
|
185
|
-
* @param value New array length
|
|
186
|
-
*/
|
|
187
|
-
set(property: typeof PROPERTY_LENGTH, value: number): void;
|
|
188
|
-
|
|
189
|
-
set(first?: unknown, second?: unknown): void {
|
|
190
|
-
setProxyValue<Item[], Item>(
|
|
191
|
-
true,
|
|
192
|
-
this.state,
|
|
193
|
-
isArrayValue,
|
|
194
|
-
isArrayIndex,
|
|
195
|
-
setArray,
|
|
196
|
-
setAtIndex,
|
|
197
|
-
first,
|
|
198
|
-
second,
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Remove and return the first item of the array
|
|
204
|
-
* @returns Removed item, or `undefined` if the array is empty
|
|
205
|
-
*/
|
|
206
|
-
shift(): Item | undefined {
|
|
207
|
-
return this.state.value.shift();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Remove and return items from the array _(and optionally add new items)_
|
|
212
|
-
* @param from Index to start removing items from
|
|
213
|
-
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
214
|
-
* @param items Optional items to add
|
|
215
|
-
* @returns Removed items
|
|
216
|
-
*/
|
|
217
|
-
splice(from: number, to?: number, ...items: Item[]): Item[] {
|
|
218
|
-
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* @inheritdoc
|
|
223
|
-
*/
|
|
224
|
-
override subscribe(callback: (value: Item[]) => void): Unsubscribe;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Subscribe to changes at a specific index
|
|
228
|
-
* @param index Index of item to subscribe to
|
|
229
|
-
* @param callback Callback for changes
|
|
230
|
-
* @returns Unsubscribe callback
|
|
231
|
-
*/
|
|
232
|
-
override subscribe(index: number, callback: (value: Item | undefined) => void): Unsubscribe;
|
|
233
|
-
|
|
234
|
-
override subscribe(first: number | GenericCallback, second?: GenericCallback): Unsubscribe {
|
|
235
|
-
if (typeof first === 'number' && typeof second === 'function') {
|
|
236
|
-
return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return typeof first === 'function' ? subscribe(this.state, first) : noop;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Add items to the beginning of the array
|
|
244
|
-
* @param items Items to add
|
|
245
|
-
* @returns New array length
|
|
246
|
-
*/
|
|
247
|
-
unshift(...items: Item[]): number {
|
|
248
|
-
return this.state.value.unshift(...items);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Update the value _(based on the current value)_
|
|
253
|
-
* @param callback Callback to update the value
|
|
254
|
-
*/
|
|
255
|
-
update(callback: (value: Item[]) => Item[]): void {
|
|
256
|
-
const updated = callback(this.state.value);
|
|
257
|
-
|
|
258
|
-
if (updated == null || Array.isArray(updated)) {
|
|
259
|
-
this.set(updated);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
19
|
+
import {emitValue, equalArrays, getSimpleValue} from '../helpers/value';
|
|
20
|
+
import type {
|
|
21
|
+
Computed,
|
|
22
|
+
ComputedEffect,
|
|
23
|
+
ReactiveArray,
|
|
24
|
+
ReactiveOptions,
|
|
25
|
+
ReactiveState,
|
|
26
|
+
ReadonlyInstances,
|
|
27
|
+
Signal,
|
|
28
|
+
} from '../models';
|
|
29
|
+
import {subscribe, unsubscribe} from '../subscription';
|
|
30
|
+
import {computed} from './computed';
|
|
31
|
+
import {reactive} from './reactive';
|
|
32
|
+
import {getReadonlyInstance} from './readonly';
|
|
33
|
+
import {signal} from './signal';
|
|
263
34
|
|
|
264
35
|
/**
|
|
265
36
|
* Create a reactive array from a function result
|
|
37
|
+
*
|
|
266
38
|
* @param value Initial array of items
|
|
267
39
|
* @param options Reactivity options
|
|
268
40
|
* @returns Reactive array
|
|
@@ -274,6 +46,7 @@ export function array<Item>(
|
|
|
274
46
|
|
|
275
47
|
/**
|
|
276
48
|
* Create a reactive array from a promise
|
|
49
|
+
*
|
|
277
50
|
* @param value Initial array of items
|
|
278
51
|
* @param options Reactivity options
|
|
279
52
|
* @returns Reactive array
|
|
@@ -285,6 +58,7 @@ export function array<Item>(
|
|
|
285
58
|
|
|
286
59
|
/**
|
|
287
60
|
* Create a reactive array
|
|
61
|
+
*
|
|
288
62
|
* @param value Initial array of items
|
|
289
63
|
* @param options Reactivity options
|
|
290
64
|
* @returns Reactive array
|
|
@@ -295,11 +69,140 @@ export function array<Item>(
|
|
|
295
69
|
value: Item[] | (() => Item[] | Promise<Item[]>) | Promise<Item[]>,
|
|
296
70
|
options?: ReactiveOptions<Item>,
|
|
297
71
|
): ReactiveArray<Item> {
|
|
298
|
-
const
|
|
72
|
+
const [rx, state] = reactive<Item[], Item>([], options);
|
|
73
|
+
|
|
74
|
+
const indiced = new Map<number, [Computed<unknown>, ComputedEffect]>();
|
|
75
|
+
const length = signal(0);
|
|
76
|
+
const readonlies: ReadonlyInstances<Item[]> = {};
|
|
77
|
+
|
|
78
|
+
let instance: Record<string, unknown> = {};
|
|
79
|
+
|
|
80
|
+
state.value = new Proxy([], {
|
|
81
|
+
get: (target: Item[], property: PropertyKey) =>
|
|
82
|
+
METHODS_UPDATE.has(property as string)
|
|
83
|
+
? updateArray(property as string, target, state, length)
|
|
84
|
+
: Reflect.get(target, property),
|
|
85
|
+
set: (target: Item[], property: PropertyKey, value: Item) =>
|
|
86
|
+
setValueInProxy({
|
|
87
|
+
length,
|
|
88
|
+
property,
|
|
89
|
+
state,
|
|
90
|
+
target,
|
|
91
|
+
value,
|
|
92
|
+
isArray: true,
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
299
95
|
|
|
300
|
-
|
|
96
|
+
function get(): Item[];
|
|
97
|
+
function get(index: number): Item | undefined;
|
|
98
|
+
function get(property: typeof PROPERTY_LENGTH): number;
|
|
99
|
+
function get(value?: unknown): number | Item | Item[] | undefined;
|
|
301
100
|
|
|
302
|
-
|
|
101
|
+
function get(value?: unknown): number | Item | Item[] | undefined {
|
|
102
|
+
return getArrayValue(instance as ReactiveArray<Item>, indiced, state, length, value);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function set(first?: unknown, second?: unknown): void {
|
|
106
|
+
setProxyValue<Item[], Item>(
|
|
107
|
+
true,
|
|
108
|
+
state,
|
|
109
|
+
isArrayValue,
|
|
110
|
+
isArrayIndex,
|
|
111
|
+
setArray,
|
|
112
|
+
setAtIndex,
|
|
113
|
+
first,
|
|
114
|
+
second,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const handlers = {
|
|
119
|
+
...rx,
|
|
120
|
+
get: (value?: number | typeof PROPERTY_LENGTH) => get(value),
|
|
121
|
+
peek: (first?: unknown, second?: boolean) => peekArrayValue(state, length, first, second),
|
|
122
|
+
subscribe: (first: number | GenericCallback, second?: GenericCallback) => {
|
|
123
|
+
if (typeof first === 'number' && typeof second === 'function') {
|
|
124
|
+
return getReactiveValueInProxy(
|
|
125
|
+
instance as ReactiveArray<Item>,
|
|
126
|
+
indiced,
|
|
127
|
+
first,
|
|
128
|
+
true,
|
|
129
|
+
).subscribe(second);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return typeof first === 'function' ? subscribe(state, first) : noop;
|
|
133
|
+
},
|
|
134
|
+
unsubscribe: (first: number | GenericCallback, second?: GenericCallback) => {
|
|
135
|
+
if (typeof first === 'number' && typeof second === 'function') {
|
|
136
|
+
getReactiveValueInProxy(instance as ReactiveArray<Item>, indiced, first, true)?.unsubscribe(
|
|
137
|
+
second,
|
|
138
|
+
);
|
|
139
|
+
} else if (typeof first === 'function') {
|
|
140
|
+
unsubscribe(state, first);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
instance = {
|
|
146
|
+
...handlers,
|
|
147
|
+
asReadonly: (frozen?: unknown) =>
|
|
148
|
+
getReadonlyInstance(state, readonlies, handlers, frozen === true),
|
|
149
|
+
at: (index: number): Item | undefined => get(index),
|
|
150
|
+
clear: () => {
|
|
151
|
+
state.value.length = 0;
|
|
152
|
+
},
|
|
153
|
+
filter: (callback: (item: Item, index: number, array: Item[]) => boolean) =>
|
|
154
|
+
computed(() => filter(get(), callback)),
|
|
155
|
+
map: <Mapped>(callback: (item: Item, index: number, array: Item[]) => Mapped) =>
|
|
156
|
+
computed(() => get().map(callback)),
|
|
157
|
+
notify: () => {
|
|
158
|
+
emityProxyValues(state, indiced);
|
|
159
|
+
},
|
|
160
|
+
pop: () => state.value.pop(),
|
|
161
|
+
push: (...items: Item[]) => state.value.push(...items),
|
|
162
|
+
select: <Mapped>(
|
|
163
|
+
filter: (item: Item, index: number, array: Item[]) => boolean,
|
|
164
|
+
map: (item: Item, index: number, array: Item[]) => Mapped,
|
|
165
|
+
) => computed(() => select(get() as Item[], filter, map)),
|
|
166
|
+
set: (first?: unknown, second?: unknown) => {
|
|
167
|
+
set(first, second);
|
|
168
|
+
},
|
|
169
|
+
shift: () => state.value.shift(),
|
|
170
|
+
splice: (from: number, to?: number, ...items: Item[]) =>
|
|
171
|
+
state.value.splice(from, to ?? state.value.length, ...items),
|
|
172
|
+
unshift: (...items: Item[]) => state.value.unshift(...items),
|
|
173
|
+
update: (callback: (value: Item[]) => Item[]) =>
|
|
174
|
+
updateArrayValue(instance as ReactiveArray<Item>, state, callback),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
Object.defineProperties(instance, {
|
|
178
|
+
[NAME_MORA]: {
|
|
179
|
+
enumerable: false,
|
|
180
|
+
value: NAME_ARRAY,
|
|
181
|
+
},
|
|
182
|
+
length: {
|
|
183
|
+
enumerable: true,
|
|
184
|
+
get: () => length.get(),
|
|
185
|
+
set: (value: number) => setArrayLength(state, value),
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
set(value);
|
|
190
|
+
|
|
191
|
+
return Object.freeze(instance) as ReactiveArray<Item>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function getArrayValue<Item>(
|
|
195
|
+
instance: ReactiveArray<Item>,
|
|
196
|
+
indiced: Map<number, [Computed<unknown>, ComputedEffect]>,
|
|
197
|
+
state: ReactiveState<Item[], Item>,
|
|
198
|
+
length: Signal<number>,
|
|
199
|
+
first?: unknown,
|
|
200
|
+
): number | Item | Item[] | undefined {
|
|
201
|
+
if (typeof first === 'number') {
|
|
202
|
+
return getReactiveValueInProxy(instance, indiced, first, true).get();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return first === PROPERTY_LENGTH ? length.get() : getSimpleValue(state);
|
|
303
206
|
}
|
|
304
207
|
|
|
305
208
|
function isArrayIndex(value: unknown): boolean {
|
|
@@ -310,6 +213,57 @@ function isArrayValue<Item>(value: unknown): value is Item[] | undefined {
|
|
|
310
213
|
return value == null || Array.isArray(value);
|
|
311
214
|
}
|
|
312
215
|
|
|
216
|
+
function peekArrayValue<Item>(
|
|
217
|
+
state: ReactiveState<Item[], Item>,
|
|
218
|
+
length: Signal<number>,
|
|
219
|
+
first?: unknown,
|
|
220
|
+
second?: boolean,
|
|
221
|
+
): number | Item | Item[] | undefined {
|
|
222
|
+
if (first === PROPERTY_LENGTH) {
|
|
223
|
+
return length.peek();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let value: Item | Item[] | undefined;
|
|
227
|
+
|
|
228
|
+
if (typeof first === 'number') {
|
|
229
|
+
value = state.value.at(first);
|
|
230
|
+
} else {
|
|
231
|
+
value = state.value;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!(first === true || second === true)) {
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (Array.isArray(value)) {
|
|
239
|
+
return value.slice();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (isPlainObject(value)) {
|
|
243
|
+
return {...value};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return value;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function setArray<Item>(state: ReactiveState<Item[], Item>, value: Item[] | undefined): void {
|
|
250
|
+
state.value.splice(0, state.value.length, ...(value ?? []));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function setArrayLength<Item>(state: ReactiveState<Item[], Item>, value: number): void {
|
|
254
|
+
if (typeof value === 'number' && value >= 0 && value !== state.value.length) {
|
|
255
|
+
state.value.length = value;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function setAtIndex<Item>(state: ReactiveState<Item[], Item>, index: unknown, value: Item): void {
|
|
260
|
+
const actual = (index as number) < 0 ? state.value.length + (index as number) : (index as number);
|
|
261
|
+
|
|
262
|
+
if (actual > -1) {
|
|
263
|
+
state.value[actual] = value;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
313
267
|
function updateArray<Item>(
|
|
314
268
|
type: string,
|
|
315
269
|
array: Item[],
|
|
@@ -335,14 +289,14 @@ function updateArray<Item>(
|
|
|
335
289
|
};
|
|
336
290
|
}
|
|
337
291
|
|
|
338
|
-
function
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const
|
|
292
|
+
function updateArrayValue<Item>(
|
|
293
|
+
instance: ReactiveArray<Item>,
|
|
294
|
+
state: ReactiveState<Item[], Item>,
|
|
295
|
+
callback: (value: Item[]) => Item[],
|
|
296
|
+
): void {
|
|
297
|
+
const updated = callback(state.value);
|
|
344
298
|
|
|
345
|
-
if (
|
|
346
|
-
|
|
299
|
+
if (updated == null || Array.isArray(updated)) {
|
|
300
|
+
instance.set(updated);
|
|
347
301
|
}
|
|
348
302
|
}
|