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 +31 -17
- package/jsx-runtime.mjs +43 -23
- package/package.json +3 -3
- package/types/html.d.ts +7 -0
- package/types/mono.d.ts +85 -54
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 (
|
|
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
|
-
|
|
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
|
|
459
|
-
<
|
|
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
|
|
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.
|
|
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
|
|
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 =
|
|
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 (
|
|
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
|
|
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 (
|
|
416
|
-
const data = JSON.stringify(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1267
|
-
|
|
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
|
+
"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": "
|
|
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
|
-
*
|
|
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
|
|
126
|
+
* The visibility of the children.
|
|
131
127
|
*/
|
|
132
128
|
show?: any;
|
|
133
129
|
/**
|
|
134
|
-
* The
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
162
|
+
* The name of the component to render.
|
|
155
163
|
*/
|
|
156
164
|
name?: string;
|
|
157
165
|
/**
|
|
158
|
-
* The
|
|
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
|
|
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
|
-
*
|
|
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
|
|
189
|
+
* The base URL for the router.
|
|
172
190
|
*/
|
|
173
191
|
base?: string;
|
|
174
192
|
/**
|
|
175
|
-
* The
|
|
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
|
-
*
|
|
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
|
|
209
|
+
* The key of the cache.
|
|
186
210
|
*/
|
|
187
211
|
key?: string;
|
|
188
212
|
/**
|
|
189
|
-
* The
|
|
213
|
+
* The time-to-live of the cache in seconds.
|
|
190
214
|
*/
|
|
191
215
|
ttl?: number;
|
|
192
216
|
};
|
|
193
217
|
/**
|
|
194
|
-
*
|
|
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
|
-
*
|
|
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
|
|
229
|
+
* The redirect URL.
|
|
204
230
|
*/
|
|
205
231
|
to?: string | URL;
|
|
206
232
|
/**
|
|
207
|
-
* The
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
263
|
+
* The session storage API.
|
|
233
264
|
*/
|
|
234
265
|
export interface Session {
|
|
235
266
|
/**
|
|
236
|
-
* The
|
|
267
|
+
* The session ID.
|
|
237
268
|
*/
|
|
238
269
|
readonly sessionId: string;
|
|
239
270
|
/**
|
|
240
|
-
*
|
|
271
|
+
* If true, update the session cookie to the client.
|
|
241
272
|
*/
|
|
242
273
|
readonly isDirty: boolean;
|
|
243
274
|
/**
|
|
244
|
-
*
|
|
275
|
+
* Gets a value from the session.
|
|
245
276
|
*/
|
|
246
277
|
get<T = unknown>(key: string): T | undefined;
|
|
247
278
|
/**
|
|
248
|
-
*
|
|
279
|
+
* Gets all the entries from the session.
|
|
249
280
|
*/
|
|
250
|
-
|
|
281
|
+
all(): Record<string, unknown>;
|
|
251
282
|
/**
|
|
252
|
-
*
|
|
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
|
-
*
|
|
287
|
+
* Deletes a value from the session.
|
|
257
288
|
*/
|
|
258
289
|
delete(key: string): void;
|
|
259
290
|
/**
|
|
260
|
-
*
|
|
291
|
+
* Destroys the session.
|
|
261
292
|
*/
|
|
262
293
|
destroy(): void;
|
|
263
294
|
}
|
|
264
295
|
|
|
265
296
|
declare global {
|
|
266
297
|
/**
|
|
267
|
-
*
|
|
298
|
+
* Creates XSS-unsafed HTML content.
|
|
268
299
|
*/
|
|
269
300
|
var html: JSX.Raw;
|
|
270
301
|
/**
|
|
271
|
-
*
|
|
302
|
+
* An alias to `html`.
|
|
272
303
|
*/
|
|
273
304
|
var css: JSX.Raw;
|
|
274
305
|
/**
|
|
275
|
-
*
|
|
306
|
+
* An alias to `html`.
|
|
276
307
|
*/
|
|
277
308
|
var js: JSX.Raw;
|
|
278
309
|
/**
|
|
279
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
367
|
+
* Creates a computed signal.
|
|
337
368
|
*/
|
|
338
369
|
readonly computed: <T = unknown>(fn: () => T) => T;
|
|
339
370
|
/**
|
|
340
|
-
*
|
|
371
|
+
* A shortcut for `this.computed(fn)`.
|
|
341
372
|
*/
|
|
342
373
|
readonly $: FC["computed"];
|
|
343
374
|
/**
|
|
344
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
397
|
+
* The `<router>` element.
|
|
367
398
|
*/
|
|
368
399
|
type RouterElement = {
|
|
369
400
|
navigate: (url: string | URL, options?: { replace?: boolean }) => Promise<void>;
|