@esportsplus/reactivity 0.0.23 → 0.0.25

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.
Files changed (76) hide show
  1. package/build/api/effect.d.ts +7 -0
  2. package/build/api/effect.js +3 -0
  3. package/build/api/index.d.ts +4 -0
  4. package/build/api/index.js +4 -0
  5. package/build/api/macro.d.ts +9 -0
  6. package/build/api/macro.js +8 -0
  7. package/build/api/promise.d.ts +8 -0
  8. package/build/api/promise.js +38 -0
  9. package/build/api/reactive.d.ts +11 -0
  10. package/build/api/reactive.js +27 -0
  11. package/build/context/index.d.ts +5 -0
  12. package/build/context/index.js +3 -0
  13. package/build/context/node.d.ts +7 -0
  14. package/build/context/node.js +21 -0
  15. package/build/context/nodes.d.ts +7 -0
  16. package/build/context/nodes.js +33 -0
  17. package/build/index.d.ts +2 -2
  18. package/build/index.js +2 -2
  19. package/build/signal.d.ts +25 -10
  20. package/build/signal.js +236 -2
  21. package/build/symbols.d.ts +2 -2
  22. package/build/symbols.js +2 -2
  23. package/build/types.d.ts +24 -18
  24. package/build/types.js +2 -1
  25. package/package.json +2 -2
  26. package/src/api/effect.ts +5 -0
  27. package/src/api/index.ts +4 -0
  28. package/src/api/macro.ts +15 -0
  29. package/src/api/promise.ts +48 -0
  30. package/src/api/reactive.ts +47 -0
  31. package/src/context/index.ts +5 -0
  32. package/src/context/node.ts +36 -0
  33. package/src/context/nodes.ts +52 -0
  34. package/src/index.ts +2 -2
  35. package/src/signal.ts +325 -11
  36. package/src/symbols.ts +5 -5
  37. package/src/types.ts +26 -23
  38. package/tsconfig.json +1 -1
  39. package/build/core.d.ts +0 -30
  40. package/build/core.js +0 -218
  41. package/build/methods/effect.d.ts +0 -2
  42. package/build/methods/effect.js +0 -4
  43. package/build/methods/index.d.ts +0 -3
  44. package/build/methods/index.js +0 -3
  45. package/build/methods/reactive.d.ts +0 -3
  46. package/build/methods/reactive.js +0 -52
  47. package/build/primitives/closure.d.ts +0 -3
  48. package/build/primitives/closure.js +0 -10
  49. package/build/primitives/computed.d.ts +0 -3
  50. package/build/primitives/computed.js +0 -11
  51. package/build/primitives/dispatch.d.ts +0 -3
  52. package/build/primitives/dispatch.js +0 -13
  53. package/build/primitives/dispose.d.ts +0 -3
  54. package/build/primitives/dispose.js +0 -13
  55. package/build/primitives/effect.d.ts +0 -7
  56. package/build/primitives/effect.js +0 -9
  57. package/build/primitives/index.d.ts +0 -8
  58. package/build/primitives/index.js +0 -8
  59. package/build/primitives/reactive.d.ts +0 -3
  60. package/build/primitives/reactive.js +0 -35
  61. package/build/primitives/reset.d.ts +0 -3
  62. package/build/primitives/reset.js +0 -13
  63. package/build/primitives/signal.d.ts +0 -8
  64. package/build/primitives/signal.js +0 -14
  65. package/build/reactive.d.ts +0 -22
  66. package/build/reactive.js +0 -190
  67. package/src/core.ts +0 -295
  68. package/src/primitives/closure.ts +0 -15
  69. package/src/primitives/computed.ts +0 -16
  70. package/src/primitives/dispatch.ts +0 -17
  71. package/src/primitives/dispose.ts +0 -17
  72. package/src/primitives/effect.ts +0 -13
  73. package/src/primitives/index.ts +0 -8
  74. package/src/primitives/reactive.ts +0 -43
  75. package/src/primitives/reset.ts +0 -17
  76. package/src/primitives/signal.ts +0 -18
