mono-jsx 0.6.11 → 0.6.12

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
@@ -543,6 +543,15 @@ function App(this: FC<{ value: string }>) {
543
543
  }
544
544
  ```
545
545
 
546
+ You can also use the `$checked` attribute to bind a signal to the checked state of a checkbox or radio input element.
547
+
548
+ ```tsx
549
+ function App(this: FC<{ checked: boolean }>) {
550
+ this.checked = false;
551
+ return <input type="checkbox" $checked={this.checked} />;
552
+ }
553
+ ```
554
+
546
555
  ### Limitation of Signals
547
556
 
548
557
  1\. Arrow function are non-stateful components.
@@ -1063,6 +1072,38 @@ export default {
1063
1072
  }
1064
1073
  ```
1065
1074
 
1075
+ ## Using View Transition
1076
+
1077
+ mono-jsx supports [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) to create smooth transitions between views. To use view transition, add `viewTransition` attribute to below components:
1078
+
1079
+ - `<toggle viewTransition="transition-name">`
1080
+ - `<switch viewTransition="transition-name">`
1081
+ - `<component viewTransition="transition-name">`
1082
+ - `<router viewTransition="transition-name">`
1083
+
1084
+ You can set custom transition animation by adding [`::view-transition-group`](https://developer.mozilla.org/en-US/docs/Web/CSS/::view-transition-group) and [`::view-transition-old`](https://developer.mozilla.org/en-US/docs/Web/CSS/::view-transition-old) and [`::view-transition-new`](https://developer.mozilla.org/en-US/docs/Web/CSS/::view-transition-new) pseudo-elements with your own CSS animation. For example,
1085
+
1086
+ ```tsx
1087
+ function App(this: FC<{ show: boolean }>) {
1088
+ return (
1089
+ <div
1090
+ style={{
1091
+ "@keyframes fade-in": { from: { opacity: 0 }, to: { opacity: 1 } },
1092
+ "@keyframes fade-out": { from: { opacity: 1 }, to: { opacity: 0 } },
1093
+ "::view-transition-group(fade)": { animationDuration: "0.5s" },
1094
+ "::view-transition-old(fade)": { animation: "0.5s ease-in both fade-out" },
1095
+ "::view-transition-new(fade)": { animation: "0.5s ease-in both fade-in" },
1096
+ }}
1097
+ >
1098
+ <toggle show={this.show} viewTransition="fade">
1099
+ <h1>Hello world!</h1>
1100
+ </toggle>
1101
+ <button onClick={() => this.show = !this.show}>Toggle</button>
1102
+ </div>
1103
+ )
1104
+ }
1105
+ ```
1106
+
1066
1107
  ## Customizing html Response
1067
1108
 
1068
1109
  You can add `status` or `headers` attributes to the root `<html>` element to customize the http response:
package/jsx-runtime.mjs CHANGED
@@ -11,14 +11,14 @@ var LAZY = 256;
11
11
  var ROUTER = 512;
12
12
  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)};}`;
13
13
  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;}`;
