mono-jsx 0.7.1 → 0.7.3

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
@@ -161,10 +161,10 @@ mono-jsx supports [pseudo classes](https://developer.mozilla.org/en-US/docs/Web/
161
161
 
162
162
  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 transitions, add the `viewTransition` attribute to the following components:
163
163
 
164
- - `<toggle viewTransition="transition-name">`
165
- - `<switch viewTransition="transition-name">`
166
- - `<component viewTransition="transition-name">`
167
- - `<router viewTransition="transition-name">`
164
+ - `<toggle viewTransition="view-transition-name">`
165
+ - `<switch viewTransition="view-transition-name">`
166
+ - `<component viewTransition="view-transition-name">`
167
+ - `<router viewTransition="view-transition-name">`
168
168
 
169
169
  You can set custom transition animations by adding [`::view-transition-group`](https://developer.mozilla.org/en-US/docs/Web/CSS/::view-transition-group), [`::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 animations. For example:
170
170
 
@@ -175,9 +175,9 @@ function App(this: FC<{ show: boolean }>) {
175
175
  style={{
176
176
  "@keyframes fade-in": { from: { opacity: 0 }, to: { opacity: 1 } },
177
177
  "@keyframes fade-out": { from: { opacity: 1 }, to: { opacity: 0 } },
178
- "::view-transition-group(fade)": { animationDuration: "0.5s" },
179
- "::view-transition-old(fade)": { animation: "0.5s ease-in both fade-out" },
180
- "::view-transition-new(fade)": { animation: "0.5s ease-in both fade-in" },
178
+ "::view-transition-group(fade)": { animationDuration: "0.3s" },
179
+ "::view-transition-old(fade)": { animation: "0.3s ease-in both fade-out" },
180
+ "::view-transition-new(fade)": { animation: "0.3s ease-in both fade-in" },
181
181
  }}
182
182
  >
183
183
  <toggle show={this.show} viewTransition="fade">
@@ -189,6 +189,28 @@ function App(this: FC<{ show: boolean }>) {
189
189
  }
190
190
  ```
191
191
 
192
+ You can also set the `viewTransition` attribute a html element which contains signal children.
193
+
194
+ ```tsx
195
+ function App(this: FC<{ message: string }>) {
196
+ this.message = "Hello world!";
197
+ return (
198
+ <h1 viewTransition="fade">{this.message}</h1>
199
+ )
200
+ }
201
+ ```
202
+
203
+ You can also set the view transition name in the style property with the `viewTransition` attribute set to `true`.
204
+
205
+ ```tsx
206
+ function App(this: FC<{ message: string }>) {
207
+ this.message = "Hello world!";
208
+ return (
209
+ <h1 viewTransition style={{ viewTransitionName: "fade" }}>{this.message}</h1>
210
+ )
211
+ }
212
+ ```
213
+
192
214
  ### Using `<slot>` Element
193
215
 
194
216
  mono-jsx uses [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) elements to render slotted content (equivalent to React's `children` property). You can also add the `name` attribute to define named slots:
package/jsx-runtime.mjs CHANGED
@@ -16,7 +16,7 @@ var STYLE_JS = `{var l=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^o
16
16
  var RENDER_ATTR_JS = `{var s=(l,n,r)=>{let e=l.parentElement;return e.tagName==="M-GROUP"&&(e=e.previousElementSibling),()=>{let t=r();n==="value"?e.value=String(t):n==="checked"?e.checked=!!t:typeof t=="boolean"?e.toggleAttribute(n,t):t==null?e.removeAttribute(n):typeof t=="object"?n==="class"?e.setAttribute(n,$cx(t)):n==="style"?$applyStyle(e,t):e.setAttribute(n,JSON.stringify(t)):e.setAttribute(n,String(t))}};window.$renderAttr=s;}`;
17
17
  var RENDER_TOGGLE_JS = `{var i=(e,s)=>{let t,l=()=>e.replaceChildren(...s()?t:[]);return()=>{if(!t){let n=e.firstElementChild;n&&n.tagName==="TEMPLATE"&&n.hasAttribute("m-slot")?t=[...n.content.childNodes]:t=[...e.childNodes]}e.hasAttribute("vt")&&document.startViewTransition?document.startViewTransition(l):l()}};window.$renderToggle=i;}`;
18
18
  var RENDER_SWITCH_JS = `{var a=(l,u)=>{let s,r=l.getAttribute("value"),t,i,o=e=>t.get(e)??t.set(e,[]).get(e),d=()=>l.replaceChildren(...t.has(s)?t.get(s):i);return()=>{if(!t){t=new Map,i=[];for(let e of l.childNodes)if(e.nodeType===1&&e.tagName==="TEMPLATE"&&e.hasAttribute("m-slot")){for(let n of e.content.childNodes)n.nodeType===1&&n.hasAttribute("slot")?o(n.getAttribute("slot")).push(n):i.push(n);e.remove()}else r?o(r).push(e):i.push(e)}s=""+u(),l.hasAttribute("vt")&&document.startViewTransition?document.startViewTransition(d):d()}};window.$renderSwitch=a;}`;
19
- 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
+ var SIGNALS_JS = `{let m;const w=window,p=document,y=new Map,k=new Map,l=n=>k.get(n)??k.set(n,M(n)).get(n),$=()=>Object.create(null),f=(n,e)=>n.getAttribute(e),M=n=>{const e=$(),t=(i,r)=>{e[i]=r},s=new Map,a=(i,r)=>{let o=s.get(i);return o||(o=new Set,s.set(i,o)),o.add(r),()=>{o.delete(r),o.size===0&&s.delete(i)}},c=new Proxy($(),{get:(i,r)=>p.querySelector("[data-ref='"+n+":"+r+"']")});return new Proxy(e,{get:(i,r,o)=>{switch(r){case"$init":return t;case"$watch":return a;case"app":return l(0);case"refs":return c;default:return m?.(n,r),Reflect.get(i,r,o)}},set:(i,r,o,d)=>{if(o!==Reflect.get(i,r,d)){const u=s.get(r);return u&&queueMicrotask(()=>u.forEach(g=>g())),Reflect.set(i,r,o,d)}return!1}})},v=(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,a=()=>n.textContent=""+t();if(p.startViewTransition&&s.hasAttribute("data-vt")){const c=s.getAttribute("data-vt");return c&&(s.style.viewTransitionName=c),()=>p.startViewTransition(a)}return a},E=n=>{const e=n.indexOf(":");return e>0?[Number(n.slice(0,e)),n.slice(e+1)]:null},b=async n=>{const e=n();return e!==void 0?e:(await new Promise(t=>setTimeout(t,0)),b(n))},S=n=>{typeof n=="function"&&n()},T=(n,e)=>customElements.define(n,class extends HTMLElement{disposes=[];connectedCallback(){e(this)}disconnectedCallback(){this.disposes.forEach(t=>t()),this.disposes.length=0}});T("m-signal",n=>{const e=Number(f(n,"scope")),t=l(e),s=f(n,"key");if(s)n.disposes.push(t.$watch(s,v(n,f(n,"mode"),()=>t[s])));else{const a=Number(f(n,"computed"));b(()=>y.get(e*1e9+a)).then(([c,i])=>{const r=v(n,f(n,"mode"),c.bind(t));i.forEach(o=>{const[d,u]=E(o);n.disposes.push(l(d).$watch(u,r))})})}}),T("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 c=0;c<s;c++){const i="$ME_"+t+"_"+c;b(()=>w[i]).then(r=>{const o=[],d=l(t),u=()=>{S(a[c]),a[c]=r.call(d)};m=(g,h)=>o.push([g,h]),u(),m=void 0;for(const[g,h]of o)e.push(l(g).$watch(h,u))},()=>{})}}),w.$MS=(n,e)=>{const[t,s]=E(n);l(t).$init(s,e)},w.$MC=(n,e,t,s)=>{y.set(n*1e9+e,[t,s])},w.$patch=(n,...e)=>{for(const[t,...s]of e){const a=s.pop();let c=n;for(const i of s)c=c[i];c[a]=t}return n},w.$signals=n=>n!==void 0?l(n):void 0;}`;
20
20
  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())})});}`;
21
21
  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()}});}`;
