mono-jsx 0.6.8 → 0.6.10
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 +17 -8
- package/jsx-runtime.mjs +41 -22
- package/package.json +1 -1
- package/types/html.d.ts +20 -3
- package/types/mono.d.ts +24 -2
package/README.md
CHANGED
|
@@ -268,9 +268,7 @@ function Button(this: FC<{ count: 0 }>, props: { role: string }) {
|
|
|
268
268
|
}
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
mono-jsx supports `<form>` elements with the `action` attribute. The `action` attribute can be a string URL or a function that accepts a `FormData` object. The function will be called on form submission, and the `FormData` object will contain the form data.
|
|
271
|
+
mono-jsx allows you to use a function as the value of the `action` attribute of the `<form>` element. The function will be called on form submission, and the `FormData` object will contain the form data.
|
|
274
272
|
|
|
275
273
|
```tsx
|
|
276
274
|
function App() {
|
|
@@ -415,11 +413,7 @@ function App(this: FC<{ input: string }>) {
|
|
|
415
413
|
return (
|
|
416
414
|
<div>
|
|
417
415
|
<h1>{this.computed(() => this.input + "!")}</h1>
|
|
418
|
-
|
|
419
|
-
<form action={(fd) => this.input = fd.get("input") as string}>
|
|
420
|
-
<input type="text" name="input" value={"" + this.input} />
|
|
421
|
-
<button type="submit">Submit</button>
|
|
422
|
-
</form>
|
|
416
|
+
<input type="text" $value={this.input} />
|
|
423
417
|
</div>
|
|
424
418
|
)
|
|
425
419
|
}
|
|
@@ -534,6 +528,21 @@ function App(this: FC<{ lang: "en" | "zh" | "🙂" }>) {
|
|
|
534
528
|
}
|
|
535
529
|
```
|
|
536
530
|
|
|
531
|
+
### Form Input Bindings with `$value` Attribute
|
|
532
|
+
|
|
533
|
+
You can use the `$value` attribute to bind a signal to the value of a form input element. The `$value` attribute is a two-way data binding, which means that when the input value changes, the signal will be updated, and when the signal changes, the input value will be updated.
|
|
534
|
+
|
|
535
|
+
```tsx
|
|
536
|
+
function App(this: FC<{ value: string }>) {
|
|
537
|
+
this.value = "Welcome to mono-jsx";
|
|
538
|
+
this.effect(() => {
|
|
539
|
+
console.log("value changed:", this.value);
|
|
540
|
+
});
|
|
541
|
+
// return <input value={this.value} oninput={e => this.value = e.target.value} />;
|
|
542
|
+
return <input $value={this.value} />;
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
537
546
|
### Limitation of Signals
|
|
538
547
|
|
|
539
548
|
1\. Arrow function are non-stateful components.
|
package/jsx-runtime.mjs
CHANGED
|
@@ -12,10 +12,10 @@ 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
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;}`;
|
|
15
|
-
var RENDER_ATTR_JS = `{var s=(l,
|
|
16
|
-
var RENDER_TOGGLE_JS = `{var
|
|
17
|
-
var RENDER_SWITCH_JS = `{var u=(
|
|
18
|
-
var SIGNALS_JS = `{let m;const h=window,b=new Map,
|
|
15
|
+
var RENDER_ATTR_JS = `{var s=(l,n,r)=>{let t=l.parentElement;return t.tagName==="M-GROUP"&&(t=t.previousElementSibling),()=>{let e=r();e===!1||e===null||e===void 0?t.removeAttribute(n):typeof e=="object"&&e!==null?n==="class"?t.setAttribute(n,$cx(e)):n==="style"?$applyStyle(t,e):t.setAttribute(n,JSON.stringify(e)):n==="value"?t.value=String(e):t.setAttribute(n,e===!0?"":e)}};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;}`;
|
|
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
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
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}});}`;
|
|
@@ -135,7 +135,7 @@ var $signal = Symbol.for("mono.signal");
|
|
|
135
135
|
var $vnode = Symbol.for("jsx.vnode");
|
|
136
136
|
|
|
137
137
|
// version.ts
|
|
138
|
-
var VERSION = "0.6.
|
|
138
|
+
var VERSION = "0.6.9";
|
|
139
139
|
|
|
140
140
|
// render.ts
|
|
141
141
|
var cdn = "https://raw.esm.sh";
|
|
@@ -325,7 +325,6 @@ async function render(node, options, write, writeJS, componentMode) {
|
|
|
325
325
|
request,
|
|
326
326
|
signals,
|
|
327
327
|
routeFC,
|
|
328
|
-
eager: componentMode,
|
|
329
328
|
flags: { scope: 0, chunk: 0, runtime: 0 },
|
|
330
329
|
mcs: new IdGenManagerImpl(),
|
|
331
330
|
mfs: new IdGenManagerImpl()
|
|
@@ -359,7 +358,9 @@ async function render(node, options, write, writeJS, componentMode) {
|
|
|
359
358
|
js += 'window.$FLAGS="' + scope + "|" + chunk + "|" + runtimeFlag + '";';
|
|
360
359
|
}
|
|
361
360
|
if (rc.mfs.size > 0) {
|
|
362
|
-
js += rc.mfs.toJS(
|
|
361
|
+
js += rc.mfs.toJS(
|
|
362
|
+
(scope, seq, fn) => "function $MF_" + scope + "_" + seq + "(){(" + (fn.str ?? String(fn)) + ").apply(this,arguments)};"
|
|
363
|
+
);
|
|
363
364
|
rc.mfs.clear();
|
|
364
365
|
}
|
|
365
366
|
if (hasEffect) {
|
|
@@ -384,7 +385,7 @@ async function render(node, options, write, writeJS, componentMode) {
|
|
|
384
385
|
if (rc.mcs.size > 0) {
|
|
385
386
|
js += rc.mcs.toJS((scope, seq, signal) => {
|
|
386
387
|
const { compute, deps } = signal[$signal].key;
|
|
387
|
-
return "$MC(" + scope + "," + seq + ",function(){return(" + compute
|
|
388
|
+
return "$MC(" + scope + "," + seq + ",function(){return(" + String(compute) + ").call(this)}," + stringify([...deps.values()]) + ");";
|
|
388
389
|
});
|
|
389
390
|
rc.mcs.clear();
|
|
390
391
|
}
|
|
@@ -406,6 +407,14 @@ async function render(node, options, write, writeJS, componentMode) {
|
|
|
406
407
|
runtimeFlag = runtime;
|
|
407
408
|
}
|
|
408
409
|
}
|
|
410
|
+
if (componentMode) {
|
|
411
|
+
const [tag, props] = node;
|
|
412
|
+
if (typeof tag === "function") {
|
|
413
|
+
await renderFC(rc, tag, props, true);
|
|
414
|
+
await finalize();
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
409
418
|
await renderNode(rc, node);
|
|
410
419
|
if (rc.flags.scope > 0 && !componentMode) {
|
|
411
420
|
markSignals(rc, signals.app);
|
|
@@ -650,7 +659,7 @@ async function renderNode(rc, node, stripSlotProp) {
|
|
|
650
659
|
const write2 = (chunk) => {
|
|
651
660
|
attrModifiers += chunk;
|
|
652
661
|
};
|
|
653
|
-
renderSignal({ ...rc, write: write2 }, signalValue, [propName]);
|
|
662
|
+
renderSignal({ ...rc, write: write2 }, signalValue, [propName === "$value" ? "value" : propName]);
|
|
654
663
|
rc.flags.runtime |= RENDER_ATTR;
|
|
655
664
|
}
|
|
656
665
|
buffer += attr;
|
|
@@ -693,32 +702,31 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
693
702
|
let attr = "";
|
|
694
703
|
let addonHtml = "";
|
|
695
704
|
let signalValue;
|
|
705
|
+
let scopeId = rc.fcCtx?.scopeId;
|
|
696
706
|
if (isObject(attrValue)) {
|
|
697
707
|
let signal;
|
|
698
708
|
if (isSignal(attrValue)) {
|
|
699
709
|
signal = attrValue;
|
|
700
710
|
} else {
|
|
701
|
-
|
|
702
|
-
if (fcCtx) {
|
|
711
|
+
if (scopeId) {
|
|
703
712
|
const deps = /* @__PURE__ */ new Set();
|
|
704
713
|
const patches = [];
|
|
705
714
|
const staticProps = traverseProps(attrValue, (path, value) => {
|
|
706
715
|
const { scope, key } = value[$signal];
|
|
707
716
|
if (isString(key)) {
|
|
708
717
|
patches.push([
|
|
709
|
-
(scope !==
|
|
718
|
+
(scope !== scopeId ? "$signals(" + scope + ")" : "this") + "[" + stringify(key) + "]",
|
|
710
719
|
...path
|
|
711
720
|
].join(","));
|
|
712
721
|
deps.add(scope + ":" + key);
|
|
713
722
|
} else {
|
|
714
|
-
patches.push(["(" + key.compute
|
|
723
|
+
patches.push(["(" + String(key.compute) + ")(),", ...path].join(","));
|
|
715
724
|
for (const dep of key.deps) {
|
|
716
725
|
deps.add(dep);
|
|
717
726
|
}
|
|
718
727
|
}
|
|
719
728
|
});
|
|
720
729
|
if (patches.length > 0) {
|
|
721
|
-
const { scopeId } = fcCtx;
|
|
722
730
|
const compute = "()=>$patch(" + stringify(staticProps) + ",[" + patches.join("],[") + "])";
|
|
723
731
|
signal = Signal(scopeId, { compute, deps }, staticProps);
|
|
724
732
|
}
|
|
@@ -765,7 +773,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
765
773
|
} else {
|
|
766
774
|
const refId = rc.fcCtx.refs++;
|
|
767
775
|
const effects = signals[Symbol.for("effects")];
|
|
768
|
-
effects.push("()=>(" + attrValue
|
|
776
|
+
effects.push("()=>(" + String(attrValue) + ')(this.refs["' + refId + '"])');
|
|
769
777
|
attr = " data-ref=" + toAttrStringLit(rc.fcCtx.scopeId + ":" + refId);
|
|
770
778
|
}
|
|
771
779
|
} else if (attrValue instanceof Ref) {
|
|
@@ -774,8 +782,8 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
774
782
|
break;
|
|
775
783
|
case "action":
|
|
776
784
|
if (typeof attrValue === "function") {
|
|
777
|
-
const
|
|
778
|
-
attr = ' onsubmit="$onsubmit(event,$MF_' + (
|
|
785
|
+
const scopeId2 = rc.fcCtx?.scopeId;
|
|
786
|
+
attr = ' onsubmit="$onsubmit(event,$MF_' + (scopeId2 ?? 0) + "_" + rc.mfs.gen(attrValue, scopeId2) + toStr(scopeId2, (i) => "," + i) + ')"';
|
|
779
787
|
} else if (isString(attrValue)) {
|
|
780
788
|
attr = " action=" + toAttrStringLit(attrValue);
|
|
781
789
|
}
|
|
@@ -785,9 +793,20 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
785
793
|
attr = " slot=" + toAttrStringLit(attrValue);
|
|
786
794
|
}
|
|
787
795
|
break;
|
|
796
|
+
case "$value":
|
|
797
|
+
attr = " value=" + toAttrStringLit(String(attrValue));
|
|
798
|
+
if (signalValue) {
|
|
799
|
+
const { key } = signalValue[$signal];
|
|
800
|
+
if (isString(key)) {
|
|
801
|
+
const fn = () => {
|
|
802
|
+
};
|
|
803
|
+
fn.str = "e=>this[" + toAttrStringLit(key) + "]=e.target.value";
|
|
804
|
+
attr += ' oninput="$emit(event,$MF_' + (scopeId ?? 0) + "_" + rc.mfs.gen(fn, scopeId) + toStr(scopeId, (i) => "," + i) + ')"';
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
break;
|
|
788
808
|
default:
|
|
789
809
|
if (attrName.startsWith("on") && typeof attrValue === "function") {
|
|
790
|
-
const scopeId = rc.fcCtx?.scopeId;
|
|
791
810
|
attr = " " + escapeHTML(attrName.toLowerCase()) + '="$emit(event,$MF_' + (scopeId ?? 0) + "_" + rc.mfs.gen(attrValue, scopeId) + toStr(scopeId, (i) => "," + i) + ')"';
|
|
792
811
|
} else if (attrValue === false || attrValue === null || attrValue === void 0) {
|
|
793
812
|
} else {
|
|
@@ -799,7 +818,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
799
818
|
}
|
|
800
819
|
return [attr, addonHtml, signalValue];
|
|
801
820
|
}
|
|
802
|
-
async function renderFC(rc, fc, props) {
|
|
821
|
+
async function renderFC(rc, fc, props, eager) {
|
|
803
822
|
const { write } = rc;
|
|
804
823
|
const { children } = props;
|
|
805
824
|
const scopeId = ++rc.flags.scope;
|
|
@@ -810,7 +829,7 @@ async function renderFC(rc, fc, props) {
|
|
|
810
829
|
const v = fc.call(signals, props);
|
|
811
830
|
if (isObject(v) && !isVNode(v)) {
|
|
812
831
|
if (v instanceof Promise) {
|
|
813
|
-
if (
|
|
832
|
+
if (eager || (props.rendering ?? fc.rendering) === "eager") {
|
|
814
833
|
await renderNode({ ...rc, fcCtx }, await v);
|
|
815
834
|
markSignals(rc, signals);
|
|
816
835
|
} else {
|
|
@@ -832,7 +851,7 @@ async function renderFC(rc, fc, props) {
|
|
|
832
851
|
}));
|
|
833
852
|
}
|
|
834
853
|
} else if (Symbol.asyncIterator in v) {
|
|
835
|
-
if (
|
|
854
|
+
if (eager || (props.rendering ?? fc.rendering) === "eager") {
|
|
836
855
|
for await (const c of v) {
|
|
837
856
|
await renderNode({ ...rc, fcCtx }, c);
|
|
838
857
|
}
|
|
@@ -950,7 +969,7 @@ function createSignals(scopeId, appSignals, context = new NullProtoObj(), reques
|
|
|
950
969
|
return Signal(scopeId, { compute, deps }, value);
|
|
951
970
|
};
|
|
952
971
|
const markEffect = (effect) => {
|
|
953
|
-
effects.push(effect
|
|
972
|
+
effects.push(String(effect));
|
|
954
973
|
};
|
|
955
974
|
const mark = ({ signals: signals2, write }) => {
|
|
956
975
|
if (effects.length > 0) {
|
package/package.json
CHANGED
package/types/html.d.ts
CHANGED
|
@@ -185,7 +185,7 @@ export namespace HTML {
|
|
|
185
185
|
src?: string;
|
|
186
186
|
step?: number | string;
|
|
187
187
|
type?: InputType;
|
|
188
|
-
value?: string | ReadonlyArray<string
|
|
188
|
+
value?: string | number | ReadonlyArray<string | number>;
|
|
189
189
|
width?: number | string;
|
|
190
190
|
/**
|
|
191
191
|
* Turns a <button> or <input> element into a popover control button; takes the ID of the popover element to control as its value.
|
|
@@ -197,8 +197,15 @@ export namespace HTML {
|
|
|
197
197
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
198
198
|
*/
|
|
199
199
|
popovertargetaction?: "hide" | "show" | "toggle";
|
|
200
|
-
|
|
200
|
+
/**
|
|
201
|
+
* For type="search"
|
|
202
|
+
*/
|
|
201
203
|
onSearch?: EventHandler<Event, T>;
|
|
204
|
+
/**
|
|
205
|
+
* @mono-jsx: Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
206
|
+
* Similar to Vue's v-model
|
|
207
|
+
*/
|
|
208
|
+
$value?: string | number | ReadonlyArray<string | number>;
|
|
202
209
|
}
|
|
203
210
|
|
|
204
211
|
interface OptionAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -216,7 +223,12 @@ export namespace HTML {
|
|
|
216
223
|
name?: string;
|
|
217
224
|
required?: boolean;
|
|
218
225
|
size?: number;
|
|
219
|
-
value?: string | ReadonlyArray<string
|
|
226
|
+
value?: string | number | ReadonlyArray<string | number>;
|
|
227
|
+
/**
|
|
228
|
+
* @mono-jsx: Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
229
|
+
* Similar to Vue's v-model
|
|
230
|
+
*/
|
|
231
|
+
$value?: string | number | ReadonlyArray<string | number>;
|
|
220
232
|
}
|
|
221
233
|
|
|
222
234
|
interface TextareaAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
@@ -235,6 +247,11 @@ export namespace HTML {
|
|
|
235
247
|
value?: string;
|
|
236
248
|
wrap?: string;
|
|
237
249
|
onChange?: EventHandler<Event, T>;
|
|
250
|
+
/**
|
|
251
|
+
* @mono-jsx: Two-way binding prop that automatically creates value and oninput attributes for signal binding
|
|
252
|
+
* Similar to Vue's v-model
|
|
253
|
+
*/
|
|
254
|
+
$value?: string;
|
|
238
255
|
}
|
|
239
256
|
|
|
240
257
|
interface ButtonAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
package/types/mono.d.ts
CHANGED
|
@@ -3,15 +3,37 @@ import type * as CSS from "./css.d.ts";
|
|
|
3
3
|
type D9 = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
4
4
|
type D100 = 0 | D9 | `${D9}${0 | D9}` | 100;
|
|
5
5
|
|
|
6
|
-
export interface BaseCSSProperties extends CSS.Properties<string | number> {
|
|
6
|
+
export interface BaseCSSProperties extends CSS.Properties<string | number> {
|
|
7
|
+
/**
|
|
8
|
+
* The field-sizing CSS property enables you to control the sizing behavior of elements that are given a default preferred size, such as form control elements. This property enables you to override the default sizing behavior, allowing form controls to adjust in size to fit their contents.
|
|
9
|
+
* @see https://developer.mozilla.org/docs/Web/CSS/field-sizing
|
|
10
|
+
*/
|
|
11
|
+
fieldSizing?: "fixed" | "content";
|
|
12
|
+
/**
|
|
13
|
+
* The view-transition-class CSS property provides the selected elements with an identifying class (a <custom-ident>), providing an additional method of styling the view transitions for those elements.
|
|
14
|
+
* @see https://developer.mozilla.org/docs/Web/CSS/view-transition-class
|
|
15
|
+
*/
|
|
16
|
+
"view-transition-class"?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The view-transition-name CSS property specifies the view transition snapshot that selected elements will participate in, which enables an element to be animated separately from the rest of the page during a view transition.
|
|
19
|
+
* @see https://developer.mozilla.org/docs/Web/CSS/view-transition-name
|
|
20
|
+
*/
|
|
21
|
+
"view-transition-name"?: string;
|
|
22
|
+
}
|
|
7
23
|
|
|
8
24
|
export interface AtRuleCSSProperties {
|
|
9
25
|
[key: `@container${" " | "("}${string}`]: BaseCSSProperties;
|
|
10
26
|
[key: `@media${" " | "("}${string}`]: BaseCSSProperties;
|
|
11
|
-
[key: `@supports${" " | "("}${string}`]: BaseCSSProperties;
|
|
12
27
|
[key: `@keyframes ${string}`]: {
|
|
13
28
|
[key in "from" | "to" | `${D100}%`]?: BaseCSSProperties;
|
|
14
29
|
};
|
|
30
|
+
[key: `@supports${" " | "("}${string}`]: BaseCSSProperties;
|
|
31
|
+
"@view-transition"?: {
|
|
32
|
+
/**
|
|
33
|
+
* Specifies the effect this at-rule will have on the document's view transition behavior.
|
|
34
|
+
*/
|
|
35
|
+
navigation?: "auto" | "none";
|
|
36
|
+
};
|
|
15
37
|
}
|
|
16
38
|
|
|
17
39
|
export interface PseudoCSSProperties {
|