mono-jsx 0.6.10 → 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 +41 -0
- package/jsx-runtime.mjs +82 -62
- package/package.json +1 -1
- package/types/html.d.ts +25 -16
- package/types/jsx-runtime.d.ts +1 -1
- package/types/mono.d.ts +5 -1
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
|
|
15
|
-
var RENDER_ATTR_JS = `{var s=(l,n,r)=>{let
|
|
16
|
-
var RENDER_TOGGLE_JS = `{var
|
|
17
|
-
var RENDER_SWITCH_JS = `{var
|
|
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
|
+
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 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
|
|
21
|
-
var ROUTER_JS = `{const
|
|
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
|
-
|
|
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.
|
|
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
|
|
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"
|
|
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 {
|
|
502
|
-
let buf =
|
|
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
|
|
527
|
+
let signalHtml;
|
|
527
528
|
let toSlotName;
|
|
528
529
|
if (isSignal(valueProp)) {
|
|
529
|
-
const {
|
|
530
|
-
|
|
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 (
|
|
557
|
-
write(matchedSlot ?
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -651,15 +644,12 @@ async function renderNode(rc, node, stripSlotProp) {
|
|
|
651
644
|
if (propName === "children") {
|
|
652
645
|
continue;
|
|
653
646
|
}
|
|
654
|
-
const [attr, addonHtml, signalValue] = renderAttr(rc, propName, propValue, stripSlotProp);
|
|
647
|
+
const [attr, addonHtml, signalValue, binding] = renderAttr(rc, propName, propValue, stripSlotProp);
|
|
655
648
|
if (addonHtml) {
|
|
656
649
|
write(addonHtml);
|
|
657
650
|
}
|
|
658
651
|
if (signalValue) {
|
|
659
|
-
|
|
660
|
-
attrModifiers += chunk;
|
|
661
|
-
};
|
|
662
|
-
renderSignal({ ...rc, write: write2 }, signalValue, [propName === "$value" ? "value" : propName]);
|
|
652
|
+
attrModifiers += renderSignal(rc, signalValue, [binding ? propName.slice(1) : propName]);
|
|
663
653
|
rc.flags.runtime |= RENDER_ATTR;
|
|
664
654
|
}
|
|
665
655
|
buffer += attr;
|
|
@@ -702,6 +692,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
702
692
|
let attr = "";
|
|
703
693
|
let addonHtml = "";
|
|
704
694
|
let signalValue;
|
|
695
|
+
let binding = false;
|
|
705
696
|
let scopeId = rc.fcCtx?.scopeId;
|
|
706
697
|
if (isObject(attrValue)) {
|
|
707
698
|
let signal;
|
|
@@ -793,16 +784,23 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
793
784
|
attr = " slot=" + toAttrStringLit(attrValue);
|
|
794
785
|
}
|
|
795
786
|
break;
|
|
787
|
+
case "$checked":
|
|
796
788
|
case "$value":
|
|
797
|
-
|
|
789
|
+
if (!(attrValue === false || attrValue === null || attrValue === void 0)) {
|
|
790
|
+
attr = " " + attrName.slice(1);
|
|
791
|
+
if (attrValue !== true) {
|
|
792
|
+
attr += "=" + toAttrStringLit(String(attrValue));
|
|
793
|
+
}
|
|
794
|
+
}
|
|
798
795
|
if (signalValue) {
|
|
799
796
|
const { key } = signalValue[$signal];
|
|
800
797
|
if (isString(key)) {
|
|
801
798
|
const fn = () => {
|
|
802
799
|
};
|
|
803
|
-
fn.str = "e=>this[" + toAttrStringLit(key) + "]=e.target.
|
|
800
|
+
fn.str = "e=>this[" + toAttrStringLit(key) + "]=e.target." + attrName.slice(1);
|
|
804
801
|
attr += ' oninput="$emit(event,$MF_' + (scopeId ?? 0) + "_" + rc.mfs.gen(fn, scopeId) + toStr(scopeId, (i) => "," + i) + ')"';
|
|
805
802
|
}
|
|
803
|
+
binding = true;
|
|
806
804
|
}
|
|
807
805
|
break;
|
|
808
806
|
default:
|
|
@@ -816,7 +814,15 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
816
814
|
}
|
|
817
815
|
}
|
|
818
816
|
}
|
|
819
|
-
return [attr, addonHtml, signalValue];
|
|
817
|
+
return [attr, addonHtml, signalValue, binding];
|
|
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 "";
|
|
820
826
|
}
|
|
821
827
|
async function renderFC(rc, fc, props, eager) {
|
|
822
828
|
const { write } = rc;
|
|
@@ -904,17 +910,14 @@ async function renderFC(rc, fc, props, eager) {
|
|
|
904
910
|
}
|
|
905
911
|
}
|
|
906
912
|
}
|
|
907
|
-
function renderSignal(rc, signal, mode,
|
|
908
|
-
const { scope, key } = signal[$signal];
|
|
913
|
+
function renderSignal(rc, signal, mode, close) {
|
|
914
|
+
const { scope, key, value } = signal[$signal];
|
|
909
915
|
let buffer = "<m-signal";
|
|
910
916
|
if (mode) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
buffer += mode;
|
|
914
|
-
} else {
|
|
915
|
-
buffer += "[" + mode[0] + "]";
|
|
917
|
+
if (Array.isArray(mode)) {
|
|
918
|
+
mode = "[" + mode[0] + "]";
|
|
916
919
|
}
|
|
917
|
-
buffer += '"';
|
|
920
|
+
buffer += ' mode="' + mode + '"';
|
|
918
921
|
}
|
|
919
922
|
buffer += ' scope="' + scope + '"';
|
|
920
923
|
if (isString(key)) {
|
|
@@ -922,9 +925,26 @@ function renderSignal(rc, signal, mode, content, html2) {
|
|
|
922
925
|
} else {
|
|
923
926
|
buffer += ' computed="' + rc.mcs.gen(signal, rc.fcCtx?.scopeId) + '"';
|
|
924
927
|
}
|
|
925
|
-
|
|
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>" : "");
|
|
926
946
|
}
|
|
927
|
-
var
|
|
947
|
+
var collectDep;
|
|
928
948
|
function Signal(scope, key, value) {
|
|
929
949
|
const signal = { scope, key, value };
|
|
930
950
|
return new Proxy(new NullProtoObj(), {
|
|
@@ -963,9 +983,9 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
|
|
|
963
983
|
});
|
|
964
984
|
const computed = (compute) => {
|
|
965
985
|
const deps = /* @__PURE__ */ new Set();
|
|
966
|
-
|
|
986
|
+
collectDep = (scopeId2, key) => deps.add(scopeId2 + ":" + key);
|
|
967
987
|
const value = compute.call(thisProxy);
|
|
968
|
-
|
|
988
|
+
collectDep = void 0;
|
|
969
989
|
return Signal(scopeId, { compute, deps }, value);
|
|
970
990
|
};
|
|
971
991
|
const markEffect = (effect) => {
|
|
@@ -1009,7 +1029,7 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
|
|
|
1009
1029
|
return mark;
|
|
1010
1030
|
case "url":
|
|
1011
1031
|
if (scopeId === 0) {
|
|
1012
|
-
|
|
1032
|
+
collectDep?.(0, key);
|
|
1013
1033
|
return request ? request.URL ?? (request.URL = new URL(request.url)) : void 0;
|
|
1014
1034
|
}
|
|
1015
1035
|
// fallthrough
|
|
@@ -1021,8 +1041,8 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
|
|
|
1021
1041
|
if (value === void 0 && !Reflect.has(target, key)) {
|
|
1022
1042
|
Reflect.set(target, key, void 0, receiver);
|
|
1023
1043
|
}
|
|
1024
|
-
if (
|
|
1025
|
-
|
|
1044
|
+
if (collectDep) {
|
|
1045
|
+
collectDep(scopeId, key);
|
|
1026
1046
|
return value;
|
|
1027
1047
|
}
|
|
1028
1048
|
let signal = signals.get(key);
|
package/package.json
CHANGED
package/types/html.d.ts
CHANGED
|
@@ -44,7 +44,9 @@ export namespace HTML {
|
|
|
44
44
|
|
|
45
45
|
/** Global HTML attributes from https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes */
|
|
46
46
|
interface GlobalAttributes<T extends EventTarget> extends EventAttributes<T>, Aria.Attributes, Mono.BaseAttributes, JSX.HtmlTag {
|
|
47
|
-
|
|
47
|
+
/** @mono-jsx
|
|
48
|
+
* A reference to the element.
|
|
49
|
+
*/
|
|
48
50
|
ref?: HTMLElement | ((el: T) => unknown);
|
|
49
51
|
/** 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). */
|
|
50
52
|
id?: string;
|
|
@@ -122,7 +124,8 @@ export namespace HTML {
|
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
interface NavAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
125
|
-
/** @mono-jsx
|
|
127
|
+
/** @mono-jsx
|
|
128
|
+
* This attribute is used to specify the class name for the active link. */
|
|
126
129
|
"data-active-class"?: string;
|
|
127
130
|
}
|
|
128
131
|
|
|
@@ -185,7 +188,7 @@ export namespace HTML {
|
|
|
185
188
|
src?: string;
|
|
186
189
|
step?: number | string;
|
|
187
190
|
type?: InputType;
|
|
188
|
-
value?: string | number
|
|
191
|
+
value?: string | number;
|
|
189
192
|
width?: number | string;
|
|
190
193
|
/**
|
|
191
194
|
* Turns a <button> or <input> element into a popover control button; takes the ID of the popover element to control as its value.
|
|
@@ -202,10 +205,15 @@ export namespace HTML {
|
|
|
202
205
|
*/
|
|
203
206
|
onSearch?: EventHandler<Event, T>;
|
|
204
207
|
/**
|
|
205
|
-
* @mono-jsx
|
|
206
|
-
*
|
|
208
|
+
* @mono-jsx
|
|
209
|
+
* Two-way binding prop that automatically creates checked and oninput attributes for signal binding
|
|
207
210
|
*/
|
|
208
|
-
$
|
|
211
|
+
$checked?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* @mono-jsx
|
|
214
|
+
* Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
215
|
+
*/
|
|
216
|
+
$value?: string | number;
|
|
209
217
|
}
|
|
210
218
|
|
|
211
219
|
interface OptionAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -223,12 +231,12 @@ export namespace HTML {
|
|
|
223
231
|
name?: string;
|
|
224
232
|
required?: boolean;
|
|
225
233
|
size?: number;
|
|
226
|
-
value?: string | number
|
|
234
|
+
value?: string | number;
|
|
227
235
|
/**
|
|
228
|
-
* @mono-jsx
|
|
229
|
-
*
|
|
236
|
+
* @mono-jsx
|
|
237
|
+
* Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
230
238
|
*/
|
|
231
|
-
$value?: string | number
|
|
239
|
+
$value?: string | number;
|
|
232
240
|
}
|
|
233
241
|
|
|
234
242
|
interface TextareaAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -248,8 +256,8 @@ export namespace HTML {
|
|
|
248
256
|
wrap?: string;
|
|
249
257
|
onChange?: EventHandler<Event, T>;
|
|
250
258
|
/**
|
|
251
|
-
* @mono-jsx
|
|
252
|
-
*
|
|
259
|
+
* @mono-jsx
|
|
260
|
+
* Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
253
261
|
*/
|
|
254
262
|
$value?: string;
|
|
255
263
|
}
|
|
@@ -319,7 +327,7 @@ export namespace HTML {
|
|
|
319
327
|
}
|
|
320
328
|
|
|
321
329
|
interface DataAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
322
|
-
value?: string |
|
|
330
|
+
value?: string | number;
|
|
323
331
|
}
|
|
324
332
|
|
|
325
333
|
interface DetailsAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -379,7 +387,7 @@ export namespace HTML {
|
|
|
379
387
|
}
|
|
380
388
|
|
|
381
389
|
interface LiAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
382
|
-
value?: string |
|
|
390
|
+
value?: string | number;
|
|
383
391
|
}
|
|
384
392
|
|
|
385
393
|
interface LinkAttributes<T extends EventTarget> extends GlobalAttributes<T>, LoaderElementAttributes<T> {
|
|
@@ -444,6 +452,7 @@ export namespace HTML {
|
|
|
444
452
|
interface MetaAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
445
453
|
charSet?: string;
|
|
446
454
|
httpEquiv?: string;
|
|
455
|
+
property?: string;
|
|
447
456
|
name?: string;
|
|
448
457
|
content?: string;
|
|
449
458
|
media?: string;
|
|
@@ -456,7 +465,7 @@ export namespace HTML {
|
|
|
456
465
|
max?: number | string;
|
|
457
466
|
min?: number | string;
|
|
458
467
|
optimum?: number;
|
|
459
|
-
value?: string |
|
|
468
|
+
value?: string | number;
|
|
460
469
|
}
|
|
461
470
|
|
|
462
471
|
interface QuoteAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -494,7 +503,7 @@ export namespace HTML {
|
|
|
494
503
|
|
|
495
504
|
interface ProgressAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
496
505
|
max?: number | string;
|
|
497
|
-
value?: string |
|
|
506
|
+
value?: string | number;
|
|
498
507
|
}
|
|
499
508
|
|
|
500
509
|
interface SlotAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
package/types/jsx-runtime.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { FC, VNode } from "./jsx.d.ts";
|
|
|
2
2
|
|
|
3
3
|
export const html: JSX.Raw;
|
|
4
4
|
export const JSX: typeof globalThis.JSX;
|
|
5
|
-
export const Fragment: (props:
|
|
5
|
+
export const Fragment: (props: {}) => VNode;
|
|
6
6
|
export const jsx: (tag: string | FC, props: Record<string, unknown>, key?: string | number) => VNode;
|
|
7
7
|
|
|
8
8
|
export { html as css, html as js, jsx as jsxDEV, jsx as jsxs };
|
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
|
|