mono-jsx 0.7.3 → 0.7.5

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
@@ -5,7 +5,7 @@
5
5
  mono-jsx is a JSX runtime that renders the `<html>` element to a `Response` object.
6
6
 
7
7
  - 🚀 No build step needed
8
- - 🦋 Lightweight (10KB gzipped), zero dependencies
8
+ - 🦋 Lightweight (12KB gzipped), zero dependencies
9
9
  - 🚦 Signals as reactive primitives
10
10
  - ⚡️ Use web components, no virtual DOM
11
11
  - 💡 Complete Web API TypeScript definitions
@@ -428,6 +428,8 @@ export default {
428
428
 
429
429
  mono-jsx renders HTML on the server side and sends no hydration JavaScript to the client. To render a component dynamically on the client, you can use the `<component>` element to ask the server to render a component:
430
430
 
431
+ To render a component by name, you can use the `<component>` element with the `name` prop, and ensure the component is registered in the `components` prop of root `<html>` element.
432
+
431
433
  ```tsx
432
434
  export default {
433
435
  fetch: (req) => (
@@ -438,31 +440,19 @@ export default {
438
440
  }
439
441
  ```
440
442
 
441
- You can use the `<toggle>` element to control when to render a component:
443
+ Or you can use the `<component>` element with the `is` prop to render a component by function reference without registering the component in the `components` prop of root `<html>` element.
442
444
 
443
445
  ```tsx
444
- async function Lazy(this: FC<{ show: boolean }>, props: { url: string }) {
445
- this.show = false;
446
- return (
447
- <div>
448
- <toggle show={this.show}>
449
- <component name="Foo" props={{ /* props for the component */ }} placeholder={<p>Loading...</p>} />
450
- </toggle>
451
- <button onClick={() => this.show = true }>Load `Foo` Component</button>
452
- </div>
453
- )
454
- }
455
-
456
446
  export default {
457
447
  fetch: (req) => (
458
- <html components={{ Foo }}>
459
- <Lazy />
448
+ <html>
449
+ <component is={Foo} props={{ /* props for the component */ }} placeholder={<p>Loading...</p>} />
460
450
  </html>
461
451
  )
462
452
  }
463
453
  ```
464
454
 
465
- You can also use signals for `name` or `props` attributes of a component. Changing the signal value will trigger the component to re-render with the new name or props:
455
+ You can also use [signals](#using-signals) for `name` or `props` attributes of a component. Changing the signal value will trigger the component to re-render with the new name or props:
466
456
 
467
457
  ```tsx
468
458
  import { Profile, Projects, Settings } from "./pages.tsx"
@@ -493,6 +483,30 @@ export default {
493
483
  }
494
484
  ```
495
485
 
486
+ You can use the `<toggle>` element to control when to render a component:
487
+
488
+ ```tsx
489
+ async function Lazy(this: FC<{ show: boolean }>, props: { url: string }) {
490
+ this.show = false;
491
+ return (
492
+ <div>
493
+ <toggle show={this.show}>
494
+ <component name="Foo" props={{ /* props for the component */ }} placeholder={<p>Loading...</p>} />
495
+ </toggle>
496
+ <button onClick={() => this.show = true }>Load `Foo` Component</button>
497
+ </div>
498
+ )
499
+ }
500
+
501
+ export default {
502
+ fetch: (req) => (
503
+ <html components={{ Foo }}>
504
+ <Lazy />
505
+ </html>
506
+ )
507
+ }
508
+ ```
509
+
496
510
  ## Using Signals
497
511
 
498
512
  mono-jsx uses signals for updating the view when a signal changes. Signals are similar to React's state, but they are more lightweight and efficient. You can use signals to manage state in your components.
package/jsx-runtime.mjs CHANGED
@@ -12,7 +12,7 @@ var ROUTER = 512;
12
12
  var FORM = 1024;
13
13
  var EVENT_JS = `{var w=window;w.$emit=(e,f,s)=>f.call(w.$signals?.(s)??e.target,e.type==="mount"?e.target:e);w.$onsubmit=(e,f,s)=>{e.preventDefault();f.call(w.$signals?.(s)??e.target,new FormData(e.target),e)};}`;
14
14
  var CX_JS = `{var n=e=>typeof e=="string"?e:typeof e=="object"&&e!==null?Array.isArray(e)?e.map(n).filter(Boolean).join(" "):Object.entries(e).filter(([,t])=>!!t).map(([t])=>t).join(" "):"";window.$cx=n;}`;
15
- var STYLE_JS = `{var l=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;var u=e=>typeof e=="string",p=e=>typeof e=="object"&&e!==null,f=e=>e.replace(/[a-z][A-Z]/g,o=>o.charAt(0)+"-"+o.charAt(1).toLowerCase());var g=e=>{let o=[],n=[],r=new y;for(let[t,s]of Object.entries(e))switch(t.charCodeAt(0)){case 58:n.push(t.startsWith("::view-")?"":null,t+"{"+c(s)+"}");break;case 64:t.startsWith("@keyframes ")||t.startsWith("@view-")?p(s)&&n.push(t+"{"+Object.entries(s).map(([i,a])=>i+"{"+c(a)+"}").join("")+"}"):n.push(t+"{",null,"{"+c(s)+"}}");break;case 38:n.push(null,t.slice(1)+"{"+c(s)+"}");break;default:o.push([t,s])}return o.length>0&&(r.inline=c(o)),n.length>0&&(r.css=n),r},b=(e,o)=>{let{inline:n,css:r}=g(o);if(r){let t="data-css-",s="["+t+(Date.now()+Math.random()).toString(36).replace(".","")+"]";document.head.appendChild(document.createElement("style")).textContent=(n?s+"{"+n+"}":"")+r.map(i=>i===null?s:i).join(""),e.getAttributeNames().forEach(i=>i.startsWith(t)&&e.removeAttribute(i)),e.setAttribute(s.slice(1,-1),"")}else n&&e.setAttribute("style",n)},c=e=>{if(typeof e=="object"&&e!==null){let o="";for(let[n,r]of Array.isArray(e)?e:Object.entries(e))if(u(r)||typeof r=="number"){let t=f(n),s=typeof r=="number"?l.test(n)?""+r:r+"px":""+r;o+=(o?";":"")+t+":"+(t==="content"?JSON.stringify(s):s)}return o}return""},y=(()=>{function e(){}return e.prototype=Object.freeze(Object.create(null)),e})();window.$applyStyle=b;}`;
15
+ var STYLE_JS = `{var l=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;var u=e=>typeof e=="string",p=e=>typeof e=="object"&&e!==null,f=e=>e.replace(/[a-z][A-Z]/g,o=>o.charAt(0)+"-"+o.charAt(1).toLowerCase());var g=e=>{let o=[],n=[],r=new h;for(let[t,s]of Object.entries(e))switch(t.charCodeAt(0)){case 58:n.push(t.startsWith("::view-")?"":null,t+"{"+c(s)+"}");break;case 64:t.startsWith("@keyframes ")||t.startsWith("@view-")?p(s)&&n.push(t+"{"+Object.entries(s).map(([i,a])=>i+"{"+c(a)+"}").join("")+"}"):n.push(t+"{",null,"{"+c(s)+"}}");break;case 38:n.push(null,t.slice(1)+"{"+c(s)+"}");break;default:o.push([t,s])}return o.length>0&&(r.inline=c(o)),n.length>0&&(r.css=n),r},b=(e,o)=>{let{inline:n,css:r}=g(o);if(r){let t="data-css-",s="["+t+(Date.now()+Math.random()).toString(36).replace(".","")+"]";document.head.appendChild(document.createElement("style")).textContent=(n?s+"{"+n+"}":"")+r.map(i=>i===null?s:i).join(""),e.getAttributeNames().forEach(i=>i.startsWith(t)&&e.removeAttribute(i)),e.setAttribute(s.slice(1,-1),"")}else n&&e.setAttribute("style",n)},c=e=>{if(typeof e=="object"&&e!==null){let o="";for(let[n,r]of Array.isArray(e)?e:Object.entries(e))if(u(r)||typeof r=="number"){let t=f(n),s=typeof r=="number"?l.test(n)?""+r:r+"px":""+r;o+=(o?";":"")+t+":"+(t==="content"?JSON.stringify(s):s)}return o}return""},h=(()=>{function e(){}return e.prototype=Object.freeze(Object.create(null)),e})();window.$applyStyle=b;}`;
16
16
  var RENDER_ATTR_JS = `{var s=(l,n,r)=>{let e=l.parentElement;return e.tagName==="M-GROUP"&&(e=e.previousElementSibling),()=>{let t=r();n==="value"?e.value=String(t):n==="checked"?e.checked=!!t:typeof t=="boolean"?e.toggleAttribute(n,t):t==null?e.removeAttribute(n):typeof t=="object"?n==="class"?e.setAttribute(n,$cx(t)):n==="style"?$applyStyle(e,t):e.setAttribute(n,JSON.stringify(t)):e.setAttribute(n,String(t))}};window.$renderAttr=s;}`;
17
17
  var RENDER_TOGGLE_JS = `{var i=(e,s)=>{let t,l=()=>e.replaceChildren(...s()?t:[]);return()=>{if(!t){let n=e.firstElementChild;n&&n.tagName==="TEMPLATE"&&n.hasAttribute("m-slot")?t=[...n.content.childNodes]:t=[...e.childNodes]}e.hasAttribute("vt")&&document.startViewTransition?document.startViewTransition(l):l()}};window.$renderToggle=i;}`;
18
18
  var RENDER_SWITCH_JS = `{var a=(l,u)=>{let s,r=l.getAttribute("value"),t,i,o=e=>t.get(e)??t.set(e,[]).get(e),d=()=>l.replaceChildren(...t.has(s)?t.get(s):i);return()=>{if(!t){t=new Map,i=[];for(let e of l.childNodes)if(e.nodeType===1&&e.tagName==="TEMPLATE"&&e.hasAttribute("m-slot")){for(let n of e.content.childNodes)n.nodeType===1&&n.hasAttribute("slot")?o(n.getAttribute("slot")).push(n):i.push(n);e.remove()}else r?o(r).push(e):i.push(e)}s=""+u(),l.hasAttribute("vt")&&document.startViewTransition?document.startViewTransition(d):d()}};window.$renderSwitch=a;}`;
@@ -28,6 +28,19 @@ var regexpHtmlSafe = /["'&<>]/;
28
28
  var isString = (v) => typeof v === "string";
29
29
  var isObject = (v) => typeof v === "object" && v !== null;
30
30
  var toHyphenCase = (k) => k.replace(/[a-z][A-Z]/g, (m) => m.charAt(0) + "-" + m.charAt(1).toLowerCase());
31
+ var IdGen = class extends Map {
32
+ #seq = 0;
33
+ gen(v) {
34
+ return this.get(v) ?? this.set(v, this.#seq++).get(v);
35
+ }
36
+ getById(id) {
37
+ for (const [v, i] of this.entries()) {
38
+ if (i === id) {
39
+ return v;
40
+ }
41
+ }
42
+ }
43
+ };
31
44
  var cx = (className) => {
32
45
  if (typeof className === "string") {
33
46
  return className;
@@ -143,15 +156,16 @@ var $signal = Symbol.for("mono.signal");
143
156
  var $vnode = Symbol.for("jsx.vnode");
144
157
 
145
158
  // version.ts
146
- var VERSION = "0.7.2";
159
+ var VERSION = "0.7.4";
147
160
 
148
161
  // render.ts
149
162
  var cdn = "https://raw.esm.sh";
150
- var subtle = crypto.subtle;
151
163
  var encoder = new TextEncoder();
152
164
  var customElements = /* @__PURE__ */ new Map();
153
165
  var voidTags = new Set("area,base,br,col,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(","));
154
166
  var cache = /* @__PURE__ */ new Map();
167
+ var componentsMap = new IdGen();
168
+ var subtle = crypto.subtle;
155
169
  var stringify = JSON.stringify;
156
170
  var isVNode = (v) => Array.isArray(v) && v.length === 3 && v[2] === $vnode;
157
171
  var isSignal = (v) => isObject(v) && !!v[$signal];
@@ -165,12 +179,6 @@ var Ref = class {
165
179
  this.name = name;
166
180
  }
167
181
  };
168
- var IdGen = class extends Map {
169
- #seq = 0;
170
- gen(v) {
171
- return this.get(v) ?? this.set(v, this.#seq++).get(v);
172
- }
173
- };
174
182
  var IdGenManager = class {
175
183
  #scopes = /* @__PURE__ */ new Map();
176
184
  size = 0;
@@ -209,11 +217,11 @@ function renderHtml(node, options) {
209
217
  const request = options.request;
210
218
  const headers = new Headers();
211
219
  const reqHeaders = request?.headers;
212
- const componentHeader = reqHeaders?.get("x-component");
220
+ const compHeader = reqHeaders?.get("x-component");
221
+ let status = options.status;
213
222
  let routeFC = request ? Reflect.get(request, "x-route") : void 0;
214
223
  let routeForm;
215
- let component = componentHeader ? components?.[componentHeader] : null;
216
- let status = options.status;
224
+ let component = compHeader ? compHeader.startsWith("@comp_") ? componentsMap.getById(Number(compHeader.slice(6))) : components?.[compHeader] : null;
217
225
  if (request) {
218
226
  request.URL = new URL(request.url);
219
227
  }
@@ -295,7 +303,7 @@ function renderHtml(node, options) {
295
303
  }),
296
304
  { headers }
297
305
  );
298
- } else if (componentHeader) {
306
+ } else if (compHeader) {
299
307
  return new Response("Component not found: " + component, { status: 404 });
300
308
  }
301
309
  headers.set("content-type", "text/html; charset=utf-8");
@@ -408,12 +416,15 @@ async function render(node, options, write, writeJS, componentMode, routeForm) {
408
416
  mcs.clear();
409
417
  }
410
418
  if (session && session.isDirty) {
411
- const sessionEntries = session.entries();
419
+ const sessionStore = session.all();
412
420
  const { name = "session", domain, path, expires, maxAge, secure, sameSite, secret } = options.session?.cookie ?? {};
413
421
  if (secret) {
414
422
  let cookie = name + "=";
415
- if (sessionEntries.length > 0) {
416
- const data = JSON.stringify(sessionEntries);
423
+ if (Object.keys(sessionStore).length > 0) {
424
+ const data = JSON.stringify([
425
+ sessionStore,
426
+ Math.floor((expires ? expires.getTime() : Date.now() + (maxAge ?? 18e5)) / 1e3)
427
+ ]);
417
428
  const signature = await subtle.sign(
418
429
  "HMAC",
419
430
  await subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]),
@@ -630,19 +641,25 @@ async function renderNode(rc, node, stripSlotProp) {
630
641
  }
631
642
  // `<component>` element
632
643
  case "component": {
633
- let { placeholder, viewTransition } = props;
644
+ let { placeholder, viewTransition, is } = props;
634
645
  let attrs = "";
635
646
  let attrModifiers = "";
636
647
  for (const p of ["name", "props", "ref"]) {
637
- let propValue = props[p];
638
- let [attr, , attrSignal] = renderAttr(rc, p, propValue);
648
+ const [attr, , attrSignal] = renderAttr(rc, p, props[p]);
639
649
  if (attrSignal) {
640
650
  attrModifiers += renderSignal(rc, attrSignal, [p]);
641
651
  rc.flags.runtime |= RENDER_ATTR;
642
- propValue = attrSignal[$signal].value;
643
652
  }
644
653
  attrs += attr;
645
654
  }
655
+ if (!props.name && typeof is === "function" && is.name) {
656
+ const c = is.name.charCodeAt(0);
657
+ if (c >= /*A*/
658
+ 65 && c <= /*Z*/
659
+ 90) {
660
+ attrs += ' name="@comp_' + componentsMap.gen(is) + '"';
661
+ }
662
+ }
646
663
  attrs += renderViewTransitionAttr(viewTransition);
647
664
  let buf = "<m-component" + attrs + ">";
648
665
  if (placeholder) {
@@ -1230,7 +1247,7 @@ async function createSession(request, options) {
1230
1247
  return isDirty;
1231
1248
  },
1232
1249
  get: (key) => sessionStore.get(key),
1233
- entries: () => [...sessionStore.entries()],
1250
+ all: () => Object.fromEntries(sessionStore.entries()),
1234
1251
  set: (key, value) => {
1235
1252
  sessionStore.set(key, value);
1236
1253
  isDirty = true;
@@ -1263,8 +1280,11 @@ async function createSession(request, options) {
1263
1280
  encoder.encode(data)
1264
1281
  );
1265
1282
  if (verified) {
1266
- sessionId = sid;
1267
- sessionStore = new Map(JSON.parse(data));
1283
+ const [map, exp] = JSON.parse(data);
1284
+ if (typeof exp === "number" && exp * 1e3 > Date.now()) {
1285
+ sessionStore = new Map(Object.entries(map));
1286
+ sessionId = sid;
1287
+ }
1268
1288
  }
1269
1289
  } catch (_) {
1270
1290
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
7
7
  "types": "./types/index.d.ts",
8
8
  "bin": {
9
- "mono-jsx": "./bin/mono-jsx"
9
+ "mono-jsx": "bin/mono-jsx"
10
10
  },
11
11
  "exports": {
12
12
  ".": {
@@ -35,6 +35,6 @@
35
35
  "license": "MIT",
36
36
  "repository": {
37
37
  "type": "git",
38
- "url": "https://github.com/ije/mono-jsx"
38
+ "url": "git+https://github.com/ije/mono-jsx.git"
39
39
  }
40
40
  }
package/types/html.d.ts CHANGED
@@ -46,6 +46,7 @@ export namespace HTML {
46
46
  interface GlobalAttributes<T extends EventTarget> extends EventAttributes<T>, Aria.Attributes, Mono.BaseAttributes, JSX.HtmlTag {
47
47
  /**
48
48
  * A reference to the element.
49
+ * @mono-jsx
49
50
  */
50
51
  ref?: HTMLElement | ((el: T) => unknown);
51
52
  /** Defines a unique identifier (ID) which must be unique in the whole document. Its purpose is to identify the element when linking (using a fragment identifier), scripting, or styling (with CSS). */
@@ -105,6 +106,12 @@ export namespace HTML {
105
106
  is?: string;
106
107
  /** A boolean value that makes the browser disregard user input events for the element. Useful when click events are present. */
107
108
  inert?: boolean;
109
+ /**
110
+ * Enables view transition for the element.
111
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
112
+ * @mono-jsx
113
+ */
114
+ viewTransition?: string | boolean;
108
115
  }
109
116
 
110
117
  interface HtmlAttributes<T extends EventTarget> extends GlobalAttributes<T>, RenderOptions {}
package/types/mono.d.ts CHANGED
@@ -98,11 +98,6 @@ export interface BaseAttributes {
98
98
  * The `slot` attribute assigns a slot in a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) shadow tree to an element: An element with a `slot` attribute is assigned to the slot created by the `<slot>` element whose name attribute's value matches that slot attribute's value.
99
99
  */
100
100
  slot?: string;
101
- /**
102
- * The `viewTransition` attribute is used to control the view transition of the children.
103
- * @mono-jsx
104
- */
105
- viewTransition?: string | boolean;
106
101
  }
107
102
 
108
103
  export interface AsyncComponentAttributes {
@@ -123,95 +118,127 @@ export interface AsyncComponentAttributes {
123
118
 
124
119
  export interface Elements {
125
120
  /**
126
- * The `toggle` element is a built-in element of mono-jsx that toggles the visibility of its children.
121
+ * A built-in element of mono-jsx that toggles the visibility of its children.
122
+ * @mono-jsx
127
123
  */
128
124
  toggle: BaseAttributes & {
129
125
  /**
130
- * The `show` attribute is used to control the visibility of the children.
126
+ * The visibility of the children.
131
127
  */
132
128
  show?: any;
133
129
  /**
134
- * The `hidden` attribute is used to control the visibility of the children.
130
+ * The visibility of the children.
135
131
  */
136
132
  hidden?: any;
133
+
134
+ /**
135
+ * Enables view transition for the children.
136
+ */
137
+ viewTransition?: string | boolean;
137
138
  };
138
139
  /**
139
- * The `switch` element is a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
140
+ * A a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
140
141
  * It is similar to a switch statement in programming languages.
142
+ * @mono-jsx
141
143
  */
142
144
  switch: BaseAttributes & {
143
145
  /**
144
- * The `value` attribute is used to control the value of the children.
146
+ * Which child to display.
145
147
  */
146
148
  value?: string | number | boolean | null;
149
+
150
+ /**
151
+ * Enables view transition for the children.
152
+ */
153
+ viewTransition?: string | boolean;
147
154
  };
148
155
  /**
149
- * The `component` element is a built-in element of mono-jsx that is used to load components lazily,
156
+ * A built-in element of mono-jsx that is used to load components lazily,
150
157
  * which can improve performance by reducing the initial load time of the application.
158
+ * @mono-jsx
151
159
  */
152
160
  component: BaseAttributes & AsyncComponentAttributes & {
153
161
  /**
154
- * The `name` attribute is used to control the name of the component.
162
+ * The name of the component to render.
155
163
  */
156
164
  name?: string;
157
165
  /**
158
- * The `props` attribute is used to control the props of the component.
166
+ * The component to render.
167
+ */
168
+ is?: import("./jsx.d.ts").FC<any>;
169
+ /**
170
+ * The props of the component to render.
159
171
  */
160
172
  props?: Record<string, unknown>;
161
173
  /**
162
- * The `ref` attribute is used to control the ref of the component.
174
+ * The ref of the component.
163
175
  */
164
176
  ref?: ComponentElement | ((el: ComponentElement) => void);
177
+
178
+ /**
179
+ * Enables view transition for the children.
180
+ */
181
+ viewTransition?: string | boolean;
165
182
  };
166
183
  /**
167
- * The `router` element is a built-in element of mono-jsx that provides SPA routing.
184
+ * A built-in element of mono-jsx that provides SPA routing.
185
+ * @mono-jsx
168
186
  */
169
187
  router: BaseAttributes & AsyncComponentAttributes & {
170
188
  /**
171
- * The `base` attribute is used to set the base URL for the router.
189
+ * The base URL for the router.
172
190
  */
173
191
  base?: string;
174
192
  /**
175
- * The `ref` attribute is used to control the ref of the router.
193
+ * The ref of the router.
176
194
  */
177
195
  ref?: RouterElement | ((el: RouterElement) => void);
196
+ /**
197
+ * Enables view transition for the children.
198
+ * @mono-jsx
199
+ */
200
+ viewTransition?: string | boolean;
178
201
  };
179
202
  /**
180
- * The `cache` element is a built-in element of mono-jsx that caches the rendered content of the child nodes
203
+ * A built-in element of mono-jsx that caches the rendered content of the child nodes
181
204
  * with the given key and TTL.
205
+ * @mono-jsx
182
206
  */
183
207
  cache: BaseAttributes & {
184
208
  /**
185
- * The `key` attribute is used to control the key of the cache.
209
+ * The key of the cache.
186
210
  */
187
211
  key?: string;
188
212
  /**
189
- * The `ttl` attribute is used to control the TTL of the cache.
213
+ * The time-to-live of the cache in seconds.
190
214
  */
191
215
  ttl?: number;
192
216
  };
193
217
  /**
194
- * The `static` element is a built-in element of mono-jsx that treats the child nodes as static content,
218
+ * A built-in element of mono-jsx that treats the child nodes as static content,
195
219
  * When the child nodes are rendered once, they will be cached in memory and reused on subsequent renders.
220
+ * @mono-jsx
196
221
  */
197
222
  static: BaseAttributes;
198
223
  /**
199
- * The `redirect` element is a built-in element of mono-jsx that redirects to the given URL in the client side.
224
+ * A built-in element of mono-jsx that redirects to the given URL in the client side.
225
+ * @mono-jsx
200
226
  */
201
227
  redirect: {
202
228
  /**
203
- * The `to` attribute is used to control the redirect URL.
229
+ * The redirect URL.
204
230
  */
205
231
  to?: string | URL;
206
232
  /**
207
- * The `replace` attribute is used to control the replace behavior of the redirect.
233
+ * The replace behavior of the redirect.
208
234
  * Only works when the `router` element is used.
209
235
  */
210
236
  replace?: boolean;
211
237
  };
212
238
  /**
213
- * The `invalid` element is a built-in element of mono-jsx that sets custom validation
239
+ * A built-in element of mono-jsx that sets custom validation
214
240
  * state for the form elements.
241
+ * @mono-jsx
215
242
  */
216
243
  invalid: BaseAttributes & {
217
244
  /**
@@ -220,63 +247,67 @@ export interface Elements {
220
247
  for?: string;
221
248
  };
222
249
  /**
223
- * The `formslot` element is a built-in element of mono-jsx that is used to display the content of the route form
250
+ * A built-in element of mono-jsx that is used to display the content of the route form
224
251
  * in the `form` element.
252
+ * @mono-jsx
225
253
  */
226
254
  formslot: BaseAttributes & {
255
+ /**
256
+ * The insert position of the formslot.
257
+ */
227
258
  mode?: "insertbefore" | "insertafter" | "replace";
228
259
  };
229
260
  }
230
261
 
231
262
  /**
232
- * The `Session` type defines the session API.
263
+ * The session storage API.
233
264
  */
234
265
  export interface Session {
235
266
  /**
236
- * The `sessionId` is used to identify the session.
267
+ * The session ID.
237
268
  */
238
269
  readonly sessionId: string;
239
270
  /**
240
- * The `isDirty` is true, update the session cookie to the client.
271
+ * If true, update the session cookie to the client.
241
272
  */
242
273
  readonly isDirty: boolean;
243
274
  /**
244
- * The `get` method is used to get a value from the session.
275
+ * Gets a value from the session.
245
276
  */
246
277
  get<T = unknown>(key: string): T | undefined;
247
278
  /**
248
- * The `entries` method is used to get all the entries from the session.
279
+ * Gets all the entries from the session.
249
280
  */
250
- entries(): [string, unknown][];
281
+ all(): Record<string, unknown>;
251
282
  /**
252
- * The `set` method is used to set a value in the session.
283
+ * Sets a value in the session.
253
284
  */
254
285
  set(key: string, value: string | number | boolean | any[] | Record<string, unknown>): void;
255
286
  /**
256
- * The `delete` method is used to delete a value from the session.
287
+ * Deletes a value from the session.
257
288
  */
258
289
  delete(key: string): void;
259
290
  /**
260
- * The `destroy` method is used to destroy the session.
291
+ * Destroys the session.
261
292
  */
262
293
  destroy(): void;
263
294
  }
264
295
 
265
296
  declare global {
266
297
  /**
267
- * The `html` function is used to create XSS-unsafed HTML content.
298
+ * Creates XSS-unsafed HTML content.
268
299
  */
269
300
  var html: JSX.Raw;
270
301
  /**
271
- * The `css` function is an alias to `html`.
302
+ * An alias to `html`.
272
303
  */
273
304
  var css: JSX.Raw;
274
305
  /**
275
- * The `js` function is an alias to `html`.
306
+ * An alias to `html`.
276
307
  */
277
308
  var js: JSX.Raw;
278
309
  /**
279
- * The `FC` type defines Signals/Context/Refs API.
310
+ * Defines the Signals/Context/Refs types.
280
311
  */
281
312
  type FC<Signals = {}, AppSignals = {}, Context = {}, Refs = {}, AppRefs = {}> = {
282
313
  /**
@@ -284,78 +315,78 @@ declare global {
284
315
  */
285
316
  readonly app: {
286
317
  /**
287
- * The `app.refs` object is used to store variables in the application scope.
318
+ * The `app.refs` object stores variables in the application scope.
288
319
  * It is similar to `refs`, but it is shared across all components in the application.
289
320
  *
290
321
  * **⚠ This is a client-side only API.**
291
322
  */
292
323
  readonly refs: AppRefs;
293
324
  /**
294
- * The `app.url` object contains the current URL information.
325
+ * The `app.url` object contains the current URL.
295
326
  */
296
327
  readonly url: WithParams<URL>;
297
328
  } & Omit<AppSignals, "refs" | "url">;
298
329
  /**
299
- * The rendering context.
330
+ * The rendering context object.
300
331
  *
301
332
  * **⚠ This is a server-side only API.**
302
333
  */
303
334
  readonly context: Context;
304
335
  /**
305
- * The `request` object contains the current request information.
336
+ * The `request` object contains the current request.
306
337
  *
307
338
  * **⚠ This is a server-side only API.**
308
339
  */
309
340
  readonly request: WithParams<
310
341
  Request & {
311
342
  /**
312
- * Returns the URL of request as a URL object.
343
+ * Returns the URL of the request as a URL object.
313
344
  */
314
345
  URL: URL;
315
346
  }
316
347
  >;
317
348
  /**
318
- * The `form` object created by the route form submission.
349
+ * The `form` object created by the route form.
319
350
  *
320
351
  * **⚠ This is a server-side only API.**
321
352
  */
322
353
  readonly form?: FormData;
323
354
  /**
324
- * The `session` object contains the current session information.
355
+ * The `session` object contains the current session.
325
356
  *
326
357
  * **⚠ This is a server-side only API.**
327
358
  */
328
359
  readonly session: Session;
329
360
  /**
330
- * The `refs` object is used to store variables in clide side.
361
+ * The `refs` object stores variables in clide side.
331
362
  *
332
363
  * **⚠ This is a client-side only API.**
333
364
  */
334
365
  readonly refs: Refs;
335
366
  /**
336
- * The `computed` method is used to create a computed signal.
367
+ * Creates a computed signal.
337
368
  */
338
369
  readonly computed: <T = unknown>(fn: () => T) => T;
339
370
  /**
340
- * `this.$(fn)` is a shortcut for `this.computed(fn)`.
371
+ * A shortcut for `this.computed(fn)`.
341
372
  */
342
373
  readonly $: FC["computed"];
343
374
  /**
344
- * The `effect` method is used to create a side effect.
375
+ * Creates a side effect.
345
376
  * **The effect function is only called on client side.**
346
377
  */
347
378
  readonly effect: (fn: () => void | (() => void)) => void;
348
379
  } & Omit<Signals, "app" | "context" | "request" | "session" | "form" | "refs" | "computed" | "$" | "effect">;
349
380
  /**
350
- * The `Refs` defines the `refs` types.
381
+ * Defines the `refs` type.
351
382
  */
352
383
  type Refs<T, R = {}, RR = {}> = T extends FC<infer S, infer A, infer C> ? FC<S, A, C, R, RR> : never;
353
384
  /**
354
- * The `Context` defines the `context` types.
385
+ * Defines the `context` type.
355
386
  */
356
387
  type Context<T, C = {}> = T extends FC<infer S, infer A, infer _, infer R, infer RR> ? FC<S, A, C, R, RR> : never;
357
388
  /**
358
- * The `ComponentElement` type defines the component element.
389
+ * The `<component>` element.
359
390
  */
360
391
  type ComponentElement = {
361
392
  name: string;
@@ -363,7 +394,7 @@ declare global {
363
394
  refresh: () => Promise<void>;
364
395
  };
365
396
  /**
366
- * The `RouterElement` type defines the router element.
397
+ * The `<router>` element.
367
398
  */
368
399
  type RouterElement = {
369
400
  navigate: (url: string | URL, options?: { replace?: boolean }) => Promise<void>;