14
- var STYLE_JS = `{var a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;var l=e=>typeof e=="string";var u=e=>e.replace(/[a-z][A-Z]/g,r=>r.charAt(0)+"-"+r.charAt(1).toLowerCase());var p=e=>{let r=[],t=[],n=new g;for(let[o,s]of Object.entries(e))switch(o.charCodeAt(0)){case 58:t.push(null,o+"{"+c(s)+"}");break;case 64:t.push(o+"{",null,"{"+c(s)+"}}");break;case 38:t.push(null,o.slice(1)+"{"+c(s)+"}");break;default:r.push([o,s])}return r.length>0&&(n.inline=c(r)),t.length>0&&(n.css=t),n},f=(e,r)=>{let{inline:t,css:n}=p(r);if(n){let o="data-css-",s="["+o+(Date.now()+Math.random()).toString(36).replace(".","")+"]";document.head.appendChild(document.createElement("style")).textContent=(t?s+"{"+t+"}":"")+n.map(i=>i===null?s:i).join(""),e.getAttributeNames().forEach(i=>i.startsWith(o)&&e.removeAttribute(i)),e.setAttribute(s.slice(1,-1),"")}else t&&e.setAttribute("style",t)},c=e=>{if(typeof e=="object"&&e!==null){let r="";for(let[t,n]of Array.isArray(e)?e:Object.entries(e))if(l(n)||typeof n=="number"){let o=u(t),s=typeof n=="number"?a.test(t)?""+n:n+"px":""+n;r+=(r?";":"")+o+":"+(o==="content"?JSON.stringify(s):s)}return r}return""},g=(()=>{function e(){}return e.prototype=Object.freeze(Object.create(null)),e})();window.$applyStyle=f;}`;
14
+ 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
15
  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;}`;
16
- var RENDER_TOGGLE_JS = `{var r=(n,l)=>{let e;return()=>{if(!e){let t=n.firstElementChild;t&&t.tagName==="TEMPLATE"&&t.hasAttribute("m-slot")?e=[...t.content.childNodes]:e=[...n.childNodes]}n.replaceChildren(...l()?e:[])}};window.$renderToggle=r;}`;
17
- var RENDER_SWITCH_JS = `{var u=(r,d)=>{let s,i=r.getAttribute("value"),t,l,o=e=>t.get(e)??t.set(e,[]).get(e);return()=>{if(!t){t=new Map,l=[];for(let e of r.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):l.push(n);e.remove()}else i?o(i).push(e):l.push(e)}s=""+d(),r.replaceChildren(...t.has(s)?t.get(s):l)}};window.$renderSwitch=u;}`;
16
+ 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;}`;
17
+ 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;}`;
18
18
  var SIGNALS_JS = `{let m;const h=window,b=new Map,k=new Map,l=n=>k.get(n)??k.set(n,M(n)).get(n),y=()=>Object.create(null),f=(n,e)=>n.getAttribute(e),M=n=>{const e=y(),t=(r,c)=>{e[r]=c},s=new Map,a=(r,c)=>{let o=s.get(r);return o||(o=new Set,s.set(r,o)),o.add(c),()=>{o.delete(c),o.size===0&&s.delete(r)}},i=new Proxy(y(),{get:(r,c)=>document.querySelector("[data-ref='"+n+":"+c+"']")});return new Proxy(e,{get:(r,c,o)=>{switch(c){case"$init":return t;case"$watch":return a;case"app":return l(0);case"refs":return i;default:return m?.(n,c),Reflect.get(r,c,o)}},set:(r,c,o,d)=>{if(o!==Reflect.get(r,c,d)){const u=s.get(c);return u&&queueMicrotask(()=>u.forEach(g=>g())),Reflect.set(r,c,o,d)}return!1}})},$=(n,e,t)=>{switch(e){case"toggle":return $renderToggle(n,t);case"switch":return $renderSwitch(n,t);case"html":return()=>n.innerHTML=""+t()}return e&&e.length>2&&e.startsWith("[")&&e.endsWith("]")?$renderAttr(n,e.slice(1,-1),t):()=>n.textContent=""+t()},E=n=>{const e=n.indexOf(":");return e>0?[Number(n.slice(0,e)),n.slice(e+1)]:null},p=async n=>{const e=n();return e!==void 0?e:(await new Promise(t=>setTimeout(t,0)),p(n))},S=n=>{typeof n=="function"&&n()},v=(n,e)=>customElements.define(n,class extends HTMLElement{disposes=[];connectedCallback(){e(this)}disconnectedCallback(){this.disposes.forEach(t=>t()),this.disposes.length=0}});v("m-signal",n=>{const e=Number(f(n,"scope")),t=l(e),s=f(n,"key");if(s)n.disposes.push(t.$watch(s,$(n,f(n,"mode"),()=>t[s])));else{const a=Number(f(n,"computed"));p(()=>b.get(e*1e9+a)).then(([i,r])=>{const c=$(n,f(n,"mode"),i.bind(t));r.forEach(o=>{const[d,u]=E(o);n.disposes.push(l(d).$watch(u,c))})})}}),v("m-effect",n=>{const{disposes:e}=n,t=Number(f(n,"scope")),s=Number(f(n,"n")),a=new Array(s);e.push(()=>{a.forEach(S),a.length=0});for(let i=0;i<s;i++){const r="$ME_"+t+"_"+i;p(()=>h[r]).then(c=>{const o=[],d=l(t),u=()=>{S(a[i]),a[i]=c.call(d)};m=(g,w)=>o.push([g,w]),u(),m=void 0;for(const[g,w]of o)e.push(l(g).$watch(w,u))},()=>{})}}),h.$MS=(n,e)=>{const[t,s]=E(n);l(t).$init(s,e)},h.$MC=(n,e,t,s)=>{b.set(n*1e9+e,[t,s])},h.$patch=(n,...e)=>{for(const[t,...s]of e){const a=s.pop();let i=n;for(const r of s)i=i[r];i[a]=t}return n},h.$signals=n=>n!==void 0?l(n):void 0;}`;
19
19
  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())})});}`;
