mono-jsx 0.9.1 → 0.9.3

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/README.md CHANGED
@@ -538,6 +538,9 @@ function Counter(this: FC<{ count: number }>, props: { initialCount?: number })
538
538
  // Initialize a signal
539
539
  this.count = props.initialCount ?? 0;
540
540
 
541
+ // or you can use `this.init` to initialize the signals
542
+ this.init({ count: props.initialCount ?? 0 });
543
+
541
544
  return (
542
545
  <div>
543
546
  {/* render signal */}
@@ -551,25 +554,6 @@ function Counter(this: FC<{ count: number }>, props: { initialCount?: number })
551
554
  }
552
555
  ```
553
556
 
554
- You can also use `this.extend` method to extend the signals:
555
-
556
- ```tsx
557
- function Counter(this: FC, props: { initialCount?: number }) {
558
- const counter = this.extend({ count: props.initialCount ?? 0})
559
-
560
- return (
561
- <div>
562
- {/* render signal */}
563
- <span>{counter.count}</span>
564
-
565
- {/* Update signal to trigger re-render */}
566
- <button onClick={() => counter.count--}>-</button>
567
- <button onClick={() => counter.count++}>+</button>
568
- </div>
569
- )
570
- }
571
- ```
572
-
573
557
  ### Using App Signals
574
558
 
575
559
  You can define app signals by adding the `app` prop to the root `<html>` element. The app signals are available in all components via `this.app.<SignalName>`. Changes to the app signals will trigger re-renders in all components that use them:
package/dom/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  // dom/index.ts
2
- import { Store } from "./jsx-runtime.mjs";
2
+ import { atom, store } from "./jsx-runtime.mjs";
3
3
  export {
4
- Store
4
+ atom,
5
+ store
5
6
  };
@@ -34,10 +34,9 @@ var domEscapeHTML = (text) => {
34
34
  };
35
35
 
36
36
  // symbols.ts
37
- var $fragment = Symbol.for("jsx.fragment");
38
- var $html = Symbol.for("jsx.html");
39
- var $vnode = Symbol.for("jsx.vnode");
40
- var $setup = Symbol.for("mono.setup");
37
+ var $fragment = /* @__PURE__ */ Symbol.for("jsx.fragment");
38
+ var $html = /* @__PURE__ */ Symbol.for("jsx.html");
39
+ var $vnode = /* @__PURE__ */ Symbol.for("jsx.vnode");
41
40
 
42
41
  // dom/render.ts
43
42
  var Reactive = class {
@@ -65,6 +64,9 @@ var Signal = class extends Reactive {
65
64
  return this.#scope[$get](this.#key);
66
65
  }
67
66
  set(value) {
67
+ if (isFunction(value)) {
68
+ value = value(this.get());
69
+ }
68
70
  this.#scope[this.#key] = value;
69
71
  }
70
72
  watch(callback, abortSignal) {
@@ -134,11 +136,11 @@ var InsertMark = class {
134
136
  }
135
137
  };
136
138
  var document2 = globalThis.document;
137
- var $get = Symbol();
138
- var $watch = Symbol();
139
- var $expr = Symbol();
140
- var $slots = Symbol();
141
- var stores = /* @__PURE__ */ new Set();
139
+ var $get = /* @__PURE__ */ Symbol();
140
+ var $watch = /* @__PURE__ */ Symbol();
141
+ var $expr = /* @__PURE__ */ Symbol();
142
+ var $slots = /* @__PURE__ */ Symbol();
143
+ var globalScopes = /* @__PURE__ */ new Set();
142
144
  var isVNode = (v) => Array.isArray(v) && v.length === 3 && v[2] === $vnode;
143
145
  var createTextNode = (text = "") => document2.createTextNode(text);
144
146
  var createElement = (tag) => document2.createElement(tag);
@@ -156,7 +158,7 @@ var setAttribute = (el, name, value) => {
156
158
  };
157
159
  var call$expr = (scope, ok) => {
158
160
  scope[$expr](ok);
159
- stores.forEach((s) => s[$expr](ok));
161
+ globalScopes.forEach((s) => s[$expr](ok));
160
162
  };
161
163
  var $depsMark;
162
164
  var createScope = (slots, abortSignal) => {
@@ -204,10 +206,8 @@ var createScope = (slots, abortSignal) => {
204
206
  if (get) {
205
207
  target[key2] = new Computed(receiver, get);
206
208
  } else {
207
- if (key2 === "effect") {
208
- if (isFunction(value)) {
209
- receiver.effect(value);
210
- }
209
+ if (key2 === "effect" && isFunction(value)) {
210
+ receiver.effect(value);
211
211
  } else {
212
212
  target[key2] = value;
213
213
  }
@@ -272,9 +272,19 @@ var createScope = (slots, abortSignal) => {
272
272
  });
273
273
  return scope;
274
274
  };
275
- var createStore = (props) => {
275
+ var atomIndex = 0;
276
+ var atomScope;
277
+ var atom = (value) => {
278
+ if (!atomScope) {
279
+ atomScope = createScope();
280
+ }
281
+ const atomKey = "atom_" + atomIndex++;
282
+ atomScope.init({ [atomKey]: value });
283
+ return new Signal(atomScope, atomKey);
284
+ };
285
+ var store = (props) => {
276
286
  const scope = createScope().extend(props);
277
- stores.add(scope);
287
+ globalScopes.add(scope);
278
288
  return scope;
279
289
  };
280
290
  var render = (scope, child, root, abortSignal) => {
@@ -292,13 +302,13 @@ var render = (scope, child, root, abortSignal) => {
292
302
  list.forEach((items) => items.forEach(([ac]) => ac.abort()));
293
303
  list.clear();
294
304
  };
295
- reactive.reactive((arr) => {
296
- if (!Array.isArray(arr)) {
297
- throw new TypeError("map is not a function");
305
+ reactive.reactive((v) => {
306
+ if (!Array.isArray(v)) {
307
+ v = [v];
298
308
  }
299
309
  let nodes = [];
300
310
  let newList = /* @__PURE__ */ new Map();
301
- arr.forEach((item, index) => {
311
+ v.forEach((item, index) => {
302
312
  let render2 = list.get(item)?.shift();
303
313
  if (callback.length >= 2 && render2 && render2[2] !== index) {
304
314
  render2[0].abort();
@@ -709,7 +719,6 @@ HTMLElement.prototype.mount = function(node, aboutSignal) {
709
719
  render(null, node, this, aboutSignal);
710
720
  };
711
721
  Object.assign(globalThis, {
712
- Store: createStore,
713
722
  JSX,
714
723
  html,
715
724
  css: html,
@@ -718,11 +727,12 @@ Object.assign(globalThis, {
718
727
  export {
719
728
  Fragment,
720
729
  JSX,
721
- createStore as Store,
730
+ atom,
722
731
  html as css,
723
732
  html,
724
733
  html as js,
725
734
  jsx,
726
735
  jsx as jsxDEV,
727
- jsx as jsxs
736
+ jsx as jsxs,
737
+ store
728
738
  };
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // index.ts
2
2
  function buildRoutes(handler) {
3
- const { routes = {} } = handler(Symbol.for("mono.setup"));
3
+ const { routes = {} } = handler(/* @__PURE__ */ Symbol.for("mono.setup"));
4
4
  return monoRoutes(routes, handler);
5
5
  }
6
6
  function monoRoutes(routes, handler) {
package/jsx-runtime.mjs CHANGED
@@ -170,13 +170,13 @@ var escapeHTML = (str) => {
170
170
  };
171
171
 
172
172
  // symbols.ts
173
- var $fragment = Symbol.for("jsx.fragment");
174
- var $html = Symbol.for("jsx.html");
175
- var $vnode = Symbol.for("jsx.vnode");
176
- var $setup = Symbol.for("mono.setup");
173
+ var $fragment = /* @__PURE__ */ Symbol.for("jsx.fragment");
174
+ var $html = /* @__PURE__ */ Symbol.for("jsx.html");
175
+ var $vnode = /* @__PURE__ */ Symbol.for("jsx.vnode");
176
+ var $setup = /* @__PURE__ */ Symbol.for("mono.setup");
177
177
 
178
178
  // version.ts
179
- var VERSION = "0.9.0";
179
+ var VERSION = "0.9.3";
180
180
 
181
181
  // render.ts
182
182
  var FunctionIdGenerator = class extends Map {
@@ -1073,7 +1073,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
1073
1073
  console.error("[mono-jsx] Use `ref` outside of a component function");
1074
1074
  } else {
1075
1075
  const refId = rc.fc.refs++;
1076
- const effects = signals[Symbol.for("effects")];
1076
+ const effects = signals[/* @__PURE__ */ Symbol.for("effects")];
1077
1077
  effects.push("()=>(" + String(attrValue) + ')(this.refs["' + refId + '"])');
1078
1078
  attr = " data-ref=" + toAttrStringLit(rc.fc.id + ":" + refId);
1079
1079
  }
@@ -1244,9 +1244,9 @@ function createThisProxy(rc, scopeId) {
1244
1244
  return (effect) => {
1245
1245
  effects.push(String(effect));
1246
1246
  };
1247
- case Symbol.for("effects"):
1247
+ case /* @__PURE__ */ Symbol.for("effects"):
1248
1248
  return effects;
1249
- case Symbol.for("mark"):
1249
+ case /* @__PURE__ */ Symbol.for("mark"):
1250
1250
  return mark;
1251
1251
  case "url":
1252
1252
  if (scopeId === 0) {
@@ -1345,7 +1345,7 @@ async function createSession(request, options) {
1345
1345
  return session;
1346
1346
  }
1347
1347
  function markSignals(rc, signals) {
1348
- signals[Symbol.for("mark")](rc);
1348
+ signals[/* @__PURE__ */ Symbol.for("mark")](rc);
1349
1349
  }
1350
1350
  function traverseProps(obj, callback, path = []) {
1351
1351
  const isArray = Array.isArray(obj);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
package/setup.mjs CHANGED
@@ -2,20 +2,14 @@
2
2
  import { lstat, readFile, writeFile } from "node:fs/promises";
3
3
  import { argv } from "node:process";
4
4
  var serverTSX = `// mono-jsx SSR example
