rask-ui 0.22.0 → 0.24.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 (121) hide show
  1. package/dist/compiler.d.ts +3 -1
  2. package/dist/compiler.d.ts.map +1 -1
  3. package/dist/compiler.js +7 -1
  4. package/dist/component.d.ts +4 -18
  5. package/dist/component.d.ts.map +1 -1
  6. package/dist/component.js +14 -67
  7. package/dist/createComputed.d.ts +4 -0
  8. package/dist/createComputed.d.ts.map +1 -0
  9. package/dist/createComputed.js +69 -0
  10. package/dist/createContext.d.ts +26 -9
  11. package/dist/createContext.d.ts.map +1 -1
  12. package/dist/createContext.js +47 -30
  13. package/dist/createEffect.d.ts +2 -0
  14. package/dist/createEffect.d.ts.map +1 -0
  15. package/dist/createEffect.js +29 -0
  16. package/dist/createRouter.d.ts +8 -0
  17. package/dist/createRouter.d.ts.map +1 -0
  18. package/dist/createRouter.js +27 -0
  19. package/dist/createState.d.ts +2 -0
  20. package/dist/createState.d.ts.map +1 -1
  21. package/dist/createState.js +40 -5
  22. package/dist/createTask.d.ts +31 -0
  23. package/dist/createTask.d.ts.map +1 -0
  24. package/dist/createTask.js +79 -0
  25. package/dist/createView.d.ts +18 -44
  26. package/dist/createView.d.ts.map +1 -1
  27. package/dist/createView.js +57 -48
  28. package/dist/error.d.ts +3 -14
  29. package/dist/error.d.ts.map +1 -1
  30. package/dist/error.js +14 -15
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/jsx.d.ts +10 -256
  35. package/dist/observation.d.ts +1 -1
  36. package/dist/observation.d.ts.map +1 -1
  37. package/dist/patchInferno.d.ts +6 -0
  38. package/dist/patchInferno.d.ts.map +1 -0
  39. package/dist/patchInferno.js +53 -0
  40. package/dist/plugin.d.ts +1 -1
  41. package/dist/plugin.d.ts.map +1 -1
  42. package/dist/plugin.js +14 -26
  43. package/dist/scheduler.d.ts +4 -0
  44. package/dist/scheduler.d.ts.map +1 -0
  45. package/dist/scheduler.js +107 -0
  46. package/dist/tests/batch.test.d.ts +2 -0
  47. package/dist/tests/batch.test.d.ts.map +1 -0
  48. package/dist/tests/batch.test.js +244 -0
  49. package/dist/tests/createComputed.test.d.ts +2 -0
  50. package/dist/tests/createComputed.test.d.ts.map +1 -0
  51. package/dist/tests/createComputed.test.js +257 -0
  52. package/dist/tests/createContext.test.d.ts +2 -0
  53. package/dist/tests/createContext.test.d.ts.map +1 -0
  54. package/dist/tests/createContext.test.js +136 -0
  55. package/dist/tests/createEffect.test.d.ts +2 -0
  56. package/dist/tests/createEffect.test.d.ts.map +1 -0
  57. package/dist/tests/createEffect.test.js +467 -0
  58. package/dist/tests/createState.test.d.ts.map +1 -0
  59. package/dist/tests/createState.test.js +144 -0
  60. package/dist/tests/createTask.test.d.ts +2 -0
  61. package/dist/tests/createTask.test.d.ts.map +1 -0
  62. package/dist/tests/createTask.test.js +322 -0
  63. package/dist/tests/createView.test.d.ts.map +1 -0
  64. package/dist/{createView.test.js → tests/createView.test.js} +40 -40
  65. package/dist/tests/error.test.d.ts +2 -0
  66. package/dist/tests/error.test.d.ts.map +1 -0
  67. package/dist/tests/error.test.js +168 -0
  68. package/dist/tests/observation.test.d.ts.map +1 -0
  69. package/dist/tests/observation.test.js +341 -0
  70. package/dist/useCatchError.d.ts +6 -3
  71. package/dist/useCatchError.d.ts.map +1 -1
  72. package/dist/useCatchError.js +2 -2
  73. package/dist/useComputed.d.ts +5 -0
  74. package/dist/useComputed.d.ts.map +1 -0
  75. package/dist/useComputed.js +69 -0
  76. package/dist/useQuery.d.ts +25 -0
  77. package/dist/useQuery.d.ts.map +1 -0
  78. package/dist/useQuery.js +25 -0
  79. package/dist/useSuspendAsync.d.ts +18 -0
  80. package/dist/useSuspendAsync.d.ts.map +1 -0
  81. package/dist/useSuspendAsync.js +37 -0
  82. package/dist/useTask.d.ts +25 -0
  83. package/dist/useTask.d.ts.map +1 -0
  84. package/dist/useTask.js +70 -0
  85. package/package.json +1 -1
  86. package/swc-plugin/target/wasm32-wasip1/release/swc_plugin_rask_component.wasm +0 -0
  87. package/dist/asyncState.d.ts +0 -16
  88. package/dist/asyncState.d.ts.map +0 -1
  89. package/dist/asyncState.js +0 -24
  90. package/dist/context.d.ts +0 -5
  91. package/dist/context.d.ts.map +0 -1
  92. package/dist/context.js +0 -29
  93. package/dist/createAsync.test.d.ts +0 -2
  94. package/dist/createAsync.test.d.ts.map +0 -1
  95. package/dist/createAsync.test.js +0 -110
  96. package/dist/createMutation.test.d.ts +0 -2
  97. package/dist/createMutation.test.d.ts.map +0 -1
  98. package/dist/createMutation.test.js +0 -168
  99. package/dist/createQuery.test.d.ts +0 -2
  100. package/dist/createQuery.test.d.ts.map +0 -1
  101. package/dist/createQuery.test.js +0 -156
  102. package/dist/createRef.d.ts +0 -6
  103. package/dist/createRef.d.ts.map +0 -1
  104. package/dist/createRef.js +0 -8
  105. package/dist/createState.test.d.ts.map +0 -1
  106. package/dist/createState.test.js +0 -111
  107. package/dist/createView.test.d.ts.map +0 -1
  108. package/dist/observation.test.d.ts.map +0 -1
  109. package/dist/observation.test.js +0 -150
  110. package/dist/suspense.d.ts +0 -25
  111. package/dist/suspense.d.ts.map +0 -1
  112. package/dist/suspense.js +0 -97
  113. package/dist/test-setup.d.ts +0 -16
  114. package/dist/test-setup.d.ts.map +0 -1
  115. package/dist/test-setup.js +0 -40
  116. package/dist/test.d.ts +0 -2
  117. package/dist/test.d.ts.map +0 -1
  118. package/dist/test.js +0 -24
  119. /package/dist/{createState.test.d.ts → tests/createState.test.d.ts} +0 -0
  120. /package/dist/{createView.test.d.ts → tests/createView.test.d.ts} +0 -0
  121. /package/dist/{observation.test.d.ts → tests/observation.test.d.ts} +0 -0
