@esportsplus/reactivity 0.1.14 → 0.1.17
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/macro.d.ts +1 -1
- package/build/reactive/object.d.ts +1 -1
- package/build/signal.d.ts +2 -2
- package/build/signal.js +15 -10
- package/build/types.d.ts +7 -4
- package/package.json +2 -2
- package/src/reactive/object.ts +1 -1
- package/src/signal.ts +25 -20
- package/src/types.ts +7 -4
package/build/macro.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ declare class Macro<A extends unknown[], R> extends CustomFunction {
|
|
|
6
6
|
constructor(fn: Function<A, R>, options?: Options);
|
|
7
7
|
dispose(): void;
|
|
8
8
|
}
|
|
9
|
-
declare const _default: <A extends unknown[], R>(fn: () => (...args: A) => R, options?: Options) => Macro<A, R>;
|
|
9
|
+
declare const _default: <A extends unknown[], R>(fn: (instance: Computed<(...args: A) => R>) => (...args: A) => R, options?: Options) => Macro<A, R>;
|
|
10
10
|
export default _default;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Computed, Object, Options, Signal } from '../types';
|
|
2
2
|
import { ReactiveArray, ReactiveObjectArray } from './array';
|
|
3
|
-
type Node = Computed<
|
|
3
|
+
type Node = Computed<any> | ReactiveArray<any> | ReactiveObjectArray<Object> | Signal<any>;
|
|
4
4
|
declare class ReactiveObject<T extends Object> {
|
|
5
5
|
nodes: Record<PropertyKey, Node>;
|
|
6
6
|
constructor(data: T, options?: Options);
|
package/build/signal.d.ts
CHANGED
|
@@ -20,12 +20,12 @@ declare class Reactive<T> {
|
|
|
20
20
|
once<T>(event: Event, listener: Listener<T>): void;
|
|
21
21
|
set(value: T): T;
|
|
22
22
|
}
|
|
23
|
-
declare const computed: <T>(fn: () => T
|
|
23
|
+
declare const computed: <T>(fn: (instance: Computed<T>) => T, options?: Options) => Computed<T>;
|
|
24
24
|
declare const dispose: <T extends {
|
|
25
25
|
dispose: VoidFunction;
|
|
26
26
|
}>(dispose?: T | T[] | null | undefined) => T | T[] | null | undefined;
|
|
27
27
|
declare const effect: (fn: Effect['fn']) => Effect;
|
|
28
|
-
declare const root: <T>(fn: (
|
|
28
|
+
declare const root: <T>(fn: (instance: Root) => T, scheduler?: Scheduler) => T;
|
|
29
29
|
declare const signal: <T>(value: T, options?: Options) => Signal<T>;
|
|
30
30
|
export { computed, dispose, effect, root, signal };
|
|
31
31
|
export { Reactive };
|
package/build/signal.js
CHANGED
|
@@ -65,6 +65,7 @@ class Reactive {
|
|
|
65
65
|
if (this.state === DISPOSED) {
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
+
this.dispatch('cleanup', this);
|
|
68
69
|
this.dispatch('dispose', this);
|
|
69
70
|
removeSourceObservers(this, 0);
|
|
70
71
|
this.listeners = null;
|
|
@@ -96,7 +97,10 @@ class Reactive {
|
|
|
96
97
|
}
|
|
97
98
|
on(event, listener) {
|
|
98
99
|
if (this.state === DIRTY) {
|
|
99
|
-
|
|
100
|
+
if (event !== 'cleanup') {
|
|
101
|
+
throw new Error(`Reactivity: events set within computed or effects must use the 'cleanup' event name`);
|
|
102
|
+
}
|
|
103
|
+
listener.once = true;
|
|
100
104
|
}
|
|
101
105
|
if (this.listeners === null) {
|
|
102
106
|
this.listeners = { [event]: [listener] };
|
|
@@ -155,12 +159,12 @@ function removeSourceObservers(node, start) {
|
|
|
155
159
|
return;
|
|
156
160
|
}
|
|
157
161
|
for (let i = start, n = node.sources.length; i < n; i++) {
|
|
158
|
-
let
|
|
159
|
-
if (
|
|
162
|
+
let observers = node.sources[i].observers;
|
|
163
|
+
if (observers === null) {
|
|
160
164
|
continue;
|
|
161
165
|
}
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
observers[observers.indexOf(node)] = observers[observers.length - 1];
|
|
167
|
+
observers.pop();
|
|
164
168
|
}
|
|
165
169
|
}
|
|
166
170
|
function sync(node) {
|
|
@@ -185,8 +189,9 @@ function update(node) {
|
|
|
185
189
|
observer = node;
|
|
186
190
|
observers = null;
|
|
187
191
|
try {
|
|
192
|
+
node.dispatch('cleanup');
|
|
188
193
|
node.dispatch('update');
|
|
189
|
-
let value = node.fn.call(node);
|
|
194
|
+
let value = node.fn.call(null, node);
|
|
190
195
|
if (observers) {
|
|
191
196
|
removeSourceObservers(node, index);
|
|
192
197
|
if (node.sources !== null && index > 0) {
|
|
@@ -200,7 +205,7 @@ function update(node) {
|
|
|
200
205
|
}
|
|
201
206
|
for (let i = index, n = node.sources.length; i < n; i++) {
|
|
202
207
|
let source = node.sources[i];
|
|
203
|
-
if (
|
|
208
|
+
if (source.observers === null) {
|
|
204
209
|
source.observers = [node];
|
|
205
210
|
}
|
|
206
211
|
else {
|
|
@@ -249,9 +254,9 @@ const effect = (fn) => {
|
|
|
249
254
|
update(instance);
|
|
250
255
|
return instance;
|
|
251
256
|
};
|
|
252
|
-
const root = (fn, scheduler
|
|
257
|
+
const root = (fn, scheduler) => {
|
|
253
258
|
let o = observer, s = scope;
|
|
254
|
-
if (scheduler ===
|
|
259
|
+
if (scheduler === undefined) {
|
|
255
260
|
if (scope === null) {
|
|
256
261
|
throw new Error('Reactivity: `root` cannot be created without a task scheduler');
|
|
257
262
|
}
|
|
@@ -261,7 +266,7 @@ const root = (fn, scheduler = null) => {
|
|
|
261
266
|
scope = new Reactive(CLEAN, ROOT, null);
|
|
262
267
|
scope.scheduler = scheduler;
|
|
263
268
|
scope.tracking = fn.length > 0;
|
|
264
|
-
let result = fn(scope);
|
|
269
|
+
let result = fn.call(null, scope);
|
|
265
270
|
observer = o;
|
|
266
271
|
scope = s;
|
|
267
272
|
return result;
|
package/build/types.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Function, NeverAsync, Prettify } from '@esportsplus/typescript';
|
|
2
2
|
import { CHECK, CLEAN, COMPUTED, DIRTY, DISPOSED, EFFECT, ROOT, SIGNAL } from './constants';
|
|
3
3
|
import { Reactive } from './signal';
|
|
4
|
-
type Base<T> = Omit<Reactive<T>, 'changed' | 'fn' | 'scheduler' | 'task' | 'tracking'>;
|
|
4
|
+
type Base<T> = Omit<Reactive<T>, 'changed' | 'fn' | 'get' | 'scheduler' | 'set' | 'task' | 'tracking'>;
|
|
5
5
|
type Changed = (a: unknown, b: unknown) => boolean;
|
|
6
6
|
type Computed<T> = {
|
|
7
7
|
changed: Changed;
|
|
8
|
-
fn: NeverAsync<() => T>;
|
|
8
|
+
fn: NeverAsync<(instance: Computed<T>) => T>;
|
|
9
|
+
get(): T;
|
|
9
10
|
} & Base<T>;
|
|
10
11
|
type Effect = {
|
|
11
|
-
fn: NeverAsync<(
|
|
12
|
+
fn: NeverAsync<(instance: Effect) => void>;
|
|
12
13
|
root: Root;
|
|
13
14
|
task: Function;
|
|
14
15
|
} & Omit<Base<void>, 'value'>;
|
|
@@ -28,10 +29,12 @@ type Root = {
|
|
|
28
29
|
scheduler: Scheduler;
|
|
29
30
|
tracking: boolean;
|
|
30
31
|
value: void;
|
|
31
|
-
} & Omit<Reactive<void>, '
|
|
32
|
+
} & Omit<Reactive<void>, 'root'>;
|
|
32
33
|
type Scheduler = (fn: Function) => unknown;
|
|
33
34
|
type Signal<T> = {
|
|
34
35
|
changed: Changed;
|
|
36
|
+
get(): T;
|
|
37
|
+
set(value: T): T;
|
|
35
38
|
} & Base<T>;
|
|
36
39
|
type State = typeof CHECK | typeof CLEAN | typeof DIRTY | typeof DISPOSED;
|
|
37
40
|
type Type = typeof COMPUTED | typeof EFFECT | typeof ROOT | typeof SIGNAL;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"@esportsplus/custom-function": "^0.0.1"
|
|
5
5
|
},
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@esportsplus/typescript": "^0.0.
|
|
7
|
+
"@esportsplus/typescript": "^0.0.15"
|
|
8
8
|
},
|
|
9
9
|
"main": "build/index.js",
|
|
10
10
|
"name": "@esportsplus/reactivity",
|
|
@@ -16,5 +16,5 @@
|
|
|
16
16
|
"prepublishOnly": "npm run build"
|
|
17
17
|
},
|
|
18
18
|
"types": "build/index.d.ts",
|
|
19
|
-
"version": "0.1.
|
|
19
|
+
"version": "0.1.17"
|
|
20
20
|
}
|
package/src/reactive/object.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { defineProperty, isArray } from '~/utilities';
|
|
|
4
4
|
import { ReactiveArray, ReactiveObjectArray } from './array';
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
type Node = Computed<
|
|
7
|
+
type Node = Computed<any> | ReactiveArray<any> | ReactiveObjectArray<Object> | Signal<any>;
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class ReactiveObject<T extends Object> {
|
package/src/signal.ts
CHANGED
|
@@ -88,6 +88,7 @@ class Reactive<T> {
|
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
this.dispatch('cleanup', this);
|
|
91
92
|
this.dispatch('dispose', this);
|
|
92
93
|
|
|
93
94
|
removeSourceObservers(this, 0);
|
|
@@ -125,9 +126,12 @@ class Reactive<T> {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
on<T>(event: Event, listener: Listener<T>) {
|
|
128
|
-
// Events cannot be set within effects or computed's
|
|
129
129
|
if (this.state === DIRTY) {
|
|
130
|
-
|
|
130
|
+
if (event !== 'cleanup') {
|
|
131
|
+
throw new Error(`Reactivity: events set within computed or effects must use the 'cleanup' event name`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
listener.once = true;
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
if (this.listeners === null) {
|
|
@@ -186,7 +190,7 @@ function notify<T>(nodes: Reactive<T>[] | null, state: typeof CHECK | typeof DIR
|
|
|
186
190
|
|
|
187
191
|
if (node.state < state) {
|
|
188
192
|
if (node.type === EFFECT && node.state === CLEAN) {
|
|
189
|
-
node.root
|
|
193
|
+
(node as Effect).root.scheduler((node as Effect).task);
|
|
190
194
|
}
|
|
191
195
|
|
|
192
196
|
node.state = state;
|
|
@@ -201,14 +205,14 @@ function removeSourceObservers<T>(node: Reactive<T>, start: number) {
|
|
|
201
205
|
}
|
|
202
206
|
|
|
203
207
|
for (let i = start, n = node.sources.length; i < n; i++) {
|
|
204
|
-
let
|
|
208
|
+
let observers = node.sources[i].observers;
|
|
205
209
|
|
|
206
|
-
if (
|
|
210
|
+
if (observers === null) {
|
|
207
211
|
continue;
|
|
208
212
|
}
|
|
209
213
|
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
observers[observers.indexOf(node)] = observers[observers.length - 1];
|
|
215
|
+
observers.pop();
|
|
212
216
|
}
|
|
213
217
|
}
|
|
214
218
|
|
|
@@ -244,10 +248,11 @@ function update<T>(node: Reactive<T>) {
|
|
|
244
248
|
observers = null as typeof observers;
|
|
245
249
|
|
|
246
250
|
try {
|
|
251
|
+
node.dispatch('cleanup');
|
|
247
252
|
node.dispatch('update');
|
|
248
253
|
|
|
249
254
|
// @ts-ignore
|
|
250
|
-
let value = node.fn.call(node);
|
|
255
|
+
let value = node.fn.call(null, node);
|
|
251
256
|
|
|
252
257
|
if (observers) {
|
|
253
258
|
removeSourceObservers(node, index);
|
|
@@ -266,7 +271,7 @@ function update<T>(node: Reactive<T>) {
|
|
|
266
271
|
for (let i = index, n = node.sources.length; i < n; i++) {
|
|
267
272
|
let source = node.sources[i];
|
|
268
273
|
|
|
269
|
-
if (
|
|
274
|
+
if (source.observers === null) {
|
|
270
275
|
source.observers = [node];
|
|
271
276
|
}
|
|
272
277
|
else {
|
|
@@ -294,12 +299,12 @@ function update<T>(node: Reactive<T>) {
|
|
|
294
299
|
|
|
295
300
|
|
|
296
301
|
const computed = <T>(fn: Computed<T>['fn'], options?: Options) => {
|
|
297
|
-
let instance = new Reactive(DIRTY, COMPUTED, undefined as T)
|
|
302
|
+
let instance = new Reactive(DIRTY, COMPUTED, undefined as T);
|
|
298
303
|
|
|
299
304
|
instance.changed = options?.changed || changed;
|
|
300
305
|
instance.fn = fn;
|
|
301
306
|
|
|
302
|
-
return instance
|
|
307
|
+
return instance as Computed<T>;
|
|
303
308
|
};
|
|
304
309
|
|
|
305
310
|
const dispose = <T extends { dispose: VoidFunction }>(dispose?: T[] | T | null) => {
|
|
@@ -318,21 +323,21 @@ const dispose = <T extends { dispose: VoidFunction }>(dispose?: T[] | T | null)
|
|
|
318
323
|
};
|
|
319
324
|
|
|
320
325
|
const effect = (fn: Effect['fn']) => {
|
|
321
|
-
let instance = new Reactive(DIRTY, EFFECT, null)
|
|
326
|
+
let instance = new Reactive(DIRTY, EFFECT, null);
|
|
322
327
|
|
|
323
328
|
instance.fn = fn;
|
|
324
329
|
instance.task = () => instance.get();
|
|
325
330
|
|
|
326
|
-
update(instance
|
|
331
|
+
update(instance);
|
|
327
332
|
|
|
328
|
-
return instance;
|
|
333
|
+
return instance as Effect;
|
|
329
334
|
};
|
|
330
335
|
|
|
331
|
-
const root = <T>(fn: NeverAsync<(
|
|
336
|
+
const root = <T>(fn: NeverAsync<(instance: Root) => T>, scheduler?: Scheduler) => {
|
|
332
337
|
let o = observer,
|
|
333
338
|
s = scope;
|
|
334
339
|
|
|
335
|
-
if (scheduler ===
|
|
340
|
+
if (scheduler === undefined) {
|
|
336
341
|
if (scope === null) {
|
|
337
342
|
throw new Error('Reactivity: `root` cannot be created without a task scheduler');
|
|
338
343
|
}
|
|
@@ -343,10 +348,10 @@ const root = <T>(fn: NeverAsync<(root: Root) => T>, scheduler: Scheduler | null
|
|
|
343
348
|
observer = null;
|
|
344
349
|
|
|
345
350
|
scope = new Reactive(CLEAN, ROOT, null) as any as Root;
|
|
346
|
-
scope.scheduler = scheduler
|
|
351
|
+
scope.scheduler = scheduler;
|
|
347
352
|
scope.tracking = fn.length > 0;
|
|
348
353
|
|
|
349
|
-
let result = fn(scope);
|
|
354
|
+
let result = fn.call(null, scope);
|
|
350
355
|
|
|
351
356
|
observer = o;
|
|
352
357
|
scope = s;
|
|
@@ -355,11 +360,11 @@ const root = <T>(fn: NeverAsync<(root: Root) => T>, scheduler: Scheduler | null
|
|
|
355
360
|
};
|
|
356
361
|
|
|
357
362
|
const signal = <T>(value: T, options?: Options) => {
|
|
358
|
-
let instance = new Reactive(CLEAN, SIGNAL, value)
|
|
363
|
+
let instance = new Reactive(CLEAN, SIGNAL, value);
|
|
359
364
|
|
|
360
365
|
instance.changed = options?.changed || changed;
|
|
361
366
|
|
|
362
|
-
return instance
|
|
367
|
+
return instance as Signal<T>;
|
|
363
368
|
};
|
|
364
369
|
|
|
365
370
|
|
package/src/types.ts
CHANGED
|
@@ -3,17 +3,18 @@ import { CHECK, CLEAN, COMPUTED, DIRTY, DISPOSED, EFFECT, ROOT, SIGNAL } from '.
|
|
|
3
3
|
import { Reactive } from './signal';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
type Base<T> = Omit<Reactive<T>, 'changed' | 'fn' | 'scheduler' | 'task' | 'tracking'>;
|
|
6
|
+
type Base<T> = Omit<Reactive<T>, 'changed' | 'fn' | 'get' | 'scheduler' | 'set' | 'task' | 'tracking'>;
|
|
7
7
|
|
|
8
8
|
type Changed = (a: unknown, b: unknown) => boolean;
|
|
9
9
|
|
|
10
10
|
type Computed<T> = {
|
|
11
11
|
changed: Changed;
|
|
12
|
-
fn: NeverAsync<() => T>;
|
|
12
|
+
fn: NeverAsync<(instance: Computed<T>) => T>;
|
|
13
|
+
get(): T;
|
|
13
14
|
} & Base<T>;
|
|
14
15
|
|
|
15
16
|
type Effect = {
|
|
16
|
-
fn: NeverAsync<(
|
|
17
|
+
fn: NeverAsync<(instance: Effect) => void>;
|
|
17
18
|
root: Root;
|
|
18
19
|
task: Function;
|
|
19
20
|
} & Omit<Base<void>, 'value'>;
|
|
@@ -36,12 +37,14 @@ type Root = {
|
|
|
36
37
|
scheduler: Scheduler;
|
|
37
38
|
tracking: boolean;
|
|
38
39
|
value: void;
|
|
39
|
-
} & Omit<Reactive<void>, '
|
|
40
|
+
} & Omit<Reactive<void>, 'root'>;
|
|
40
41
|
|
|
41
42
|
type Scheduler = (fn: Function) => unknown;
|
|
42
43
|
|
|
43
44
|
type Signal<T> = {
|
|
44
45
|
changed: Changed;
|
|
46
|
+
get(): T;
|
|
47
|
+
set(value: T): T;
|
|
45
48
|
} & Base<T>;
|
|
46
49
|
|
|
47
50
|
type State = typeof CHECK | typeof CLEAN | typeof DIRTY | typeof DISPOSED;
|