rask-ui 0.28.3 → 0.29.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.
Files changed (65) hide show
  1. package/README.md +1 -1
  2. package/dist/component.d.ts +4 -3
  3. package/dist/component.d.ts.map +1 -1
  4. package/dist/component.js +37 -57
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -1
  8. package/dist/render.js +2 -2
  9. package/dist/scheduler.d.ts +2 -3
  10. package/dist/scheduler.d.ts.map +1 -1
  11. package/dist/scheduler.js +31 -104
  12. package/dist/tests/batch.test.js +202 -12
  13. package/dist/tests/createContext.test.js +50 -37
  14. package/dist/tests/error.test.js +25 -12
  15. package/dist/tests/renderCount.test.d.ts +2 -0
  16. package/dist/tests/renderCount.test.d.ts.map +1 -0
  17. package/dist/tests/renderCount.test.js +95 -0
  18. package/dist/tests/scopeEnforcement.test.d.ts +2 -0
  19. package/dist/tests/scopeEnforcement.test.d.ts.map +1 -0
  20. package/dist/tests/scopeEnforcement.test.js +157 -0
  21. package/dist/tests/useAction.test.d.ts +2 -0
  22. package/dist/tests/useAction.test.d.ts.map +1 -0
  23. package/dist/tests/useAction.test.js +132 -0
  24. package/dist/tests/useAsync.test.d.ts +2 -0
  25. package/dist/tests/useAsync.test.d.ts.map +1 -0
  26. package/dist/tests/useAsync.test.js +499 -0
  27. package/dist/tests/useDerived.test.d.ts +2 -0
  28. package/dist/tests/useDerived.test.d.ts.map +1 -0
  29. package/dist/tests/useDerived.test.js +407 -0
  30. package/dist/tests/useEffect.test.d.ts +2 -0
  31. package/dist/tests/useEffect.test.d.ts.map +1 -0
  32. package/dist/tests/useEffect.test.js +600 -0
  33. package/dist/tests/useLookup.test.d.ts +2 -0
  34. package/dist/tests/useLookup.test.d.ts.map +1 -0
  35. package/dist/tests/useLookup.test.js +299 -0
  36. package/dist/tests/useRef.test.d.ts +2 -0
  37. package/dist/tests/useRef.test.d.ts.map +1 -0
  38. package/dist/tests/useRef.test.js +189 -0
  39. package/dist/tests/useState.test.d.ts +2 -0
  40. package/dist/tests/useState.test.d.ts.map +1 -0
  41. package/dist/tests/useState.test.js +178 -0
  42. package/dist/tests/useSuspend.test.d.ts +2 -0
  43. package/dist/tests/useSuspend.test.d.ts.map +1 -0
  44. package/dist/tests/useSuspend.test.js +752 -0
  45. package/dist/tests/useView.test.d.ts +2 -0
  46. package/dist/tests/useView.test.d.ts.map +1 -0
  47. package/dist/tests/useView.test.js +305 -0
  48. package/dist/useAsync.d.ts.map +1 -1
  49. package/dist/useAsync.js +12 -11
  50. package/dist/useDerived.d.ts +1 -1
  51. package/dist/useDerived.d.ts.map +1 -1
  52. package/dist/useDerived.js +9 -63
  53. package/dist/useEffect.d.ts.map +1 -1
  54. package/dist/useEffect.js +4 -19
  55. package/dist/useLookup.d.ts.map +1 -1
  56. package/dist/useLookup.js +9 -14
  57. package/dist/useRef.d.ts.map +1 -1
  58. package/dist/useRef.js +4 -8
  59. package/dist/useRouter.d.ts.map +1 -1
  60. package/dist/useRouter.js +4 -8
  61. package/dist/useState.d.ts +0 -1
  62. package/dist/useState.d.ts.map +1 -1
  63. package/dist/useState.js +2 -100
  64. package/dist/useSuspend.d.ts.map +1 -1
  65. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useView.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useView.test.d.ts","sourceRoot":"","sources":["../../src/tests/useView.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,305 @@
