@oscarpalmer/mora 0.30.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/constants.d.mts +2 -1
- package/dist/constants.mjs +3 -1
- package/dist/helpers/is.d.mts +11 -10
- package/dist/helpers/is.mjs +15 -12
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/models.d.mts +84 -18
- package/dist/mora.full.mjs +121 -40
- package/dist/value/array.mjs +33 -17
- package/dist/value/readonly.d.mts +7 -0
- package/dist/value/readonly.mjs +37 -0
- package/dist/value/signal.mjs +11 -5
- package/dist/value/store.mjs +24 -8
- package/package.json +1 -1
- package/src/constants.ts +9 -1
- package/src/helpers/is.ts +28 -13
- package/src/index.ts +18 -2
- package/src/models.ts +110 -22
- package/src/value/array.ts +76 -40
- package/src/value/readonly.ts +71 -0
- package/src/value/signal.ts +15 -6
- package/src/value/store.ts +63 -17
package/dist/value/array.mjs
CHANGED
|
@@ -4,15 +4,19 @@ import { subscribe, unsubscribe } from "../subscription.mjs";
|
|
|
4
4
|
import { reactive } from "./reactive.mjs";
|
|
5
5
|
import { computed } from "./computed.mjs";
|
|
6
6
|
import { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy } from "../helpers/proxy.mjs";
|
|
7
|
+
import { getReadonlyInstance } from "./readonly.mjs";
|
|
7
8
|
import { signal } from "./signal.mjs";
|
|
8
9
|
import { select } from "@oscarpalmer/atoms/array";
|
|
9
10
|
import { filter } from "@oscarpalmer/atoms/array/filter";
|
|
10
11
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
12
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
11
13
|
//#region src/value/array.ts
|
|
12
14
|
function array(value, options) {
|
|
13
15
|
const [rx, state] = reactive([], options);
|
|
14
16
|
const indiced = /* @__PURE__ */ new Map();
|
|
15
17
|
const length = signal(0);
|
|
18
|
+
const readonlies = {};
|
|
19
|
+
let instance = {};
|
|
16
20
|
state.value = new Proxy([], {
|
|
17
21
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, state, length) : Reflect.get(target, property),
|
|
18
22
|
set: (target, property, value) => setValueInProxy({
|
|
@@ -27,37 +31,43 @@ function array(value, options) {
|
|
|
27
31
|
function get(value) {
|
|
28
32
|
return getArrayValue(instance, indiced, state, length, value);
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
function set(first, second) {
|
|
35
|
+
setProxyValue(true, state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
|
|
36
|
+
}
|
|
37
|
+
const handlers = {
|
|
31
38
|
...rx,
|
|
32
|
-
|
|
39
|
+
get: (value) => get(value),
|
|
40
|
+
peek: (first, second) => peekArrayValue(state, length, first, second),
|
|
41
|
+
subscribe: (first, second) => {
|
|
42
|
+
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(instance, indiced, first, true).subscribe(second);
|
|
43
|
+
return typeof first === "function" ? subscribe(state, first) : noop;
|
|
44
|
+
},
|
|
45
|
+
unsubscribe: (first, second) => {
|
|
46
|
+
if (typeof first === "number" && typeof second === "function") getReactiveValueInProxy(instance, indiced, first, true)?.unsubscribe(second);
|
|
47
|
+
else if (typeof first === "function") unsubscribe(state, first);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
instance = {
|
|
51
|
+
...handlers,
|
|
52
|
+
asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
|
|
33
53
|
at: (index) => get(index),
|
|
34
54
|
clear: () => {
|
|
35
55
|
state.value.length = 0;
|
|
36
56
|
},
|
|
37
57
|
filter: (callback) => computed(() => filter(get(), callback)),
|
|
38
|
-
get: (value) => get(value),
|
|
39
58
|
map: (callback) => computed(() => get().map(callback)),
|
|
40
59
|
notify: () => {
|
|
41
60
|
emityProxyValues(state, indiced);
|
|
42
61
|
},
|
|
43
|
-
peek: (value) => peekArrayValue(state, length, value),
|
|
44
62
|
pop: () => state.value.pop(),
|
|
45
63
|
push: (...items) => state.value.push(...items),
|
|
46
64
|
select: (filter, map) => computed(() => select(get(), filter, map)),
|
|
47
65
|
set: (first, second) => {
|
|
48
|
-
|
|
66
|
+
set(first, second);
|
|
49
67
|
},
|
|
50
68
|
shift: () => state.value.shift(),
|
|
51
69
|
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
70
|
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
71
|
update: (callback) => updateArrayValue(instance, state, callback)
|
|
62
72
|
};
|
|
63
73
|
Object.defineProperties(instance, {
|
|
@@ -71,7 +81,7 @@ function array(value, options) {
|
|
|
71
81
|
set: (value) => setArrayLength(state, value)
|
|
72
82
|
}
|
|
73
83
|
});
|
|
74
|
-
|
|
84
|
+
set(value);
|
|
75
85
|
return Object.freeze(instance);
|
|
76
86
|
}
|
|
77
87
|
function getArrayValue(instance, indiced, state, length, first) {
|
|
@@ -84,9 +94,15 @@ function isArrayIndex(value) {
|
|
|
84
94
|
function isArrayValue(value) {
|
|
85
95
|
return value == null || Array.isArray(value);
|
|
86
96
|
}
|
|
87
|
-
function peekArrayValue(state, length,
|
|
88
|
-
if (
|
|
89
|
-
|
|
97
|
+
function peekArrayValue(state, length, first, second) {
|
|
98
|
+
if (first === "length") return length.peek();
|
|
99
|
+
let value;
|
|
100
|
+
if (typeof first === "number") value = state.value.at(first);
|
|
101
|
+
else value = state.value;
|
|
102
|
+
if (!(first === true || second === true)) return value;
|
|
103
|
+
if (Array.isArray(value)) return value.slice();
|
|
104
|
+
if (isPlainObject(value)) return { ...value };
|
|
105
|
+
return value;
|
|
90
106
|
}
|
|
91
107
|
function setArray(state, value) {
|
|
92
108
|
state.value.splice(0, state.value.length, ...value ?? []);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactiveState, ReadonlyFrozenSignal, ReadonlyInstances, ReadonlySignal } from "../models.mjs";
|
|
2
|
+
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
|
+
//#region src/value/readonly.d.ts
|
|
4
|
+
declare function getReadonlyInstance<Value>(state: ReactiveState<Value, never>, instances: ReadonlyInstances<Value>, handlers: Record<string, GenericCallback>, frozen: boolean): ReadonlySignal<Value>;
|
|
5
|
+
declare function getReadonlySignal<Value>(state: ReactiveState<Value, never>, handlers: Record<string, GenericCallback>, frozen: boolean): ReadonlySignal<Value> | ReadonlyFrozenSignal<Value>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { getReadonlyInstance, getReadonlySignal };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { NAME_MORA, NAME_READONLY } from "../constants.mjs";
|
|
2
|
+
import { getSimpleValue } from "../helpers/value.mjs";
|
|
3
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
|
+
//#region src/value/readonly.ts
|
|
5
|
+
function getReadonlyInstance(state, instances, handlers, frozen) {
|
|
6
|
+
const key = frozen ? "frozen" : "original";
|
|
7
|
+
instances[key] ??= getReadonlySignal(state, handlers, frozen);
|
|
8
|
+
return instances[key];
|
|
9
|
+
}
|
|
10
|
+
function getReadonlySignal(state, handlers, frozen) {
|
|
11
|
+
const instance = {
|
|
12
|
+
...handlers,
|
|
13
|
+
get: () => getReadonlyValue(state, false, frozen),
|
|
14
|
+
peek: () => getReadonlyValue(state, true, frozen)
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperties(instance, {
|
|
17
|
+
[NAME_MORA]: {
|
|
18
|
+
enumerable: false,
|
|
19
|
+
value: NAME_READONLY
|
|
20
|
+
},
|
|
21
|
+
frozen: {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
value: frozen
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return Object.freeze(instance);
|
|
27
|
+
}
|
|
28
|
+
function getReadonlyValue(state, peek, frozen) {
|
|
29
|
+
let value = peek ? state.value : getSimpleValue(state);
|
|
30
|
+
if (!frozen) return value;
|
|
31
|
+
if (Array.isArray(state.value)) value = [...state.value];
|
|
32
|
+
else if (isPlainObject(state.value)) value = { ...state.value };
|
|
33
|
+
else value = state.value;
|
|
34
|
+
return Object.freeze(value);
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { getReadonlyInstance, getReadonlySignal };
|
package/dist/value/signal.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { NAME_MORA, NAME_SIGNAL } from "../constants.mjs";
|
|
|
2
2
|
import { emitValue, getSimpleValue, handleSimpleValue } from "../helpers/value.mjs";
|
|
3
3
|
import { subscribe } from "../subscription.mjs";
|
|
4
4
|
import { reactive } from "./reactive.mjs";
|
|
5
|
+
import { getReadonlyInstance } from "./readonly.mjs";
|
|
5
6
|
//#region src/value/signal.ts
|
|
6
7
|
function setAndEmit(state, value) {
|
|
7
8
|
if (!state.equal(state.value, value)) {
|
|
@@ -11,8 +12,17 @@ function setAndEmit(state, value) {
|
|
|
11
12
|
}
|
|
12
13
|
function signal(value, options) {
|
|
13
14
|
const [rx, state] = reactive(void 0, options);
|
|
14
|
-
const
|
|
15
|
+
const readonlies = {};
|
|
16
|
+
const handlers = {
|
|
15
17
|
...rx,
|
|
18
|
+
subscribe: (callback) => subscribe(state, callback),
|
|
19
|
+
unsubscribe: (callback) => {
|
|
20
|
+
state.subscriptions.delete(callback);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const instance = {
|
|
24
|
+
...handlers,
|
|
25
|
+
asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
|
|
16
26
|
get: () => getSimpleValue(state),
|
|
17
27
|
peek: () => state.value,
|
|
18
28
|
set: (value) => {
|
|
@@ -20,10 +30,6 @@ function signal(value, options) {
|
|
|
20
30
|
},
|
|
21
31
|
update: (callback) => {
|
|
22
32
|
handleSimpleValue(state, callback(state.value), setAndEmit);
|
|
23
|
-
},
|
|
24
|
-
subscribe: (callback) => subscribe(state, callback),
|
|
25
|
-
unsubscribe: (callback) => {
|
|
26
|
-
state.subscriptions.delete(callback);
|
|
27
33
|
}
|
|
28
34
|
};
|
|
29
35
|
Object.defineProperty(instance, NAME_MORA, {
|
package/dist/value/store.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { getSimpleValue } from "../helpers/value.mjs";
|
|
|
4
4
|
import { noop, subscribe, unsubscribe } from "../subscription.mjs";
|
|
5
5
|
import { reactive } from "./reactive.mjs";
|
|
6
6
|
import { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy } from "../helpers/proxy.mjs";
|
|
7
|
+
import { getReadonlyInstance } from "./readonly.mjs";
|
|
7
8
|
import { isKey, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
8
9
|
//#region src/value/store.ts
|
|
9
10
|
function isStoreObject(value) {
|
|
@@ -27,12 +28,23 @@ function setObject(state, value) {
|
|
|
27
28
|
}
|
|
28
29
|
stopBatch();
|
|
29
30
|
}
|
|
31
|
+
function peekStoreValue(state, first, second) {
|
|
32
|
+
let value;
|
|
33
|
+
if (isKey(first)) value = state.value[first];
|
|
34
|
+
else value = state.value;
|
|
35
|
+
if (!(first === true || second === true)) return value;
|
|
36
|
+
if (Array.isArray(value)) return value.slice();
|
|
37
|
+
if (isPlainObject(value)) return { ...value };
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
30
40
|
function setProperty(state, key, value) {
|
|
31
41
|
state.value[key] = value;
|
|
32
42
|
}
|
|
33
43
|
function store(value, options) {
|
|
34
44
|
const [rx, state] = reactive(void 0, options);
|
|
35
45
|
const keyed = /* @__PURE__ */ new Map();
|
|
46
|
+
const readonlies = {};
|
|
47
|
+
let instance = {};
|
|
36
48
|
state.value = new Proxy({}, { set: (target, property, value) => setValueInProxy({
|
|
37
49
|
target,
|
|
38
50
|
property,
|
|
@@ -40,16 +52,10 @@ function store(value, options) {
|
|
|
40
52
|
value,
|
|
41
53
|
isArray: false
|
|
42
54
|
}) });
|
|
43
|
-
const
|
|
55
|
+
const handlers = {
|
|
44
56
|
...rx,
|
|
45
57
|
get: (value) => isKey(value) ? getReactiveValueInProxy(instance, keyed, value, false).get() : getSimpleValue(state),
|
|
46
|
-
|
|
47
|
-
emityProxyValues(state, keyed);
|
|
48
|
-
},
|
|
49
|
-
peek: (value) => isKey(value) ? state.value[value] : { ...state.value },
|
|
50
|
-
set: (first, second) => {
|
|
51
|
-
setProxyValue(false, state, isStoreObject, isKey, setObject, setProperty, first, second);
|
|
52
|
-
},
|
|
58
|
+
peek: (first, second) => peekStoreValue(state, first, second),
|
|
53
59
|
subscribe: (first, second) => {
|
|
54
60
|
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(instance, keyed, first, false).subscribe(second);
|
|
55
61
|
return typeof first === "function" ? subscribe(state, first) : noop;
|
|
@@ -57,6 +63,16 @@ function store(value, options) {
|
|
|
57
63
|
unsubscribe: (first, second) => {
|
|
58
64
|
if (isKey(first) && typeof second === "function") getReactiveValueInProxy(instance, keyed, first, false)?.unsubscribe(second);
|
|
59
65
|
else if (typeof first === "function") unsubscribe(state, first);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
instance = {
|
|
69
|
+
...handlers,
|
|
70
|
+
asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
|
|
71
|
+
notify() {
|
|
72
|
+
emityProxyValues(state, keyed);
|
|
73
|
+
},
|
|
74
|
+
set: (first, second) => {
|
|
75
|
+
setProxyValue(false, state, isStoreObject, isKey, setObject, setProperty, first, second);
|
|
60
76
|
},
|
|
61
77
|
update: (callback) => {
|
|
62
78
|
const updated = callback(state.value);
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -33,10 +33,18 @@ export const NAME_EFFECT = 'effect';
|
|
|
33
33
|
|
|
34
34
|
export const NAME_MORA = '$mora';
|
|
35
35
|
|
|
36
|
+
export const NAME_READONLY = 'readonly';
|
|
37
|
+
|
|
36
38
|
export const NAME_SIGNAL = 'signal';
|
|
37
39
|
|
|
38
40
|
export const NAME_STORE = 'store';
|
|
39
41
|
|
|
40
|
-
export const NAME_ALL = new Set([
|
|
42
|
+
export const NAME_ALL = new Set([
|
|
43
|
+
NAME_ARRAY,
|
|
44
|
+
NAME_COMPUTED,
|
|
45
|
+
NAME_READONLY,
|
|
46
|
+
NAME_SIGNAL,
|
|
47
|
+
NAME_STORE,
|
|
48
|
+
]);
|
|
41
49
|
|
|
42
50
|
export const PROPERTY_LENGTH = 'length';
|
package/src/helpers/is.ts
CHANGED
|
@@ -5,20 +5,19 @@ 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
|
-
return isMora<ReactiveArray<Item>>(value, NAME_ARRAY);
|
|
21
|
-
}
|
|
12
|
+
import type {
|
|
13
|
+
Computed,
|
|
14
|
+
Effect,
|
|
15
|
+
Reactive,
|
|
16
|
+
ReactiveArray,
|
|
17
|
+
ReactiveStore,
|
|
18
|
+
ReadonlySignal,
|
|
19
|
+
Signal,
|
|
20
|
+
} from '../models';
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
* Is the value a computed signal?
|
|
@@ -40,7 +39,7 @@ export function isEffect(value: unknown): value is Effect {
|
|
|
40
39
|
return isMora<Effect>(value, NAME_EFFECT);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
function isMora<
|
|
42
|
+
function isMora<Instance>(value: unknown, name: string | Set<string>): value is Instance {
|
|
44
43
|
return (
|
|
45
44
|
typeof value === 'object' &&
|
|
46
45
|
value != null &&
|
|
@@ -71,12 +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?
|
|
76
85
|
*
|
|
77
86
|
* @param value Value to check
|
|
78
87
|
* @returns True if value is a {@link Store}
|
|
79
88
|
*/
|
|
80
|
-
export function
|
|
89
|
+
export function isReactiveStore<Value extends PlainObject>(
|
|
90
|
+
value: unknown,
|
|
91
|
+
): value is ReactiveStore<Value> {
|
|
81
92
|
return isMora<ReactiveStore<Value>>(value, NAME_STORE);
|
|
82
93
|
}
|
|
94
|
+
|
|
95
|
+
export function isReadonlySignal<Value>(value: unknown): value is ReadonlySignal<Value> {
|
|
96
|
+
return isMora<ReadonlySignal<Value>>(value, NAME_READONLY);
|
|
97
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
export {startBatch, stopBatch} from './batch';
|
|
2
2
|
export {effect} from './effect';
|
|
3
|
-
export {
|
|
4
|
-
|
|
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';
|
|
5
21
|
export {array} from './value/array';
|
|
6
22
|
export {computed} from './value/computed';
|
|
7
23
|
export {signal} from './value/signal';
|
package/src/models.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {GenericCallback, Key} from '@oscarpalmer/atoms/models';
|
|
1
|
+
import type {GenericCallback, Key, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import type {PROPERTY_LENGTH} from './constants';
|
|
3
3
|
|
|
4
4
|
export type Active = {
|
|
@@ -52,6 +52,24 @@ export type ReactiveArray<Item> = {
|
|
|
52
52
|
*/
|
|
53
53
|
set length(value: number);
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Get a readonly version of the reactive array
|
|
57
|
+
*
|
|
58
|
+
* @param frozen Freeze the array? _(defaults to `false`)_
|
|
59
|
+
* @returns Readonly reactive array
|
|
60
|
+
*/
|
|
61
|
+
asReadonly(frozen: true): ReadonlyFrozenSignal<Item[]>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get a readonly version of the reactive array
|
|
65
|
+
*
|
|
66
|
+
* @param frozen Freeze the array? _(defaults to `false`)_
|
|
67
|
+
* @returns Readonly reactive array
|
|
68
|
+
*/
|
|
69
|
+
asReadonly(
|
|
70
|
+
frozen?: boolean,
|
|
71
|
+
): typeof frozen extends true ? ReadonlyFrozenSignal<Item[]> : ReadonlySignal<Item[]>;
|
|
72
|
+
|
|
55
73
|
/**
|
|
56
74
|
* Get the value at an index
|
|
57
75
|
*
|
|
@@ -114,17 +132,19 @@ export type ReactiveArray<Item> = {
|
|
|
114
132
|
/**
|
|
115
133
|
* Get the array _(without reactivity)_
|
|
116
134
|
*
|
|
135
|
+
* @param copy Copy the array? _(defaults to `false`)_
|
|
117
136
|
* @returns Array of items
|
|
118
137
|
*/
|
|
119
|
-
peek(): Item[];
|
|
138
|
+
peek(copy?: boolean): Item[];
|
|
120
139
|
|
|
121
140
|
/**
|
|
122
141
|
* Get the value at an index _(without reactivity)_
|
|
123
142
|
*
|
|
124
143
|
* @param index Index of item to get _(if negative, starts from the end)_
|
|
144
|
+
* @param copy If the item is an array or record, should it be copied? _(defaults to `false`)_
|
|
125
145
|
* @returns Item at index, or `undefined` if it doesn't exist
|
|
126
146
|
*/
|
|
127
|
-
peek(index: number): Item | undefined;
|
|
147
|
+
peek(index: number, copy?: boolean): Item | undefined;
|
|
128
148
|
|
|
129
149
|
/**
|
|
130
150
|
* Get the length of the array _(without reactivity)_
|
|
@@ -272,13 +292,31 @@ export type ReactiveState<Value, Equal> = {
|
|
|
272
292
|
value: Value;
|
|
273
293
|
};
|
|
274
294
|
|
|
275
|
-
export type ReactiveStore<
|
|
295
|
+
export type ReactiveStore<Store> = {
|
|
296
|
+
/**
|
|
297
|
+
* Get a readonly version of the reactive store
|
|
298
|
+
*
|
|
299
|
+
* @param frozen Freeze the store? _(defaults to `false`)_
|
|
300
|
+
* @returns Readonly reactive store
|
|
301
|
+
*/
|
|
302
|
+
asReadonly(frozen: true): ReadonlyFrozenSignal<Store>;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get a readonly version of the reactive store
|
|
306
|
+
*
|
|
307
|
+
* @param frozen Freeze the store? _(defaults to `false`)_
|
|
308
|
+
* @returns Readonly reactive store
|
|
309
|
+
*/
|
|
310
|
+
asReadonly(
|
|
311
|
+
frozen?: boolean,
|
|
312
|
+
): typeof frozen extends true ? ReadonlyFrozenSignal<Store> : ReadonlySignal<Store>;
|
|
313
|
+
|
|
276
314
|
/**
|
|
277
315
|
* Get the value
|
|
278
316
|
*
|
|
279
317
|
* @returns Current value
|
|
280
318
|
*/
|
|
281
|
-
get():
|
|
319
|
+
get(): Store;
|
|
282
320
|
|
|
283
321
|
/**
|
|
284
322
|
* Get a value by key
|
|
@@ -286,7 +324,7 @@ export type ReactiveStore<Value> = {
|
|
|
286
324
|
* @param key Key of the value to get
|
|
287
325
|
* @returns Value for the specified key, or `undefined` if it doesn't exist
|
|
288
326
|
*/
|
|
289
|
-
get<Key extends keyof
|
|
327
|
+
get<Key extends keyof Store>(key: Key): Store[Key];
|
|
290
328
|
|
|
291
329
|
/**
|
|
292
330
|
* Get a value by key
|
|
@@ -307,25 +345,28 @@ export type ReactiveStore<Value> = {
|
|
|
307
345
|
/**
|
|
308
346
|
* Get the value _(without reactivity)_
|
|
309
347
|
*
|
|
348
|
+
* @param copy Copy the store? _(defaults to `false`)_
|
|
310
349
|
* @returns Current value
|
|
311
350
|
*/
|
|
312
|
-
peek():
|
|
351
|
+
peek(copy?: boolean): Store;
|
|
313
352
|
|
|
314
353
|
/**
|
|
315
354
|
* Get a value by key _(without reactivity)_
|
|
316
355
|
*
|
|
317
356
|
* @param key Key of the value to get
|
|
357
|
+
* @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
|
|
318
358
|
* @returns Value for the specified key, or `undefined` if it doesn't exist
|
|
319
359
|
*/
|
|
320
|
-
peek<Key extends keyof
|
|
360
|
+
peek<Key extends keyof Store>(key: Key, copy?: boolean): Store[Key];
|
|
321
361
|
|
|
322
362
|
/**
|
|
323
363
|
* Get a value by key _(without reactivity)_
|
|
324
364
|
*
|
|
325
365
|
* @param key Key of the value to get
|
|
366
|
+
* @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
|
|
326
367
|
* @returns Value for the specified key, or `undefined` if it doesn't exist
|
|
327
368
|
*/
|
|
328
|
-
peek(key: Key): unknown;
|
|
369
|
+
peek(key: Key, copy?: boolean): unknown;
|
|
329
370
|
|
|
330
371
|
/**
|
|
331
372
|
* Set the value
|
|
@@ -334,9 +375,9 @@ export type ReactiveStore<Value> = {
|
|
|
334
375
|
*/
|
|
335
376
|
set(
|
|
336
377
|
value?:
|
|
337
|
-
|
|
|
338
|
-
| (() => null | undefined |
|
|
339
|
-
| Promise<null | undefined |
|
|
378
|
+
| Store
|
|
379
|
+
| (() => null | undefined | Store | Promise<null | undefined | Store>)
|
|
380
|
+
| Promise<null | undefined | Store>,
|
|
340
381
|
): void;
|
|
341
382
|
|
|
342
383
|
/**
|
|
@@ -345,9 +386,9 @@ export type ReactiveStore<Value> = {
|
|
|
345
386
|
* @param key Key of the value to set
|
|
346
387
|
* @param value New value
|
|
347
388
|
*/
|
|
348
|
-
set<Key extends keyof
|
|
389
|
+
set<Key extends keyof Store>(
|
|
349
390
|
key: Key,
|
|
350
|
-
value:
|
|
391
|
+
value: Store[Key] | (() => Store[Key] | Promise<Store[Key]>) | Promise<Store[Key]>,
|
|
351
392
|
): void;
|
|
352
393
|
|
|
353
394
|
/**
|
|
@@ -364,7 +405,7 @@ export type ReactiveStore<Value> = {
|
|
|
364
405
|
* @param callback Callback for changes
|
|
365
406
|
* @returns Unsubscribe callback
|
|
366
407
|
*/
|
|
367
|
-
subscribe(callback: (value:
|
|
408
|
+
subscribe(callback: (value: Store) => void): Unsubscribe;
|
|
368
409
|
|
|
369
410
|
/**
|
|
370
411
|
* Subscribe to changes for a specific key
|
|
@@ -373,9 +414,9 @@ export type ReactiveStore<Value> = {
|
|
|
373
414
|
* @param callback Callback for changes
|
|
374
415
|
* @returns Unsubscribe callback
|
|
375
416
|
*/
|
|
376
|
-
subscribe<Key extends keyof
|
|
417
|
+
subscribe<Key extends keyof Store>(
|
|
377
418
|
key: Key,
|
|
378
|
-
callback: (value:
|
|
419
|
+
callback: (value: Store[Key] | undefined) => void,
|
|
379
420
|
): Unsubscribe;
|
|
380
421
|
|
|
381
422
|
/**
|
|
@@ -393,25 +434,54 @@ export type ReactiveStore<Value> = {
|
|
|
393
434
|
* @param key Key of the value to unsubscribe from
|
|
394
435
|
* @param callback Callback to unsubscribe
|
|
395
436
|
*/
|
|
396
|
-
unsubscribe<Key extends keyof
|
|
437
|
+
unsubscribe<Key extends keyof Store>(
|
|
397
438
|
key: Key,
|
|
398
|
-
callback: (value:
|
|
439
|
+
callback: (value: Store[Key] | undefined) => void,
|
|
399
440
|
): void;
|
|
400
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Unsubscribe from changes for a specific key
|
|
444
|
+
*
|
|
445
|
+
* @param key Key of the value to unsubscribe from
|
|
446
|
+
* @param callback Callback to unsubscribe
|
|
447
|
+
*/
|
|
448
|
+
unsubscribe(key: Key, callback: (value: unknown | undefined) => void): void;
|
|
449
|
+
|
|
401
450
|
/**
|
|
402
451
|
* Unsubscribe from changes
|
|
403
452
|
*
|
|
404
453
|
* @param callback Callback to unsubscribe
|
|
405
454
|
*/
|
|
406
|
-
unsubscribe(callback: (value:
|
|
455
|
+
unsubscribe(callback: (value: Store) => void): void;
|
|
407
456
|
|
|
408
457
|
/**
|
|
409
458
|
* Update the value _(based on the current value)_
|
|
410
459
|
*
|
|
411
460
|
* @param callback Callback to update the value
|
|
412
461
|
*/
|
|
413
|
-
update(callback: (value:
|
|
414
|
-
} & Reactive<
|
|
462
|
+
update(callback: (value: Store) => Store): void;
|
|
463
|
+
} & Reactive<Store>;
|
|
464
|
+
|
|
465
|
+
export type ReadonlyInstances<Value> = {
|
|
466
|
+
frozen?: ReadonlyFrozenSignal<Value>;
|
|
467
|
+
original?: ReadonlySignal<Value>;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
export type ReadonlyFrozenSignal<Value> = ReadonlySignal<ReadonlySignalValue<Value>>;
|
|
471
|
+
|
|
472
|
+
export type ReadonlySignal<Value> = {
|
|
473
|
+
/**
|
|
474
|
+
* Is the signal frozen?
|
|
475
|
+
*/
|
|
476
|
+
get frozen(): boolean;
|
|
477
|
+
} & Reactive<Value> &
|
|
478
|
+
SimpleReactive<Value>;
|
|
479
|
+
|
|
480
|
+
export type ReadonlySignalValue<Value> = Value extends unknown[]
|
|
481
|
+
? Readonly<Value>
|
|
482
|
+
: Value extends PlainObject
|
|
483
|
+
? Readonly<Value>
|
|
484
|
+
: Value;
|
|
415
485
|
|
|
416
486
|
export type SetValueInProxyParameters<Value, Equal> = {
|
|
417
487
|
target: Value;
|
|
@@ -423,6 +493,24 @@ export type SetValueInProxyParameters<Value, Equal> = {
|
|
|
423
493
|
};
|
|
424
494
|
|
|
425
495
|
export type Signal<Value> = {
|
|
496
|
+
/**
|
|
497
|
+
* Get a readonly version of the signal
|
|
498
|
+
*
|
|
499
|
+
* @param frozen Freeze the signal? _(defaults to `false`)_
|
|
500
|
+
* @returns Readonly signal
|
|
501
|
+
*/
|
|
502
|
+
asReadonly(frozen: true): ReadonlyFrozenSignal<Value>;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Get a readonly version of the signal
|
|
506
|
+
*
|
|
507
|
+
* @param frozen Freeze the signal? _(defaults to `false`)_
|
|
508
|
+
* @returns Readonly signal
|
|
509
|
+
*/
|
|
510
|
+
asReadonly(
|
|
511
|
+
frozen?: boolean,
|
|
512
|
+
): typeof frozen extends true ? ReadonlyFrozenSignal<Value> : ReadonlySignal<Value>;
|
|
513
|
+
|
|
426
514
|
/**
|
|
427
515
|
* Set the value
|
|
428
516
|
*
|