@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/effect.ts
CHANGED
|
@@ -1,52 +1,47 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {ACTIVE, NAME_EFFECT
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* Internal state of the effect
|
|
15
|
-
*
|
|
16
|
-
* @internal
|
|
17
|
-
*/
|
|
18
|
-
declare private readonly state: EffectState;
|
|
19
|
-
|
|
20
|
-
constructor(callback: GenericCallback) {
|
|
21
|
-
Object.defineProperty(this, NAME_MORA, {
|
|
22
|
-
value: NAME_EFFECT,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
this.state = {
|
|
26
|
-
callback,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
runEffect(this);
|
|
2
|
+
import {ACTIVE, NAME_EFFECT} from './constants';
|
|
3
|
+
import type {Effect, EffectState} from './models';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create an effect
|
|
7
|
+
*
|
|
8
|
+
* @param callback Callback for handling signal effects
|
|
9
|
+
* @returns Effect
|
|
10
|
+
*/
|
|
11
|
+
export function effect(callback: GenericCallback): Effect {
|
|
12
|
+
if (typeof callback !== 'function') {
|
|
13
|
+
throw new TypeError('Effect callback must be a function');
|
|
30
14
|
}
|
|
15
|
+
|
|
16
|
+
return getEffect(callback)[0];
|
|
31
17
|
}
|
|
32
18
|
|
|
33
|
-
|
|
19
|
+
function getEffect(callback: GenericCallback): [Effect, EffectState] {
|
|
20
|
+
const state: EffectState = {
|
|
21
|
+
callback,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const instance = Object.freeze({
|
|
25
|
+
$mora: NAME_EFFECT,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
runEffect(state);
|
|
29
|
+
|
|
30
|
+
return [instance, state];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function internalEffect(callback: GenericCallback): EffectState {
|
|
34
|
+
return getEffect(callback)[1];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function runEffect(state: EffectState): void {
|
|
34
38
|
const previousEffect = ACTIVE.effect;
|
|
35
39
|
|
|
36
|
-
ACTIVE.effect =
|
|
40
|
+
ACTIVE.effect = state;
|
|
37
41
|
|
|
38
42
|
try {
|
|
39
|
-
|
|
43
|
+
state.callback();
|
|
40
44
|
} finally {
|
|
41
45
|
ACTIVE.effect = previousEffect;
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Create an effect
|
|
47
|
-
* @param callback Callback for handling signal effects
|
|
48
|
-
* @returns Effect
|
|
49
|
-
*/
|
|
50
|
-
export function effect(callback: GenericCallback): Effect {
|
|
51
|
-
return typeof callback === 'function' ? new Effect(callback) : (undefined as never);
|
|
52
|
-
}
|
package/src/helpers/is.ts
CHANGED
|
@@ -5,27 +5,23 @@ import {
|
|
|
5
5
|
NAME_COMPUTED,
|
|
6
6
|
NAME_EFFECT,
|
|
7
7
|
NAME_MORA,
|
|
8
|
+
NAME_READONLY,
|
|
8
9
|
NAME_SIGNAL,
|
|
9
10
|
NAME_STORE,
|
|
10
11
|
} from '../constants';
|
|
11
|
-
import type {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* @param value Value to check
|
|
21
|
-
* @returns True if value is a {@link ReactiveArray}
|
|
22
|
-
*/
|
|
23
|
-
export function isArray<Item>(value: unknown): value is ReactiveArray<Item> {
|
|
24
|
-
return isMora<ReactiveArray<Item>>(value, NAME_ARRAY);
|
|
25
|
-
}
|
|
12
|
+
import type {
|
|
13
|
+
Computed,
|
|
14
|
+
Effect,
|
|
15
|
+
Reactive,
|
|
16
|
+
ReactiveArray,
|
|
17
|
+
ReactiveStore,
|
|
18
|
+
ReadonlySignal,
|
|
19
|
+
Signal,
|
|
20
|
+
} from '../models';
|
|
26
21
|
|
|
27
22
|
/**
|
|
28
23
|
* Is the value a computed signal?
|
|
24
|
+
*
|
|
29
25
|
* @param value Value to check
|
|
30
26
|
* @returns True if value is a {@link Computed}
|
|
31
27
|
*/
|
|
@@ -35,6 +31,7 @@ export function isComputed<Value>(value: unknown): value is Computed<Value> {
|
|
|
35
31
|
|
|
36
32
|
/**
|
|
37
33
|
* Is the value an effect?
|
|
34
|
+
*
|
|
38
35
|
* @param value Value to check
|
|
39
36
|
* @returns True if value is an {@link Effect}
|
|
40
37
|
*/
|
|
@@ -42,7 +39,7 @@ export function isEffect(value: unknown): value is Effect {
|
|
|
42
39
|
return isMora<Effect>(value, NAME_EFFECT);
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
function isMora<
|
|
42
|
+
function isMora<Instance>(value: unknown, name: string | Set<string>): value is Instance {
|
|
46
43
|
return (
|
|
47
44
|
typeof value === 'object' &&
|
|
48
45
|
value != null &&
|
|
@@ -55,15 +52,17 @@ function isMora<T>(value: unknown, name: string | Set<string>): value is T {
|
|
|
55
52
|
|
|
56
53
|
/**
|
|
57
54
|
* Is the value reactive?
|
|
55
|
+
*
|
|
58
56
|
* @param value Value to check
|
|
59
57
|
* @returns True if value is a {@link Reactive}
|
|
60
58
|
*/
|
|
61
|
-
export function isReactive<Value
|
|
62
|
-
return isMora<Reactive<Value
|
|
59
|
+
export function isReactive<Value>(value: unknown): value is Reactive<Value> {
|
|
60
|
+
return isMora<Reactive<Value>>(value, NAME_ALL);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
/**
|
|
66
64
|
* Is the value a signal?
|
|
65
|
+
*
|
|
67
66
|
* @param value Value to check
|
|
68
67
|
* @returns True if value is a {@link Signal}
|
|
69
68
|
*/
|
|
@@ -71,11 +70,28 @@ export function isSignal<Value>(value: unknown): value is Signal<Value> {
|
|
|
71
70
|
return isMora<Signal<Value>>(value, NAME_SIGNAL);
|
|
72
71
|
}
|
|
73
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Is the value a reactive array?
|
|
75
|
+
*
|
|
76
|
+
* @param value Value to check
|
|
77
|
+
* @returns True if value is a {@link ReactiveArray}
|
|
78
|
+
*/
|
|
79
|
+
export function isReactiveArray<Item>(value: unknown): value is ReactiveArray<Item> {
|
|
80
|
+
return isMora<ReactiveArray<Item>>(value, NAME_ARRAY);
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
/**
|
|
75
84
|
* Is the value a reactive store?
|
|
85
|
+
*
|
|
76
86
|
* @param value Value to check
|
|
77
87
|
* @returns True if value is a {@link Store}
|
|
78
88
|
*/
|
|
79
|
-
export function
|
|
80
|
-
|
|
89
|
+
export function isReactiveStore<Value extends PlainObject>(
|
|
90
|
+
value: unknown,
|
|
91
|
+
): value is ReactiveStore<Value> {
|
|
92
|
+
return isMora<ReactiveStore<Value>>(value, NAME_STORE);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isReadonlySignal<Value>(value: unknown): value is ReadonlySignal<Value> {
|
|
96
|
+
return isMora<ReadonlySignal<Value>>(value, NAME_READONLY);
|
|
81
97
|
}
|
package/src/helpers/proxy.ts
CHANGED
|
@@ -1,68 +1,73 @@
|
|
|
1
1
|
import type {ArrayOrPlainObject, Key, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {PROPERTY_LENGTH} from '../constants';
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import type {
|
|
4
|
+
Computed,
|
|
5
|
+
ComputedEffect,
|
|
6
|
+
ReactiveArray,
|
|
7
|
+
ReactiveState,
|
|
8
|
+
ReactiveStore,
|
|
9
|
+
SetValueInProxyParameters,
|
|
10
|
+
} from '../models';
|
|
11
|
+
import {internalComputed} from '../value/computed';
|
|
7
12
|
import {emitValue} from './value';
|
|
8
13
|
|
|
9
14
|
export function emityProxyValues<Value>(
|
|
10
15
|
state: ReactiveState<Value, Value>,
|
|
11
|
-
mapped: Map<Key, Computed<unknown
|
|
16
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
12
17
|
): void;
|
|
13
18
|
|
|
14
19
|
export function emityProxyValues<Value>(
|
|
15
20
|
state: ReactiveState<Value[], Value>,
|
|
16
|
-
mapped: Map<Key, Computed<unknown
|
|
21
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
17
22
|
): void;
|
|
18
23
|
|
|
19
24
|
export function emityProxyValues(
|
|
20
25
|
state: ReactiveState<unknown, unknown>,
|
|
21
|
-
mapped: Map<Key, Computed<unknown
|
|
26
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
22
27
|
): void {
|
|
23
28
|
const values = [...mapped.values()];
|
|
24
29
|
const {length} = values;
|
|
25
30
|
|
|
26
31
|
for (let index = 0; index < length; index += 1) {
|
|
27
|
-
|
|
32
|
+
values[index][1].dirty = true;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
emitValue(state);
|
|
31
36
|
}
|
|
32
37
|
|
|
33
|
-
export function getReactiveValueInProxy<Value>(
|
|
38
|
+
export function getReactiveValueInProxy<Value, Result = Value>(
|
|
34
39
|
array: ReactiveArray<Value>,
|
|
35
|
-
mapped: Map<Key, Computed<unknown
|
|
40
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
36
41
|
index: number,
|
|
37
42
|
isArray: true,
|
|
38
|
-
): Computed<
|
|
43
|
+
): Computed<Result>;
|
|
39
44
|
|
|
40
45
|
export function getReactiveValueInProxy<Value extends PlainObject>(
|
|
41
|
-
store:
|
|
42
|
-
mapped: Map<Key, Computed<unknown
|
|
46
|
+
store: ReactiveStore<Value>,
|
|
47
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
43
48
|
key: Key,
|
|
44
49
|
isArray: false,
|
|
45
50
|
): Computed<unknown>;
|
|
46
51
|
|
|
47
52
|
export function getReactiveValueInProxy(
|
|
48
|
-
reactive: ReactiveArray<unknown> |
|
|
49
|
-
mapped: Map<Key, Computed<unknown
|
|
53
|
+
reactive: ReactiveArray<unknown> | ReactiveStore<PlainObject>,
|
|
54
|
+
mapped: Map<Key, [Computed<unknown>, ComputedEffect]>,
|
|
50
55
|
key: Key,
|
|
51
56
|
isArray: boolean,
|
|
52
57
|
): Computed<unknown> {
|
|
53
58
|
let item = mapped.get(key);
|
|
54
59
|
|
|
55
60
|
if (item == null) {
|
|
56
|
-
item =
|
|
61
|
+
item = internalComputed(() =>
|
|
57
62
|
isArray
|
|
58
63
|
? (reactive.get() as unknown[]).at(key as number)
|
|
59
64
|
: (reactive.get() as PlainObject)[key],
|
|
60
|
-
)
|
|
65
|
+
);
|
|
61
66
|
|
|
62
67
|
mapped.set(key, item);
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
return item;
|
|
70
|
+
return item[0];
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
export function setProxyValue<Value, Item = Value>(
|
package/src/helpers/value.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {round} from '@oscarpalmer/atoms/math';
|
|
2
1
|
import {flushHandlers} from '../batch';
|
|
3
2
|
import {ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH} from '../constants';
|
|
4
|
-
import type {
|
|
3
|
+
import type {ReactiveState} from '../models';
|
|
5
4
|
|
|
6
5
|
export function emitValue<Value>(state: ReactiveState<Value, never>): void {
|
|
7
6
|
for (const computed of state.computeds) {
|
|
8
|
-
|
|
7
|
+
computed.dirty = true;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
for (const effect of state.effects) {
|
|
@@ -35,7 +34,7 @@ export function equalArrays<Value>(
|
|
|
35
34
|
let offset = 0;
|
|
36
35
|
|
|
37
36
|
if (length >= ARRAY_THRESHOLD) {
|
|
38
|
-
offset = round(length / ARRAY_PEEK);
|
|
37
|
+
offset = Math.round(length / ARRAY_PEEK);
|
|
39
38
|
offset = offset > ARRAY_OFFSET ? ARRAY_OFFSET : offset;
|
|
40
39
|
|
|
41
40
|
for (let index = 0; index < offset; index += 1) {
|
|
@@ -56,7 +55,7 @@ export function equalArrays<Value>(
|
|
|
56
55
|
return true;
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
export function
|
|
58
|
+
export function getSimpleValue<Value>(state: ReactiveState<Value, never>): Value {
|
|
60
59
|
if (ACTIVE.computed != null) {
|
|
61
60
|
state.computeds.add(ACTIVE.computed);
|
|
62
61
|
}
|
|
@@ -67,3 +66,38 @@ export function getValue<Value>(state: ReactiveState<Value, never>): Value {
|
|
|
67
66
|
|
|
68
67
|
return state.value;
|
|
69
68
|
}
|
|
69
|
+
|
|
70
|
+
export function handleSimpleValue<Value>(
|
|
71
|
+
state: ReactiveState<Value, Value>,
|
|
72
|
+
origin: Value | (() => Value | Promise<Value>) | Promise<Value>,
|
|
73
|
+
setValue: (state: ReactiveState<Value, Value>, value: Value) => void,
|
|
74
|
+
onAfter?: () => void,
|
|
75
|
+
): void {
|
|
76
|
+
try {
|
|
77
|
+
let actual = typeof origin === 'function' ? (origin as () => unknown)() : origin;
|
|
78
|
+
|
|
79
|
+
if (actual instanceof Promise) {
|
|
80
|
+
state.promise = actual;
|
|
81
|
+
|
|
82
|
+
void actual
|
|
83
|
+
.then(value => {
|
|
84
|
+
if (actual === state.promise) {
|
|
85
|
+
state.promise = undefined;
|
|
86
|
+
|
|
87
|
+
setValue(state, value);
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
.catch(() => {
|
|
91
|
+
if (actual === state.promise) {
|
|
92
|
+
state.promise = undefined;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
setValue(state, actual as Value);
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
// ?
|
|
100
|
+
} finally {
|
|
101
|
+
onAfter?.();
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
export {startBatch, stopBatch} from './batch';
|
|
2
|
-
export {effect
|
|
3
|
-
export {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
export {effect} from './effect';
|
|
3
|
+
export {
|
|
4
|
+
isComputed,
|
|
5
|
+
isEffect,
|
|
6
|
+
isReactive,
|
|
7
|
+
isReactiveArray,
|
|
8
|
+
isReactiveStore,
|
|
9
|
+
isReadonlySignal,
|
|
10
|
+
isSignal,
|
|
11
|
+
} from './helpers/is';
|
|
12
|
+
export type {
|
|
13
|
+
Computed,
|
|
14
|
+
Effect,
|
|
15
|
+
ReactiveArray,
|
|
16
|
+
ReactiveStore,
|
|
17
|
+
ReadonlySignal,
|
|
18
|
+
Signal,
|
|
19
|
+
Unsubscribe,
|
|
20
|
+
} from './models';
|
|
21
|
+
export {array} from './value/array';
|
|
22
|
+
export {computed} from './value/computed';
|
|
23
|
+
export {signal} from './value/signal';
|
|
24
|
+
export {store} from './value/store';
|