1
+ import { jsx as _jsx } from "rask-ui/jsx-runtime";
2
+ import { describe, it, expect } from "vitest";
3
+ import { useView } from "../useView";
4
+ import { useState } from "../useState";
5
+ import { Observer } from "../observation";
6
+ import { render } from "../";
7
+ describe("createView", () => {
8
+ it("should merge two plain objects", () => {
9
+ let view;
10
+ function Component() {
11
+ const a = { x: 1, y: 2 };
12
+ const b = { z: 3 };
13
+ view = useView(a, b);
14
+ return () => _jsx("div", { children: "test" });
15
+ }
16
+ const container = document.createElement("div");
17
+ render(_jsx(Component, {}), container);
18
+ expect(view.x).toBe(1);
19
+ expect(view.y).toBe(2);
20
+ expect(view.z).toBe(3);
21
+ });
22
+ it("should allow later arguments to override earlier ones", () => {
23
+ let view;
24
+ function Component() {
25
+ const a = { x: 1, y: 2 };
26
+ const b = { y: 3, z: 4 };
27
+ view = useView(a, b);
28
+ return () => _jsx("div", { children: "test" });
29
+ }
30
+ const container = document.createElement("div");
31
+ render(_jsx(Component, {}), container);
32
+ expect(view.x).toBe(1);
33
+ expect(view.y).toBe(3); // b.y overrides a.y
34
+ expect(view.z).toBe(4);
35
+ });
36
+ it("should maintain reactivity with reactive objects", async () => {
37
+ let view;
38
+ let state;
39
+ function Component() {
40
+ state = useState({ count: 0 });
41
+ view = useView(state);
42
+ return () => _jsx("div", { children: "test" });
43
+ }
44
+ const container = document.createElement("div");
45
+ render(_jsx(Component, {}), container);
46
+ let renderCount = 0;
47
+ let lastValue = 0;
48
+ const observer = new Observer(() => {
49
+ renderCount++;
50
+ });
51
+ const dispose = observer.observe();
52
+ lastValue = view.count; // Track the property
53
+ dispose();
54
+ expect(renderCount).toBe(0);
55
+ state.count = 5;
56
+ // Wait for microtask to process notification
57
+ await new Promise((resolve) => {
58
+ queueMicrotask(() => {
59
+ expect(renderCount).toBe(1);
60
+ lastValue = view.count;
61
+ expect(lastValue).toBe(5);
62
+ resolve(undefined);
63
+ });
64
+ });
65
+ });
66
+ it("should merge reactive and plain objects while maintaining reactivity", () => {
67
+ let view;
68
+ let state;
69
+ function Component() {
70
+ state = useState({ count: 0 });
71
+ const helpers = {
72
+ increment() {
73
+ state.count++;
74
+ },
75
+ decrement() {
76
+ state.count--;
77
+ },
78
+ };
79
+ view = useView(state, helpers);
80
+ return () => _jsx("div", { children: "test" });
81
+ }
82
+ const container = document.createElement("div");
83
+ render(_jsx(Component, {}), container);
84
+ expect(view.count).toBe(0);
85
+ expect(typeof view.increment).toBe("function");
86
+ expect(typeof view.decrement).toBe("function");
87
+ view.increment();
88
+ expect(view.count).toBe(1);
89
+ view.decrement();
90
+ expect(view.count).toBe(0);
91
+ });
92
+ it("should merge multiple reactive objects", () => {
93
+ let view;
94
+ let state1;
95
+ let state2;
96
+ let state3;
97
+ function Component() {
98
+ state1 = useState({ count: 0 });
99
+ state2 = useState({ name: "Alice" });
100
+ state3 = useState({ age: 25 });
101
+ view = useView(state1, state2, state3);
102
+ return () => _jsx("div", { children: "test" });
103
+ }
104
+ const container = document.createElement("div");
105
+ render(_jsx(Component, {}), container);
106
+ expect(view.count).toBe(0);
107
+ expect(view.name).toBe("Alice");
108
+ expect(view.age).toBe(25);
109
+ state1.count = 10;
110
+ state2.name = "Bob";
111
+ state3.age = 30;
112
+ expect(view.count).toBe(10);
113
+ expect(view.name).toBe("Bob");
114
+ expect(view.age).toBe(30);
115
+ });
116
+ it("should reflect changes in source objects", () => {
117
+ let view;
118
+ let source;
119
+ function Component() {
120
+ source = { x: 1 };
121
+ view = useView(source);
122
+ return () => _jsx("div", { children: "test" });
123
+ }
124
+ const container = document.createElement("div");
125
+ render(_jsx(Component, {}), container);
126
+ expect(view.x).toBe(1);
127
+ source.x = 2;
128
+ expect(view.x).toBe(2);
129
+ });
130
+ it("should handle property override order correctly", () => {
131
+ let view;
132
+ function Component() {
133
+ const a = { x: 1, y: 2, z: 3 };
134
+ const b = { y: 20 };
135
+ const c = { z: 30 };
136
+ view = useView(a, b, c);
137
+ return () => _jsx("div", { children: "test" });
138
+ }
139
+ const container = document.createElement("div");
140
+ render(_jsx(Component, {}), container);
141
+ expect(view.x).toBe(1); // From a
142
+ expect(view.y).toBe(20); // From b (overrides a)
143
+ expect(view.z).toBe(30); // From c (overrides a)
144
+ });
145
+ it("should only include enumerable properties", () => {
146
+ let view;
147
+ function Component() {
148
+ const obj = { x: 1 };
149
+ Object.defineProperty(obj, "hidden", {
150
+ value: 42,
151
+ enumerable: false,
152
+ });
153
+ view = useView(obj);
154
+ return () => _jsx("div", { children: "test" });
155
+ }
156
+ const container = document.createElement("div");
157
+ render(_jsx(Component, {}), container);
158
+ expect(view.x).toBe(1);
159
+ expect(view.hidden).toBeUndefined();
160
+ });
161
+ it("should handle symbol keys", () => {
162
+ let view;
163
+ let sym;
164
+ function Component() {
165
+ sym = Symbol("test");
166
+ const obj = { x: 1, [sym]: "symbol value" };
167
+ view = useView(obj);
168
+ return () => _jsx("div", { children: "test" });
169
+ }
170
+ const container = document.createElement("div");
171
+ render(_jsx(Component, {}), container);
172
+ expect(view.x).toBe(1);
173
+ expect(view[sym]).toBe("symbol value");
174
+ });
175
+ it("should track dependencies for each property independently", async () => {
176
+ let view;
177
+ let state;
178
+ function Component() {
179
+ state = useState({ count: 0, name: "Alice" });
180
+ view = useView(state);
181
+ return () => _jsx("div", { children: "test" });
182
+ }
183
+ const container = document.createElement("div");
184
+ render(_jsx(Component, {}), container);
185
+ let countRenderCount = 0;
186
+ let nameRenderCount = 0;
187
+ // Observer that only accesses count
188
+ const countObserver = new Observer(() => {
189
+ countRenderCount++;
190
+ });
191
+ const dispose1 = countObserver.observe();
192
+ view.count; // Track count
193
+ dispose1();
194
+ expect(countRenderCount).toBe(0);
195
+ // Change count - should trigger
196
+ state.count = 1;
197
+ await new Promise((resolve) => {
198
+ queueMicrotask(() => {
199
+ expect(countRenderCount).toBe(1);
200
+ resolve(undefined);
201
+ });
202
+ });
203
+ // Change name - should NOT trigger (not tracked)
204
+ state.name = "Bob";
205
+ await new Promise((resolve) => {
206
+ queueMicrotask(() => {
207
+ expect(countRenderCount).toBe(1); // Still 1
208
+ resolve(undefined);
209
+ });
210
+ });
211
+ // Now track name with a different observer
212
+ const nameObserver = new Observer(() => {
213
+ nameRenderCount++;
214
+ });
215
+ const dispose2 = nameObserver.observe();
216
+ view.name; // Track name
217
+ dispose2();
218
+ expect(nameRenderCount).toBe(0);
219
+ // Change name - should trigger name observer
220
+ state.name = "Charlie";
221
+ await new Promise((resolve) => {
222
+ queueMicrotask(() => {
223
+ expect(nameRenderCount).toBe(1);
224
+ resolve(undefined);
225
+ });
226
+ });
227
+ });
228
+ it("should return the same value type as source", () => {
229
+ let view;
230
+ function Component() {
231
+ const obj = { nums: [1, 2, 3], nested: { x: 1 } };
232
+ view = useView(obj);
233
+ return () => _jsx("div", { children: "test" });
234
+ }
235
+ const container = document.createElement("div");
236
+ render(_jsx(Component, {}), container);
237
+ expect(Array.isArray(view.nums)).toBe(true);
238
+ expect(view.nums).toEqual([1, 2, 3]);
239
+ expect(typeof view.nested).toBe("object");
240
+ expect(view.nested.x).toBe(1);
241
+ });
242
+ it("should handle empty merge", () => {
243
+ let view;
244
+ function Component() {
245
+ view = useView({});
246
+ return () => _jsx("div", { children: "test" });
247
+ }
248
+ const container = document.createElement("div");
249
+ render(_jsx(Component, {}), container);
250
+ expect(Object.keys(view).length).toBe(0);
251
+ });
252
+ it("should merge single object", () => {
253
+ let view;
254
+ function Component() {
255
+ const obj = { x: 1, y: 2 };
256
+ view = useView(obj);
257
+ return () => _jsx("div", { children: "test" });
258
+ }
259
+ const container = document.createElement("div");
260
+ render(_jsx(Component, {}), container);
261
+ expect(view.x).toBe(1);
262
+ expect(view.y).toBe(2);
263
+ });
264
+ it("should maintain function context", () => {
265
+ let view;
266
+ let state;
267
+ function Component() {
268
+ state = useState({ count: 0 });
269
+ const methods = {
270
+ increment() {
271
+ state.count++;
272
+ },
273
+ };
274
+ view = useView(state, methods);
275
+ return () => _jsx("div", { children: "test" });
276
+ }
277
+ const container = document.createElement("div");
278
+ render(_jsx(Component, {}), container);
279
+ expect(view.count).toBe(0);
280
+ view.increment();
281
+ expect(view.count).toBe(1);
282
+ expect(state.count).toBe(1);
283
+ });
284
+ it("should work with reactive state and computed-like patterns", () => {
285
+ let view;
286
+ let state;
287
+ function Component() {
288
+ state = useState({ firstName: "John", lastName: "Doe" });
289
+ const computed = {
290
+ get fullName() {
291
+ return `${state.firstName} ${state.lastName}`;
292
+ },
293
+ };
294
+ view = useView(state, computed);
295
+ return () => _jsx("div", { children: "test" });
296
+ }
297
+ const container = document.createElement("div");
298
+ render(_jsx(Component, {}), container);
299
+ expect(view.firstName).toBe("John");
300
+ expect(view.lastName).toBe("Doe");
301
+ expect(view.fullName).toBe("John Doe");
302
+ state.firstName = "Jane";
303
+ expect(view.fullName).toBe("Jane Doe");
304
+ });
305
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEN,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,IAAI;IAC9C,UAAU,CAAC,CAAC,CAAC;IACb,MAAM,OAAO,CAAC,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,WAWrC;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,EACjD,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GA0InC,KAAK,CAAC,CAAC,CAAC,CACd"}
1
+ {"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEN,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,IAAI;IAC9C,UAAU,CAAC,CAAC,CAAC;IACb,MAAM,OAAO,CAAC,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,WAWrC;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,EACjD,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GA4InC,KAAK,CAAC,CAAC,CAAC,CACd"}
package/dist/useAsync.js CHANGED
@@ -1,7 +1,7 @@
1
- import { syncBatch } from "./batch";
2
1
  import { useCleanup, getCurrentComponent } from "./component";
3
- import { Observer } from "./observation";
2
+ import { transaction } from "./scheduler";
4
3
  import { assignState, useState } from "./useState";
4
+ import { Reaction } from "mobx";
5
5
  export function isAsync(value) {
6
6
  if (value === null || typeof value !== "object") {
7
7
  return false;
@@ -27,15 +27,16 @@ export function useAsync(fn) {
27
27
  const refresh = () => {
28
28
  currentAbortController?.abort();
29
29
  const abortController = (currentAbortController = new AbortController());
30
- const stopObserving = observer.observe();
31
- const promise = fn(abortController.signal);
32
- stopObserving();
30
+ let promise;
31
+ reaction.track(() => {
32
+ promise = fn(abortController.signal);
33
+ });
33
34
  promise
34
35
  .then((result) => {
35
36
  if (abortController.signal.aborted) {
36
37
  return;
37
38
  }
38
- syncBatch(() => {
39
+ transaction(() => {
39
40
  assignState(state, {
40
41
  isLoading: false,
41
42
  isRefreshing: false,
@@ -50,7 +51,7 @@ export function useAsync(fn) {
50
51
  if (abortController.signal.aborted) {
51
52
  return;
52
53
  }
53
- syncBatch(() => {
54
+ transaction(() => {
54
55
  assignState(state, {
55
56
  isLoading: state.isLoading,
56
57
  isRefreshing: state.isRefreshing,
@@ -63,8 +64,8 @@ export function useAsync(fn) {
63
64
  });
64
65
  return promise;
65
66
  };
66
- const observer = new Observer(() => {
67
- syncBatch(() => {
67
+ const reaction = new Reaction("AsyncReaction", () => {
68
+ transaction(() => {
68
69
  if (state.isLoading) {
69
70
  refresh();
70
71
  }
@@ -90,7 +91,7 @@ export function useAsync(fn) {
90
91
  });
91
92
  useCleanup(() => {
92
93
  currentAbortController?.abort();
93
- observer.dispose();
94
+ reaction.dispose();
94
95
  });
95
96
  refresh();
96
97
  return [
@@ -99,7 +100,7 @@ export function useAsync(fn) {
99
100
  if (state.isLoading && !state.error) {
100
101
  return;
101
102
  }
102
- syncBatch(() => {
103
+ transaction(() => {
103
104
  if (state.error && state.value === null) {
104
105
  assignState(state, {
105
106
  isLoading: true,
@@ -1,5 +1,5 @@
1
1
  export type Derived<T extends Record<string, () => any>> = {
2
2
  [K in keyof T]: ReturnType<T[K]>;
3
3
  };
4
- export declare function useDerived<T extends Record<string, () => any>>(computed: T): Derived<T>;
4
+ export declare function useDerived<T extends Record<string, () => any>>(computedDefs: T): Derived<T>;
5
5
  //# sourceMappingURL=useDerived.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDerived.d.ts","sourceRoot":"","sources":["../src/useDerived.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,IAAI;KACxD,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACjC,CAAC;AAEF,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAC5D,QAAQ,EAAE,CAAC,GACV,OAAO,CAAC,CAAC,CAAC,CAiFZ"}
1
+ {"version":3,"file":"useDerived.d.ts","sourceRoot":"","sources":["../src/useDerived.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,IAAI;KACxD,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACjC,CAAC;AAEF,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAC5D,YAAY,EAAE,CAAC,GACd,OAAO,CAAC,CAAC,CAAC,CAmBZ"}
@@ -1,72 +1,18 @@
1
- import { getCurrentComponent, useCleanup } from "./component";
2
- import { INSPECT_MARKER, INSPECTOR_ENABLED } from "./inspect";
3
- import { getCurrentObserver, Observer, Signal } from "./observation";
4
- export function useDerived(computed) {
1
+ import { getCurrentComponent } from "./component";
2
+ import { computed } from "mobx";
3
+ export function useDerived(computedDefs) {
5
4
  const currentComponent = getCurrentComponent();
6
5
  if (!currentComponent || currentComponent.isRendering) {
7
6
  throw new Error("Only use useDerived in component setup");
8
7
  }
9
- const proxy = {};
10
- let notifyInspectorRef = {};
11
- for (const prop in computed) {
12
- let isDirty = true;
13
- let value;
14
- const signal = new Signal();
15
- const computedObserver = new Observer(() => {
16
- isDirty = true;
17
- signal.notify();
18
- if (INSPECTOR_ENABLED) {
19
- notifyInspectorRef.current?.notify({
20
- type: "computed",
21
- path: notifyInspectorRef.current.path.concat(prop),
22
- isDirty: true,
23
- value,
24
- });
25
- }
26
- }, false);
27
- useCleanup(() => computedObserver.dispose());
28
- Object.defineProperty(proxy, prop, {
29
- enumerable: true,
30
- configurable: true,
8
+ const derived = {};
9
+ for (const key in computedDefs) {
10
+ const computedValue = computed(computedDefs[key]);
11
+ Object.defineProperty(derived, key, {
31
12
  get() {
32
- const currentObserver = getCurrentObserver();
33
- if (currentObserver) {
34
- currentObserver.subscribeSignal(signal);
35
- }
36
- if (isDirty) {
37
- const stopObserving = computedObserver.observe();
38
- value = computed[prop]();
39
- stopObserving();
40
- isDirty = false;
41
- if (INSPECTOR_ENABLED) {
42
- notifyInspectorRef.current?.notify({
43
- type: "computed",
44
- path: notifyInspectorRef.current.path.concat(prop),
45
- isDirty: false,
46
- value,
47
- });
48
- }
49
- return value;
50
- }
51
- return value;
13
+ return computedValue.get();
52
14
  },
53
15
  });
54
16
  }
55
- if (INSPECTOR_ENABLED) {
56
- Object.defineProperty(proxy, INSPECT_MARKER, {
57
- enumerable: false,
58
- configurable: false,
59
- get() {
60
- return !notifyInspectorRef.current;
61
- },
62
- set: (value) => {
63
- Object.defineProperty(notifyInspectorRef, "current", {
64
- get() {
65
- return value.current;
66
- },
67
- });
68
- },
69
- });
70
- }
71
- return proxy;
17
+ return derived;
72
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useEffect.d.ts","sourceRoot":"","sources":["../src/useEffect.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QA2BtD"}
1
+ {"version":3,"file":"useEffect.d.ts","sourceRoot":"","sources":["../src/useEffect.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QActD"}
package/dist/useEffect.js CHANGED
@@ -1,29 +1,14 @@
1
- import { syncBatch } from "./batch";
2
1
  import { useCleanup, getCurrentComponent } from "./component";
3
- import { Observer } from "./observation";
2
+ import { autorun } from "./scheduler";
4
3
  export function useEffect(cb) {
5
4
  const component = getCurrentComponent();
6
5
  if (!component || component.isRendering) {
7
6
  throw new Error("Only use useEffect in component setup");
8
7
  }
9
8
  let disposer;
10
- const observer = new Observer(() => {
11
- syncBatch(runEffect);
12
- });
13
- const runEffect = () => {
14
- try {
15
- disposer?.();
16
- }
17
- catch (error) {
18
- console.error("Error in effect dispose function:", error);
19
- }
20
- const stopObserving = observer.observe();
21
- disposer = cb();
22
- stopObserving();
23
- };
24
- useCleanup(() => {
25
- observer.dispose();
9
+ const autorunDisposer = autorun(() => {
26
10
  disposer?.();
11
+ disposer = cb();
27
12
  });
28
- runEffect();
13
+ useCleanup(autorunDisposer);
29
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useLookup.d.ts","sourceRoot":"","sources":["../src/useLookup.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,EAC3D,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,GAAG,EAAE,CAAC,IAsBE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAG,CAAC,GAAG,SAAS,CAGlC"}
1
+ {"version":3,"file":"useLookup.d.ts","sourceRoot":"","sources":["../src/useLookup.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,EAC3D,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,GAAG,EAAE,CAAC,IAeE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAG,CAAC,GAAG,SAAS,CAGlC"}
package/dist/useLookup.js CHANGED
@@ -1,22 +1,17 @@
1
1
  import { useCleanup } from "./component";
2
- import { Observer } from "./observation";
2
+ import { autorun } from "./scheduler";
3
3
  import { useState } from "./useState";
4
4
  export function useLookup(getArray, key) {
5
- const state = useState({
6
- lookup: {},
7
- });
5
+ const state = useState(new Map());
8
6
  function updateMap() {
9
- const disposeObserve = observer.observe();
10
- state.lookup = getArray().reduce((aggr, item) => {
11
- aggr[item[key]] = item;
12
- return aggr;
13
- }, {});
14
- disposeObserve();
7
+ state.clear();
8
+ getArray().forEach((item) => {
9
+ state.set(item[key], item);
10
+ });
15
11
  }
16
- const observer = new Observer(updateMap, false);
17
- updateMap();
18
- useCleanup(() => observer.dispose());
12
+ const dispose = autorun(updateMap);
13
+ useCleanup(dispose);
19
14
  return (key) => {
20
- return state.lookup[key];
15
+ return state.get(key);
21
16
  };
22
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useRef.d.ts","sourceRoot":"","sources":["../src/useRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;AAElC,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,QAE1D;AAED,wBAAgB,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAoBxC"}
1
+ {"version":3,"file":"useRef.d.ts","sourceRoot":"","sources":["../src/useRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;AAElC,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,QAE1D;AAED,wBAAgB,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAiBxC"}
package/dist/useRef.js CHANGED
@@ -1,24 +1,20 @@
1
- import { getCurrentObserver, Signal } from "./observation";
2
1
  import { getCurrentComponent } from "./component";
2
+ import { observable } from "mobx";
3
3
  export function assignRef(ref, refValue) {
4
4
  ref.current = refValue;
5
5
  }
6
6
  export function useRef() {
7
- let value = null;
8
7
  const currentComponent = getCurrentComponent();
9
8
  if (!currentComponent || currentComponent.isRendering) {
10
9
  throw new Error("Only use useRef in component setup");
11
10
  }
12
- const signal = new Signal();
11
+ const observableValue = observable.box(null);
13
12
  return {
14
13
  get current() {
15
- const currentObserver = getCurrentObserver();
16
- currentObserver?.subscribeSignal(signal);
17
- return value;
14
+ return observableValue.get();
18
15
  },
19
16
  set current(newValue) {
20
- signal.notify();
21
- value = newValue;
17
+ observableValue.set(newValue);
22
18
  },
23
19
  };
24
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useRouter.d.ts","sourceRoot":"","sources":["../src/useRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,OAAO,EACP,OAAO,EACR,MAAM,qBAAqB,CAAC;AAI7B,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,YAAY,IAAI,IAAI,CAC/C,OAAO,CAAC,CAAC,CAAC,EACV,SAAS,GAAG,QAAQ,GAAG,UAAU,CAClC,GAAG;IACF,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,YAAY,EACpD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,MAAM,CAAC,CAAC,CAAC,CA4BX"}
1
+ {"version":3,"file":"useRouter.d.ts","sourceRoot":"","sources":["../src/useRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,OAAO,EACP,OAAO,EACR,MAAM,qBAAqB,CAAC;AAI7B,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,YAAY,IAAI,IAAI,CAC/C,OAAO,CAAC,CAAC,CAAC,EACV,SAAS,GAAG,QAAQ,GAAG,UAAU,CAClC,GAAG;IACF,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,YAAY,EACpD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,MAAM,CAAC,CAAC,CAAC,CAsBX"}
package/dist/useRouter.js CHANGED
@@ -1,20 +1,16 @@
1
1
  import { createRouter as internalCreateRouter, } from "typed-client-router";
2
- import { getCurrentObserver, Signal } from "./observation";
3
2
  import { useCleanup, getCurrentComponent } from "./component";
3
+ import { observable } from "mobx";
4
4
  export function useRouter(config, options) {
5
5
  if (!getCurrentComponent()) {
6
6
  throw new Error("Only use useRouter in component setup");
7
7
  }
8
8
  const router = internalCreateRouter(config, options);
9
- const signal = new Signal();
10
- useCleanup(router.listen(() => signal.notify()));
9
+ const route = observable.box(router.current);
10
+ useCleanup(router.listen((newRoute) => route.set(newRoute)));
11
11
  return {
12
12
  get route() {
13
- const observer = getCurrentObserver();
14
- if (observer) {
15
- observer.subscribeSignal(signal);
16
- }
17
- return router.current;
13
+ return route.get();
18
14
  },
19
15
  get queries() {
20
16
  return router.queries;
@@ -24,5 +24,4 @@ export declare function assignState<T extends object>(state: T, newState: T): T;
24
24
  * @returns A reactive proxy of the state object
25
25
  */
26
26
  export declare function useState<T extends object>(state: T): T;
27
- export declare const PROXY_MARKER: unique symbol;
28
27
  //# sourceMappingURL=useState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useState.d.ts","sourceRoot":"","sources":["../src/useState.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAOtD;AAGD,eAAO,MAAM,YAAY,eAAoB,CAAC"}
1
+ {"version":3,"file":"useState.d.ts","sourceRoot":"","sources":["../src/useState.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAEtD"}