22
22
  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-slot")){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}});}`;
@@ -143,7 +143,7 @@ var $signal = Symbol.for("mono.signal");
143
143
  var $vnode = Symbol.for("jsx.vnode");
144
144
 
145
145
  // version.ts
146
- var VERSION = "0.7.0";
146
+ var VERSION = "0.7.2";
147
147
 
148
148
  // render.ts
149
149
  var cdn = "https://raw.esm.sh";
@@ -665,7 +665,7 @@ async function renderNode(rc, node, stripSlotProp) {
665
665
  const { routeFC } = rc;
666
666
  write("<m-router" + (!routeFC ? " fallback" : "") + renderViewTransitionAttr(viewTransition) + ">");
667
667
  if (routeFC) {
668
- await renderFC(rc, routeFC instanceof Promise ? (await routeFC).default : routeFC, {});
668
+ await renderFC(rc, routeFC instanceof Promise ? (await routeFC).default : routeFC, {}, true);
669
669
  }
670
670
  let buf = "";
671
671
  if (children) {
@@ -938,6 +938,13 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
938
938
  binding = true;
939
939
  }
940
940
  break;
941
+ case "viewTransition":
942
+ if (attrValue === true || attrValue === "") {
943
+ attr = " data-vt";
944
+ } else if (isString(attrValue)) {
945
+ attr = " data-vt=" + toAttrStringLit(attrValue);
946
+ }
947
+ break;
941
948
  default:
942
949
  if (attrName.startsWith("on") && typeof attrValue === "function") {
943
950
  attr = " " + escapeHTML(attrName.toLowerCase()) + '="$emit(event,$MF_' + (scopeId ?? 0) + "_" + rc.mfs.gen(attrValue, scopeId) + toStr(scopeId, (i) => "," + i) + ')"';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
package/types/html.d.ts CHANGED
@@ -101,8 +101,6 @@ export namespace HTML {
101
101
  popover?: boolean | "auto" | "manual";
102
102
  /** A space-separated list of the part names of the element. Part names allows CSS to select and style specific elements in a shadow tree via the [`::part`](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) pseudo-element. */
103
103
  part?: string;
104
- /** The `slot` attribute assigns a slot in a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) shadow tree to an element: An element with a `slot` attribute is assigned to the slot created by the `<slot>` element whose name attribute's value matches that slot attribute's value. */
105
- slot?: string;
106
104
  /** Allows you to specify that a standard HTML element should behave like a registered custom built-in element (see [Using custom elements](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) for more details). */
107
105
  is?: string;
108
106
  /** A boolean value that makes the browser disregard user input events for the element. Useful when click events are present. */
package/types/mono.d.ts CHANGED
@@ -93,7 +93,16 @@ export type WithParams<T> = T & { params?: Record<string, string> };
93
93
 
94
94
  export interface BaseAttributes {
95
95
  children?: MaybeArray<ChildType>;
96
+ key?: string | number;
97
+ /**
98
+ * The `slot` attribute assigns a slot in a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) shadow tree to an element: An element with a `slot` attribute is assigned to the slot created by the `<slot>` element whose name attribute's value matches that slot attribute's value.
99
+ */
96
100
  slot?: string;
101
+ /**
102
+ * The `viewTransition` attribute is used to control the view transition of the children.
103
+ * @mono-jsx
104
+ */
105
+ viewTransition?: string | boolean;
97
106
  }
98
107
 
99
108
  export interface AsyncComponentAttributes {
@@ -125,10 +134,6 @@ export interface Elements {
125
134
  * The `hidden` attribute is used to control the visibility of the children.
126
135
  */
127
136
  hidden?: any;
128
- /**
129
- * The `viewTransition` attribute is used to control the view transition of the children.
130
- */
131
- viewTransition?: string | boolean;
132
137
  };
133
138
  /**
134
139
  * The `switch` element is a built-in element of mono-jsx that chooses one of its children based on the `slot` attribute to display.
@@ -139,10 +144,6 @@ export interface Elements {
139
144
  * The `value` attribute is used to control the value of the children.
140
145
  */
141
146
  value?: string | number | boolean | null;
142
- /**
143
- * The `viewTransition` attribute is used to control the view transition of the children.
144
- */
145
- viewTransition?: string | boolean;
146
147
  };
147
148
  /**
148
149
  * The `component` element is a built-in element of mono-jsx that is used to load components lazily,
@@ -161,10 +162,6 @@ export interface Elements {
161
162
  * The `ref` attribute is used to control the ref of the component.
162
163
  */
163
164
  ref?: ComponentElement | ((el: ComponentElement) => void);
164
- /**
165
- * The `viewTransition` attribute is used to control the view transition of the children.
166
- */
167
- viewTransition?: string | boolean;
168
165
  };
169
166
  /**
170
167
  * The `router` element is a built-in element of mono-jsx that provides SPA routing.
@@ -178,10 +175,6 @@ export interface Elements {
178
175
  * The `ref` attribute is used to control the ref of the router.
179
176
  */
180
177
  ref?: RouterElement | ((el: RouterElement) => void);
181
- /**
182
- * The `viewTransition` attribute is used to control the view transition of the children.
183
- */
184
- viewTransition?: string | boolean;
185
178
  };
186
179
  /**
187
180
  * The `cache` element is a built-in element of mono-jsx that caches the rendered content of the child nodes
@@ -313,7 +306,14 @@ declare global {
313
306
  *
314
307
  * **⚠ This is a server-side only API.**
315
308
  */
316
- readonly request: WithParams<Request & { URL: URL }>;
309
+ readonly request: WithParams<
310
+ Request & {
311
+ /**
312
+ * Returns the URL of request as a URL object.
313
+ */
314
+ URL: URL;
315
+ }
316
+ >;
317
317
  /**
318
318
  * The `form` object created by the route form submission.
319
319
  *