5
- // Documentation: https://ije.github.io/mono-jsx/docs/ssr
5
+ // Docs: https://github.com/ije/mono-jsx
6
6
 
7
7
  function App(this: FC<{ a: number; b: number }>) {
8
- this.init({
9
- a: 1,
10
- b: 2,
11
- })
8
+ this.init({ a: 1, b: 2 })
12
9
 
13
10
  this.effect(() => {
14
11
  // effect is called when the component is mounted or when the dependencies(calc.a & calc.b) change
15
12
  console.log("sum", this.a * this.b);
16
- return () => {
17
- console.log("cleanup");
18
- };
19
13
  });
20
14
 
21
15
  return (
@@ -52,8 +46,6 @@ export default {
52
46
  <head>
53
47
  <meta charSet="utf-8" />
54
48
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
55
- <meta name="description" content="Building user interfaces." />
56
- <meta name="keywords" content="ssr,jsx" />
57
49
  <title>Welcome to mono-jsx!</title>
58
50
  </head>
59
51
  <body>
@@ -1,3 +1,10 @@
1
1
  /// <reference types="../jsx.d.ts" />
2
2
 
3
- export const Store: <T extends Record<string, unknown>>(initValue: T) => FC & T;
3
+ export interface IAtom<T> {
4
+ get: () => T;
5
+ set: (value: T | ((prev: T) => T)) => void;
6
+ map: (callback: (value: T extends (infer V)[] ? V : T, index: number) => JSX.Element) => JSX.Element[];
7
+ }
8
+
9
+ export const atom: <T>(initValue: T) => IAtom<T>;
10
+ export const store: <T extends Record<string, unknown>>(initValue: T) => T;
@@ -1,5 +1,4 @@
1
1
  import type { ComponentType, VNode } from "../jsx.d.ts";
2
- import type * as Mono from "./mono.d.ts";
3
2
 
4
3
  export const html: JSX.Raw;
5
4
  export const JSX: typeof globalThis.JSX;
@@ -10,8 +9,13 @@ export const jsx: (tag: string | ComponentType, props: Record<string, unknown>,
10
9
  export { html as css, html as js, jsx as jsxDEV, jsx as jsxs };
11
10
 
12
11
  declare global {
13
- namespace JSX {
14
- interface BuiltinElements extends Mono.Elements {}
12
+ interface FCExtension<FC> {
13
+ /**
14
+ * Creates a new signals object.
15
+ *
16
+ * **⚠ This is a client-side only API.**
17
+ */
18
+ extend<T extends Record<string, unknown>>(initValue: T): FC & T;
15
19
  }
16
20
 
17
21
  interface HTMLElement {
package/types/jsx.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { HTML } from "./html.d.ts";
2
2
 
3
- export type ChildType = MaybeArray<JSX.Element | string | number | bigint | boolean | null | undefined>;
3
+ export type ChildPrimitiveType = JSX.Element | string | number | bigint | boolean | null | undefined;
4
+ export type ChildType = MaybeArray<ChildPrimitiveType | MaybeGetter<ChildPrimitiveType>>;
4
5
  export type MaybeArray<T> = T | T[];
6
+ export type MaybeGetter<T> = { get: () => T };
5
7
  export type MaybePromiseOrGenerator<T> = T | Promise<T> | Generator<T> | AsyncGenerator<T>;
6
8
 
7
9
  export interface BaseAttributes {
@@ -57,6 +59,57 @@ export interface ComponentType<P = {}> {
57
59
  rendering?: string;
58
60
  }
59
61
 
62
+ export interface MonoBuiltinElements {
63
+ /**
64
+ * A built-in element of mono-jsx that toggles the visibility of its children.
65
+ * @mono-jsx
66
+ */
67
+ show: BaseAttributes & {
68
+ /**
69
+ * Show the children if the value is truthy.
70
+ */
71
+ when?: any;
72
+
73
+ /**
74
+ * Enables view transition for the children.
75
+ */
76
+ viewTransition?: string | boolean;
77
+ };
78
+
79
+ /**
80
+ * A built-in element of mono-jsx that toggles the visibility of its children.
81
+ * @mono-jsx
82
+ */
83
+ hidden: BaseAttributes & {
84
+ /**
85
+ * Hide the children if the value is truthy.
86
+ */
87
+ when?: any;
88
+
89
+ /**
90
+ * Enables view transition for the children.
91
+ */
92
+ viewTransition?: string | boolean;
93
+ };
94
+
95
+ /**
96
+ * A a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
97
+ * It is similar to a switch statement in programming languages.
98
+ * @mono-jsx
99
+ */
100
+ switch: BaseAttributes & {
101
+ /**
102
+ * Which child to display.
103
+ */
104
+ value?: string | number | boolean | null;
105
+
106
+ /**
107
+ * Enables view transition for the children.
108
+ */
109
+ viewTransition?: string | boolean;
110
+ };
111
+ }
112
+
60
113
  declare global {
61
114
  namespace JSX {
62
115
  type ElementType<P = any> =
@@ -71,7 +124,7 @@ declare global {
71
124
  interface CustomElements {}
72
125
  interface Element extends VNode, Response {}
73
126
  interface IntrinsicAttributes extends BaseAttributes, AsyncComponentAttributes {}
74
- interface IntrinsicElements extends HTML.Elements, HTML.SVGElements, HTML.CustomElements, JSX.BuiltinElements {}
127
+ interface IntrinsicElements extends HTML.Elements, HTML.SVGElements, HTML.CustomElements, JSX.BuiltinElements, MonoBuiltinElements {}
75
128
  }
76
129
 
77
130
  interface FCExtension<FC = {}> {}
package/types/mono.d.ts CHANGED
@@ -3,55 +3,6 @@ import type { AsyncComponentAttributes, BaseAttributes, ComponentType } from "./
3
3
  export type WithParams<T> = T & { params?: Record<string, string> };
4
4
 
5
5
  export interface Elements {
6
- /**
7
- * A built-in element of mono-jsx that toggles the visibility of its children.
8
- * @mono-jsx
9
- */
10
- show: BaseAttributes & {
11
- /**
12
- * Show the children if the value is truthy.
13
- */
14
- when?: any;
15
-
16
- /**
17
- * Enables view transition for the children.
18
- */
19
- viewTransition?: string | boolean;
20
- };
21
-
22
- /**
23
- * A built-in element of mono-jsx that toggles the visibility of its children.
24
- * @mono-jsx
25
- */
26
- hidden: BaseAttributes & {
27
- /**
28
- * Hide the children if the value is truthy.
29
- */
30
- when?: any;
31
-
32
- /**
33
- * Enables view transition for the children.
34
- */
35
- viewTransition?: string | boolean;
36
- };
37
-
38
- /**
39
- * A a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
40
- * It is similar to a switch statement in programming languages.
41
- * @mono-jsx
42
- */
43
- switch: BaseAttributes & {
44
- /**
45
- * Which child to display.
46
- */
47
- value?: string | number | boolean | null;
48
-
49
- /**
50
- * Enables view transition for the children.
51
- */
52
- viewTransition?: string | boolean;
53
- };
54
-
55
6
  /**
56
7
  * A built-in element of mono-jsx that is used to load components lazily,
57
8
  * which can improve performance by reducing the initial load time of the application.
@@ -238,7 +189,7 @@ export interface Session {
238
189
  }
239
190
 
240
191
  declare global {
241
- interface FCExtension {
192
+ interface FCExtension<FC> {
242
193
  /**
243
194
  * The global signals shared across the application.
244
195
  */
@@ -1,65 +0,0 @@
1
- import type { BaseAttributes } from "../jsx.d.ts";
2
-
3
- export interface Elements {
4
- /**
5
- * A built-in element of mono-jsx that toggles the visibility of its children.
6
- * @mono-jsx
7
- */
8
- show: BaseAttributes & {
9
- /**
10
- * Show the children if the value is truthy.
11
- */
12
- when?: any;
13
-
14
- /**
15
- * Enables view transition for the children.
16
- */
17
- viewTransition?: string | boolean;
18
- };
19
-
20
- hidden: BaseAttributes & {
21
- /**
22
- * Hide the children if the value is truthy.
23
- */
24
- when?: any;
25
-
26
- /**
27
- * Enables view transition for the children.
28
- */
29
- viewTransition?: string | boolean;
30
- };
31
-
32
- /**
33
- * A a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
34
- * It is similar to a switch statement in programming languages.
35
- * @mono-jsx
36
- */
37
- switch: BaseAttributes & {
38
- /**
39
- * Which child to display.
40
- */
41
- value?: string | number | boolean | null;
42
-
43
- /**
44
- * Enables view transition for the children.
45
- */
46
- viewTransition?: string | boolean;
47
- };
48
- }
49
-
50
- declare global {
51
- interface FCExtension<FC> {
52
- /**
53
- * Creates a new signals object.
54
- *
55
- * **⚠ This is a client-side only API.**
56
- */
57
- extend<T extends Record<string, unknown>>(initValue: T): FC & T;
58
- }
59
-
60
- /**
61
- * Creates a new signals object.
62
- * @mono-jsx
63
- */
64
- var Store: <T extends Record<string, unknown>>(initValue: T) => FC & T;
65
- }