20
- var LAZY_JS = `{const r=document,o=(t,s)=>t.getAttribute(s),i=(t,s=[])=>t.replaceChildren(...s);customElements.define("m-component",class extends HTMLElement{static observedAttributes=["name","props"];#t;#e;#i;#n;#s;async#r(){if(!this.#t){i(this);return}const t={"x-component":this.#t,"x-props":this.#e||"{}","x-flags":$FLAGS},s=new AbortController;this.#n?.abort(),this.#n=s,i(this,this.#i);const e=await fetch(location.href,{headers:t,signal:s.signal});if(!e.ok)throw i(this),new Error("Failed to fetch component '"+this.#t+"'");const[h,n]=await e.json();this.innerHTML=h,n&&(r.body.appendChild(r.createElement("script")).textContent=n)}get name(){return this.#t??null}set name(t){t&&t!==this.#t&&(this.#t=t,this.refresh())}get props(){return this.#e?JSON.parse(this.#e):void 0}set props(t){const s=typeof t=="string"?t:JSON.stringify(t);s&&s!==this.#e&&(this.#e=s,this.refresh())}connectedCallback(){setTimeout(()=>{if(!this.#i){const t=o(this,"props");this.#t=o(this,"name"),this.#e=t?.startsWith("base64,")?atob(t.slice(7)):void 0,this.#i=[...this.childNodes]}this.#r()})}disconnectedCallback(){i(this,this.#i),this.#n?.abort(),this.#n=void 0,this.#s&&clearTimeout(this.#s),this.#s=void 0}attributeChangedCallback(t,s,e){this.#t&&e&&(t==="name"?this.name=e:t==="props"&&(this.props=e))}refresh(){this.#s&&clearTimeout(this.#s),this.#s=setTimeout(()=>{this.#s=void 0,this.#r()},50)}});}`;
21
- var ROUTER_JS = `{const a=document,n=location,l=t=>t.split("#",1)[0],c=t=>l(t)===l(n.href);customElements.define("m-router",class extends HTMLElement{#t;#e;#s;#i;async#o(t){const s=new AbortController,e={"x-route":"true","x-flags":$FLAGS};this.#i?.abort(),this.#i=s;const i=await fetch(t,{headers:e,signal:s.signal});if(i.status===404)return this.replaceChildren(...this.#t),!0;if(!i.ok)throw this.replaceChildren(),new Error("Failed to fetch route: "+i.status+" "+i.statusText);const[o,r]=await i.json();this.innerHTML=o,r&&(a.body.appendChild(a.createElement("script")).textContent=r)}#n(){a.querySelectorAll("nav a").forEach(t=>{const{href:s,classList:e}=t,i=t.closest("nav")?.getAttribute("data-active-class")??"active";c(s)?e.add(i):e.remove(i)})}navigate(t,s){const e=new URL(t,n.href);if(e.origin!==n.origin){n.href=t;return}c(e.href)||this.#a(t,s)}async#a(t,s){const e=await this.#o(t);s?.replace?history.replaceState({},"",t):history.pushState({},"",t),e&&typeof $signals<"u"&&($signals(0).url=new URL(t)),this.#n(),window.scrollTo(0,0)}connectedCallback(){setTimeout(()=>{if(!this.#t)if(this.getAttribute("status")==="404")this.#t=[...this.childNodes];else{this.#t=[];for(const t of this.childNodes)if(t.nodeType===1&&t.tagName==="TEMPLATE"&&t.hasAttribute("m-slot")){this.#t.push(...t.content.childNodes),t.remove();break}}}),this.#e=t=>{if(t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey||!(t.target instanceof HTMLAnchorElement))return;const{download:s,href:e,rel:i,target:o}=t.target;s||i==="external"||o==="_blank"||!e.startsWith(n.origin)||(t.preventDefault(),this.navigate(e))},this.#s=()=>this.#a(n.href),addEventListener("popstate",this.#s),a.addEventListener("click",this.#e),setTimeout(()=>this.#n())}disconnectedCallback(){removeEventListener("popstate",this.#s),a.removeEventListener("click",this.#e),this.#i?.abort(),this.#i=void 0,this.#e=void 0,this.#s=void 0}});}`;
20
+ var LAZY_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()}});}`;
21
+ var ROUTER_JS = `{const n=document,a=location,l=t=>t.split("#",1)[0],c=t=>l(t)===l(a.href);customElements.define("m-router",class extends HTMLElement{#t;#e;#s;#i;#n=new Map;#r=!0;async#c(t){this.#n.has(t)&&this.#a(this.#n.get(t));const e=new AbortController,s={"x-route":"true","x-flags":$FLAGS};this.#i?.abort(),this.#i=e;const i=await fetch(t,{headers:s,signal:e.signal});if(i.status===404)return this.#a(this.#t??[]),404;if(!i.ok)throw this.replaceChildren(),new Error("Failed to fetch route: "+i.status+" "+i.statusText);const[r,o]=await i.json();this.#n.set(t,r),this.#a(r),o&&(n.body.appendChild(n.createElement("script")).textContent=o)}#a(t){const e=()=>typeof t=="string"?this.innerHTML=t:this.replaceChildren(...t);this.hasAttribute("vt")&&n.startViewTransition&&!this.#r?n.startViewTransition(e):e(),this.#r=!1}#o(){n.querySelectorAll("nav a").forEach(t=>{const{href:e,classList:s}=t,i=t.closest("nav")?.getAttribute("data-active-class")??"active";c(e)?s.add(i):s.remove(i)})}async#l(t,e){const s=await this.#c(t)===404;e?.replace?history.replaceState({},"",t):history.pushState({},"",t),s&&typeof $signals<"u"&&($signals(0).url=new URL(t)),this.#o(),window.scrollTo(0,0)}navigate(t,e){const s=new URL(t,a.href);if(s.origin!==a.origin){a.href=t;return}c(s.href)||this.#l(t,e)}connectedCallback(){setTimeout(()=>{if(!this.#t)if(this.getAttribute("status")==="404")this.#t=[...this.childNodes];else{this.#t=[];for(const t of this.childNodes)if(t.nodeType===1&&t.tagName==="TEMPLATE"&&t.hasAttribute("m-slot")){this.#t.push(...t.content.childNodes),t.remove();break}}}),this.#e=t=>{if(t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey||!(t.target instanceof HTMLAnchorElement))return;const{download:e,href:s,rel:i,target:r}=t.target;e||i==="external"||r==="_blank"||!s.startsWith(a.origin)||(t.preventDefault(),this.navigate(s))},this.#s=()=>this.#l(a.href),addEventListener("popstate",this.#s),n.addEventListener("click",this.#e),setTimeout(()=>this.#o())}disconnectedCallback(){removeEventListener("popstate",this.#s),n.removeEventListener("click",this.#e),this.#i?.abort(),this.#i=void 0,this.#n.clear(),this.#e=void 0,this.#s=void 0}});}`;
22
22
 
23
23
  // runtime/utils.ts
24
24
  var regexpCssBareUnitProps = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
@@ -46,11 +46,17 @@ var styleToCSS = (style) => {
46
46
  switch (k.charCodeAt(0)) {
47
47
  case /* ':' */
48
48
  58:
49
- css.push(null, k + "{" + renderStyle(v) + "}");
49
+ css.push(k.startsWith("::view-") ? "" : null, k + "{" + renderStyle(v) + "}");
50
50
  break;
51
51
  case /* '@' */
52
52
  64:
53
- css.push(k + "{", null, "{" + renderStyle(v) + "}}");
53
+ if (k.startsWith("@keyframes ") || k.startsWith("@view-")) {
54
+ if (isObject(v)) {
55
+ css.push(k + "{" + Object.entries(v).map(([k2, v2]) => k2 + "{" + renderStyle(v2) + "}").join("") + "}");
56
+ }
57
+ } else {
58
+ css.push(k + "{", null, "{" + renderStyle(v) + "}}");
59
+ }
54
60
  break;
55
61
  case /* '&' */
56
62
  38:
@@ -135,7 +141,7 @@ var $signal = Symbol.for("mono.signal");
135
141
  var $vnode = Symbol.for("jsx.vnode");
136
142
 
137
143
  // version.ts
138
- var VERSION = "0.6.10";
144
+ var VERSION = "0.6.11";
139
145
 
140
146
  // render.ts
141
147
  var cdn = "https://raw.esm.sh";
@@ -434,7 +440,7 @@ async function renderNode(rc, node, stripSlotProp) {
434
440
  case "object":
435
441
  if (node === null) {
436
442
  } else if (isSignal(node)) {
437
- renderSignal(rc, node, void 0, node[$signal].value);
443
+ rc.write(renderSignal(rc, node));
438
444
  } else if (isVNode(node)) {
439
445
  const [tag, props] = node;
440
446
  switch (tag) {
@@ -450,7 +456,7 @@ async function renderNode(rc, node, stripSlotProp) {
450
456
  const { innerHTML } = props;
451
457
  if (innerHTML) {
452
458
  if (isSignal(innerHTML)) {
453
- renderSignal(rc, innerHTML, "html", String(innerHTML[$signal].value), true);
459
+ rc.write(renderSignal(rc, innerHTML, "html"));
454
460
  } else {
455
461
  write(innerHTML);
456
462
  }
@@ -476,7 +482,7 @@ async function renderNode(rc, node, stripSlotProp) {
476
482
  }
477
483
  // `<toggle>` element
478
484
  case "toggle": {
479
- let { show, hidden, children } = props;
485
+ let { show, hidden, viewTransition, children } = props;
480
486
  if (children !== void 0) {
481
487
  if (show === void 0 && hidden !== void 0) {
482
488
  if (isSignal(hidden)) {
@@ -498,13 +504,8 @@ async function renderNode(rc, node, stripSlotProp) {
498
504
  }
499
505
  }
500
506
  if (isSignal(show)) {
501
- const { scope, key, value } = show[$signal];
502
- let buf = '<m-signal mode="toggle" scope="' + scope + '" ';
503
- if (isString(key)) {
504
- buf += "key=" + toAttrStringLit(key) + ">";
505
- } else {
506
- buf += 'computed="' + rc.mcs.gen(show, rc.fcCtx?.scopeId) + '">';
507
- }
507
+ const { value } = show[$signal];
508
+ let buf = renderSignal(rc, show, "toggle", false).slice(0, -1) + renderViewTransitionAttr(viewTransition) + ">";
508
509
  if (!value) {
509
510
  buf += "<template m-slot>";
510
511
  }
@@ -520,19 +521,14 @@ async function renderNode(rc, node, stripSlotProp) {
520
521
  }
521
522
  // `<switch>` element
522
523
  case "switch": {
523
- const { value: valueProp, children } = props;
524
+ const { value: valueProp, viewTransition, children } = props;
524
525
  if (children !== void 0) {
525
526
  let slots = Array.isArray(children) ? isVNode(children) ? [children] : children : [children];
526
- let stateful;
527
+ let signalHtml;
527
528
  let toSlotName;
528
529
  if (isSignal(valueProp)) {
529
- const { scope, key, value } = valueProp[$signal];
530
- stateful = '<m-signal mode="switch" scope="' + scope + '" ';
531
- if (isString(key)) {
532
- stateful += "key=" + toAttrStringLit(key) + ">";
533
- } else {
534
- stateful += 'computed="' + rc.mcs.gen(valueProp, rc.fcCtx?.scopeId) + '">';
535
- }
530
+ const { value } = valueProp[$signal];
531
+ signalHtml = renderSignal(rc, valueProp, "switch", false).slice(0, -1) + renderViewTransitionAttr(viewTransition) + ">";
536
532
  rc.flags.runtime |= RENDER_SWITCH;
537
533
  toSlotName = String(value);
538
534
  } else {
@@ -553,15 +549,15 @@ async function renderNode(rc, node, stripSlotProp) {
553
549
  namedSlots.push(slot);
554
550
  }
555
551
  }
556
- if (stateful) {
557
- write(matchedSlot ? stateful.slice(0, -1) + " match=" + toAttrStringLit(matchedSlot[0]) + ">" : stateful);
552
+ if (signalHtml) {
553
+ write(matchedSlot ? signalHtml.slice(0, -1) + " match=" + toAttrStringLit(matchedSlot[0]) + ">" : signalHtml);
558
554
  }
559
555
  if (matchedSlot) {
560
556
  await renderNode(rc, matchedSlot[1], true);
561
557
  } else if (unnamedSlots.length > 0) {
562
558
  await renderChildren(rc, unnamedSlots);
563
559
  }
564
- if (stateful) {
560
+ if (signalHtml) {
565
561
  if (namedSlots.length > 0 || matchedSlot && unnamedSlots.length > 0) {
566
562
  write("<template m-slot>");
567
563
  await renderChildren(rc, namedSlots);
@@ -577,22 +573,20 @@ async function renderNode(rc, node, stripSlotProp) {
577
573
  }
578
574
  // `<component>` element
579
575
  case "component": {
580
- let { placeholder } = props;
576
+ let { placeholder, viewTransition } = props;
581
577
  let attrs = "";
582
578
  let attrModifiers = "";
583
579
  for (const p of ["name", "props", "ref"]) {
584
580
  let propValue = props[p];
585
581
  let [attr, , attrSignal] = renderAttr(rc, p, propValue);
586
582
  if (attrSignal) {
587
- const write2 = (chunk) => {
588
- attrModifiers += chunk;
589
- };
590
- renderSignal({ ...rc, write: write2 }, attrSignal, [p]);
583
+ attrModifiers += renderSignal(rc, attrSignal, [p]);
591
584
  rc.flags.runtime |= RENDER_ATTR;
592
585
  propValue = attrSignal[$signal].value;
593
586
  }
594
587
  attrs += attr;
595
588
  }
589
+ attrs += renderViewTransitionAttr(viewTransition);
596
590
  let buf = "<m-component" + attrs + ">";
597
591
  if (placeholder) {
598
592
  const write2 = (chunk) => {
@@ -610,10 +604,9 @@ async function renderNode(rc, node, stripSlotProp) {
610
604
  }
611
605
  // `<router>` element
612
606
  case "router": {
607
+ const { children, viewTransition } = props;
613
608
  const { routeFC } = rc;
614
- const { children } = props;
615
- const status = routeFC ? 200 : 404;
616
- write('<m-router status="' + status + '">');
609
+ write('<m-router status="' + (routeFC ? 200 : 404) + '"' + renderViewTransitionAttr(viewTransition) + ">");
617
610
  if (routeFC) {
618
611
  await renderFC(rc, routeFC instanceof Promise ? (await routeFC).default : routeFC, {});
619
612
  }
@@ -656,10 +649,7 @@ async function renderNode(rc, node, stripSlotProp) {
656
649
  write(addonHtml);
657
650
  }
658
651
  if (signalValue) {
659
- const write2 = (chunk) => {
660
- attrModifiers += chunk;
661
- };
662
- renderSignal({ ...rc, write: write2 }, signalValue, [binding ? propName.slice(1) : propName]);
652
+ attrModifiers += renderSignal(rc, signalValue, [binding ? propName.slice(1) : propName]);
663
653
  rc.flags.runtime |= RENDER_ATTR;
664
654
  }
665
655
  buffer += attr;
@@ -826,6 +816,14 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
826
816
  }
827
817
  return [attr, addonHtml, signalValue, binding];
828
818
  }
819
+ function renderViewTransitionAttr(viewTransition) {
820
+ if (viewTransition === true || viewTransition === "") {
821
+ return " vt";
822
+ } else if (isString(viewTransition)) {
823
+ return " style=" + toAttrStringLit("view-transition-name:" + viewTransition) + " vt";
824
+ }
825
+ return "";
826
+ }
829
827
  async function renderFC(rc, fc, props, eager) {
830
828
  const { write } = rc;
831
829
  const { children } = props;
@@ -912,17 +910,14 @@ async function renderFC(rc, fc, props, eager) {
912
910
  }
913
911
  }
914
912
  }
915
- function renderSignal(rc, signal, mode, content, html2) {
916
- const { scope, key } = signal[$signal];
913
+ function renderSignal(rc, signal, mode, close) {
914
+ const { scope, key, value } = signal[$signal];
917
915
  let buffer = "<m-signal";
918
916
  if (mode) {
919
- buffer += ' mode="';
920
- if (isString(mode)) {
921
- buffer += mode;
922
- } else {
923
- buffer += "[" + mode[0] + "]";
917
+ if (Array.isArray(mode)) {
918
+ mode = "[" + mode[0] + "]";
924
919
  }
925
- buffer += '"';
920
+ buffer += ' mode="' + mode + '"';
926
921
  }
927
922
  buffer += ' scope="' + scope + '"';
928
923
  if (isString(key)) {
@@ -930,9 +925,26 @@ function renderSignal(rc, signal, mode, content, html2) {
930
925
  } else {
931
926
  buffer += ' computed="' + rc.mcs.gen(signal, rc.fcCtx?.scopeId) + '"';
932
927
  }
933
- rc.write(buffer + ">" + (html2 ? content : escapeHTML(String(content ?? ""))) + "</m-signal>");
928
+ buffer += ">";
929
+ if (!mode || mode === "html") {
930
+ let text;
931
+ switch (typeof value) {
932
+ case "string":
933
+ text = value;
934
+ break;
935
+ case "number":
936
+ case "bigint": {
937
+ text = String(value);
938
+ break;
939
+ }
940
+ }
941
+ if (text) {
942
+ buffer += !mode ? escapeHTML(text) : text;
943
+ }
944
+ }
945
+ return buffer + (close !== false ? "</m-signal>" : "");
934
946
  }
935
- var collectDeps;
947
+ var collectDep;
936
948
  function Signal(scope, key, value) {
937
949
  const signal = { scope, key, value };
938
950
  return new Proxy(new NullProtoObj(), {
@@ -971,9 +983,9 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
971
983
  });
972
984
  const computed = (compute) => {
973
985
  const deps = /* @__PURE__ */ new Set();
974
- collectDeps = (scopeId2, key) => deps.add(scopeId2 + ":" + key);
986
+ collectDep = (scopeId2, key) => deps.add(scopeId2 + ":" + key);
975
987
  const value = compute.call(thisProxy);
976
- collectDeps = void 0;
988
+ collectDep = void 0;
977
989
  return Signal(scopeId, { compute, deps }, value);
978
990
  };
979
991
  const markEffect = (effect) => {
@@ -1017,7 +1029,7 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
1017
1029
  return mark;
1018
1030
  case "url":
1019
1031
  if (scopeId === 0) {
1020
- collectDeps?.(0, key);
1032
+ collectDep?.(0, key);
1021
1033
  return request ? request.URL ?? (request.URL = new URL(request.url)) : void 0;
1022
1034
  }
1023
1035
  // fallthrough
@@ -1029,8 +1041,8 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
1029
1041
  if (value === void 0 && !Reflect.has(target, key)) {
1030
1042
  Reflect.set(target, key, void 0, receiver);
1031
1043
  }
1032
- if (collectDeps) {
1033
- collectDeps(scopeId, key);
1044
+ if (collectDep) {
1045
+ collectDep(scopeId, key);
1034
1046
  return value;
1035
1047
  }
1036
1048
  let signal = signals.get(key);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
package/types/html.d.ts CHANGED
@@ -452,6 +452,7 @@ export namespace HTML {
452
452
  interface MetaAttributes<T extends EventTarget> extends GlobalAttributes<T> {
453
453
  charSet?: string;
454
454
  httpEquiv?: string;
455
+ property?: string;
455
456
  name?: string;
456
457
  content?: string;
457
458
  media?: string;
package/types/mono.d.ts CHANGED
@@ -24,10 +24,10 @@ export interface BaseCSSProperties extends CSS.Properties<string | number> {
24
24
  export interface AtRuleCSSProperties {
25
25
  [key: `@container${" " | "("}${string}`]: BaseCSSProperties;
26
26
  [key: `@media${" " | "("}${string}`]: BaseCSSProperties;
27
+ [key: `@supports${" " | "("}${string}`]: BaseCSSProperties;
27
28
  [key: `@keyframes ${string}`]: {
28
29
  [key in "from" | "to" | `${D100}%`]?: BaseCSSProperties;
29
30
  };
30
- [key: `@supports${" " | "("}${string}`]: BaseCSSProperties;
31
31
  "@view-transition"?: {
32
32
  /**
33
33
  * Specifies the effect this at-rule will have on the document's view transition behavior.
@@ -118,6 +118,7 @@ export interface Elements {
118
118
  toggle: BaseAttributes & {
119
119
  show?: any;
120
120
  hidden?: any;
121
+ viewTransition?: string | boolean;
121
122
  };
122
123
  /**
123
124
  * The `switch` element is a built-in element that chooses one of its children based on the `slot` attribute to display.
@@ -125,6 +126,7 @@ export interface Elements {
125
126
  */
126
127
  switch: BaseAttributes & {
127
128
  value?: string | number | boolean | null;
129
+ viewTransition?: string | boolean;
128
130
  };
129
131
  /**
130
132
  * The `component` element is a built-in element that is used to load components lazily,
@@ -134,6 +136,7 @@ export interface Elements {
134
136
  name?: string;
135
137
  props?: Record<string, unknown>;
136
138
  ref?: ComponentElement | ((el: ComponentElement) => void);
139
+ viewTransition?: string | boolean;
137
140
  };
138
141
  /**
139
142
  * The `router` element is a built-in element that implements client-side routing.
@@ -144,6 +147,7 @@ export interface Elements {
144
147
  */
145
148
  base?: string;
146
149
  ref?: RouterElement | ((el: RouterElement) => void);
150
+ viewTransition?: string | boolean;
147
151
  };
148
152
  }
149
153