mono-jsx 0.8.1 → 0.9.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.
- package/README.md +32 -21
- package/dom/jsx-runtime.mjs +9 -9
- package/jsx-runtime.mjs +9 -9
- package/package.json +1 -1
- package/types/jsx.d.ts +3 -3
- package/types/mono.d.ts +2 -2
package/README.md
CHANGED
|
@@ -344,7 +344,7 @@ async function Loader(props: { url: string }) {
|
|
|
344
344
|
export default {
|
|
345
345
|
fetch: (req) => (
|
|
346
346
|
<html>
|
|
347
|
-
<Loader url="https://api.example.com/data"
|
|
347
|
+
<Loader url="https://api.example.com/data" pending={<p>Loading...</p>} />
|
|
348
348
|
</html>
|
|
349
349
|
)
|
|
350
350
|
}
|
|
@@ -371,13 +371,13 @@ async function* Chat(props: { prompt: string }) {
|
|
|
371
371
|
export default {
|
|
372
372
|
fetch: (req) => (
|
|
373
373
|
<html>
|
|
374
|
-
<Chat prompt="Tell me a story"
|
|
374
|
+
<Chat prompt="Tell me a story" pending={<span style="color:grey">●</span>} />
|
|
375
375
|
</html>
|
|
376
376
|
)
|
|
377
377
|
}
|
|
378
378
|
```
|
|
379
379
|
|
|
380
|
-
You can use `
|
|
380
|
+
You can use `pending` to display a loading state while waiting for async components to render:
|
|
381
381
|
|
|
382
382
|
```tsx
|
|
383
383
|
async function Sleep({ ms }) {
|
|
@@ -388,7 +388,7 @@ async function Sleep({ ms }) {
|
|
|
388
388
|
export default {
|
|
389
389
|
fetch: (req) => (
|
|
390
390
|
<html>
|
|
391
|
-
<Sleep ms={1000}
|
|
391
|
+
<Sleep ms={1000} pending={<p>Loading...</p>}>
|
|
392
392
|
<p>After 1 second</p>
|
|
393
393
|
</Sleep>
|
|
394
394
|
</html>
|
|
@@ -396,7 +396,7 @@ export default {
|
|
|
396
396
|
}
|
|
397
397
|
```
|
|
398
398
|
|
|
399
|
-
You can set the `rendering` attribute to `"eager"` to force synchronous rendering (the `
|
|
399
|
+
You can set the `rendering` attribute to `"eager"` to force synchronous rendering (the `pending` property will be ignored):
|
|
400
400
|
|
|
401
401
|
```tsx
|
|
402
402
|
export default {
|
|
@@ -441,7 +441,7 @@ function Foo(props: { bar: string }) {
|
|
|
441
441
|
export default {
|
|
442
442
|
fetch: (req) => (
|
|
443
443
|
<html request={req} components={{ Foo }}>
|
|
444
|
-
<component name="Foo" props={{ bar: "baz" }}
|
|
444
|
+
<component name="Foo" props={{ bar: "baz" }} pending={<p>Loading...</p>} />
|
|
445
445
|
</html>
|
|
446
446
|
)
|
|
447
447
|
}
|
|
@@ -453,7 +453,7 @@ You can use the `<component>` element with the `is` prop to render a component b
|
|
|
453
453
|
export default {
|
|
454
454
|
fetch: (req) => (
|
|
455
455
|
<html request={req}>
|
|
456
|
-
<component is={Foo} props={{ bar: "baz" }}
|
|
456
|
+
<component is={Foo} props={{ bar: "baz" }} pending={<p>Loading...</p>} />
|
|
457
457
|
</html>
|
|
458
458
|
)
|
|
459
459
|
}
|
|
@@ -465,7 +465,7 @@ Or you can use the `<component>` element with the `as` prop to render a componen
|
|
|
465
465
|
export default {
|
|
466
466
|
fetch: (req) => (
|
|
467
467
|
<html request={req}>
|
|
468
|
-
<component as={<Foo bar="baz" />}
|
|
468
|
+
<component as={<Foo bar="baz" />} pending={<p>Loading...</p>} />
|
|
469
469
|
</html>
|
|
470
470
|
)
|
|
471
471
|
}
|
|
@@ -487,7 +487,7 @@ function Dash(this: FC<{ page: "Profile" | "Projects" | "Settings" }>) {
|
|
|
487
487
|
<button onClick={() => this.page = "Settings"}>Settings</button>
|
|
488
488
|
</div>
|
|
489
489
|
<div class="page">
|
|
490
|
-
<component name={this.page}
|
|
490
|
+
<component name={this.page} pending={<p>Loading...</p>} />
|
|
491
491
|
</div>
|
|
492
492
|
</>
|
|
493
493
|
)
|
|
@@ -509,7 +509,7 @@ async function Lazy(this: FC<{ show: boolean }>, props: { url: string }) {
|
|
|
509
509
|
return (
|
|
510
510
|
<div>
|
|
511
511
|
<show when={this.show}>
|
|
512
|
-
<component name="Foo" props={{ bar: "baz" }}
|
|
512
|
+
<component name="Foo" props={{ bar: "baz" }} pending={<p>Loading...</p>} />
|
|
513
513
|
</show>
|
|
514
514
|
<button onClick={() => this.show = true }>Load `Foo` Component</button>
|
|
515
515
|
</div>
|
|
@@ -559,11 +559,11 @@ function Counter(
|
|
|
559
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:
|
|
560
560
|
|
|
561
561
|
```tsx
|
|
562
|
-
interface
|
|
562
|
+
interface IAppSignals {
|
|
563
563
|
themeColor: string;
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
function Header(this:
|
|
566
|
+
function Header(this: WithAppSignals<FC, IAppSignals>) {
|
|
567
567
|
return (
|
|
568
568
|
<header>
|
|
569
569
|
<h1 style={{ color: this.app.themeColor }}>Welcome to mono-jsx!</h1>
|
|
@@ -571,7 +571,7 @@ function Header(this: App<FC, AppSignals>) {
|
|
|
571
571
|
)
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
function Footer(this:
|
|
574
|
+
function Footer(this: WithAppSignals<FC, IAppSignals>) {
|
|
575
575
|
return (
|
|
576
576
|
<footer>
|
|
577
577
|
<p style={{ color: this.app.themeColor }}>(c) 2025 mono-jsx.</p>
|
|
@@ -579,7 +579,7 @@ function Footer(this: App<FC, AppSignals>) {
|
|
|
579
579
|
)
|
|
580
580
|
}
|
|
581
581
|
|
|
582
|
-
function Main(this:
|
|
582
|
+
function Main(this: WithAppSignals<FC, IAppSignals>) {
|
|
583
583
|
return (
|
|
584
584
|
<main>
|
|
585
585
|
<p>
|
|
@@ -879,20 +879,31 @@ The `this` object has the following built-in properties:
|
|
|
879
879
|
- `request`: The request object from the `fetch` handler.
|
|
880
880
|
- `session`: The session storage.
|
|
881
881
|
- `refs`: A map of refs defined in the component.
|
|
882
|
-
- `computed`: A method to create a computed signal.
|
|
883
|
-
-
|
|
882
|
+
- `computed(fn)`: A method to create a computed signal.
|
|
883
|
+
- `$(fn)`: A shortcut for `computed(fn)`.
|
|
884
|
+
- `effect(fn)`: A method to create side effects.
|
|
884
885
|
|
|
885
886
|
```ts
|
|
886
|
-
type FC<Signals = {}, Refs = {}
|
|
887
|
+
type FC<Signals = {}, Refs = {}> = {
|
|
887
888
|
readonly app: AppSignals & { refs: AppRefs; url: WithParams<URL> }
|
|
888
889
|
readonly context: Context;
|
|
889
890
|
readonly request: WithParams<Request>;
|
|
890
891
|
readonly session: Session;
|
|
891
892
|
readonly refs: Refs;
|
|
892
893
|
readonly computed: <T = unknown>(fn: () => T) => T;
|
|
893
|
-
readonly $: FC["computed"];
|
|
894
|
+
readonly $: FC["computed"]; // A shortcut for `FC.computed`.
|
|
894
895
|
readonly effect: (fn: () => void | (() => void)) => void;
|
|
895
896
|
} & Signals;
|
|
897
|
+
|
|
898
|
+
// define `AppSignals` type
|
|
899
|
+
function Component(this: WithAppSignals<FC, { title: string }>) {
|
|
900
|
+
this.app.title // type: 'string'
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// define `Context` type
|
|
904
|
+
function Component(this: WithContext<FC, { secret: string }>) {
|
|
905
|
+
this.context.secret // type: 'string'
|
|
906
|
+
}
|
|
896
907
|
```
|
|
897
908
|
|
|
898
909
|
### Using Signals
|
|
@@ -904,7 +915,7 @@ See the [Using Signals](#using-signals) section for more details on how to use s
|
|
|
904
915
|
You can use `this.refs` to access refs in your components. Refs are defined using the `ref` attribute in JSX, and they allow you to access DOM elements directly. The `refs` object is a map of ref names to DOM elements.
|
|
905
916
|
|
|
906
917
|
```tsx
|
|
907
|
-
function App(this:
|
|
918
|
+
function App(this: WithRefs<FC, { input?: HTMLInputElement }>) {
|
|
908
919
|
this.effect(() => {
|
|
909
920
|
this.refs.input?.addEventListener("input", (evt) => {
|
|
910
921
|
console.log("Input changed:", evt.target.value);
|
|
@@ -946,7 +957,7 @@ The `<component>` element also supports the `ref` attribute, which allows you to
|
|
|
946
957
|
```tsx
|
|
947
958
|
import type { ComponentElement } from "mono-jsx";
|
|
948
959
|
|
|
949
|
-
function App(this:
|
|
960
|
+
function App(this: WithRefs<FC, { component: ComponentElement }>) {
|
|
950
961
|
this.effect(() => {
|
|
951
962
|
// updating the component name and props will trigger a re-render of the component
|
|
952
963
|
this.refs.component.name = "Foo";
|
|
@@ -971,7 +982,7 @@ function App(this: Refs<FC, { component: ComponentElement }>) {
|
|
|
971
982
|
You can use the `context` property in `this` to access context values in your components. The context is defined on the root `<html>` element:
|
|
972
983
|
|
|
973
984
|
```tsx
|
|
974
|
-
function Dash(this:
|
|
985
|
+
function Dash(this: WithContext<FC, { auth: { uuid: string; name: string } }>) {
|
|
975
986
|
const { auth } = this.context;
|
|
976
987
|
return (
|
|
977
988
|
<div>
|
package/dom/jsx-runtime.mjs
CHANGED
|
@@ -543,28 +543,28 @@ var renderFC = (fc, props, root, abortSignal) => {
|
|
|
543
543
|
call$expr(scope, true);
|
|
544
544
|
v = fc.call(scope, props);
|
|
545
545
|
if (v instanceof Promise) {
|
|
546
|
-
let
|
|
547
|
-
if (isVNode(props.
|
|
548
|
-
|
|
546
|
+
let pendingNodes;
|
|
547
|
+
if (isVNode(props.pending)) {
|
|
548
|
+
pendingNodes = [...renderToFragment(scope, props.pending, abortSignal).childNodes];
|
|
549
549
|
}
|
|
550
|
-
if (!
|
|
551
|
-
|
|
550
|
+
if (!pendingNodes?.length) {
|
|
551
|
+
pendingNodes = [createTextNode()];
|
|
552
552
|
}
|
|
553
|
-
root.append(...
|
|
553
|
+
root.append(...pendingNodes);
|
|
554
554
|
v.then((nodes) => {
|
|
555
555
|
call$expr(scope, false);
|
|
556
|
-
|
|
556
|
+
pendingNodes[0].replaceWith(...renderToFragment(scope, nodes, abortSignal).childNodes);
|
|
557
557
|
}).catch((err) => {
|
|
558
558
|
if (isFunction(props.catch)) {
|
|
559
559
|
const v2 = props.catch(err);
|
|
560
560
|
if (isVNode(v2)) {
|
|
561
|
-
|
|
561
|
+
pendingNodes[0].replaceWith(...renderToFragment(scope, v2, abortSignal).childNodes);
|
|
562
562
|
}
|
|
563
563
|
} else {
|
|
564
564
|
console.error(err);
|
|
565
565
|
}
|
|
566
566
|
}).finally(() => {
|
|
567
|
-
|
|
567
|
+
pendingNodes.forEach((node) => node.remove());
|
|
568
568
|
});
|
|
569
569
|
} else {
|
|
570
570
|
call$expr(scope, false);
|
package/jsx-runtime.mjs
CHANGED
|
@@ -26,7 +26,7 @@ var STYLE_JS = `{var f=/^(-|f[lo].*[^se]$|g.{5,}[^ps]$|z|o[pr]|(W.{5})?[lL]i.*(t
|
|
|
26
26
|
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;}`;
|
|
27
27
|
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;}`;
|
|
28
28
|
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;}`;
|
|
29
|
-
var SIGNALS_JS = `{let h;const
|
|
29
|
+
var SIGNALS_JS = `{let h;const a=window,b=document,y=new Map,E=new Map,k=new Map,v=new Map,$=new Map,m=new Map,l=n=>y.get(n)??y.set(n,V(n)).get(n),F=()=>Object.create(null),p=(n,e)=>n.getAttribute(e),V=n=>{const e=F(),t=(o,c)=>{e[o]=c},s=new Map,r=(o,c)=>{let u=s.get(o);return u||(u=new Set,s.set(o,u)),u.add(c),()=>{u.delete(c),u.size===0&&s.delete(o)}},i=new Proxy(F(),{get:(o,c)=>b.querySelector("[data-ref='"+n+":"+c+"']")});return new Proxy(e,{get:(o,c,u)=>{switch(c){case"$init":return t;case"$watch":return r;case"app":return l(0);case"refs":return i;default:return h?.(n,c),Reflect.get(o,c,u)}},set:(o,c,u,g)=>{if(u!==Reflect.get(o,c,g)){const f=s.get(c);return f&&queueMicrotask(()=>f.forEach(d=>d())),Reflect.set(o,c,u,g)}return!1}})},M=(n,e,t)=>{switch(e){case"toggle":return $renderToggle(n,t);case"switch":return $renderSwitch(n,t);case"html":return()=>n.innerHTML=""+t()}if(e&&e.length>2&&e.startsWith("[")&&e.endsWith("]"))return $renderAttr(n,e.slice(1,-1),t);const s=n.parentElement,r=()=>n.textContent=""+t();if(b.startViewTransition&&s.hasAttribute("data-vt")){const i=s.getAttribute("data-vt");return i&&(s.style.viewTransitionName=i),()=>b.startViewTransition(r)}return r},S=n=>{const e=n.indexOf(":");return e>0?[Number(n.slice(0,e)),n.slice(e+1)]:null},q=(n,e,t,s)=>{const r=n.get(t);if(r!==void 0){s(r);return}const i=e.get(t);i?i.push(s):e.set(t,[s])},N=(n,e)=>{const t=a.$fmap?.get(n);if(t){e(t);return}const s=m.get(n);s?s.push(e):m.set(n,[e])};if(typeof a.$F=="function"){const n=a.$F;a.$F=(e,t)=>{n(e,t);const s=m.get(e);s&&(m.delete(e),s.forEach(r=>r(t)))}}const T=n=>typeof n=="function"&&n(),A=(n,e)=>customElements.define(n,class extends HTMLElement{disposes=[];connectedCallback(){e(this)}disconnectedCallback(){this.disposes.forEach(t=>t()),this.disposes.length=0}});A("m-signal",n=>{const e=Number(p(n,"scope")),t=l(e),s=p(n,"key");if(s)n.disposes.push(t.$watch(s,M(n,p(n,"mode"),()=>t[s])));else{const r=Number(p(n,"computed")),i=e+":"+r;q(E,v,i,o=>{N(r,c=>{const u=M(n,p(n,"mode"),c.bind(t));o.forEach(g=>{const[f,d]=S(g);n.disposes.push(l(f).$watch(d,u))})})})}}),A("m-effect",n=>{const{disposes:e}=n,t=Number(p(n,"scope"));q(k,$,t,s=>{const r=s.length,i=new Array(r);e.push(()=>{i.forEach(T),i.length=0});for(let o=0;o<r;o++)N(s[o],c=>{const u=[],g=l(t),f=()=>{T(i[o]),i[o]=c.call(g)};h=(d,w)=>u.push([d,w]),f(),h=void 0;for(const[d,w]of u)e.push(l(d).$watch(w,f))})})}),a.$S=(n,e)=>{const[t,s]=S(n);l(t).$init(s,e)},a.$C=(n,e,t)=>{const s=n+":"+e;E.set(s,t);const r=v.get(s);r&&(v.delete(s),r.forEach(i=>i(t)))},a.$E=(n,...e)=>{k.set(n,e);const t=$.get(n);t&&($.delete(n),t.forEach(s=>s(e)))},a.$patch=(n,...e)=>{for(const[t,...s]of e){let r=s.pop(),i=n;for(const o of s)i=i[o];i[r]=t}return n},a.$signals=n=>n!==void 0?l(n):void 0;}`;
|
|
30
30
|
var SUSPENSE_JS = `{const i=new Map,o=e=>e.getAttribute("chunk-id"),l=(e,t)=>customElements.define(e,class extends HTMLElement{connectedCallback(){t(this)}});l("m-portal",e=>{i.set(o(e),e)}),l("m-chunk",e=>{setTimeout(()=>{const t=o(e),n=i.get(t),s=e.firstChild?.content.childNodes;n&&(e.hasAttribute("next")?s&&n.before(...s):(e.hasAttribute("done")?n.remove():s&&n.replaceWith(...s),i.delete(t)),e.remove())})});}`;
|
|
31
31
|
var COMPONENT_JS = `{const e=document,a=(t,s)=>t.getAttribute(s);customElements.define("m-component",class extends HTMLElement{static observedAttributes=["name","props"];#t;#s;#r;#h;#i;#e=new Map;#a=!0;async#l(){if(!this.#t){this.#n("");return}const t=this.#s||"{}",s=this.#t+t,i={"x-component":this.#t,"x-props":t,"x-flags":$FLAGS},n=new AbortController;if(this.#h?.abort(),this.#h=n,this.#e.has(s)){this.#n(this.#e.get(s));return}this.#r?.length&&this.#n(this.#r);const r=await fetch(location.href,{headers:i,signal:n.signal});if(!r.ok)throw this.#n(""),new Error("Failed to fetch component '"+this.#t+"'");const[h,o]=await r.json();this.#e.set(s,h),this.#n(h),o&&(e.body.appendChild(e.createElement("script")).textContent=o)}#n(t){const s=()=>typeof t=="string"?this.innerHTML=t:this.replaceChildren(...t);this.hasAttribute("vt")&&e.startViewTransition&&!this.#a?e.startViewTransition(s):s(),this.#a=!1}get name(){return this.#t??null}set name(t){t&&t!==this.#t&&(this.#t=t,this.#o())}get props(){return this.#s?JSON.parse(this.#s):void 0}set props(t){const s=typeof t=="string"?t:JSON.stringify(t);s&&s!==this.#s&&(this.#s=s,this.#o())}attributeChangedCallback(t,s,i){this.#t&&i&&(t==="name"?this.name=i:t==="props"&&(this.props=i))}connectedCallback(){setTimeout(()=>{if(!this.#r){const t=a(this,"props");this.#t=a(this,"name"),this.#s=t?.startsWith("base64,")?atob(t.slice(7)):void 0,this.#r=[...this.childNodes]}this.#l()})}disconnectedCallback(){this.#e.clear(),this.#h?.abort(),this.#h=void 0,this.#i&&clearTimeout(this.#i),this.#i=void 0}#o(){this.#i&&clearTimeout(this.#i),this.#i=setTimeout(()=>{this.#i=void 0,this.#l()},50)}refresh(){this.#t&&this.#e.delete(this.#t+(this.#s||"{}")),this.#o()}});}`;
|
|
32
32
|
var ROUTER_JS = `{const n=document,a=location,o=t=>t.split("#",1)[0],l=t=>o(t)===o(a.href);customElements.define("m-router",class extends HTMLElement{#t;#s;#i;#n;#e=new Map;#r=!0;async#c(t){const s=new AbortController,i={"x-route":"true","x-flags":$FLAGS};this.#n?.abort(),this.#n=s;const e=await fetch(t,{headers:i,signal:s.signal});if(e.status===404)return null;if(!e.ok)throw this.replaceChildren(),new Error("Failed to fetch route: "+e.status+" "+e.statusText);return e.json()}#a(t){const s=()=>typeof t=="string"?this.innerHTML=t:this.replaceChildren(...t);this.hasAttribute("vt")&&n.startViewTransition&&!this.#r?n.startViewTransition(s):s(),this.#r=!1}#o(){n.querySelectorAll("nav a").forEach(t=>{const{href:s,classList:i}=t,e=t.closest("nav")?.getAttribute("data-active-class")??"active";l(s)?i.add(e):i.remove(e)})}async#l(t,s){const i=this.#c(t).then(e=>{if(e){const[r,c]=e;return this.#e.set(t,r),this.#a(r),c}else this.#e.delete(t),this.#a(this.#t??[]),typeof $signals<"u"&&($signals(0).url=new URL(t))});this.#e.has(t)?this.#a(this.#e.get(t)):await i,history[s?.replace?"replaceState":"pushState"]({},"",t),this.#o(),window.scrollTo(0,0),i.then(e=>{e&&(n.body.appendChild(n.createElement("script")).textContent=e)})}navigate(t,s){const i=new URL(t,a.href);if(i.origin!==a.origin){a.href=t;return}l(i.href)||this.#l(t,s)}connectedCallback(){setTimeout(()=>{if(!this.#t)if(this.hasAttribute("fallback"))this.removeAttribute("fallback"),this.#t=[...this.childNodes];else{this.#t=[];for(const t of this.childNodes)if(t.nodeType===1&&t.tagName==="TEMPLATE"&&t.hasAttribute("m-fallback")){this.#t.push(...t.content.childNodes),t.remove();break}}}),this.#s=t=>{if(t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey||!(t.target instanceof HTMLAnchorElement))return;const{download:s,href:i,rel:e,target:r}=t.target;s||e==="external"||r==="_blank"||!i.startsWith(a.origin)||(t.preventDefault(),this.navigate(i))},this.#i=()=>this.#l(a.href),addEventListener("popstate",this.#i),n.addEventListener("click",this.#s),setTimeout(()=>this.#o()),globalThis.$router=this}disconnectedCallback(){removeEventListener("popstate",this.#i),n.removeEventListener("click",this.#s),delete globalThis.$router,this.#n?.abort(),this.#n=void 0,this.#e.clear(),this.#s=void 0,this.#i=void 0}});}`;
|
|
@@ -176,7 +176,7 @@ var $vnode = Symbol.for("jsx.vnode");
|
|
|
176
176
|
var $setup = Symbol.for("mono.setup");
|
|
177
177
|
|
|
178
178
|
// version.ts
|
|
179
|
-
var VERSION = "0.8.
|
|
179
|
+
var VERSION = "0.8.2";
|
|
180
180
|
|
|
181
181
|
// render.ts
|
|
182
182
|
var FunctionIdGenerator = class extends Map {
|
|
@@ -681,7 +681,7 @@ async function renderNode(rc, node, stripSlotProp) {
|
|
|
681
681
|
}
|
|
682
682
|
// `<component>` element
|
|
683
683
|
case "component": {
|
|
684
|
-
let {
|
|
684
|
+
let { pending, is, as } = props;
|
|
685
685
|
let attrs = "";
|
|
686
686
|
let attrModifiers = "";
|
|
687
687
|
let writeAttr = (propName, propValue = props[propName]) => {
|
|
@@ -710,11 +710,11 @@ async function renderNode(rc, node, stripSlotProp) {
|
|
|
710
710
|
writeAttr("ref");
|
|
711
711
|
attrs += renderViewTransitionAttr(props);
|
|
712
712
|
let buf = "<m-component" + attrs + ">";
|
|
713
|
-
if (
|
|
713
|
+
if (pending) {
|
|
714
714
|
const write2 = (chunk) => {
|
|
715
715
|
buf += chunk;
|
|
716
716
|
};
|
|
717
|
-
await renderChildren({ ...rc, write: write2 },
|
|
717
|
+
await renderChildren({ ...rc, write: write2 }, pending);
|
|
718
718
|
}
|
|
719
719
|
buf += "</m-component>";
|
|
720
720
|
if (attrModifiers) {
|
|
@@ -927,8 +927,8 @@ async function renderFC(rc, fcFn, props, eager) {
|
|
|
927
927
|
} else {
|
|
928
928
|
const chunkIdAttr = 'chunk-id="' + (rc.flags.chunk++).toString(36) + '"';
|
|
929
929
|
write("<m-portal " + chunkIdAttr + ">");
|
|
930
|
-
if (props.
|
|
931
|
-
await renderNode(rc, props.
|
|
930
|
+
if (props.pending) {
|
|
931
|
+
await renderNode(rc, props.pending);
|
|
932
932
|
}
|
|
933
933
|
write("</m-portal>");
|
|
934
934
|
rc.suspenses.push(v.then(async (node) => {
|
|
@@ -951,8 +951,8 @@ async function renderFC(rc, fcFn, props, eager) {
|
|
|
951
951
|
} else {
|
|
952
952
|
const chunkIdAttr = 'chunk-id="' + (rc.flags.chunk++).toString(36) + '"';
|
|
953
953
|
write("<m-portal " + chunkIdAttr + ">");
|
|
954
|
-
if (props.
|
|
955
|
-
await renderNode(rc, props.
|
|
954
|
+
if (props.pending) {
|
|
955
|
+
await renderNode(rc, props.pending);
|
|
956
956
|
}
|
|
957
957
|
write("</m-portal>");
|
|
958
958
|
const iter = () => rc.suspenses.push(
|
package/package.json
CHANGED
package/types/jsx.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface AsyncComponentAttributes {
|
|
|
38
38
|
/**
|
|
39
39
|
* The loading spinner for an async component.
|
|
40
40
|
*/
|
|
41
|
-
|
|
41
|
+
pending?: JSX.Element;
|
|
42
42
|
/**
|
|
43
43
|
* Rendering mode of an async component.
|
|
44
44
|
* - `eager`: render async components eagerly
|
|
@@ -106,12 +106,12 @@ declare global {
|
|
|
106
106
|
effect(fn: () => (() => void) | void): void;
|
|
107
107
|
}
|
|
108
108
|
& FCExtension<FC>
|
|
109
|
-
& Omit<Omit<Signals, "
|
|
109
|
+
& Omit<Omit<Signals, "refs" | "init" | "computed" | "$" | "effect">, keyof FCExtension>;
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
112
|
* Defines the `this.refs` type.
|
|
113
113
|
*/
|
|
114
|
-
type
|
|
114
|
+
type WithRefs<T, R extends {}> = T extends FC<infer S> ? FC<S, R> : never;
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
117
|
* The JSX namespace object.
|
package/types/mono.d.ts
CHANGED
|
@@ -279,7 +279,7 @@ declare global {
|
|
|
279
279
|
/**
|
|
280
280
|
* Defines the `this.app` type.
|
|
281
281
|
*/
|
|
282
|
-
type
|
|
282
|
+
type WithAppSignals<T, AppSignals = {}, AppRefs = Record<string, HTMLElement>> = T extends FC<infer S, infer R> ? FC<S, R> & {
|
|
283
283
|
/**
|
|
284
284
|
* The global signals shared across the application.
|
|
285
285
|
*/
|
|
@@ -302,7 +302,7 @@ declare global {
|
|
|
302
302
|
/**
|
|
303
303
|
* Defines the `this.context` type.
|
|
304
304
|
*/
|
|
305
|
-
type
|
|
305
|
+
type WithContext<T, Context = {}> = T extends FC<infer S, infer R> ? FC<S, R> & {
|
|
306
306
|
/**
|
|
307
307
|
* The rendering context object.
|
|
308
308
|
*
|