@oscarpalmer/mora 0.25.0 → 0.27.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 +14 -0
- package/dist/{batch.js → batch.mjs} +13 -3
- package/dist/constants-Cy6_M9Vk.d.mts +20 -0
- package/dist/constants.d.mts +2 -0
- package/dist/{constants.js → constants.mjs} +2 -0
- package/dist/effect-BkupB1p9.d.mts +17 -0
- package/dist/effect.d.mts +2 -0
- package/dist/{effect.js → effect.mjs} +11 -4
- package/dist/helpers/is.d.mts +45 -0
- package/dist/helpers/is.mjs +55 -0
- package/dist/helpers/proxy.d.mts +14 -0
- package/dist/helpers/{proxy.js → proxy.mjs} +6 -4
- package/dist/helpers/value.d.mts +8 -0
- package/dist/helpers/{value.js → value.mjs} +4 -2
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +8 -0
- package/dist/models-QwNga87R.d.mts +148 -0
- package/dist/models.d.mts +2 -0
- package/dist/models.mjs +1 -0
- package/dist/{mora.full.js → mora.full.mjs} +68 -62
- package/dist/subscription.d.mts +2 -0
- package/dist/{subscription.js → subscription.mjs} +2 -0
- package/dist/value/array.d.mts +140 -0
- package/dist/value/{array.js → array.mjs} +80 -18
- package/dist/value/computed.d.mts +2 -0
- package/dist/value/{computed.js → computed.mjs} +16 -5
- package/dist/value/reactive.d.mts +2 -0
- package/dist/value/{reactive.js → reactive.mjs} +25 -2
- package/dist/value/signal.d.mts +2 -0
- package/dist/value/signal.mjs +43 -0
- package/dist/value/store.d.mts +97 -0
- package/dist/value/{store.js → store.mjs} +25 -7
- package/package.json +41 -35
- package/src/constants.ts +1 -6
- package/src/helpers/is.ts +1 -1
- package/src/value/array.ts +6 -6
- package/src/value/store.ts +1 -1
- package/dist/helpers/is.js +0 -23
- package/dist/index.js +0 -8
- package/dist/models.js +0 -0
- package/dist/value/signal.js +0 -24
|
@@ -1,7 +1,5 @@
|
|
|
1
|
+
//#region src/constants.ts
|
|
1
2
|
const ACTIVE = {};
|
|
2
|
-
const ARRAY_THRESHOLD = 100;
|
|
3
|
-
const ARRAY_OFFSET = 25;
|
|
4
|
-
const ARRAY_PEEK = 10;
|
|
5
3
|
const BATCH = {
|
|
6
4
|
depth: 0,
|
|
7
5
|
handlers: /* @__PURE__ */ new Set()
|
|
@@ -32,8 +30,8 @@ const NAME_ALL = new Set([
|
|
|
32
30
|
NAME_SIGNAL,
|
|
33
31
|
NAME_STORE
|
|
34
32
|
]);
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/effect.ts
|
|
37
35
|
var Effect = class {
|
|
38
36
|
constructor(callback) {
|
|
39
37
|
Object.defineProperty(this, NAME_MORA, { value: NAME_EFFECT });
|
|
@@ -41,11 +39,11 @@ var Effect = class {
|
|
|
41
39
|
runEffect(this);
|
|
42
40
|
}
|
|
43
41
|
};
|
|
44
|
-
function runEffect(effect
|
|
42
|
+
function runEffect(effect) {
|
|
45
43
|
const previousEffect = ACTIVE.effect;
|
|
46
|
-
ACTIVE.effect = effect
|
|
44
|
+
ACTIVE.effect = effect;
|
|
47
45
|
try {
|
|
48
|
-
effect
|
|
46
|
+
effect.state.callback();
|
|
49
47
|
} finally {
|
|
50
48
|
ACTIVE.effect = previousEffect;
|
|
51
49
|
}
|
|
@@ -58,7 +56,8 @@ function runEffect(effect$1) {
|
|
|
58
56
|
function effect(callback) {
|
|
59
57
|
return typeof callback === "function" ? new Effect(callback) : void 0;
|
|
60
58
|
}
|
|
61
|
-
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/helpers/is.ts
|
|
62
61
|
/**
|
|
63
62
|
* Is the value a reactive array?
|
|
64
63
|
* @param value Value to check
|
|
@@ -84,7 +83,7 @@ function isEffect(value) {
|
|
|
84
83
|
return isMora(value, NAME_EFFECT);
|
|
85
84
|
}
|
|
86
85
|
function isMora(value, name) {
|
|
87
|
-
return typeof value === "object" && value != null &&
|
|
86
|
+
return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value["$mora"] === name : name.has(value["$mora"]));
|
|
88
87
|
}
|
|
89
88
|
/**
|
|
90
89
|
* Is the value reactive?
|
|
@@ -102,7 +101,8 @@ function isReactive(value) {
|
|
|
102
101
|
function isSignal(value) {
|
|
103
102
|
return isMora(value, NAME_SIGNAL);
|
|
104
103
|
}
|
|
105
|
-
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/batch.ts
|
|
106
106
|
function flushHandlers() {
|
|
107
107
|
while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
|
|
108
108
|
const handlers = [...BATCH.handlers];
|
|
@@ -126,7 +126,8 @@ function stopBatch() {
|
|
|
126
126
|
if (BATCH.depth > 0) BATCH.depth -= 1;
|
|
127
127
|
flushHandlers();
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/subscription.ts
|
|
130
131
|
var Subscription = class {
|
|
131
132
|
callback;
|
|
132
133
|
state;
|
|
@@ -152,7 +153,8 @@ function unsubscribe(state, callback) {
|
|
|
152
153
|
state.subscriptions.get(callback)?.destroy();
|
|
153
154
|
state.subscriptions.delete(callback);
|
|
154
155
|
}
|
|
155
|
-
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/value/reactive.ts
|
|
156
158
|
var Reactive = class {
|
|
157
159
|
state = {
|
|
158
160
|
computeds: /* @__PURE__ */ new Set(),
|
|
@@ -203,7 +205,8 @@ var Reactive = class {
|
|
|
203
205
|
unsubscribe(this.state, callback);
|
|
204
206
|
}
|
|
205
207
|
};
|
|
206
|
-
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/value/computed.ts
|
|
207
210
|
var Computed = class extends Reactive {
|
|
208
211
|
effect = {
|
|
209
212
|
dirty: true,
|
|
@@ -219,8 +222,8 @@ var Computed = class extends Reactive {
|
|
|
219
222
|
ACTIVE.computed = previousComputed;
|
|
220
223
|
if (!this.state.equal(this.state.value, value)) {
|
|
221
224
|
this.state.value = value;
|
|
222
|
-
for (const computed
|
|
223
|
-
for (const effect
|
|
225
|
+
for (const computed of this.state.computeds) computed.effect.dirty = true;
|
|
226
|
+
for (const effect of this.state.effects) BATCH.handlers.add(effect);
|
|
224
227
|
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
225
228
|
}
|
|
226
229
|
this.effect.dirty = false;
|
|
@@ -245,10 +248,11 @@ var Computed = class extends Reactive {
|
|
|
245
248
|
function computed(callback, options) {
|
|
246
249
|
return new Computed(callback, options);
|
|
247
250
|
}
|
|
248
|
-
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/helpers/value.ts
|
|
249
253
|
function emitValue(state) {
|
|
250
|
-
for (const computed
|
|
251
|
-
for (const effect
|
|
254
|
+
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
255
|
+
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
252
256
|
for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
|
|
253
257
|
if (BATCH.depth === 0) flushHandlers();
|
|
254
258
|
}
|
|
@@ -256,9 +260,9 @@ function equalArrays(state, first, second) {
|
|
|
256
260
|
let { length } = first;
|
|
257
261
|
if (length !== second.length) return false;
|
|
258
262
|
let offset = 0;
|
|
259
|
-
if (length >=
|
|
260
|
-
offset = Math.round(length /
|
|
261
|
-
offset = offset >
|
|
263
|
+
if (length >= 100) {
|
|
264
|
+
offset = Math.round(length / 10);
|
|
265
|
+
offset = offset > 25 ? 25 : offset;
|
|
262
266
|
for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
263
267
|
}
|
|
264
268
|
length -= offset;
|
|
@@ -270,17 +274,18 @@ function getValue(state) {
|
|
|
270
274
|
if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
|
|
271
275
|
return state.value;
|
|
272
276
|
}
|
|
273
|
-
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/helpers/proxy.ts
|
|
274
279
|
function emityProxyValues(state, mapped) {
|
|
275
280
|
const values = [...mapped.values()];
|
|
276
281
|
const { length } = values;
|
|
277
282
|
for (let index = 0; index < length; index += 1) values[index].effect.dirty = true;
|
|
278
283
|
emitValue(state);
|
|
279
284
|
}
|
|
280
|
-
function getReactiveValueInProxy(reactive, mapped, key, isArray
|
|
285
|
+
function getReactiveValueInProxy(reactive, mapped, key, isArray) {
|
|
281
286
|
let item = mapped.get(key);
|
|
282
287
|
if (item == null) {
|
|
283
|
-
item = computed(() => isArray
|
|
288
|
+
item = computed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
|
|
284
289
|
mapped.set(key, item);
|
|
285
290
|
}
|
|
286
291
|
return item;
|
|
@@ -302,19 +307,20 @@ function setProxyValue(proxy, value) {
|
|
|
302
307
|
stopBatch();
|
|
303
308
|
}
|
|
304
309
|
function setValueInProxy(parameters) {
|
|
305
|
-
const { isArray
|
|
306
|
-
if (isArray
|
|
307
|
-
if (!(!Number.isNaN(Number(property)) || property ===
|
|
310
|
+
const { isArray, length, property, state, target, value } = parameters;
|
|
311
|
+
if (isArray) {
|
|
312
|
+
if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
|
|
308
313
|
}
|
|
309
314
|
const previous = Reflect.get(target, property);
|
|
310
315
|
if (!state.equal(previous, value)) {
|
|
311
316
|
Reflect.set(target, property, value);
|
|
312
317
|
emitValue(state);
|
|
313
|
-
if (isArray
|
|
318
|
+
if (isArray) length?.set(target.length);
|
|
314
319
|
}
|
|
315
320
|
return true;
|
|
316
321
|
}
|
|
317
|
-
|
|
322
|
+
//#endregion
|
|
323
|
+
//#region src/value/signal.ts
|
|
318
324
|
var Signal = class extends Reactive {
|
|
319
325
|
constructor(value, options) {
|
|
320
326
|
super(NAME_SIGNAL, value, options);
|
|
@@ -352,7 +358,8 @@ var Signal = class extends Reactive {
|
|
|
352
358
|
function signal(value, options) {
|
|
353
359
|
return new Signal(value, options);
|
|
354
360
|
}
|
|
355
|
-
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region src/value/array.ts
|
|
356
363
|
var ReactiveArray = class extends Reactive {
|
|
357
364
|
#indiced = /* @__PURE__ */ new Map();
|
|
358
365
|
#size = signal(0);
|
|
@@ -371,10 +378,10 @@ var ReactiveArray = class extends Reactive {
|
|
|
371
378
|
constructor(value, options) {
|
|
372
379
|
super(NAME_ARRAY, new Proxy(value, {
|
|
373
380
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
374
|
-
set: (target, property, value
|
|
381
|
+
set: (target, property, value) => setValueInProxy({
|
|
375
382
|
property,
|
|
376
383
|
target,
|
|
377
|
-
value
|
|
384
|
+
value,
|
|
378
385
|
isArray: true,
|
|
379
386
|
state: this.state,
|
|
380
387
|
length: this.#size
|
|
@@ -398,7 +405,7 @@ var ReactiveArray = class extends Reactive {
|
|
|
398
405
|
}
|
|
399
406
|
get(first) {
|
|
400
407
|
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
401
|
-
return first ===
|
|
408
|
+
return first === "length" ? this.length : getValue(this.state);
|
|
402
409
|
}
|
|
403
410
|
/**
|
|
404
411
|
* Create a computed, mapped array
|
|
@@ -488,54 +495,53 @@ var ReactiveArray = class extends Reactive {
|
|
|
488
495
|
function array(value, options) {
|
|
489
496
|
return new ReactiveArray(Array.isArray(value) ? value : [], options);
|
|
490
497
|
}
|
|
491
|
-
function updateArray(type, array
|
|
498
|
+
function updateArray(type, array, state, length) {
|
|
492
499
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
493
|
-
const previousArray = affectsLength ? [] : [...array
|
|
494
|
-
const previousLength = array
|
|
500
|
+
const previousArray = affectsLength ? [] : [...array];
|
|
501
|
+
const previousLength = array.length;
|
|
495
502
|
return (...args) => {
|
|
496
|
-
const result = array
|
|
497
|
-
if (affectsLength ? array
|
|
503
|
+
const result = array[type](...args);
|
|
504
|
+
if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
|
|
498
505
|
emitValue(state);
|
|
499
|
-
length.set(array
|
|
506
|
+
length.set(array.length);
|
|
500
507
|
}
|
|
501
508
|
return result;
|
|
502
509
|
};
|
|
503
510
|
}
|
|
504
|
-
function setAtIndex(array
|
|
505
|
-
const actual = index < 0 ? array
|
|
506
|
-
if (actual > -1) array
|
|
511
|
+
function setAtIndex(array, index, value) {
|
|
512
|
+
const actual = index < 0 ? array.length + index : index;
|
|
513
|
+
if (actual > -1) array[actual] = value;
|
|
507
514
|
}
|
|
508
|
-
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
517
|
+
/**
|
|
518
|
+
* Is the value a key?
|
|
519
|
+
* @param value Value to check
|
|
520
|
+
* @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
|
|
521
|
+
*/
|
|
509
522
|
function isKey(value) {
|
|
510
523
|
return typeof value === "number" || typeof value === "string";
|
|
511
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Is the value a plain object?
|
|
527
|
+
* @param value Value to check
|
|
528
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
529
|
+
*/
|
|
512
530
|
function isPlainObject(value) {
|
|
513
531
|
if (value === null || typeof value !== "object") return false;
|
|
514
532
|
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
515
533
|
const prototype = Object.getPrototypeOf(value);
|
|
516
534
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
517
535
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
Uint8Array,
|
|
521
|
-
Uint8ClampedArray,
|
|
522
|
-
Int16Array,
|
|
523
|
-
Uint16Array,
|
|
524
|
-
Int32Array,
|
|
525
|
-
Uint32Array,
|
|
526
|
-
Float32Array,
|
|
527
|
-
Float64Array,
|
|
528
|
-
BigInt64Array,
|
|
529
|
-
BigUint64Array
|
|
530
|
-
]);
|
|
531
|
-
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/value/store.ts
|
|
532
538
|
var Store = class extends Reactive {
|
|
533
539
|
#keyed = /* @__PURE__ */ new Map();
|
|
534
540
|
constructor(value, options) {
|
|
535
|
-
super(NAME_STORE, new Proxy(value, { set: (target, property, value
|
|
541
|
+
super(NAME_STORE, new Proxy(value, { set: (target, property, value) => setValueInProxy({
|
|
536
542
|
target,
|
|
537
543
|
property,
|
|
538
|
-
value
|
|
544
|
+
value,
|
|
539
545
|
isArray: false,
|
|
540
546
|
state: this.state
|
|
541
547
|
}) }), options);
|
|
@@ -581,5 +587,5 @@ var Store = class extends Reactive {
|
|
|
581
587
|
function store(value, options) {
|
|
582
588
|
return new Store(isPlainObject(value) ? value : {}, options);
|
|
583
589
|
}
|
|
584
|
-
|
|
585
|
-
export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
590
|
+
//#endregion
|
|
591
|
+
export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/subscription.ts
|
|
1
2
|
var Subscription = class {
|
|
2
3
|
callback;
|
|
3
4
|
state;
|
|
@@ -23,4 +24,5 @@ function unsubscribe(state, callback) {
|
|
|
23
24
|
state.subscriptions.get(callback)?.destroy();
|
|
24
25
|
state.subscriptions.delete(callback);
|
|
25
26
|
}
|
|
27
|
+
//#endregion
|
|
26
28
|
export { Subscription, noop, subscribe, unsubscribe };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { h as Reactive, p as Computed, s as ReactiveOptions, u as Unsubscribe } from "../models-QwNga87R.mjs";
|
|
2
|
+
import { h as PROPERTY_LENGTH } from "../constants-Cy6_M9Vk.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/value/array.d.ts
|
|
5
|
+
declare class ReactiveArray<Item> extends Reactive<Item[], Item> {
|
|
6
|
+
#private;
|
|
7
|
+
/**
|
|
8
|
+
* The length of the array
|
|
9
|
+
*/
|
|
10
|
+
get length(): number;
|
|
11
|
+
/**
|
|
12
|
+
* Set the length of the array
|
|
13
|
+
*/
|
|
14
|
+
set length(value: number);
|
|
15
|
+
constructor(value: Item[], options?: ReactiveOptions<Item>);
|
|
16
|
+
/**
|
|
17
|
+
* Clear the array
|
|
18
|
+
*/
|
|
19
|
+
clear(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Create a computed, filtered array
|
|
22
|
+
* @param callback Callback to evaluate each item
|
|
23
|
+
* @return Computed array of filtered items
|
|
24
|
+
*/
|
|
25
|
+
filter(callback: (item: Item, index: number, array: Item[]) => boolean): Computed<Item[]>;
|
|
26
|
+
/**
|
|
27
|
+
* @inheritdoc
|
|
28
|
+
*/
|
|
29
|
+
get(): Item[];
|
|
30
|
+
/**
|
|
31
|
+
* Get the value at an index
|
|
32
|
+
* @param index Index of item to get _(if negative, starts from the end)_
|
|
33
|
+
* @returns Item at index, or `undefined` if it doesn't exist
|
|
34
|
+
*/
|
|
35
|
+
get(index: number): Item | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Get the length of the array
|
|
38
|
+
* @returns Length of the array
|
|
39
|
+
*/
|
|
40
|
+
get(property: typeof PROPERTY_LENGTH): number;
|
|
41
|
+
/**
|
|
42
|
+
* Create a computed, mapped array
|
|
43
|
+
* @param callback Callback to transform each item
|
|
44
|
+
* @return Computed array of mapped items
|
|
45
|
+
*/
|
|
46
|
+
map<Mapped>(callback: (item: Item, index: number, array: Item[]) => Mapped): Computed<Mapped[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Notify dependents of changes
|
|
49
|
+
*
|
|
50
|
+
* _This bypasses equality checks and will immediately notify dependents.
|
|
51
|
+
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
52
|
+
*/
|
|
53
|
+
notify(): void;
|
|
54
|
+
/**
|
|
55
|
+
* @inheritdoc
|
|
56
|
+
*/
|
|
57
|
+
peek(): Item[];
|
|
58
|
+
/**
|
|
59
|
+
* Get the value at an index _(without reactivity)_
|
|
60
|
+
* @param index Index of item to get _(if negative, starts from the end)_
|
|
61
|
+
* @returns Item at index, or `undefined` if it doesn't exist
|
|
62
|
+
*/
|
|
63
|
+
peek(index: number): Item | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Get the length of the array _(without reactivity)_
|
|
66
|
+
* @returns Length of the array
|
|
67
|
+
*/
|
|
68
|
+
peek(property: typeof PROPERTY_LENGTH): number;
|
|
69
|
+
/**
|
|
70
|
+
* Remove and return the last item of the array
|
|
71
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
72
|
+
*/
|
|
73
|
+
pop(): Item | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Add items to the end of the array
|
|
76
|
+
* @param items Items to add
|
|
77
|
+
* @returns New array length
|
|
78
|
+
*/
|
|
79
|
+
push(...items: Item[]): number;
|
|
80
|
+
/**
|
|
81
|
+
* Set the value
|
|
82
|
+
* @param value New array of items _(defaults to an empty array)_
|
|
83
|
+
*/
|
|
84
|
+
set(value?: Item[]): void;
|
|
85
|
+
/**
|
|
86
|
+
* Set the value at an index
|
|
87
|
+
* @param index Index of item to set __(if negative, starts from the end)_
|
|
88
|
+
* @param value New item
|
|
89
|
+
*/
|
|
90
|
+
set(index: number, value: Item): void;
|
|
91
|
+
/**
|
|
92
|
+
* Set the length of the array
|
|
93
|
+
* @param value New array length
|
|
94
|
+
*/
|
|
95
|
+
set(property: typeof PROPERTY_LENGTH, value: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Remove and return the first item of the array
|
|
98
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
99
|
+
*/
|
|
100
|
+
shift(): Item | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Remove and return items from the array _(and optionally add new items)_
|
|
103
|
+
* @param from Index to start removing items from
|
|
104
|
+
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
105
|
+
* @param items Optional items to add
|
|
106
|
+
* @returns Removed items
|
|
107
|
+
*/
|
|
108
|
+
splice(from: number, to?: number, ...items: Item[]): Item[];
|
|
109
|
+
/**
|
|
110
|
+
* @inheritdoc
|
|
111
|
+
*/
|
|
112
|
+
subscribe(callback: (value: Item[]) => void): Unsubscribe;
|
|
113
|
+
/**
|
|
114
|
+
* Subscribe to changes at a specific index
|
|
115
|
+
* @param index Index of item to subscribe to
|
|
116
|
+
* @param callback Callback for changes
|
|
117
|
+
* @returns Unsubscribe callback
|
|
118
|
+
*/
|
|
119
|
+
subscribe(index: number, callback: (value: Item | undefined) => void): Unsubscribe;
|
|
120
|
+
/**
|
|
121
|
+
* Add items to the beginning of the array
|
|
122
|
+
* @param items Items to add
|
|
123
|
+
* @returns New array length
|
|
124
|
+
*/
|
|
125
|
+
unshift(...items: Item[]): number;
|
|
126
|
+
/**
|
|
127
|
+
* Update the value _(based on the current value)_
|
|
128
|
+
* @param callback Callback to update the value
|
|
129
|
+
*/
|
|
130
|
+
update(callback: (value: Item[]) => Item[]): void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Create a reactive array
|
|
134
|
+
* @param value Initial array of items
|
|
135
|
+
* @param options Reactivity options
|
|
136
|
+
* @returns Reactive array
|
|
137
|
+
*/
|
|
138
|
+
declare function array<Item>(value: Item[], options?: ReactiveOptions<Item>): ReactiveArray<Item>;
|
|
139
|
+
//#endregion
|
|
140
|
+
export { ReactiveArray, array };
|
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY
|
|
2
|
-
import { noop, subscribe } from "../subscription.
|
|
3
|
-
import { Reactive } from "./reactive.
|
|
4
|
-
import { computed } from "./computed.
|
|
5
|
-
import { emitValue, equalArrays, getValue } from "../helpers/value.
|
|
6
|
-
import { emityProxyValues, getReactiveValueInProxy, setValueInProxy } from "../helpers/proxy.
|
|
7
|
-
import { signal } from "./signal.
|
|
1
|
+
import { METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ARRAY } from "../constants.mjs";
|
|
2
|
+
import { noop, subscribe } from "../subscription.mjs";
|
|
3
|
+
import { Reactive } from "./reactive.mjs";
|
|
4
|
+
import { computed } from "./computed.mjs";
|
|
5
|
+
import { emitValue, equalArrays, getValue } from "../helpers/value.mjs";
|
|
6
|
+
import { emityProxyValues, getReactiveValueInProxy, setValueInProxy } from "../helpers/proxy.mjs";
|
|
7
|
+
import { signal } from "./signal.mjs";
|
|
8
|
+
//#region src/value/array.ts
|
|
8
9
|
var ReactiveArray = class extends Reactive {
|
|
9
10
|
#indiced = /* @__PURE__ */ new Map();
|
|
10
11
|
#size = signal(0);
|
|
12
|
+
/**
|
|
13
|
+
* The length of the array
|
|
14
|
+
*/
|
|
11
15
|
get length() {
|
|
12
16
|
return this.#size.get();
|
|
13
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Set the length of the array
|
|
20
|
+
*/
|
|
14
21
|
set length(value) {
|
|
15
22
|
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
|
|
16
23
|
}
|
|
17
24
|
constructor(value, options) {
|
|
18
25
|
super(NAME_ARRAY, new Proxy(value, {
|
|
19
26
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
20
|
-
set: (target, property, value
|
|
27
|
+
set: (target, property, value) => setValueInProxy({
|
|
21
28
|
property,
|
|
22
29
|
target,
|
|
23
|
-
value
|
|
30
|
+
value,
|
|
24
31
|
isArray: true,
|
|
25
32
|
state: this.state,
|
|
26
33
|
length: this.#size
|
|
@@ -28,9 +35,17 @@ var ReactiveArray = class extends Reactive {
|
|
|
28
35
|
}), options);
|
|
29
36
|
this.#size.set(value.length);
|
|
30
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Clear the array
|
|
40
|
+
*/
|
|
31
41
|
clear() {
|
|
32
42
|
this.length = 0;
|
|
33
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a computed, filtered array
|
|
46
|
+
* @param callback Callback to evaluate each item
|
|
47
|
+
* @return Computed array of filtered items
|
|
48
|
+
*/
|
|
34
49
|
filter(callback) {
|
|
35
50
|
return computed(() => this.get().filter(callback));
|
|
36
51
|
}
|
|
@@ -38,9 +53,20 @@ var ReactiveArray = class extends Reactive {
|
|
|
38
53
|
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
39
54
|
return first === "length" ? this.length : getValue(this.state);
|
|
40
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a computed, mapped array
|
|
58
|
+
* @param callback Callback to transform each item
|
|
59
|
+
* @return Computed array of mapped items
|
|
60
|
+
*/
|
|
41
61
|
map(callback) {
|
|
42
62
|
return computed(() => this.get().map(callback));
|
|
43
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
|
+
*/
|
|
44
70
|
notify() {
|
|
45
71
|
emityProxyValues(this.state, this.#indiced);
|
|
46
72
|
}
|
|
@@ -48,9 +74,18 @@ var ReactiveArray = class extends Reactive {
|
|
|
48
74
|
if (value === "length") return this.#size.peek();
|
|
49
75
|
return typeof value === "number" ? this.state.value.at(value) : [...this.state.value];
|
|
50
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Remove and return the last item of the array
|
|
79
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
80
|
+
*/
|
|
51
81
|
pop() {
|
|
52
82
|
return this.state.value.pop();
|
|
53
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Add items to the end of the array
|
|
86
|
+
* @param items Items to add
|
|
87
|
+
* @returns New array length
|
|
88
|
+
*/
|
|
54
89
|
push(...items) {
|
|
55
90
|
return this.state.value.push(...items);
|
|
56
91
|
}
|
|
@@ -59,9 +94,20 @@ var ReactiveArray = class extends Reactive {
|
|
|
59
94
|
else if (first === "length") this.length = second;
|
|
60
95
|
else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
|
|
61
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove and return the first item of the array
|
|
99
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
100
|
+
*/
|
|
62
101
|
shift() {
|
|
63
102
|
return this.state.value.shift();
|
|
64
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Remove and return items from the array _(and optionally add new items)_
|
|
106
|
+
* @param from Index to start removing items from
|
|
107
|
+
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
108
|
+
* @param items Optional items to add
|
|
109
|
+
* @returns Removed items
|
|
110
|
+
*/
|
|
65
111
|
splice(from, to, ...items) {
|
|
66
112
|
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
67
113
|
}
|
|
@@ -69,32 +115,48 @@ var ReactiveArray = class extends Reactive {
|
|
|
69
115
|
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
70
116
|
return typeof first === "function" ? subscribe(this.state, first) : noop;
|
|
71
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Add items to the beginning of the array
|
|
120
|
+
* @param items Items to add
|
|
121
|
+
* @returns New array length
|
|
122
|
+
*/
|
|
72
123
|
unshift(...items) {
|
|
73
124
|
return this.state.value.unshift(...items);
|
|
74
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Update the value _(based on the current value)_
|
|
128
|
+
* @param callback Callback to update the value
|
|
129
|
+
*/
|
|
75
130
|
update(callback) {
|
|
76
131
|
const updated = callback(this.state.value);
|
|
77
132
|
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
78
133
|
}
|
|
79
134
|
};
|
|
135
|
+
/**
|
|
136
|
+
* Create a reactive array
|
|
137
|
+
* @param value Initial array of items
|
|
138
|
+
* @param options Reactivity options
|
|
139
|
+
* @returns Reactive array
|
|
140
|
+
*/
|
|
80
141
|
function array(value, options) {
|
|
81
142
|
return new ReactiveArray(Array.isArray(value) ? value : [], options);
|
|
82
143
|
}
|
|
83
|
-
function updateArray(type, array
|
|
144
|
+
function updateArray(type, array, state, length) {
|
|
84
145
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
85
|
-
const previousArray = affectsLength ? [] : [...array
|
|
86
|
-
const previousLength = array
|
|
146
|
+
const previousArray = affectsLength ? [] : [...array];
|
|
147
|
+
const previousLength = array.length;
|
|
87
148
|
return (...args) => {
|
|
88
|
-
const result = array
|
|
89
|
-
if (affectsLength ? array
|
|
149
|
+
const result = array[type](...args);
|
|
150
|
+
if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
|
|
90
151
|
emitValue(state);
|
|
91
|
-
length.set(array
|
|
152
|
+
length.set(array.length);
|
|
92
153
|
}
|
|
93
154
|
return result;
|
|
94
155
|
};
|
|
95
156
|
}
|
|
96
|
-
function setAtIndex(array
|
|
97
|
-
const actual = index < 0 ? array
|
|
98
|
-
if (actual > -1) array
|
|
157
|
+
function setAtIndex(array, index, value) {
|
|
158
|
+
const actual = index < 0 ? array.length + index : index;
|
|
159
|
+
if (actual > -1) array[actual] = value;
|
|
99
160
|
}
|
|
161
|
+
//#endregion
|
|
100
162
|
export { ReactiveArray, array };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ACTIVE, BATCH, NAME_COMPUTED } from "../constants.
|
|
2
|
-
import { effect, runEffect } from "../effect.
|
|
3
|
-
import { Reactive } from "./reactive.
|
|
1
|
+
import { ACTIVE, BATCH, NAME_COMPUTED } from "../constants.mjs";
|
|
2
|
+
import { effect, runEffect } from "../effect.mjs";
|
|
3
|
+
import { Reactive } from "./reactive.mjs";
|
|
4
|
+
//#region src/value/computed.ts
|
|
4
5
|
var Computed = class extends Reactive {
|
|
5
6
|
effect = {
|
|
6
7
|
dirty: true,
|
|
@@ -16,13 +17,16 @@ var Computed = class extends Reactive {
|
|
|
16
17
|
ACTIVE.computed = previousComputed;
|
|
17
18
|
if (!this.state.equal(this.state.value, value)) {
|
|
18
19
|
this.state.value = value;
|
|
19
|
-
for (const computed
|
|
20
|
-
for (const effect
|
|
20
|
+
for (const computed of this.state.computeds) computed.effect.dirty = true;
|
|
21
|
+
for (const effect of this.state.effects) BATCH.handlers.add(effect);
|
|
21
22
|
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
22
23
|
}
|
|
23
24
|
this.effect.dirty = false;
|
|
24
25
|
});
|
|
25
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* @inheritdoc
|
|
29
|
+
*/
|
|
26
30
|
get() {
|
|
27
31
|
if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
|
|
28
32
|
if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
|
|
@@ -30,7 +34,14 @@ var Computed = class extends Reactive {
|
|
|
30
34
|
return this.state.value;
|
|
31
35
|
}
|
|
32
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Create a computed value
|
|
39
|
+
* @param callback Callback to compute the value
|
|
40
|
+
* @param options Reactivity options
|
|
41
|
+
* @returns Computed value
|
|
42
|
+
*/
|
|
33
43
|
function computed(callback, options) {
|
|
34
44
|
return new Computed(callback, options);
|
|
35
45
|
}
|
|
46
|
+
//#endregion
|
|
36
47
|
export { Computed, computed };
|