package/build/reactive.js DELETED
@@ -1,190 +0,0 @@
1
- import { CLEAN, CHECK, DIRTY } from './symbols';
2
- let index = 0, reaction = null, queue = [], scheduled = false, schedulers = new Set, stack = null;
3
- function mark(instances, state) {
4
- if (!instances) {
5
- return;
6
- }
7
- for (let i = 0, n = instances.length; i < n; i++) {
8
- let instance = instances[i];
9
- if (instance.state < state) {
10
- if (instance.effect && instance.state === CLEAN) {
11
- queue.push(instance);
12
- if (!scheduled) {
13
- schedule();
14
- }
15
- }
16
- instance.state = state;
17
- if (instance.observers) {
18
- mark(instance.observers, CHECK);
19
- }
20
- }
21
- }
22
- }
23
- function schedule() {
24
- if (scheduled) {
25
- return;
26
- }
27
- for (let scheduler of schedulers) {
28
- scheduler.schedule();
29
- }
30
- scheduled = true;
31
- }
32
- async function task() {
33
- let n = queue.length;
34
- for (let i = 0; i < n; i++) {
35
- await queue[i].get();
36
- }
37
- queue.splice(0, n);
38
- scheduled = false;
39
- if (queue.length) {
40
- schedule();
41
- }
42
- }
43
- class Reactive {
44
- fn;
45
- value;
46
- effect;
47
- cleanup = null;
48
- observers = null;
49
- sources = null;
50
- state;
51
- constructor(data, effect = false) {
52
- this.effect = effect;
53
- if (typeof data === 'function') {
54
- this.fn = data;
55
- this.state = DIRTY;
56
- this.value = undefined;
57
- if (effect) {
58
- this.update();
59
- }
60
- }
61
- else {
62
- this.state = CLEAN;
63
- this.value = data;
64
- }
65
- }
66
- get() {
67
- if (reaction) {
68
- if (!stack && reaction.sources && reaction.sources[index] == this) {
69
- index++;
70
- }
71
- else {
72
- if (!stack) {
73
- stack = [this];
74
- }
75
- else {
76
- stack.push(this);
77
- }
78
- }
79
- }
80
- if (this.fn) {
81
- this.sync();
82
- }
83
- return this.value;
84
- }
85
- set(value) {
86
- if (this.value !== value) {
87
- mark(this.observers, DIRTY);
88
- }
89
- this.value = value;
90
- }
91
- removeParentObservers() {
92
- if (!this.sources) {
93
- return;
94
- }
95
- for (let i = index; i < this.sources.length; i++) {
96
- let source = this.sources[i];
97
- source.observers[source.observers.findIndex((v) => v === this)] = source.observers[source.observers.length - 1];
98
- source.observers.pop();
99
- }
100
- }
101
- sync() {
102
- if (this.state === CHECK && this.sources) {
103
- for (let i = 0, n = this.sources.length; i < n; i++) {
104
- this.sources[i].sync();
105
- if (this.state === DIRTY) {
106
- break;
107
- }
108
- }
109
- }
110
- if (this.state === DIRTY) {
111
- this.update();
112
- }
113
- this.state = CLEAN;
114
- }
115
- update() {
116
- let previous = {
117
- index: index,
118
- reaction: reaction,
119
- stack: stack,
120
- value: this.value
121
- };
122
- index = 0;
123
- reaction = this;
124
- stack = [];
125
- try {
126
- if (this.cleanup) {
127
- for (let i = 0, n = this.cleanup.length; i < n; i++) {
128
- this.cleanup[i](this.value);
129
- }
130
- this.cleanup.length = 0;
131
- }
132
- this.value = this.fn((fn) => {
133
- if (!this.cleanup) {
134
- this.cleanup = [fn];
135
- }
136
- else {
137
- this.cleanup.push(fn);
138
- }
139
- });
140
- if (stack.length) {
141
- this.removeParentObservers();
142
- if (this.sources && index > 0) {
143
- this.sources.length = index + stack.length;
144
- for (let i = 0; i < stack.length; i++) {
145
- this.sources[index + i] = stack[i];
146
- }
147
- }
148
- else {
149
- this.sources = stack;
150
- }
151
- for (let i = index; i < this.sources.length; i++) {
152
- let source = this.sources[i];
153
- if (!source.observers) {
154
- source.observers = [this];
155
- }
156
- else {
157
- source.observers.push(this);
158
- }
159
- }
160
- }
161
- else if (this.sources && index < this.sources.length) {
162
- this.removeParentObservers();
163
- this.sources.length = index;
164
- }
165
- }
166
- finally {
167
- index = previous.index;
168
- reaction = previous.reaction;
169
- stack = previous.stack;
170
- }
171
- if (this.observers && previous.value !== this.value) {
172
- for (let i = 0; i < this.observers.length; i++) {
173
- this.observers[i].state = DIRTY;
174
- }
175
- }
176
- this.state = CLEAN;
177
- }
178
- }
179
- const scheduler = {
180
- add: (scheduler) => {
181
- scheduler.tasks.add(task);
182
- schedulers.add(scheduler);
183
- },
184
- delete: (scheduler) => {
185
- scheduler.tasks.delete(task);
186
- schedulers.delete(scheduler);
187
- }
188
- };
189
- export default Reactive;
190
- export { scheduler };
package/src/core.ts DELETED
@@ -1,295 +0,0 @@
1
- import { CHECK, CLEAN, COMPUTED, DIRTY, DISPOSED, DISPOSE, EFFECT, RESET, SIGNAL, UPDATE } from './symbols';
2
- import { Computed, Effect, Fn, Listener, Options, Root, Scheduler } from './types';
3
- import Signal from './signal';
4
-
5
-
6
- let index = 0,
7
- observer: Signal | null = null,
8
- observers: Signal[] | null = null,
9
- scope: Root | null = null;
10
-
11
-
12
- function changed(a: unknown, b: unknown) {
13
- return a !== b;
14
- }
15
-
16
- function notify(nodes: Signal[], state: typeof CHECK | typeof DIRTY) {
17
- for (let i = 0, n = nodes.length; i < n; i++) {
18
- let node = nodes[i];
19
-
20
- if (node.state < state) {
21
- if (node.type === EFFECT && node.state === CLEAN) {
22
- (node as Effect).root.scheduler((node as Effect).task);
23
- }
24
-
25
- node.state = state;
26
-
27
- if (node.observers) {
28
- notify(node.observers, CHECK);
29
- }
30
- }
31
- }
32
- }
33
-
34
- function removeSourceObservers(node: Signal, start: number) {
35
- if (!node.sources) {
36
- return;
37
- }
38
-
39
- for (let i = start, n = node.sources.length; i < n; i++) {
40
- let source = node.sources[i];
41
-
42
- if (!source?.observers) {
43
- continue;
44
- }
45
-
46
- source.observers[source.observers.indexOf(node)] = source.observers[source.observers.length - 1];
47
- source.observers.pop();
48
- }
49
- }
50
-
51
- function sync(node: Signal) {
52
- if (node.state === CHECK && node.sources) {
53
- for (let i = 0, n = node.sources.length; i < n; i++) {
54
- sync(node.sources[i]);
55
-
56
- // Stop the loop here so we won't trigger updates on other parents unnecessarily
57
- // If our computation changes to no longer use some sources, we don't
58
- // want to update() a source we used last time, but now don't use.
59
- if ((node.state as Signal['state']) === DIRTY) {
60
- break;
61
- }
62
- }
63
- }
64
-
65
- if (node.state === DIRTY) {
66
- update(node);
67
- }
68
- else {
69
- node.state = CLEAN;
70
- }
71
- }
72
-
73
- function update(node: Signal) {
74
- let i = index,
75
- o = observer,
76
- os = observers;
77
-
78
- index = 0;
79
- observer = node;
80
- observers = null as typeof observers;
81
-
82
- try {
83
- if (node.listeners) {
84
- dispatch(UPDATE, node);
85
- }
86
-
87
- let value = node.fn!.call( node.context );
88
-
89
- if (observers) {
90
- if (node.sources) {
91
- removeSourceObservers(node, index);
92
- }
93
-
94
- if (node.sources && index > 0) {
95
- node.sources.length = index + observers.length;
96
-
97
- for (let i = 0, n = observers.length; i < n; i++) {
98
- node.sources[index + i] = observers[i];
99
- }
100
- }
101
- else {
102
- node.sources = observers;
103
- }
104
-
105
- for (let i = index, n = node.sources.length; i < n; i++) {
106
- let source = node.sources[i];
107
-
108
- if (!source.observers) {
109
- source.observers = [node];
110
- }
111
- else {
112
- source.observers.push(node);
113
- }
114
- }
115
- }
116
- else if (node.sources && index < node.sources.length) {
117
- removeSourceObservers(node, index);
118
- node.sources.length = index;
119
- }
120
-
121
- if (node.type === COMPUTED) {
122
- write(node, value);
123
- }
124
- }
125
- catch {
126
- if (node.state === DIRTY && node.sources) {
127
- removeSourceObservers(node, 0);
128
- }
129
- return;
130
- }
131
- finally {
132
- index = i;
133
- observer = o;
134
- observers = os;
135
- }
136
-
137
- node.state = CLEAN;
138
- }
139
-
140
-
141
- const computed = <T>(fn: Fn<T>, options: Options = {}) => {
142
- let node = new Signal(undefined as unknown, DIRTY, COMPUTED, options);
143
-
144
- node.fn = fn;
145
-
146
- return node as Computed;
147
- };
148
-
149
- const dispose = (node: Signal) => {
150
- if (node.state === DISPOSED) {
151
- return;
152
- }
153
-
154
- node.state = DISPOSED;
155
-
156
- if (node.listeners) {
157
- dispatch(DISPOSE, node);
158
- }
159
-
160
- if (node.sources) {
161
- removeSourceObservers(node, 0);
162
- }
163
-
164
- node.observers = null;
165
- node.sources = null;
166
- };
167
-
168
- const effect = <T>(fn: Fn<T>, options: Options = {}) => {
169
- if (!scope) {
170
- throw new Error('Reactivity: effects cannot be created without a reactive root');
171
- }
172
-
173
- let node = new Signal(undefined as unknown, DIRTY, EFFECT, options);
174
-
175
- node.fn = fn;
176
- node.root = scope;
177
- node.task = () => read(node);
178
-
179
- update(node);
180
-
181
- return node as Effect;
182
- };
183
-
184
- const dispatch = (event: symbol, node: Signal) => {
185
- if (!node.listeners?.[event]) {
186
- return;
187
- }
188
-
189
- let listeners = node.listeners[event],
190
- value = node.value;
191
-
192
- for (let i = 0, n = listeners.length; i < n; i++) {
193
- listeners[i](value);
194
- }
195
-
196
- node.listeners = null;
197
- };
198
-
199
- const on = (event: symbol, listener: Listener, node: Signal) => {
200
- if (!node.listeners?.[event]) {
201
- node.listeners ??= {};
202
- node.listeners[event] = [listener];
203
- }
204
- else {
205
- node.listeners[event].push(listener);
206
- }
207
- };
208
-
209
- const read = (node: Signal): typeof node['value'] => {
210
- if (node.state === DISPOSED) {
211
- return node.value;
212
- }
213
-
214
- if (observer) {
215
- if (!observers) {
216
- if (observer?.sources?.[index] == node) {
217
- index++;
218
- }
219
- else {
220
- observers = [node];
221
- }
222
- }
223
- else {
224
- observers.push(node);
225
- }
226
- }
227
-
228
- if (node.fn) {
229
- sync(node);
230
- }
231
-
232
- return node.value;
233
- };
234
-
235
- const reset = (node: Signal) => {
236
- if (node.listeners) {
237
- dispatch(RESET, node);
238
- }
239
-
240
- if (node.sources) {
241
- removeSourceObservers(node, 0);
242
- }
243
-
244
- node.observers = null;
245
- node.sources = null;
246
-
247
- if (node.type === COMPUTED) {
248
- node.state = DIRTY;
249
- node.value = undefined;
250
- }
251
- else if (node.type === SIGNAL) {
252
- node.state = CLEAN;
253
- }
254
- };
255
-
256
- const root = <T>(fn: () => T, properties: { scheduler?: Scheduler } = {}) => {
257
- let o = observer,
258
- s = scope;
259
-
260
- properties.scheduler = properties?.scheduler || scope?.scheduler;
261
-
262
- if (!properties.scheduler) {
263
- throw new Error('Reactivity: root cannot be created without a task scheduler');
264
- }
265
-
266
- observer = null;
267
- scope = properties as Root;
268
-
269
- let result = fn();
270
-
271
- observer = o;
272
- scope = s;
273
-
274
- return result;
275
- };
276
-
277
- const signal = <T>(data: T, options: Options = {}) => {
278
- return new Signal(data, CLEAN, SIGNAL, options);
279
- };
280
-
281
- const write = (node: Signal, value: unknown) => {
282
- if ((node?.changed || changed)(node.value, value)) {
283
- node.value = value;
284
-
285
- if (node.observers) {
286
- notify(node.observers, DIRTY);
287
- }
288
- }
289
-
290
- return node.value;
291
- };
292
-
293
-
294
- export default { computed, dispatch, dispose, effect, on, read, reset, root, signal, write };
295
- export { computed, dispatch, dispose, effect, on, read, reset, root, signal, write };
@@ -1,15 +0,0 @@
1
- import { computed, read } from '~/core';
2
- import { NODE } from '~/symbols';
3
- import { Options } from '~/types';
4
-
5
-
6
- export default (fn: () => (...args: unknown[]) => unknown, options: Options = {}) => {
7
- let node = computed(fn, options);
8
-
9
- node.context = function (...args: Parameters<ReturnType<typeof fn>>) {
10
- return (read(node) as ReturnType<typeof fn>)(...args);
11
- };
12
- node.context[NODE] = node;
13
-
14
- return node.context;
15
- };
@@ -1,16 +0,0 @@
1
- import { computed, on, read } from '~/core';
2
- import { NODE } from '~/symbols';
3
- import { Fn, Listener, Options } from '~/types';
4
-
5
-
6
- export default <T>(fn: Fn<T>, options: Options = {}) => {
7
- let node = computed(fn, options);
8
-
9
- node.context = function () {
10
- return read(node);
11
- };
12
- node.context[NODE] = node;
13
- node.context.on = (event: symbol, listener: Listener) => on(event, listener, node);
14
-
15
- return node.context;
16
- };
@@ -1,17 +0,0 @@
1
- import { dispatch } from '~/core';
2
- import { NODE, NODES } from '~/symbols';
3
- import { Wrapper } from '~/types';
4
-
5
-
6
- export default (key: symbol, wrapper: Wrapper) => {
7
- if (wrapper[NODE]) {
8
- dispatch(key, wrapper[NODE]);
9
- }
10
- else if (wrapper[NODES]) {
11
- let nodes = wrapper[NODES];
12
-
13
- for (let i = 0, n = nodes.length; i < n; i++) {
14
- dispatch(key, nodes[i]);
15
- }
16
- }
17
- };
@@ -1,17 +0,0 @@
1
- import { dispose } from '~/core';
2
- import { NODE, NODES } from '~/symbols';
3
- import { Wrapper } from '~/types';
4
-
5
-
6
- export default (wrapper: Wrapper) => {
7
- if (wrapper[NODE]) {
8
- dispose(wrapper[NODE]);
9
- }
10
- else if (wrapper[NODES]) {
11
- let nodes = wrapper[NODES];
12
-
13
- for (let i = 0, n = nodes.length; i < n; i++) {
14
- dispose(nodes[i]);
15
- }
16
- }
17
- };
@@ -1,13 +0,0 @@
1
- import { effect, on } from '~/core';
2
- import { NODE } from '~/symbols';
3
- import { Listener, Options } from '~/types';
4
-
5
-
6
- export default (fn: () => unknown, options: Options = {}) => {
7
- let node = effect(fn, options);
8
-
9
- return node.context = {
10
- [NODE]: node,
11
- on: (event: symbol, listener: Listener) => on(event, listener, node)
12
- };
13
- };
@@ -1,8 +0,0 @@
1
- export { default as closure } from './closure';
2
- export { default as computed } from './computed';
3
- export { default as dispatch } from './dispatch';
4
- export { default as dispose } from './dispose';
5
- export { default as effect } from './effect';
6
- export { default as reactive } from './reactive';
7
- export { default as reset } from './reset';
8
- export { default as signal } from './signal';
@@ -1,43 +0,0 @@
1
- import { computed as c, read, signal as s, write } from '~/core';
2
- import { NODES } from '~/symbols';
3
- import { Fn, Infer, Options, Signal } from '~/types';
4
- import computed from './computed';
5
- import signal from './signal';
6
-
7
-
8
- export default <T>(value: Fn<T> | T, options: Options = {}) => {
9
- if (typeof value === 'object' && value !== null && (value.constructor === Object)) {
10
- let nodes: Record<string, Signal> = {},
11
- properties: PropertyDescriptorMap = {};
12
-
13
- for (let key in value) {
14
- if (typeof value[key] === 'function') {
15
- nodes[key] = c(value[key] as Parameters<typeof c>[0], options);
16
- properties[key] = {
17
- get() {
18
- return read(nodes[key]);
19
- }
20
- };
21
- }
22
- else {
23
- nodes[key] = s(value[key], options);
24
- properties[key] = {
25
- get() {
26
- return read(nodes[key]);
27
- },
28
- set(value) {
29
- write(nodes[key], value);
30
- }
31
- };
32
- }
33
- }
34
-
35
- return Object.defineProperties({ [NODES]: Object.values(nodes) }, properties) as Infer<typeof value>;
36
- }
37
-
38
- if (typeof value === 'function') {
39
- return computed(value as Parameters<typeof computed>[0], options);
40
- }
41
-
42
- return signal(value, options);
43
- };
@@ -1,17 +0,0 @@
1
- import { reset } from '~/core';
2
- import { NODE, NODES } from '~/symbols';
3
- import { Wrapper } from '~/types';
4
-
5
-
6
- export default (wrapper: Wrapper) => {
7
- if (wrapper[NODE]) {
8
- reset(wrapper[NODE]);
9
- }
10
- else if (wrapper[NODES]) {
11
- let nodes = wrapper[NODES];
12
-
13
- for (let i = 0, n = nodes.length; i < n; i++) {
14
- reset(nodes[i]);
15
- }
16
- }
17
- };
@@ -1,18 +0,0 @@
1
- import { read, signal, write } from '~/core';
2
- import { NODE } from '~/symbols';
3
- import { Options } from '~/types';
4
-
5
-
6
- export default <T>(data: T, options: Options = {}) => {
7
- let node = signal(data, options);
8
-
9
- return node.context = {
10
- [NODE]: node,
11
- get: () => {
12
- return read(node);
13
- },
14
- set: (value: T) => {
15
- write(node, value);
16
- }
17
- };
18
- };