@esportsplus/reactivity 0.0.2 → 0.0.5
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/build/index.d.ts +29 -4
- package/build/index.js +24 -21
- package/build/obj.d.ts +1 -1
- package/build/obj.js +11 -8
- package/build/types.d.ts +4 -1
- package/package.json +3 -3
- package/src/index.ts +41 -36
- package/src/obj.ts +22 -15
- package/src/types.ts +5 -1
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Queue } from './types';
|
|
2
|
+
type Infer<T> = T extends (...args: any[]) => any ? Infer<ReturnType<T>> : T extends Record<string, any> ? {
|
|
3
|
+
[K in keyof T]: Infer<T[K]>;
|
|
4
|
+
} : Reactive<T>;
|
|
5
|
+
declare class Reactive<T> {
|
|
6
|
+
private effect;
|
|
7
|
+
private fn?;
|
|
8
|
+
private observers;
|
|
9
|
+
private queue;
|
|
10
|
+
private sources;
|
|
11
|
+
private state;
|
|
12
|
+
private value;
|
|
13
|
+
cleanup: ((old: T) => void)[] | null;
|
|
14
|
+
constructor(input: ((fn: VoidFunction) => T) | T, queue?: Queue | null, effect?: boolean);
|
|
15
|
+
get(): T;
|
|
16
|
+
set(value: T): void;
|
|
17
|
+
private mark;
|
|
18
|
+
private removeParentObservers;
|
|
19
|
+
private sync;
|
|
20
|
+
private update;
|
|
21
|
+
}
|
|
22
|
+
declare const effect: (queue: Queue) => <T>(value: () => T) => void;
|
|
23
|
+
declare const reactive: <T>(value: T) => Infer<T>;
|
|
24
|
+
declare const _default: {
|
|
25
|
+
effect: (queue: Queue) => <T>(value: () => T) => void;
|
|
26
|
+
reactive: <T_1>(value: T_1) => Infer<T_1>;
|
|
27
|
+
};
|
|
28
|
+
export default _default;
|
|
29
|
+
export { effect, reactive };
|
package/build/index.js
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { CLEAN, CHECK, DIRTY } from './symbols';
|
|
2
2
|
import obj from './obj';
|
|
3
|
-
let index = 0,
|
|
3
|
+
let index = 0, reaction = null, stack = null;
|
|
4
4
|
class Reactive {
|
|
5
5
|
effect;
|
|
6
6
|
fn;
|
|
7
7
|
observers = null;
|
|
8
|
+
queue = null;
|
|
8
9
|
sources = null;
|
|
9
10
|
state;
|
|
10
11
|
value;
|
|
11
12
|
cleanup = null;
|
|
12
|
-
constructor(
|
|
13
|
+
constructor(input, queue = null, effect = false) {
|
|
13
14
|
this.effect = effect;
|
|
14
|
-
if (typeof
|
|
15
|
-
this.fn =
|
|
15
|
+
if (typeof input === 'function') {
|
|
16
|
+
this.fn = input;
|
|
16
17
|
this.state = DIRTY;
|
|
17
18
|
this.value = undefined;
|
|
18
19
|
if (effect) {
|
|
20
|
+
this.queue = queue;
|
|
19
21
|
this.update();
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
else {
|
|
23
25
|
this.state = CLEAN;
|
|
24
|
-
this.value =
|
|
26
|
+
this.value = input;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
get() {
|
|
@@ -54,7 +56,12 @@ class Reactive {
|
|
|
54
56
|
mark(state) {
|
|
55
57
|
if (this.state < state) {
|
|
56
58
|
if (this.state === CLEAN && this.effect) {
|
|
57
|
-
|
|
59
|
+
if (!this.queue) {
|
|
60
|
+
throw new Error('Effects cannot be updated without a queue');
|
|
61
|
+
}
|
|
62
|
+
this.queue.add(async () => {
|
|
63
|
+
await this.get();
|
|
64
|
+
});
|
|
58
65
|
}
|
|
59
66
|
this.state = state;
|
|
60
67
|
if (!this.observers) {
|
|
@@ -153,24 +160,20 @@ class Reactive {
|
|
|
153
160
|
this.state = CLEAN;
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
|
-
const effect = (
|
|
157
|
-
|
|
163
|
+
const effect = (queue) => {
|
|
164
|
+
return (value) => {
|
|
165
|
+
new Reactive(value, queue, true);
|
|
166
|
+
};
|
|
158
167
|
};
|
|
159
168
|
const reactive = (value) => {
|
|
169
|
+
let v;
|
|
160
170
|
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
return new Reactive(value);
|
|
164
|
-
};
|
|
165
|
-
const tick = () => {
|
|
166
|
-
if (running) {
|
|
167
|
-
return;
|
|
171
|
+
v = obj(value);
|
|
168
172
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
queue[i].get();
|
|
173
|
+
else {
|
|
174
|
+
v = new Reactive(value);
|
|
172
175
|
}
|
|
173
|
-
|
|
174
|
-
running = false;
|
|
176
|
+
return v;
|
|
175
177
|
};
|
|
176
|
-
export { effect, reactive
|
|
178
|
+
export default { effect, reactive };
|
|
179
|
+
export { effect, reactive };
|
package/build/obj.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const factory: <T
|
|
1
|
+
declare const factory: <T extends Record<string, any>>(values: T) => {};
|
|
2
2
|
export default factory;
|
package/build/obj.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import { reactive } from './index';
|
|
2
|
+
function setup(value) {
|
|
3
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
4
|
+
return factory(value);
|
|
5
|
+
}
|
|
6
|
+
return reactive(value);
|
|
7
|
+
}
|
|
2
8
|
const factory = (values) => {
|
|
3
9
|
let lazy = {}, properties = {};
|
|
4
10
|
for (let key in values) {
|
|
5
11
|
properties[key] = {
|
|
6
12
|
get() {
|
|
7
13
|
if (!lazy[key]) {
|
|
8
|
-
|
|
9
|
-
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
10
|
-
lazy[key] = factory(value);
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
lazy[key] = reactive(value);
|
|
14
|
-
}
|
|
14
|
+
lazy[key] = setup(values[key]);
|
|
15
15
|
}
|
|
16
|
-
return lazy[key]
|
|
16
|
+
return lazy[key].get();
|
|
17
17
|
},
|
|
18
18
|
set(value) {
|
|
19
|
+
if (!lazy[key]) {
|
|
20
|
+
lazy[key] = setup(values[key]);
|
|
21
|
+
}
|
|
19
22
|
lazy[key].set(value);
|
|
20
23
|
}
|
|
21
24
|
};
|
package/build/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"author": "ICJR",
|
|
3
3
|
"description": "Reactivity",
|
|
4
4
|
"devDependencies": {
|
|
5
|
-
"tsc-alias": "^1.8.
|
|
6
|
-
"typescript": "^4.9.
|
|
5
|
+
"tsc-alias": "^1.8.2",
|
|
6
|
+
"typescript": "^4.9.4"
|
|
7
7
|
},
|
|
8
8
|
"main": "./build/index.js",
|
|
9
9
|
"name": "@esportsplus/reactivity",
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
"prepublishOnly": "npm run build"
|
|
16
16
|
},
|
|
17
17
|
"types": "./build/index.d.ts",
|
|
18
|
-
"version": "0.0.
|
|
18
|
+
"version": "0.0.5"
|
|
19
19
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { CLEAN, CHECK, DIRTY } from './symbols';
|
|
2
|
-
import { State } from './types';
|
|
2
|
+
import { Queue, State } from './types';
|
|
3
3
|
import obj from './obj';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
type Infer<T> =
|
|
7
|
+
T extends (...args: any[]) => any
|
|
8
|
+
? Infer<ReturnType<T>>
|
|
9
|
+
: T extends Record<string, any>
|
|
10
|
+
? { [K in keyof T]: Infer<T[K]> }
|
|
11
|
+
// Requires class type
|
|
12
|
+
: Reactive<T>;
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
let index = 0,
|
|
7
|
-
queue: Reactive<any>[] = [],
|
|
8
16
|
reaction: Reactive<any> | null = null,
|
|
9
|
-
running: boolean = false,
|
|
10
17
|
stack: Reactive<any>[] | null = null;
|
|
11
18
|
|
|
12
19
|
|
|
@@ -14,6 +21,7 @@ class Reactive<T> {
|
|
|
14
21
|
private effect: boolean;
|
|
15
22
|
private fn?: (onCleanup: (fn: VoidFunction) => void) => T;
|
|
16
23
|
private observers: Reactive<any>[] | null = null;
|
|
24
|
+
private queue: Queue | null = null;
|
|
17
25
|
private sources: Reactive<any>[] | null = null;
|
|
18
26
|
private state: State;
|
|
19
27
|
private value: T;
|
|
@@ -22,21 +30,22 @@ class Reactive<T> {
|
|
|
22
30
|
cleanup: ((old: T) => void)[] | null = null;
|
|
23
31
|
|
|
24
32
|
|
|
25
|
-
constructor(
|
|
33
|
+
constructor(input: ((fn: VoidFunction) => T) | T, queue: Queue | null = null, effect: boolean = false) {
|
|
26
34
|
this.effect = effect;
|
|
27
35
|
|
|
28
|
-
if (typeof
|
|
29
|
-
this.fn =
|
|
36
|
+
if (typeof input === 'function') {
|
|
37
|
+
this.fn = input as (onCleanup: (fn: VoidFunction) => void) => T;
|
|
30
38
|
this.state = DIRTY;
|
|
31
39
|
this.value = undefined as any;
|
|
32
40
|
|
|
33
41
|
if (effect) {
|
|
42
|
+
this.queue = queue;
|
|
34
43
|
this.update();
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
else {
|
|
38
47
|
this.state = CLEAN;
|
|
39
|
-
this.value =
|
|
48
|
+
this.value = input;
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
|
|
@@ -63,7 +72,7 @@ class Reactive<T> {
|
|
|
63
72
|
return this.value;
|
|
64
73
|
}
|
|
65
74
|
|
|
66
|
-
set(value: T)
|
|
75
|
+
set(value: T) {
|
|
67
76
|
if (this.observers && this.value !== value) {
|
|
68
77
|
for (let i = 0; i < this.observers.length; i++) {
|
|
69
78
|
this.observers[i].mark(DIRTY);
|
|
@@ -74,11 +83,17 @@ class Reactive<T> {
|
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
|
|
77
|
-
private mark(state: typeof CHECK | typeof DIRTY)
|
|
86
|
+
private mark(state: typeof CHECK | typeof DIRTY) {
|
|
78
87
|
if (this.state < state) {
|
|
79
88
|
// If previous state was clean we need to update effects
|
|
80
89
|
if (this.state === CLEAN && this.effect) {
|
|
81
|
-
|
|
90
|
+
if (!this.queue) {
|
|
91
|
+
throw new Error('Effects cannot be updated without a queue');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.queue.add(async () => {
|
|
95
|
+
await this.get();
|
|
96
|
+
});
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
this.state = state;
|
|
@@ -94,7 +109,7 @@ class Reactive<T> {
|
|
|
94
109
|
}
|
|
95
110
|
|
|
96
111
|
// We don't actually delete sources here because we're replacing the entire array soon
|
|
97
|
-
private removeParentObservers()
|
|
112
|
+
private removeParentObservers() {
|
|
98
113
|
if (!this.sources) {
|
|
99
114
|
return;
|
|
100
115
|
}
|
|
@@ -108,7 +123,7 @@ class Reactive<T> {
|
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
// Update if dirty or if a parent is dirty
|
|
111
|
-
private sync()
|
|
126
|
+
private sync() {
|
|
112
127
|
// If we are potentially dirty, see if we have a parent who has actually changed value
|
|
113
128
|
if (this.state === CHECK && this.sources) {
|
|
114
129
|
for (let i = 0, n = this.sources.length; i < n; i++) {
|
|
@@ -132,7 +147,7 @@ class Reactive<T> {
|
|
|
132
147
|
this.state = CLEAN;
|
|
133
148
|
}
|
|
134
149
|
|
|
135
|
-
private update()
|
|
150
|
+
private update() {
|
|
136
151
|
let previous = {
|
|
137
152
|
index: index,
|
|
138
153
|
reaction: reaction,
|
|
@@ -217,35 +232,25 @@ class Reactive<T> {
|
|
|
217
232
|
}
|
|
218
233
|
|
|
219
234
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
235
|
+
const effect = (queue: Queue) => {
|
|
236
|
+
return <T>(value: () => T) => {
|
|
237
|
+
new Reactive(value, queue, true);
|
|
238
|
+
};
|
|
223
239
|
};
|
|
224
240
|
|
|
225
|
-
const reactive = <T>(value: T)
|
|
226
|
-
|
|
227
|
-
return obj(value);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return new Reactive(value) as T;
|
|
231
|
-
};
|
|
241
|
+
const reactive = <T>(value: T) => {
|
|
242
|
+
let v;
|
|
232
243
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return;
|
|
244
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
245
|
+
v = obj(value);
|
|
236
246
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
for (let i = 0, n = queue.length; i < n; i++) {
|
|
241
|
-
queue[i].get();
|
|
247
|
+
else {
|
|
248
|
+
v = new Reactive(value);
|
|
242
249
|
}
|
|
243
250
|
|
|
244
|
-
|
|
245
|
-
running = false;
|
|
251
|
+
return v as Infer<T>;
|
|
246
252
|
};
|
|
247
253
|
|
|
248
254
|
|
|
249
|
-
export { effect, reactive
|
|
250
|
-
|
|
251
|
-
|
|
255
|
+
export default { effect, reactive };
|
|
256
|
+
export { effect, reactive };
|
package/src/obj.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { reactive } from './index';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function setup(value: unknown) {
|
|
5
|
+
// if (Array.isArray(value)) {
|
|
6
|
+
// TODO: Need a solution
|
|
7
|
+
// }
|
|
8
|
+
// TODO: Can remove isArray once solution is found ^
|
|
9
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
10
|
+
return factory(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return reactive(value);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
// TODO: Typecheck on values tro get rid of lazy var
|
|
18
|
+
const factory = <T extends Record<string, any>>(values: T) => {
|
|
5
19
|
let lazy: Record<string, any> = {},
|
|
6
20
|
properties: PropertyDescriptorMap = {};
|
|
7
21
|
|
|
@@ -9,29 +23,22 @@ const factory = <T>(values: T) => {
|
|
|
9
23
|
properties[key] = {
|
|
10
24
|
get() {
|
|
11
25
|
if (!lazy[key]) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// if (Array.isArray(value)) {
|
|
15
|
-
// TODO: Need a solution
|
|
16
|
-
// }
|
|
17
|
-
// TODO: Can remove isArray once solution is found ^
|
|
18
|
-
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
19
|
-
lazy[key] = factory(value as Record<string, unknown>);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
lazy[key] = reactive(value);
|
|
23
|
-
}
|
|
26
|
+
lazy[key] = setup(values[key]);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
return lazy[key]
|
|
29
|
+
return lazy[key].get();
|
|
27
30
|
},
|
|
28
31
|
set(value: unknown) {
|
|
32
|
+
if (!lazy[key]) {
|
|
33
|
+
lazy[key] = setup(values[key]);
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
lazy[key].set(value);
|
|
30
37
|
}
|
|
31
38
|
};
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
return Object.defineProperties({}, properties)
|
|
41
|
+
return Object.defineProperties({}, properties);
|
|
35
42
|
};
|
|
36
43
|
|
|
37
44
|
|
package/src/types.ts
CHANGED