@oscarpalmer/mora 0.26.0 → 0.28.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.d.mts +20 -0
- package/dist/{constants.js → constants.mjs} +2 -0
- package/dist/effect.d.mts +17 -0
- package/dist/{effect.js → effect.mjs} +11 -4
- package/dist/helpers/is.d.mts +47 -0
- package/dist/helpers/is.mjs +55 -0
- package/dist/helpers/proxy.d.mts +15 -0
- package/dist/helpers/proxy.mjs +72 -0
- package/dist/helpers/value.d.mts +8 -0
- package/dist/helpers/{value.js → value.mjs} +4 -2
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +8 -0
- package/dist/models.d.mts +62 -0
- package/dist/models.mjs +1 -0
- package/dist/{mora.full.js → mora.full.mjs} +206 -106
- package/dist/subscription.d.mts +15 -0
- package/dist/{subscription.js → subscription.mjs} +2 -0
- package/dist/value/array.d.mts +156 -0
- package/dist/value/array.mjs +165 -0
- package/dist/value/computed.d.mts +21 -0
- package/dist/value/computed.mjs +68 -0
- package/dist/value/reactive.d.mts +40 -0
- package/dist/value/{reactive.js → reactive.mjs} +25 -2
- package/dist/value/signal.d.mts +44 -0
- package/dist/value/signal.mjs +59 -0
- package/dist/value/store.d.mts +112 -0
- package/dist/value/store.mjs +81 -0
- package/package.json +41 -35
- package/src/constants.ts +1 -6
- package/src/helpers/is.ts +1 -1
- package/src/helpers/proxy.ts +64 -17
- package/src/models.ts +3 -1
- package/src/value/array.ts +79 -23
- package/src/value/computed.ts +65 -30
- package/src/value/signal.ts +77 -9
- package/src/value/store.ts +101 -12
- package/dist/helpers/is.js +0 -23
- package/dist/helpers/proxy.js +0 -48
- package/dist/index.js +0 -8
- package/dist/models.js +0 -0
- package/dist/value/array.js +0 -100
- package/dist/value/computed.js +0 -36
- package/dist/value/signal.js +0 -24
- package/dist/value/store.js +0 -43
|
@@ -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,
|
|
@@ -212,18 +215,10 @@ var Computed = class extends Reactive {
|
|
|
212
215
|
constructor(callback, options) {
|
|
213
216
|
super(NAME_COMPUTED, void 0, options);
|
|
214
217
|
this.effect.instance = effect(() => {
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const value = callback();
|
|
219
|
-
ACTIVE.computed = previousComputed;
|
|
220
|
-
if (!this.state.equal(this.state.value, value)) {
|
|
221
|
-
this.state.value = value;
|
|
222
|
-
for (const computed$1 of this.state.computeds) computed$1.effect.dirty = true;
|
|
223
|
-
for (const effect$1 of this.state.effects) BATCH.handlers.add(effect$1);
|
|
224
|
-
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
218
|
+
if (this.effect.dirty) {
|
|
219
|
+
setValue$1(this, this.state, callback);
|
|
220
|
+
this.effect.dirty = false;
|
|
225
221
|
}
|
|
226
|
-
this.effect.dirty = false;
|
|
227
222
|
});
|
|
228
223
|
}
|
|
229
224
|
/**
|
|
@@ -245,10 +240,39 @@ var Computed = class extends Reactive {
|
|
|
245
240
|
function computed(callback, options) {
|
|
246
241
|
return new Computed(callback, options);
|
|
247
242
|
}
|
|
248
|
-
|
|
243
|
+
function setAndEmit$1(state, value) {
|
|
244
|
+
if (state.equal(state.value, value)) return;
|
|
245
|
+
state.value = value;
|
|
246
|
+
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
247
|
+
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
248
|
+
for (const [, subscription] of state.subscriptions) subscription.callback(value);
|
|
249
|
+
flushHandlers();
|
|
250
|
+
}
|
|
251
|
+
function setValue$1(instance, state, callback) {
|
|
252
|
+
const previousComputed = ACTIVE.computed;
|
|
253
|
+
ACTIVE.computed = instance;
|
|
254
|
+
try {
|
|
255
|
+
const value = callback();
|
|
256
|
+
if (value instanceof Promise) {
|
|
257
|
+
state.promise = value;
|
|
258
|
+
value.then((resolvedValue) => {
|
|
259
|
+
if (state.promise === value) {
|
|
260
|
+
state.promise = void 0;
|
|
261
|
+
setAndEmit$1(state, resolvedValue);
|
|
262
|
+
}
|
|
263
|
+
}).catch(() => {
|
|
264
|
+
if (state.promise === value) state.promise = void 0;
|
|
265
|
+
});
|
|
266
|
+
} else setAndEmit$1(state, value);
|
|
267
|
+
} finally {
|
|
268
|
+
ACTIVE.computed = previousComputed;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region src/helpers/value.ts
|
|
249
273
|
function emitValue(state) {
|
|
250
|
-
for (const computed
|
|
251
|
-
for (const effect
|
|
274
|
+
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
275
|
+
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
252
276
|
for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
|
|
253
277
|
if (BATCH.depth === 0) flushHandlers();
|
|
254
278
|
}
|
|
@@ -256,9 +280,9 @@ function equalArrays(state, first, second) {
|
|
|
256
280
|
let { length } = first;
|
|
257
281
|
if (length !== second.length) return false;
|
|
258
282
|
let offset = 0;
|
|
259
|
-
if (length >=
|
|
260
|
-
offset = Math.round(length /
|
|
261
|
-
offset = offset >
|
|
283
|
+
if (length >= 100) {
|
|
284
|
+
offset = Math.round(length / 10);
|
|
285
|
+
offset = offset > 25 ? 25 : offset;
|
|
262
286
|
for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
263
287
|
}
|
|
264
288
|
length -= offset;
|
|
@@ -270,51 +294,76 @@ function getValue(state) {
|
|
|
270
294
|
if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
|
|
271
295
|
return state.value;
|
|
272
296
|
}
|
|
273
|
-
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/helpers/proxy.ts
|
|
274
299
|
function emityProxyValues(state, mapped) {
|
|
275
300
|
const values = [...mapped.values()];
|
|
276
301
|
const { length } = values;
|
|
277
302
|
for (let index = 0; index < length; index += 1) values[index].effect.dirty = true;
|
|
278
303
|
emitValue(state);
|
|
279
304
|
}
|
|
280
|
-
function getReactiveValueInProxy(reactive, mapped, key, isArray
|
|
305
|
+
function getReactiveValueInProxy(reactive, mapped, key, isArray) {
|
|
281
306
|
let item = mapped.get(key);
|
|
282
307
|
if (item == null) {
|
|
283
|
-
item = computed(() => isArray
|
|
308
|
+
item = computed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
|
|
284
309
|
mapped.set(key, item);
|
|
285
310
|
}
|
|
286
311
|
return item;
|
|
287
312
|
}
|
|
288
|
-
function setProxyValue(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
313
|
+
function setProxyValue(array, state, isObject, isProperty, setObject, setProperty, first, second) {
|
|
314
|
+
if (array && first === "length") {
|
|
315
|
+
state.value.length = second;
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (isObject(first)) {
|
|
319
|
+
setObject(state, first);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const property = isProperty(first);
|
|
323
|
+
if (array && property && Number.isNaN(first)) return;
|
|
324
|
+
let actual = property ? second : first;
|
|
325
|
+
if (typeof actual === "function") try {
|
|
326
|
+
actual = actual();
|
|
327
|
+
} catch {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (actual instanceof Promise) {
|
|
331
|
+
if (property) {
|
|
332
|
+
state.promises ??= /* @__PURE__ */ new Map();
|
|
333
|
+
state.promises.set(first, actual);
|
|
334
|
+
} else state.promise = actual;
|
|
335
|
+
actual.then((value) => {
|
|
336
|
+
if (property && state.promises.get(first) === actual) {
|
|
337
|
+
state.promises.delete(first);
|
|
338
|
+
setProperty(state, first, value);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (!property && isObject(value) && state.promise === actual) {
|
|
342
|
+
state.promise = void 0;
|
|
343
|
+
setObject(state, value);
|
|
344
|
+
}
|
|
345
|
+
}).catch(() => {
|
|
346
|
+
if (property && state.promises.get(first) === actual) state.promises.delete(first);
|
|
347
|
+
else if (!property && state.promise === actual) state.promise = void 0;
|
|
348
|
+
});
|
|
349
|
+
} else if (property) setProperty(state, first, actual);
|
|
350
|
+
else if (isObject(actual)) setObject(state, actual);
|
|
303
351
|
}
|
|
304
352
|
function setValueInProxy(parameters) {
|
|
305
|
-
const { isArray
|
|
306
|
-
if (isArray
|
|
307
|
-
if (!(!Number.isNaN(Number(property)) || property ===
|
|
353
|
+
const { isArray, length, property, state, target, value } = parameters;
|
|
354
|
+
if (isArray) {
|
|
355
|
+
if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
|
|
308
356
|
}
|
|
309
357
|
const previous = Reflect.get(target, property);
|
|
310
358
|
if (!state.equal(previous, value)) {
|
|
311
359
|
Reflect.set(target, property, value);
|
|
312
360
|
emitValue(state);
|
|
313
|
-
if (isArray
|
|
361
|
+
if (isArray) length?.set(target.length);
|
|
314
362
|
}
|
|
315
363
|
return true;
|
|
316
364
|
}
|
|
317
|
-
|
|
365
|
+
//#endregion
|
|
366
|
+
//#region src/value/signal.ts
|
|
318
367
|
var Signal = class extends Reactive {
|
|
319
368
|
constructor(value, options) {
|
|
320
369
|
super(NAME_SIGNAL, value, options);
|
|
@@ -330,10 +379,7 @@ var Signal = class extends Reactive {
|
|
|
330
379
|
* @param value New value
|
|
331
380
|
*/
|
|
332
381
|
set(value) {
|
|
333
|
-
|
|
334
|
-
this.state.value = value;
|
|
335
|
-
emitValue(this.state);
|
|
336
|
-
}
|
|
382
|
+
setValue(this.state, value);
|
|
337
383
|
}
|
|
338
384
|
/**
|
|
339
385
|
* Update the value _(based on the current value)_
|
|
@@ -343,16 +389,36 @@ var Signal = class extends Reactive {
|
|
|
343
389
|
this.set(callback(this.state.value));
|
|
344
390
|
}
|
|
345
391
|
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
392
|
+
function setAndEmit(state, value) {
|
|
393
|
+
if (!state.equal(state.value, value)) {
|
|
394
|
+
state.value = value;
|
|
395
|
+
emitValue(state);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function setValue(state, value) {
|
|
399
|
+
try {
|
|
400
|
+
let actual = value;
|
|
401
|
+
if (typeof value === "function") actual = value();
|
|
402
|
+
if (actual instanceof Promise) {
|
|
403
|
+
state.promise = actual;
|
|
404
|
+
actual.then((value) => {
|
|
405
|
+
if (actual === state.promise) {
|
|
406
|
+
state.promise = void 0;
|
|
407
|
+
setAndEmit(state, value);
|
|
408
|
+
}
|
|
409
|
+
}).catch(() => {
|
|
410
|
+
if (actual === state.promise) state.promise = void 0;
|
|
411
|
+
});
|
|
412
|
+
} else setAndEmit(state, actual);
|
|
413
|
+
} catch {}
|
|
414
|
+
}
|
|
352
415
|
function signal(value, options) {
|
|
353
|
-
|
|
416
|
+
const instance = new Signal(void 0, options);
|
|
417
|
+
instance.set(value);
|
|
418
|
+
return instance;
|
|
354
419
|
}
|
|
355
|
-
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/value/array.ts
|
|
356
422
|
var ReactiveArray = class extends Reactive {
|
|
357
423
|
#indiced = /* @__PURE__ */ new Map();
|
|
358
424
|
#size = signal(0);
|
|
@@ -371,10 +437,10 @@ var ReactiveArray = class extends Reactive {
|
|
|
371
437
|
constructor(value, options) {
|
|
372
438
|
super(NAME_ARRAY, new Proxy(value, {
|
|
373
439
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
374
|
-
set: (target, property, value
|
|
440
|
+
set: (target, property, value) => setValueInProxy({
|
|
375
441
|
property,
|
|
376
442
|
target,
|
|
377
|
-
value
|
|
443
|
+
value,
|
|
378
444
|
isArray: true,
|
|
379
445
|
state: this.state,
|
|
380
446
|
length: this.#size
|
|
@@ -398,7 +464,7 @@ var ReactiveArray = class extends Reactive {
|
|
|
398
464
|
}
|
|
399
465
|
get(first) {
|
|
400
466
|
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
401
|
-
return first ===
|
|
467
|
+
return first === "length" ? this.length : getValue(this.state);
|
|
402
468
|
}
|
|
403
469
|
/**
|
|
404
470
|
* Create a computed, mapped array
|
|
@@ -419,7 +485,7 @@ var ReactiveArray = class extends Reactive {
|
|
|
419
485
|
}
|
|
420
486
|
peek(value) {
|
|
421
487
|
if (value === "length") return this.#size.peek();
|
|
422
|
-
return typeof value === "number" ? this.state.value.at(value) :
|
|
488
|
+
return typeof value === "number" ? this.state.value.at(value) : this.state.value.slice();
|
|
423
489
|
}
|
|
424
490
|
/**
|
|
425
491
|
* Remove and return the last item of the array
|
|
@@ -437,9 +503,7 @@ var ReactiveArray = class extends Reactive {
|
|
|
437
503
|
return this.state.value.push(...items);
|
|
438
504
|
}
|
|
439
505
|
set(first, second) {
|
|
440
|
-
|
|
441
|
-
else if (first === "length") this.length = second;
|
|
442
|
-
else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
|
|
506
|
+
setProxyValue(true, this.state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
|
|
443
507
|
}
|
|
444
508
|
/**
|
|
445
509
|
* Remove and return the first item of the array
|
|
@@ -479,50 +543,67 @@ var ReactiveArray = class extends Reactive {
|
|
|
479
543
|
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
480
544
|
}
|
|
481
545
|
};
|
|
482
|
-
/**
|
|
483
|
-
* Create a reactive array
|
|
484
|
-
* @param value Initial array of items
|
|
485
|
-
* @param options Reactivity options
|
|
486
|
-
* @returns Reactive array
|
|
487
|
-
*/
|
|
488
546
|
function array(value, options) {
|
|
489
|
-
|
|
547
|
+
const instance = new ReactiveArray([], options);
|
|
548
|
+
instance.set(value);
|
|
549
|
+
return instance;
|
|
550
|
+
}
|
|
551
|
+
function isArrayIndex(value) {
|
|
552
|
+
return typeof value === "number";
|
|
553
|
+
}
|
|
554
|
+
function isArrayValue(value) {
|
|
555
|
+
return value == null || Array.isArray(value);
|
|
490
556
|
}
|
|
491
|
-
function updateArray(type, array
|
|
557
|
+
function updateArray(type, array, state, length) {
|
|
492
558
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
493
|
-
const previousArray = affectsLength ? [] :
|
|
494
|
-
const previousLength = array
|
|
559
|
+
const previousArray = affectsLength ? [] : array.slice();
|
|
560
|
+
const previousLength = array.length;
|
|
495
561
|
return (...args) => {
|
|
496
|
-
const result = array
|
|
497
|
-
if (affectsLength ? array
|
|
562
|
+
const result = array[type](...args);
|
|
563
|
+
if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
|
|
498
564
|
emitValue(state);
|
|
499
|
-
length.set(array
|
|
565
|
+
length.set(array.length);
|
|
500
566
|
}
|
|
501
567
|
return result;
|
|
502
568
|
};
|
|
503
569
|
}
|
|
504
|
-
function
|
|
505
|
-
|
|
506
|
-
if (actual > -1) array$1[actual] = value;
|
|
570
|
+
function setArray(state, value) {
|
|
571
|
+
state.value.splice(0, state.value.length, ...value ?? []);
|
|
507
572
|
}
|
|
508
|
-
|
|
573
|
+
function setAtIndex(state, index, value) {
|
|
574
|
+
const actual = index < 0 ? state.value.length + index : index;
|
|
575
|
+
if (actual > -1) state.value[actual] = value;
|
|
576
|
+
}
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
579
|
+
/**
|
|
580
|
+
* Is the value a key?
|
|
581
|
+
* @param value Value to check
|
|
582
|
+
* @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
|
|
583
|
+
*/
|
|
509
584
|
function isKey(value) {
|
|
510
585
|
return typeof value === "number" || typeof value === "string";
|
|
511
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* Is the value a plain object?
|
|
589
|
+
* @param value Value to check
|
|
590
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
591
|
+
*/
|
|
512
592
|
function isPlainObject(value) {
|
|
513
593
|
if (value === null || typeof value !== "object") return false;
|
|
514
594
|
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
515
595
|
const prototype = Object.getPrototypeOf(value);
|
|
516
596
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
517
597
|
}
|
|
518
|
-
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/value/store.ts
|
|
519
600
|
var Store = class extends Reactive {
|
|
520
601
|
#keyed = /* @__PURE__ */ new Map();
|
|
521
602
|
constructor(value, options) {
|
|
522
|
-
super(NAME_STORE, new Proxy(value, { set: (target, property, value
|
|
603
|
+
super(NAME_STORE, new Proxy(value, { set: (target, property, value) => setValueInProxy({
|
|
523
604
|
target,
|
|
524
605
|
property,
|
|
525
|
-
value
|
|
606
|
+
value,
|
|
526
607
|
isArray: false,
|
|
527
608
|
state: this.state
|
|
528
609
|
}) }), options);
|
|
@@ -543,8 +624,7 @@ var Store = class extends Reactive {
|
|
|
543
624
|
return isKey(key) ? this.state.value[key] : { ...this.state.value };
|
|
544
625
|
}
|
|
545
626
|
set(first, second) {
|
|
546
|
-
|
|
547
|
-
else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
|
|
627
|
+
setProxyValue(false, this.state, isStoreObject, isKey, setObject, setProperty, first, second);
|
|
548
628
|
}
|
|
549
629
|
subscribe(first, second) {
|
|
550
630
|
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
|
|
@@ -555,18 +635,38 @@ var Store = class extends Reactive {
|
|
|
555
635
|
* @param callback Callback to update the value
|
|
556
636
|
*/
|
|
557
637
|
update(callback) {
|
|
558
|
-
const updated = callback(
|
|
559
|
-
if (updated == null || isPlainObject(updated))
|
|
638
|
+
const updated = callback(this.state.value);
|
|
639
|
+
if (updated == null || isPlainObject(updated)) setObject(this.state, updated);
|
|
560
640
|
}
|
|
561
641
|
};
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
642
|
+
function isStoreObject(value) {
|
|
643
|
+
return value == null || isPlainObject(value);
|
|
644
|
+
}
|
|
645
|
+
function setObject(state, value) {
|
|
646
|
+
startBatch();
|
|
647
|
+
const actual = value ?? {};
|
|
648
|
+
const proxy = state.value;
|
|
649
|
+
const proxyKeys = Object.keys(proxy);
|
|
650
|
+
const actualKeys = Object.keys(actual);
|
|
651
|
+
let { length } = proxyKeys;
|
|
652
|
+
for (let index = 0; index < length; index += 1) {
|
|
653
|
+
const key = proxyKeys[index];
|
|
654
|
+
proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
|
|
655
|
+
}
|
|
656
|
+
length = actualKeys.length;
|
|
657
|
+
for (let index = 0; index < length; index += 1) {
|
|
658
|
+
const key = actualKeys[index];
|
|
659
|
+
if (!proxyKeys.includes(key)) proxy[key] = actual[key];
|
|
660
|
+
}
|
|
661
|
+
stopBatch();
|
|
662
|
+
}
|
|
663
|
+
function setProperty(state, key, value) {
|
|
664
|
+
state.value[key] = value;
|
|
665
|
+
}
|
|
568
666
|
function store(value, options) {
|
|
569
|
-
|
|
667
|
+
const instance = new Store({}, options);
|
|
668
|
+
instance.set(value);
|
|
669
|
+
return instance;
|
|
570
670
|
}
|
|
571
|
-
|
|
572
|
-
export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
671
|
+
//#endregion
|
|
672
|
+
export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactiveState, Unsubscribe } from "./models.mjs";
|
|
2
|
+
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
|
+
|
|
4
|
+
//#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
|
+
declare function noop(): void;
|
|
12
|
+
declare function subscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): Unsubscribe;
|
|
13
|
+
declare function unsubscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Subscription, noop, subscribe, unsubscribe };
|
|
@@ -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 };
|