@@ -1,2 +1,4 @@
1
- export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
1
+ export { createVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
2
+ import { VNode } from "inferno";
3
+ export declare function createComponentVNode(_: any, component: any, props: any | undefined, key: any, ref: any): VNode;
2
4
  //# sourceMappingURL=compiler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC;AAEjB,OAAO,EAGL,KAAK,EACN,MAAM,SAAS,CAAC;AAIjB,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,GAAG,EACN,SAAS,EAAE,GAAG,EACd,KAAK,EAAE,GAAG,YAAK,EACf,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,GACP,KAAK,CASP"}
package/dist/compiler.js CHANGED
@@ -1 +1,7 @@
1
- export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
1
+ export { createVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
2
+ import { createComponentVNode as infernoCreateComponentVnode, } from "inferno";
3
+ import { RaskComponent } from "./component";
4
+ export function createComponentVNode(_, component, props = {}, key, ref) {
5
+ props.__component = component;
6
+ return infernoCreateComponentVnode(4 /* VNodeFlags.ComponentClass */, RaskComponent, props, key, ref);
7
+ }
@@ -1,25 +1,12 @@
1
1
  import { VNode, Component, Props, InfernoNode } from "inferno";
2
2
  import { Observer, Signal } from "./observation";
3
- export type RaskStatelessFunctionComponent<P extends Props<any>> = (() => VNode) | ((props: P) => VNode);
4
- export declare class RaskStatelessComponent extends Component {
5
- renderFn: RaskStatelessFunctionComponent<any>;
6
- private isNotified;
7
- private isReconciling;
8
- observer: Observer;
9
- propsSignals: Record<string, Signal>;
10
- private reactiveProps;
11
- shouldComponentUpdate(): boolean;
12
- componentWillMount(): void;
13
- componentWillReceiveProps(nextProps: any): void;
14
- render(): any;
15
- }
16
- export declare function getCurrentComponent(): RaskStatefulComponent<any> | undefined;
3
+ export declare function getCurrentComponent(): RaskComponent<any> | undefined;
17
4
  export declare function useMountEffect(cb: () => void): void;
18
5
  export declare function useCleanup(cb: () => void): void;
6
+ export type RaskStatelessFunctionComponent<P extends Props<any>> = (() => VNode) | ((props: P) => VNode);
19
7
  export type RaskStatefulFunctionComponent<P extends Props<any>> = (() => () => VNode) | ((props: P) => () => VNode);
20
- export declare class RaskStatefulComponent<P extends Props<any>> extends Component<P> {
21
- setup: RaskStatefulFunctionComponent<P>;
22
- private renderFn?;
8
+ export declare class RaskComponent<P extends Props<any>> extends Component<P> {
9
+ renderFn: RaskStatelessFunctionComponent<P>;
23
10
  propsSignals: Record<string, Signal>;
24
11
  private reactiveProps;
25
12
  private isNotified;
@@ -42,5 +29,4 @@ export declare class RaskStatefulComponent<P extends Props<any>> extends Compone
42
29
  shouldComponentUpdate(): boolean;
43
30
  render(): any;
44
31
  }
45
- export declare function createComponent(props: Props<any>, key?: string): VNode;
46
32
  //# sourceMappingURL=component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,QAAQ,WAML;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAC1C,OAAO,CAAC,aAAa,CAAc;IAEnC,qBAAqB,IAAI,OAAO;IAMhC,kBAAkB,IAAI,IAAI;IAG1B,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAe/C,MAAM;CAoBP;AAID,wBAAgB,mBAAmB,2CAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAC1C,OAAO,CAAC,aAAa,CAAc;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAcf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;CA6CP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAMrE,wBAAgB,mBAAmB,mCAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,aAAa,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,EAAE,8BAA8B,CAAC,CAAC,CAAC,CAAC;IACpD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAC1C,OAAO,CAAC,aAAa,CAAc;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAcf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;CAkDP"}
package/dist/component.js CHANGED
@@ -1,61 +1,7 @@
1
- import { createComponentVNode, Component, } from "inferno";
1
+ import { Component, } from "inferno";
2
2
  import { getCurrentObserver, Observer, Signal } from "./observation";
3
3
  import { syncBatch } from "./batch";
4
4
  import { CatchErrorContext } from "./useCatchError";
5
- export class RaskStatelessComponent extends Component {
6
- isNotified = false;
7
- isReconciling = false;
8
- observer = new Observer(() => {
9
- if (this.isReconciling) {
10
- this.isNotified = true;
11
- return;
12
- }
13
- this.forceUpdate();
14
- });
15
- propsSignals = {};
16
- reactiveProps;
17
- shouldComponentUpdate() {
18
- const shouldRender = this.isNotified;
19
- this.isNotified = false;
20
- this.isReconciling = false;
21
- return shouldRender;
22
- }
23
- componentWillMount() {
24
- this.reactiveProps = createReactiveProps(this);
25
- }
26
- componentWillReceiveProps(nextProps) {
27
- this.isReconciling = true;
28
- const prevProps = this.props;
29
- this.props = nextProps;
30
- syncBatch(() => {
31
- for (const prop in this.propsSignals) {
32
- if (prevProps[prop] === nextProps[prop]) {
33
- continue;
34
- }
35
- // This just triggers the signal
36
- this.propsSignals[prop].notify();
37
- }
38
- });
39
- }
40
- render() {
41
- const stopObserving = this.observer.observe();
42
- let result = null;
43
- try {
44
- result = this.renderFn(this.reactiveProps);
45
- }
46
- catch (error) {
47
- const notifyError = this.context.getContext?.(CatchErrorContext);
48
- if (typeof notifyError !== "function") {
49
- throw error;
50
- }
51
- notifyError(error);
52
- }
53
- finally {
54
- stopObserving();
55
- }
56
- return result;
57
- }
58
- }
59
5
  let currentComponent;
60
6
  export function getCurrentComponent() {
61
7
  return currentComponent;
@@ -72,8 +18,7 @@ export function useCleanup(cb) {
72
18
  }
73
19
  currentComponent.onCleanups.push(cb);
74
20
  }
75
- export class RaskStatefulComponent extends Component {
76
- renderFn;
21
+ export class RaskComponent extends Component {
77
22
  propsSignals = {};
78
23
  reactiveProps;
79
24
  // RECONCILIATION FLAGS
@@ -152,12 +97,19 @@ export class RaskStatefulComponent extends Component {
152
97
  }
153
98
  render() {
154
99
  currentComponent = this;
100
+ const stopObserving = this.observer.observe();
155
101
  if (!this.renderFn) {
156
102
  this.reactiveProps = createReactiveProps(this);
157
103
  try {
158
- this.renderFn = this.setup(this.reactiveProps);
159
- if (typeof this.renderFn !== "function") {
160
- throw new Error("Component must return a render function");
104
+ const component = this.props.__component;
105
+ const renderFn = component(this.reactiveProps);
106
+ if (typeof renderFn === "function") {
107
+ this.renderFn = renderFn;
108
+ }
109
+ else {
110
+ this.renderFn = component;
111
+ // Since we ran a setup function we need to clear any signals accessed
112
+ this.observer.clearSignals();
161
113
  }
162
114
  }
163
115
  catch (error) {
@@ -168,16 +120,14 @@ export class RaskStatefulComponent extends Component {
168
120
  return null;
169
121
  }
170
122
  }
171
- const stopObserving = this.observer.observe();
172
123
  let result = null;
173
124
  try {
174
125
  this.isRendering = true;
175
- result = this.renderFn();
126
+ result = this.renderFn(this.reactiveProps);
176
127
  this.isRendering = false;
177
128
  }
178
129
  catch (error) {
179
- const notifyError = this.contexts.get(CatchErrorContext) ||
180
- this.context.getContext?.(CatchErrorContext);
130
+ const notifyError = CatchErrorContext.use();
181
131
  if (typeof notifyError !== "function") {
182
132
  throw error;
183
133
  }
@@ -190,9 +140,6 @@ export class RaskStatefulComponent extends Component {
190
140
  return result;
191
141
  }
192
142
  }
193
- export function createComponent(props, key) {
194
- return createComponentVNode(4 /* VNodeFlags.ComponentClass */, RaskStatefulComponent, props, key);
195
- }
196
143
  function createReactiveProps(comp) {
197
144
  const props = new Proxy({}, {
198
145
  ownKeys() {
@@ -0,0 +1,4 @@
1
+ export declare function createComputed<T extends Record<string, () => any>>(computed: T): {
2
+ [K in keyof T]: ReturnType<T[K]>;
3
+ };
4
+ //# sourceMappingURL=createComputed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createComputed.d.ts","sourceRoot":"","sources":["../src/createComputed.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAChE,QAAQ,EAAE,CAAC,GACV;KACA,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACjC,CA0EA"}
@@ -0,0 +1,69 @@
1
+ import { getCurrentComponent, createCleanup } from "./component";
2
+ import { INSPECT_MARKER, INSPECTOR_ENABLED } from "./inspect";
3
+ import { getCurrentObserver, Observer, Signal } from "./observation";
4
+ export function createComputed(computed) {
5
+ const currentComponent = getCurrentComponent();
6
+ const proxy = {};
7
+ let notifyInspectorRef = {};
8
+ for (const prop in computed) {
9
+ let isDirty = true;
10
+ let value;
11
+ const signal = new Signal();
12
+ const computedObserver = new Observer(() => {
13
+ isDirty = true;
14
+ signal.notify();
15
+ if (INSPECTOR_ENABLED) {
16
+ notifyInspectorRef.current?.notify({
17
+ type: "computed",
18
+ path: notifyInspectorRef.current.path.concat(prop),
19
+ isDirty: true,
20
+ value,
21
+ });
22
+ }
23
+ });
24
+ createCleanup(() => computedObserver.dispose());
25
+ Object.defineProperty(proxy, prop, {
26
+ enumerable: true,
27
+ configurable: true,
28
+ get() {
29
+ const currentObserver = getCurrentObserver();
30
+ if (currentObserver) {
31
+ currentObserver.subscribeSignal(signal);
32
+ }
33
+ if (isDirty) {
34
+ const stopObserving = computedObserver.observe();
35
+ value = computed[prop]();
36
+ stopObserving();
37
+ isDirty = false;
38
+ if (INSPECTOR_ENABLED) {
39
+ notifyInspectorRef.current?.notify({
40
+ type: "computed",
41
+ path: notifyInspectorRef.current.path.concat(prop),
42
+ isDirty: false,
43
+ value,
44
+ });
45
+ }
46
+ return value;
47
+ }
48
+ return value;
49
+ },
50
+ });
51
+ }
52
+ if (INSPECTOR_ENABLED) {
53
+ Object.defineProperty(proxy, INSPECT_MARKER, {
54
+ enumerable: false,
55
+ configurable: false,
56
+ get() {
57
+ return !notifyInspectorRef.current;
58
+ },
59
+ set: (value) => {
60
+ Object.defineProperty(notifyInspectorRef, "current", {
61
+ get() {
62
+ return value.current;
63
+ },
64
+ });
65
+ },
66
+ });
67
+ }
68
+ return proxy;
69
+ }
@@ -1,32 +1,49 @@
1
1
  /**
2
- * Creates a context by wrapping a hook function that will be used as a context identifier.
2
+ * Creates a context that provides two methods: `use()` to consume context values and
3
+ * `inject()` to provide context values to child components.
3
4
  *
4
5
  * @warning **Do not destructure context values!** The returned value may be a reactive
5
6
  * object, and destructuring breaks reactivity.
6
7
  *
7
8
  * @example
8
- * // Create a context hook
9
- * const useTheme = createContext(() => {
9
+ * // Create a context
10
+ * const ThemeContext = createContext(() => {
10
11
  * return useState({ color: "blue" });
11
12
  * });
12
13
  *
13
14
  * // Provider component
14
15
  * function App() {
15
- * const theme = useInjectContext(useTheme);
16
+ * const theme = ThemeContext.inject();
16
17
  * // theme is now available to all children
17
18
  * return () => <Child />;
18
19
  * }
19
20
  *
20
21
  * // Consumer component
21
22
  * function Child() {
22
- * const theme = useContext(useTheme);
23
+ * const theme = ThemeContext.use();
23
24
  * return () => <div style={{ color: theme.color }}>Text</div>;
24
25
  * }
25
26
  *
26
27
  * @param hook - A function that will be used as the context identifier
27
- * @returns The same hook function, to be used with useContext() and useInjectContext()
28
+ * @returns An object with `use()` and `inject()` methods
28
29
  */
29
- export declare function createContext<T, P extends any[]>(hook: (...params: P) => T): (...params: P) => T;
30
- export declare function useContext<T, P extends any[]>(hook: (...params: P) => T): T;
31
- export declare function useInjectContext<T, P extends any[]>(hook: (...params: P) => T, ...params: P): T;
30
+ export declare function createContext<T, P extends any[]>(hook: (...params: P) => T): {
31
+ /**
32
+ * Consumes the context value from the nearest parent component that called `inject()`.
33
+ * Must be called during component setup.
34
+ *
35
+ * @returns The context value provided by the nearest parent
36
+ * @throws Error if called outside component setup, if no parent context exists, or if the specific context was not provided
37
+ */
38
+ use(): any;
39
+ /**
40
+ * Injects a context value by calling the hook function and making it available to all child components.
41
+ * Must be called during component setup.
42
+ *
43
+ * @param params - Parameters to pass to the hook function
44
+ * @returns The context value created by the hook
45
+ * @throws Error if called outside component setup
46
+ */
47
+ inject(...params: P): T;
48
+ };
32
49
  //# sourceMappingURL=createContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createContext.d.ts","sourceRoot":"","sources":["../src/createContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,eAAP,CAAC,KAAK,CAAC,CAE1E;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAkB3E;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EACjD,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,EACzB,GAAG,MAAM,EAAE,CAAC,KAab"}
1
+ {"version":3,"file":"createContext.d.ts","sourceRoot":"","sources":["../src/createContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC;IAEvE;;;;;;OAMG;;IAsBH;;;;;;;OAOG;sBACe,CAAC;EActB"}
@@ -1,55 +1,72 @@
1
1
  /**
2
- * Creates a context by wrapping a hook function that will be used as a context identifier.
2
+ * Creates a context that provides two methods: `use()` to consume context values and
3
+ * `inject()` to provide context values to child components.
3
4
  *
4
5
  * @warning **Do not destructure context values!** The returned value may be a reactive
5
6
  * object, and destructuring breaks reactivity.
6
7
  *
7
8
  * @example
8
- * // Create a context hook
9
- * const useTheme = createContext(() => {
9
+ * // Create a context
10
+ * const ThemeContext = createContext(() => {
10
11
  * return useState({ color: "blue" });
11
12
  * });
12
13
  *
13
14
  * // Provider component
14
15
  * function App() {
15
- * const theme = useInjectContext(useTheme);
16
+ * const theme = ThemeContext.inject();
16
17
  * // theme is now available to all children
17
18
  * return () => <Child />;
18
19
  * }
19
20
  *
20
21
  * // Consumer component
21
22
  * function Child() {
22
- * const theme = useContext(useTheme);
23
+ * const theme = ThemeContext.use();
23
24
  * return () => <div style={{ color: theme.color }}>Text</div>;
24
25
  * }
25
26
  *
26
27
  * @param hook - A function that will be used as the context identifier
27
- * @returns The same hook function, to be used with useContext() and useInjectContext()
28
+ * @returns An object with `use()` and `inject()` methods
28
29
  */
29
30
  import { getCurrentComponent } from "./component";
30
31
  export function createContext(hook) {
31
- return hook;
32
- }
33
- export function useContext(hook) {
34
- let currentComponent = getCurrentComponent();
35
- if (!currentComponent) {
36
- throw new Error("Only use useContext in component setup");
37
- }
38
- if (typeof currentComponent.context.getContext !== "function") {
39
- throw new Error("There is no parent context");
40
- }
41
- const contextValue = currentComponent.context.getContext(hook);
42
- if (!contextValue) {
43
- throw new Error("There is a parent context, but not the one you are using");
44
- }
45
- return contextValue;
46
- }
47
- export function useInjectContext(hook, ...params) {
48
- const currentComponent = getCurrentComponent();
49
- if (!currentComponent) {
50
- throw new Error("Only use useInjectContext in component setup");
51
- }
52
- const value = hook(...params);
53
- currentComponent.contexts.set(hook, value);
54
- return value;
32
+ return {
33
+ /**
34
+ * Consumes the context value from the nearest parent component that called `inject()`.
35
+ * Must be called during component setup.
36
+ *
37
+ * @returns The context value provided by the nearest parent
38
+ * @throws Error if called outside component setup, if no parent context exists, or if the specific context was not provided
39
+ */
40
+ use() {
41
+ let currentComponent = getCurrentComponent();
42
+ if (!currentComponent) {
43
+ throw new Error("Only use useContext in component setup");
44
+ }
45
+ if (typeof currentComponent.context.getContext !== "function") {
46
+ throw new Error("There is no parent context");
47
+ }
48
+ const contextValue = currentComponent.context.getContext(hook);
49
+ if (!contextValue) {
50
+ throw new Error("There is a parent context, but not the one you are using");
51
+ }
52
+ return contextValue;
53
+ },
54
+ /**
55
+ * Injects a context value by calling the hook function and making it available to all child components.
56
+ * Must be called during component setup.
57
+ *
58
+ * @param params - Parameters to pass to the hook function
59
+ * @returns The context value created by the hook
60
+ * @throws Error if called outside component setup
61
+ */
62
+ inject(...params) {
63
+ const currentComponent = getCurrentComponent();
64
+ if (!currentComponent) {
65
+ throw new Error("Only use useInjectContext in component setup");
66
+ }
67
+ const value = hook(...params);
68
+ currentComponent.contexts.set(hook, value);
69
+ return value;
70
+ },
71
+ };
55
72
  }
@@ -0,0 +1,2 @@
1
+ export declare function createEffect(cb: () => void | (() => void)): void;
2
+ //# sourceMappingURL=createEffect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createEffect.d.ts","sourceRoot":"","sources":["../src/createEffect.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QA2BzD"}
@@ -0,0 +1,29 @@
1
+ import { syncBatch } from "./batch";
2
+ import { createCleanup, getCurrentComponent } from "./component";
3
+ import { Observer } from "./observation";
4
+ export function createEffect(cb) {
5
+ const component = getCurrentComponent();
6
+ if (!component || component.isRendering) {
7
+ throw new Error("Only use createEffect in component setup");
8
+ }
9
+ 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
+ createCleanup(() => {
25
+ observer.dispose();
26
+ disposer?.();
27
+ });
28
+ runEffect();
29
+ }
@@ -0,0 +1,8 @@
1
+ import { RoutesConfig, TRouter, TRoutes } from "typed-client-router";
2
+ export type Router<T extends RoutesConfig> = Omit<TRouter<T>, "current" | "listen" | "pathname"> & {
3
+ route?: TRoutes<T>;
4
+ };
5
+ export declare function createRouter<const T extends RoutesConfig>(config: T, options?: {
6
+ base?: string;
7
+ }): Router<T>;
8
+ //# sourceMappingURL=createRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRouter.d.ts","sourceRoot":"","sources":["../src/createRouter.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,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,YAAY,EACvD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,MAAM,CAAC,CAAC,CAAC,CA4BX"}
@@ -0,0 +1,27 @@
1
+ import { createRouter as internalCreateRouter, } from "typed-client-router";
2
+ import { getCurrentObserver, Signal } from "./observation";
3
+ import { createCleanup, getCurrentComponent } from "./component";
4
+ export function createRouter(config, options) {
5
+ if (!getCurrentComponent()) {
6
+ throw new Error("Only use createRouter in component setup");
7
+ }
8
+ const router = internalCreateRouter(config, options);
9
+ const signal = new Signal();
10
+ createCleanup(router.listen(() => signal.notify()));
11
+ return {
12
+ get route() {
13
+ const observer = getCurrentObserver();
14
+ if (observer) {
15
+ observer.subscribeSignal(signal);
16
+ }
17
+ return router.current;
18
+ },
19
+ get queries() {
20
+ return router.queries;
21
+ },
22
+ setQuery: router.setQuery,
23
+ push: router.push,
24
+ replace: router.replace,
25
+ url: router.url,
26
+ };
27
+ }
@@ -1,3 +1,4 @@
1
+ export declare function assignState<T extends object>(state: T, newState: T): T;
1
2
  /**
2
3
  * Creates a reactive state object that tracks property access and notifies observers on changes.
3
4
  *
@@ -23,4 +24,5 @@
23
24
  * @returns A reactive proxy of the state object
24
25
  */
25
26
  export declare function createState<T extends object>(state: T): T;
27
+ export declare const PROXY_MARKER: unique symbol;
26
28
  //# sourceMappingURL=createState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createState.d.ts","sourceRoot":"","sources":["../src/createState.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAEzD"}
1
+ {"version":3,"file":"createState.d.ts","sourceRoot":"","sources":["../src/createState.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,KAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAOzD;AAGD,eAAO,MAAM,YAAY,eAAoB,CAAC"}
@@ -1,4 +1,9 @@
1
+ import { getCurrentComponent } from "./component";
2
+ import { INSPECT_MARKER, INSPECTOR_ENABLED } from "./inspect";
1
3
  import { getCurrentObserver, Signal } from "./observation";
4
+ export function assignState(state, newState) {
5
+ return Object.assign(state, newState);
6
+ }
2
7
  /**
3
8
  * Creates a reactive state object that tracks property access and notifies observers on changes.
4
9
  *
@@ -24,11 +29,14 @@ import { getCurrentObserver, Signal } from "./observation";
24
29
  * @returns A reactive proxy of the state object
25
30
  */
26
31
  export function createState(state) {
27
- return getProxy(state);
32
+ if (getCurrentComponent()?.isRendering) {
33
+ throw new Error("createState cannot be called during render. Call it in component setup or globally.");
34
+ }
35
+ return getProxy(state, {});
28
36
  }
29
37
  const proxyCache = new WeakMap();
30
- const PROXY_MARKER = Symbol("isProxy");
31
- function getProxy(value) {
38
+ export const PROXY_MARKER = Symbol("isProxy");
39
+ function getProxy(value, notifyInspectorRef) {
32
40
  // Check if already a proxy to avoid double-wrapping
33
41
  if (PROXY_MARKER in value) {
34
42
  return value;
@@ -43,6 +51,9 @@ function getProxy(value) {
43
51
  if (key === PROXY_MARKER) {
44
52
  return true;
45
53
  }
54
+ if (INSPECTOR_ENABLED && key === INSPECT_MARKER) {
55
+ return true;
56
+ }
46
57
  return Reflect.has(target, key);
47
58
  },
48
59
  get(target, key) {
@@ -50,6 +61,9 @@ function getProxy(value) {
50
61
  if (key === PROXY_MARKER) {
51
62
  return true;
52
63
  }
64
+ if (INSPECTOR_ENABLED && key === INSPECT_MARKER) {
65
+ return !notifyInspectorRef.current;
66
+ }
53
67
  const value = Reflect.get(target, key);
54
68
  if (typeof key === "symbol" || typeof value === "function") {
55
69
  return value;
@@ -61,11 +75,26 @@ function getProxy(value) {
61
75
  }
62
76
  if (Array.isArray(value) ||
63
77
  (typeof value === "object" && value !== null)) {
64
- return getProxy(value);
78
+ return getProxy(value, INSPECTOR_ENABLED && notifyInspectorRef.current
79
+ ? {
80
+ current: {
81
+ notify: notifyInspectorRef.current.notify,
82
+ path: notifyInspectorRef.current.path.concat(key),
83
+ },
84
+ }
85
+ : notifyInspectorRef);
65
86
  }
66
87
  return value;
67
88
  },
68
89
  set(target, key, newValue) {
90
+ if (INSPECTOR_ENABLED && key === INSPECT_MARKER) {
91
+ Object.defineProperty(notifyInspectorRef, "current", {
92
+ get() {
93
+ return newValue.current;
94
+ },
95
+ });
96
+ return Reflect.set(target, key, newValue);
97
+ }
69
98
  if (typeof key === "symbol") {
70
99
  return Reflect.set(target, key, newValue);
71
100
  }
@@ -73,10 +102,16 @@ function getProxy(value) {
73
102
  const setResult = Reflect.set(target, key, newValue);
74
103
  // We only notify if actual change, though array length actually updates under the hood
75
104
  if (newValue !== oldValue || (Array.isArray(value) && key === "length")) {
76
- console.log("WTF", key, newValue);
77
105
  const signal = signals[key];
78
106
  signal?.notify();
79
107
  }
108
+ if (INSPECTOR_ENABLED) {
109
+ notifyInspectorRef.current?.notify({
110
+ type: "mutation",
111
+ path: notifyInspectorRef.current.path,
112
+ value: newValue,
113
+ });
114
+ }
80
115
  return setResult;
81
116
  },
82
117
  deleteProperty(target, key) {