@grainular/router 2.0.0-next.6 → 2.0.0-next.8

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.
@@ -1,3 +1,3 @@
1
- var Nord=(function(exports){'use strict';var M=(e,r)=>Object.assign(()=>r(e()),{subscribe(t){return e.subscribe(n=>{t(r(n));})}});var q=(e,r)=>Object.is(e,r),v=(e,r=q)=>{let t=e,n=new Set,a=()=>{for(let s of Array.from(n))s(t);},o=s=>{r(t,s)||(t=s,a());};return Object.assign(()=>t,{set:o,update:s=>o(s(t)),subscribe:s=>(n.add(s),()=>n.delete(s))})},w=e=>Object.assign(()=>e(),{subscribe:e.subscribe});var C=e=>"default"in e?e.default():typeof e=="function"?e():e;var R=async(e,r)=>{for(let{handler:t}of e)if(await t({...r,navigate:a=>navigation.navigate(a)})===false)return false;return true};var E=e=>navigation.navigate(e);var O=e=>Object.fromEntries(Object.entries(e?.pathname?.groups??{}).filter(([r,t])=>t!==void 0));var U=e=>{let r=w(e);return Object.assign(r,{select:t=>M(e,t)})};var H=new Map,L=(e,r)=>{for(let t of r){let n=new URL(t.path,`http://localhost${e}`);H.set(new URLPattern({pathname:n.pathname}),t);}return {match:t=>[...H.entries()].find(([n])=>n.test(t))??null}};var W=e=>e.canIntercept&&!e.hashChange&&!e.downloadRequest&&!e.formData,D=(e,r)=>{let t=v({}),n=v({}),{match:a}=L(e,r),o=v({resolved:null,component:null,path:null,route:null}),s=i=>{let[c,f]=a(i)??[];return !c||!f?null:{params:O(c.exec(i)),query:Object.fromEntries(i.searchParams),resolved:c.pathname,path:i.pathname,pattern:c,route:f,url:i}},l=i=>{queueMicrotask(()=>{E(i);});},u=async i=>{let{pattern:c,route:f,params:b,query:y,url:h}=i,g=(f.use??[]).filter(I=>I.run==="pre");if(!await R(g,{...i,redirect:l}))return;let k=C(await f.component());t.set(b),n.set(y),o.update(()=>({route:f,component:k,resolved:c.pathname,path:h.pathname}));},m=i=>r.some(c=>c===i);navigation.addEventListener("navigate",i=>{if(!W(i))return;let c=new URL(i.destination.url),f=s(c);if(!f||!m(f.route))return;let b=true;i.intercept({scroll:"after-transition",precommitHandler:async()=>{let y=(o().route?.use??[]).filter(g=>g.run==="post");b=await R(y,{...o(),params:t(),query:n(),redirect:l});let h=(f.route.use??[]).filter(g=>g.run==="pre");if(b=await R(h,{...f,redirect:l}),!b)throw new Error("Navigation Cancelled")},handler:async()=>{let{pattern:y,route:h,params:g,query:N}=f,k=C(await h.component());t.set(g),n.set(N),o.update(()=>({route:h,component:k,resolved:y.pathname,path:c.pathname}));}});});let p=s(new URL(navigation.currentEntry?.url??""));return p&&u(p),{params:U(t),query:w(n),state:w(o),match:a,base:e}};var $=new(typeof MutationObserver<"u"?class extends MutationObserver{pendingMounts=new Set;activeUnmounts=new Map;constructor(){super(()=>{this.processLifecycle();});}processLifecycle(){for(let e of this.pendingMounts){let{node:r,callback:t}=e;if(r.isConnected){let n=t();if(typeof n=="function"){let a=this.activeUnmounts.get(r);a||(a=new Set,this.activeUnmounts.set(r,a)),a.add(n);}this.pendingMounts.delete(e);}}for(let[e,r]of this.activeUnmounts)if(!e.isConnected){for(let t of r)t();this.activeUnmounts.delete(e);}}start(e){this.observe(e,{childList:true,subtree:true});}trackMount(e,r){this.pendingMounts.add({node:e,callback:r});}trackUnmount(e,r){let t=this.activeUnmounts.get(e);t||(t=new Set,this.activeUnmounts.set(e,t)),t.add(r);}}:class{start(){}trackUnmount(){}trackMount(){}disconnect(){}}),j=e=>{for(let r of e)r.remove();};var z=/<!--(nø-.{6})-->/g,x=()=>{let e="";return {fragmentId:true,create:r=>{e=`n\xF8-${r.padStart(6,"0")}`;},get:()=>e}},G=Symbol.for("nord.component"),T=new WeakMap,K=/^(disabled|checked|readonly|required|hidden|open|selected|autofocus|multiple)$/,Q=(e,r,t,n)=>{let a=T.get(e);a||(a=new Map,T.set(e,a));let o=a.get(r);o||(o=n,a.set(r,o));let s=K.test(r),l=o.indexOf(t);return l===-1?()=>{}:u=>{o[l]=String(u);let m=o.join("");if(!s){e.setAttribute(r,m);return}m==="false"||!m?e.removeAttribute(r):e.setAttribute(r,"");}},V=(e,r)=>{let t=a=>a.nodeType===1||a.nodeType===8;t(e)&&r(e);let n=e.firstChild;for(;n;){if(t(n)&&r(n),n.firstChild){n=n.firstChild;continue}for(;n&&n!==e;){if(n.nextSibling){n=n.nextSibling;break}n=n.parentNode;}if(n===e)return}},_=(e,r,t)=>{let n=[];return V(e,a=>{if(a instanceof Comment){let o=a.data;if(o.startsWith("n\xF8-")){let s=o.slice(3),l=Number.parseInt(s,10),u=r[l];u&&n.push({fragment:u,args:[a]});}}if(a instanceof Element){let o=[...a.attributes];for(let{name:s,value:l}of o){if(s.startsWith("n\xF8-")){let m=Number.parseInt(s.slice(3),10),p=r[m];p&&(n.push({fragment:p,args:[a]}),a.removeAttribute(s));continue}if(!l.includes("n\xF8-"))continue;let u=l.split(z);for(let m of u)if(m.startsWith("n\xF8-")){let p=Number.parseInt(m.slice(3),10),i=r[p];if(i){let c=Q(a,s,m,u);n.push({fragment:i,args:[a,{binding:c}]});}}}t&&a.setAttribute(t,"");}}),n},P=new Map,B=e=>{let r=P.get(e);if(r&&r.ownerDocument===document)return r;let t=document.createElement("template");return t.innerHTML=e.trim(),P.set(e,t),t},X=(e,r)=>{let t=e.join(""),n=x();return {fragmentId:n,[G]:true,resolve:()=>`<!--${n.get()}-->`,render:()=>e.filter((a,o)=>o%2===0).flatMap((a,o)=>[a,r[o]?.render()??""]).join(""),hydrate:(a,o)=>{if(!(a instanceof Comment))return;let s=B(t).content.cloneNode(true);for(let{fragment:l,args:u}of _(s,r,o?.scope))l.hydrate(...u);a.replaceWith(s);}}},Y=e=>{let r=x();return {fragmentId:r,resolve:()=>`<!--${r.get()}-->`,render:()=>String(e),hydrate:(t,{binding:n}={})=>{if(t instanceof Comment)return t.replaceWith(new Text(String(e)));t instanceof Element&&n?.(e);}}},Z=e=>{let r=x();return {fragmentId:r,resolve:()=>`<!--${r.get()}-->`,render:()=>String(e()??""),hydrate:(t,{binding:n}={})=>{if(t instanceof Comment){let a=new Text(String(e()??""));t.replaceWith(a);let o=e.subscribe(s=>{a.textContent=String(s??"");});o&&$.trackUnmount(a,o);}if(t instanceof Element){n?.(e()??"");let a=e.subscribe(o=>{n?.(o??"");});a&&$.trackUnmount(t,a);}}}},J=e=>["string","boolean","number","bigint"].includes(typeof e),ee=e=>e!==null&&typeof e=="function"&&"subscribe"in e,te=e=>e.replace(/\s{2,}/g," "),re=e=>{switch(true){case ee(e):return Z(e);case(J(e)||e==null):return Y(e??"");default:return e}},S=(e,...r)=>{let t=[],n=e.flatMap((a,o)=>[te(a),(()=>{let s=re(r[o]);return "fragmentId"in s&&s.fragmentId.create(String(o)),t.push(s),s.resolve()})()]);return X(n.flat(),t)},F=e=>{let r=x();return {fragmentId:r,resolve:()=>r.get(),render:()=>"",hydrate:t=>{if(t instanceof Element){let n=e(t);n&&$.trackUnmount(t,n);}}}};var ne=e=>{let r=document.createElement("template"),t=new Comment;return r.content.append(t),e.hydrate(t),Array.from(r.content.childNodes)},ae=(e,r=()=>"")=>{let t=x();return {fragmentId:t,resolve:()=>`<!--${t.get()}-->`,render:()=>r(),hydrate:n=>{if(n instanceof Comment){let a=e(n);a&&$.trackUnmount(n,a);}}}};var A=e=>ae(r=>{let t=[],n=o=>{j(t);let s=typeof o=="function"?o():o;t=ne(s),r.before(...t);};n(e());let a=e.subscribe(n);return ()=>{a?.(),j(t),t=[];}},()=>e().render());var oe=(e,{exact:r}={exact:true})=>F(t=>{let n=()=>{let a=t.getAttribute("href"),o=navigation.currentEntry?.url;if(!o||!a)return;let s=new URL(o);t.classList.toggle(e,r?s.pathname===a:s.pathname.startsWith(a));};return navigation.addEventListener("navigatesuccess",n),()=>navigation.removeEventListener("navigatesuccess",n)});var se=e=>({run:"pre",handler:e}),ie=e=>({run:"post",handler:e});var le=({for:e,transitionElement:r})=>{let t=v(S``),n=`outlet-${e.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return e.state.subscribe(a=>{let{component:o,route:s}=a,l=o??S``;if(!s?.transition)return t.set(l);let u=r?.current??document.documentElement;u.style.viewTransitionName=n,document.startViewTransition(()=>t.set(l)).ready.then(()=>{[s.transition??[]].flat().forEach(({keyframes:i,...c})=>{document.documentElement.animate(i,{pseudoElement:c.element?.replace("(root)",`(${n})`)?.replace("(outlet)",`(${n})`),...c});});});}),A(t)};var d=e=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...e});var ce=e=>[d({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:e}),d({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:e})],ue=(e,r="right")=>{let t=r==="left"||r==="right"?"X":"Y",n=r==="right"||r==="down"?"":"-";return [d({keyframes:[{transform:`translate${t}(${n}100%)`},{transform:`translate${t}(0)`}],element:"::view-transition-new(root)",duration:e}),d({keyframes:[{transform:`translate${t}(0)`},{transform:`translate${t}(${n===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:e})]},me=e=>[d({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:e}),d({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:e})],fe=e=>[d({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:e})];
2
- exports.$outlet=le;exports.active=oe;exports.createRouter=D;exports.crossFade=ce;exports.fade=fe;exports.navigate=E;exports.post=ie;exports.pre=se;exports.scale=me;exports.slide=ue;return exports;})({});//# sourceMappingURL=index.global.js.map
1
+ var Nord=(function(exports){'use strict';var U=(e,r)=>Object.assign(()=>r(e()),{subscribe(t){return e.subscribe(n=>{t(r(n));})}});var G=(e,r)=>Object.is(e,r),h=(e,r=G)=>{let t=e,n=new Set,o=()=>{for(let s of Array.from(n))s(t);},a=s=>{r(t,s)||(t=s,o());};return Object.assign(()=>t,{set:a,update:s=>a(s(t)),subscribe:s=>(n.add(s),()=>n.delete(s))})},R=e=>Object.assign(()=>e(),{subscribe:e.subscribe});var H=e=>"default"in e?e.default():typeof e=="function"?e():e;var b=(e,r)=>{for(let{handler:t}of e)if(t({...r})===false)return false;return true};var N=e=>{navigation.navigate(typeof e=="string"?e:e.path,typeof e=="string"?{}:e??{});};var L=e=>Object.fromEntries(Object.entries(e?.pathname?.groups??{}).filter(([r,t])=>t!==void 0));var j=e=>{let r=R(e);return Object.assign(r,{select:t=>U(e,t)})};var T=new Map,F=(e,r)=>{for(let t of r){let n=new URL(t.path,`http://localhost${e}`);T.set(new URLPattern({pathname:n.pathname}),t);}return {match:t=>[...T.entries()].find(([n])=>n.test(t))??null}};var K=e=>e.canIntercept&&!e.hashChange&&!e.downloadRequest&&!e.formData,Q=(e,r)=>{let t=h({}),n=h({}),{match:o}=F(e,r),a=h({resolved:null,component:null,path:null,route:null}),s=i=>{let[l,c]=o(i)??[];return !l||!c?null:{params:L(l.exec(i)),query:Object.fromEntries(i.searchParams),resolved:l.pathname,path:i.pathname,pattern:l,route:c,url:i}},u=async i=>{let{pattern:l,route:c,params:v,query:y,url:w}=i,x=new Set,$=d=>{x.add(()=>queueMicrotask(()=>{N({path:d,history:"replace"});}));},f=(c.use??[]).filter(d=>d.run==="pre");if(!b(f,{...i,redirect:$})){let[d]=x.values();return x.clear(),d?.()}let E=(c.use??[]).filter(d=>d.run==="load");b(E,{...i,redirect:$});let O=H(await c.component());t.set(v),n.set(y),a.update(()=>({route:c,component:O,resolved:l.pathname,path:w.pathname}));},m=i=>r.some(l=>l===i);navigation.addEventListener("navigate",i=>{if(!K(i))return;let l=new URL(i.destination.url),c=s(l);if(!c||!m(c.route))return;let v=true,y=new Set,w=f=>{y.add(()=>queueMicrotask(()=>{N({path:f,history:"replace"});}));},x=(a().route?.use??[]).filter(f=>f.run==="post");v=b(x,{...a(),params:t(),query:n(),redirect:w});let $=(c.route.use??[]).filter(f=>f.run==="pre");if(v=v&&b($,{...c,redirect:w}),!v){i.preventDefault();let[f]=y.values();return y.clear(),f?.()}i.intercept({scroll:"after-transition",handler:async()=>{let{pattern:f,route:C,params:E,query:O}=c,d=H(await C.component()),D=(C.use??[]).filter(z=>z.run==="load");b(D,{...c,redirect:w}),t.set(E),n.set(O),a.update(()=>({route:C,component:d,resolved:f.pathname,path:l.pathname}));}});});let p=s(new URL(navigation.currentEntry?.url??""));return p&&u(p),{params:j(t),query:R(n),state:R(a),match:o,base:e}};var S=new(typeof MutationObserver<"u"?class extends MutationObserver{pendingMounts=new Set;activeUnmounts=new Map;constructor(){super(()=>{this.processLifecycle();});}processLifecycle(){for(let e of this.pendingMounts){let{node:r,callback:t}=e;if(r.isConnected){let n=t();if(typeof n=="function"){let o=this.activeUnmounts.get(r);o||(o=new Set,this.activeUnmounts.set(r,o)),o.add(n);}this.pendingMounts.delete(e);}}for(let[e,r]of this.activeUnmounts)if(!e.isConnected){for(let t of r)t();this.activeUnmounts.delete(e);}}start(e){this.observe(e,{childList:true,subtree:true});}trackMount(e,r){this.pendingMounts.add({node:e,callback:r});}trackUnmount(e,r){let t=this.activeUnmounts.get(e);t||(t=new Set,this.activeUnmounts.set(e,t)),t.add(r);}}:class{start(){}trackUnmount(){}trackMount(){}disconnect(){}}),P=e=>{for(let r of e)r.remove();};var V=/<!--(nø-.{6})-->/g,k=()=>{let e="";return {fragmentId:true,create:r=>{e=`n\xF8-${r.padStart(6,"0")}`;},get:()=>e}},_=Symbol.for("nord.component"),A=new WeakMap,B=/^(disabled|checked|readonly|required|hidden|open|selected|autofocus|multiple)$/,X=(e,r,t,n)=>{let o=A.get(e);o||(o=new Map,A.set(e,o));let a=o.get(r);a||(a=n,o.set(r,a));let s=B.test(r),u=a.indexOf(t);return u===-1?()=>{}:m=>{a[u]=String(m);let p=a.join("");if(!s){e.setAttribute(r,p);return}p==="false"||!p?e.removeAttribute(r):e.setAttribute(r,"");}},Y=(e,r)=>{let t=o=>o.nodeType===1||o.nodeType===8;t(e)&&r(e);let n=e.firstChild;for(;n;){if(t(n)&&r(n),n.firstChild){n=n.firstChild;continue}for(;n&&n!==e;){if(n.nextSibling){n=n.nextSibling;break}n=n.parentNode;}if(n===e)return}},Z=(e,r,t)=>{let n=[];return Y(e,o=>{if(o instanceof Comment){let a=o.data;if(a.startsWith("n\xF8-")){let s=a.slice(3),u=Number.parseInt(s,10),m=r[u];m&&n.push({fragment:m,args:[o]});}}if(o instanceof Element){let a=[...o.attributes];for(let{name:s,value:u}of a){if(s.startsWith("n\xF8-")){let p=Number.parseInt(s.slice(3),10),i=r[p];i&&(n.push({fragment:i,args:[o]}),o.removeAttribute(s));continue}if(!u.includes("n\xF8-"))continue;let m=u.split(V);for(let p of m)if(p.startsWith("n\xF8-")){let i=Number.parseInt(p.slice(3),10),l=r[i];if(l){let c=X(o,s,p,m);n.push({fragment:l,args:[o,{binding:c}]});}}}t&&o.setAttribute(t,"");}}),n},I=new Map,J=e=>{let r=I.get(e);if(r&&r.ownerDocument===document)return r;let t=document.createElement("template");return t.innerHTML=e.trim(),I.set(e,t),t},ee=(e,r)=>{let t=e.join(""),n=k();return {fragmentId:n,[_]:true,resolve:()=>`<!--${n.get()}-->`,render:()=>e.filter((o,a)=>a%2===0).flatMap((o,a)=>[o,r[a]?.render()??""]).join(""),hydrate:(o,a)=>{if(!(o instanceof Comment))return;let s=J(t).content.cloneNode(true);for(let{fragment:u,args:m}of Z(s,r,a?.scope))u.hydrate(...m);o.replaceWith(s);}}},te=e=>{let r=k();return {fragmentId:r,resolve:()=>`<!--${r.get()}-->`,render:()=>String(e),hydrate:(t,{binding:n}={})=>{if(t instanceof Comment)return t.replaceWith(new Text(String(e)));t instanceof Element&&n?.(e);}}},re=e=>{let r=k();return {fragmentId:r,resolve:()=>`<!--${r.get()}-->`,render:()=>String(e()??""),hydrate:(t,{binding:n}={})=>{if(t instanceof Comment){let o=new Text(String(e()??""));t.replaceWith(o);let a=e.subscribe(s=>{o.textContent=String(s??"");});a&&S.trackUnmount(o,a);}if(t instanceof Element){n?.(e()??"");let o=e.subscribe(a=>{n?.(a??"");});o&&S.trackUnmount(t,o);}}}},ne=e=>["string","boolean","number","bigint"].includes(typeof e),oe=e=>e!==null&&typeof e=="function"&&"subscribe"in e,ae=e=>e.replace(/\s{2,}/g," "),se=e=>{switch(true){case oe(e):return re(e);case(ne(e)||e==null):return te(e??"");default:return e}},M=(e,...r)=>{let t=[],n=e.flatMap((o,a)=>[ae(o),(()=>{let s=se(r[a]);return "fragmentId"in s&&s.fragmentId.create(String(a)),t.push(s),s.resolve()})()]);return ee(n.flat(),t)},q=e=>{let r=k();return {fragmentId:r,resolve:()=>r.get(),render:()=>"",hydrate:t=>{if(t instanceof Element){let n=e(t);n&&S.trackUnmount(t,n);}}}};var ie=e=>{let r=document.createElement("template"),t=new Comment;return r.content.append(t),e.hydrate(t),Array.from(r.content.childNodes)},ce=(e,r=()=>"")=>{let t=k();return {fragmentId:t,resolve:()=>`<!--${t.get()}-->`,render:()=>r(),hydrate:n=>{if(n instanceof Comment){let o=e(n);o&&S.trackUnmount(n,o);}}}};var W=e=>ce(r=>{let t=[],n=a=>{P(t);let s=typeof a=="function"?a():a;t=ie(s),r.before(...t);};n(e());let o=e.subscribe(n);return ()=>{o?.(),P(t),t=[];}},()=>e().render());var le=(e,{exact:r}={exact:true})=>q(t=>{let n=()=>{let o=t.getAttribute("href"),a=navigation.currentEntry?.url;if(!a||!o)return;let s=new URL(a);t.classList.toggle(e,r?s.pathname===o:s.pathname.startsWith(o));};return navigation.addEventListener("navigatesuccess",n),()=>navigation.removeEventListener("navigatesuccess",n)});var ue=e=>({run:"pre",handler:e}),me=e=>({run:"post",handler:e}),pe=e=>({run:"load",handler:e});var fe=({for:e,transitionElement:r})=>{let t=h(M``),n=`outlet-${e.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return e.state.subscribe(o=>{let{component:a,route:s}=o,u=a??M``;if(!s?.transition)return t.set(u);let m=r?.current??document.documentElement;m.style.viewTransitionName=n,document.startViewTransition(()=>t.set(u)).ready.then(()=>{[s.transition??[]].flat().forEach(({keyframes:l,...c})=>{document.documentElement.animate(l,{pseudoElement:c.element?.replace("(root)",`(${n})`)?.replace("(outlet)",`(${n})`),...c});});});}),W(t)};var g=e=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...e});var de=e=>[g({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:e}),g({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:e})],ge=(e,r="right")=>{let t=r==="left"||r==="right"?"X":"Y",n=r==="right"||r==="down"?"":"-";return [g({keyframes:[{transform:`translate${t}(${n}100%)`},{transform:`translate${t}(0)`}],element:"::view-transition-new(root)",duration:e}),g({keyframes:[{transform:`translate${t}(0)`},{transform:`translate${t}(${n===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:e})]},ve=e=>[g({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:e}),g({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:e})],he=e=>[g({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:e})];
2
+ exports.$outlet=fe;exports.active=le;exports.createRouter=Q;exports.crossFade=de;exports.fade=he;exports.load=pe;exports.navigate=N;exports.post=me;exports.pre=ue;exports.scale=ve;exports.slide=ge;return exports;})({});//# sourceMappingURL=index.global.js.map
3
3
  //# sourceMappingURL=index.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../grains/src/derived.ts","../../../grains/src/grain.ts","../../../grains/src/readonly.ts","../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../../nord/src/application/lifecycle-observer.ts","../../../nord/src/internals/identifier.ts","../../../nord/src/component/component-fragment.ts","../../../nord/src/internals/attribute-bindings.ts","../../../nord/src/internals/iterate-nodes.ts","../../../nord/src/component/hydrate-component-template.ts","../../../nord/src/component/create-component-fragment.ts","../../../nord/src/internals/create-primitive-fragment.ts","../../../nord/src/internals/create-reactive-fragment.ts","../../../nord/src/internals/is-primitive-value.ts","../../../nord/src/internals/is-subscribable-value.ts","../../../nord/src/internals/trim-whitespace.ts","../../../nord/src/application/template-parser.ts","../../../nord/src/directives/create-directive.ts","../../../nord/src/internals/hydrate-fragment.ts","../../../nord/src/structs/create-struct.ts","../../../nord/src/structs/render.struct.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["derived","source","run","subscriber","value","defaultCompareFn","current","next","grain","start","compareFunc","_value","consumers","notifyConsumers","consumer","set","newValue","updater","readonly","getFragment","resolved","resolveHooks","hooks","context","handler","path","navigate","getPathParamGroup","result","_","parameterized","internal","read","p","fn","u","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","V","query","match","state","getURLState","redirect","setRouterState","matchedParams","matchedQuery","preHooks","hook","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","lifecycleObserver","entry","node","callback","cleanup","unmounts","callbacks","disconnectNodes","nodes","identifierRegex","createIdentifier","_id","idx","IS_COMPONENT","nodeState","booleanAttributes","createAttributeBinding","attributeName","marker","initialParts","bindings","parts","isBoolean","partIndex","attributeValue","iterateNodes","root","work","shouldProcess","n","hydrateComponentTemplate","fragments","scope","hydrationUnits","content","id","attrs","name","matches","binding","templateCache","getTemplate","html","template","created","createComponentFragment","fragmentId","i","str","def","args","createPrimitiveFragment","fragmentValue","createReactiveFragment","text","onDestroy","isPrimitiveValue","isSubscribableValue","trimWhitespace","parseTemplateFragment","templateParser","stringFragments","valueFragments","strFragment","createDirective","hydrateFragment","anchor","createStruct","struct","snapshot","$render","render","maybeFragment","ondestroy","active","cls","exact","h","href","destination","pre","post","$outlet","router","transitionRef","currentComponent","$","component","target","keyframes","props","oe","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"yCA2CO,IAAMA,CAAAA,CAAU,CAAOC,CAAAA,CAAkBC,CAAAA,GACrC,MAAA,CAAO,MAAA,CAAO,IAAMA,CAAAA,CAAID,CAAAA,EAAQ,CAAA,CAAG,CACtC,UAAUE,CAAAA,CAA2B,CACjC,OAAOF,CAAAA,CAAO,SAAA,CAAWG,CAAAA,EAAU,CAC/BD,CAAAA,CAAWD,EAAIE,CAAK,CAAC,EACzB,CAAC,CACL,CACJ,CAAC,CAAA,CCpBL,IAAMC,CAAAA,CAAmB,CAAcC,CAAAA,CAAYC,CAAAA,GAAY,MAAA,CAAO,EAAA,CAAGD,CAAAA,CAASC,CAAI,CAAA,CA2EzEC,CAAAA,CAAQ,CAAcC,CAAAA,CAAUC,CAAAA,CAA4BL,CAAAA,GAAuC,CAC5G,IAAIM,EAASF,CAAAA,CACPG,CAAAA,CAAY,IAAI,GAAA,CAEhBC,CAAAA,CAAkB,IAAM,CAC1B,IAAA,IAAWC,KAAY,KAAA,CAAM,IAAA,CAAKF,CAAS,CAAA,CAAGE,CAAAA,CAASH,CAAM,EACjE,CAAA,CAEMI,EAAOC,CAAAA,EAAgB,CACpBN,CAAAA,CAAYC,CAAAA,CAAQK,CAAQ,CAAA,GAC7BL,CAAAA,CAASK,CAAAA,CACTH,CAAAA,EAAAA,EAER,CAAA,CASA,OAAO,MAAA,CAAO,MAAA,CAAO,IAAMF,CAAAA,CAAQ,CAAE,GAAA,CAAAI,CAAAA,CAAK,MAAA,CAP1BE,CAAAA,EAA+BF,CAAAA,CAAIE,CAAAA,CAAQN,CAAM,CAAC,EAOhB,SAAA,CAL/BR,CAAAA,GACfS,CAAAA,CAAU,GAAA,CAAIT,CAAU,CAAA,CACjB,IAAMS,CAAAA,CAAU,OAAOT,CAAU,CAAA,CAGgB,CAAC,CACjE,CAAA,CCjHae,CAAAA,CAAejB,CAAAA,EACjB,MAAA,CAAO,OAAO,IAAMA,CAAAA,EAAAA,CAAU,CACjC,SAAA,CAAWA,CAAAA,CAAO,SACtB,CAAC,EChBE,IAAMkB,CAAAA,CAAeC,CAAAA,EACpB,SAAA,GAAaA,CAAAA,CACNA,CAAAA,CAAS,OAAA,EAAQ,CAGxB,OAAOA,CAAAA,EAAa,UAAA,CACbA,CAAAA,EAAS,CAGbA,CAAAA,CCTJ,IAAMC,CAAAA,CAAe,MAAOC,EAAyBC,CAAAA,GAAqD,CAC7G,IAAA,GAAW,CAAE,OAAA,CAAAC,CAAQ,CAAA,GAAKF,CAAAA,CAStB,GARe,MAAME,CAAAA,CAAQ,CACzB,GAAGD,CAAAA,CACH,QAAA,CAAWE,CAAAA,EACA,WAAW,QAAA,CAASA,CAAI,CAEvC,CAAC,CAAA,GAGc,KAAA,CAAO,OAAO,MAAA,CAGjC,OAAO,KACX,CAAA,CChBO,IAAMC,CAAAA,CAAYD,CAAAA,EAAiB,UAAA,CAAW,QAAA,CAASA,CAAI,ECA3D,IAAME,CAAAA,CAAqBC,CAAAA,EACvB,MAAA,CAAO,WAAA,CACV,MAAA,CAAO,OAAA,CAAQA,CAAAA,EAAQ,QAAA,EAAU,MAAA,EAAU,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,CAACC,EAAGzB,CAAK,CAAA,GACrDA,CAAAA,GAAU,MACpB,CACL,CAAA,CCHG,IAAM0B,CAAAA,CAAiBC,GAA4C,CACtE,IAAMC,CAAAA,CAAOC,CAAAA,CAASF,CAAQ,CAAA,CAE9B,OAAO,MAAA,CAAO,OAAOC,CAAAA,CAAM,CACvB,MAAA,CAA2BE,CAAAA,EAChBC,CAAAA,CAAQJ,CAAAA,CAAUG,CAAgD,CAEjF,CAAC,CACL,CAAA,CCRO,IAAME,CAAAA,CAAW,IAAI,GAAA,CAEfC,CAAAA,CAAuB,CAACC,CAAAA,CAAcC,CAAAA,GAAoB,CACnE,IAAA,IAAWC,CAAAA,IAASD,CAAAA,CAAQ,CACxB,IAAME,EAAa,IAAI,GAAA,CAAID,CAAAA,CAAM,IAAA,CAAM,CAAA,gBAAA,EAAmBF,CAAI,CAAA,CAAE,CAAA,CAChEF,EAAS,GAAA,CAAI,IAAI,UAAA,CAAW,CAAE,QAAA,CAAUK,CAAAA,CAAW,QAAS,CAAC,EAAGD,CAAK,EACzE,CAEA,OAAO,CACH,KAAA,CAAQE,CAAAA,EACG,CAAC,GAAGN,CAAAA,CAAS,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAACO,CAAO,IAAMA,CAAAA,CAAQ,IAAA,CAAKD,CAAG,CAAC,CAAA,EAAK,IAEjF,CACJ,CAAA,KCEME,CAAAA,CAAiBC,CAAAA,EACZA,CAAAA,CAAM,YAAA,EAAgB,CAACA,CAAAA,CAAM,UAAA,EAAc,CAACA,CAAAA,CAAM,eAAA,EAAmB,CAACA,CAAAA,CAAM,QAAA,CAG1EC,CAAAA,CAAe,CAACR,CAAAA,CAAcC,IAAoB,CAC3D,IAAMQ,CAAAA,CAASC,CAAAA,CAAM,EAAE,CAAA,CACjBC,CAAAA,CAAQD,EAA8B,EAAE,CAAA,CAExC,CAAE,KAAA,CAAAE,CAAM,CAAA,CAAIb,CAAAA,CAAqBC,EAAMC,CAAM,CAAA,CAC7CY,CAAAA,CAAQH,CAAAA,CAA2B,CAAE,QAAA,CAAU,IAAA,CAAM,SAAA,CAAW,IAAA,CAAM,IAAA,CAAM,IAAA,CAAM,KAAA,CAAO,IAAK,CAAC,CAAA,CAE/FI,CAAAA,CAAeV,GAAa,CAC9B,GAAM,CAACC,CAAAA,CAASH,CAAK,CAAA,CAAIU,CAAAA,CAAMR,CAAG,GAAK,EAAC,CACxC,OAAI,CAACC,CAAAA,EAAW,CAACH,CAAAA,CAAc,IAAA,CAExB,CACH,MAAA,CAAQb,CAAAA,CAAkBgB,CAAAA,CAAQ,IAAA,CAAKD,CAAG,CAAC,CAAA,CAC3C,KAAA,CAAO,MAAA,CAAO,WAAA,CAAYA,CAAAA,CAAI,YAAY,CAAA,CAC1C,QAAA,CAAUC,CAAAA,CAAQ,QAAA,CAClB,KAAMD,CAAAA,CAAI,QAAA,CACV,OAAA,CAASC,CAAAA,CACT,KAAA,CAAOH,CAAAA,CACP,GAAA,CAAKE,CACT,CACJ,CAAA,CAEMW,CAAAA,CAAY5B,CAAAA,EAAiB,CAC/B,cAAA,CAAe,IAAM,CACjBC,CAAAA,CAASD,CAAI,EACjB,CAAC,EACL,CAAA,CAEM6B,CAAAA,CAAiB,MAAO/C,CAAAA,EAAsD,CAChF,GAAM,CAAE,OAAA,CAAAoC,CAAAA,CAAS,KAAA,CAAAH,CAAAA,CAAO,MAAA,CAAQe,CAAAA,CAAe,KAAA,CAAOC,EAAc,GAAA,CAAAd,CAAI,CAAA,CAAInC,CAAAA,CAGtEkD,CAAAA,CAAAA,CAAYjB,CAAAA,CAAM,GAAA,EAAO,IAAI,MAAA,CAAQkB,CAAAA,EAASA,CAAAA,CAAK,GAAA,GAAQ,KAAK,CAAA,CAGtE,GAAI,CAFgB,MAAMrC,CAAAA,CAAaoC,CAAAA,CAAU,CAAE,GAAGlD,CAAAA,CAAM,QAAA,CAAA8C,CAAS,CAAC,CAAA,CAEpD,OAElB,IAAMM,CAAAA,CAAWxC,CAAAA,CAAY,MAAMqB,CAAAA,CAAM,SAAA,EAAW,CAAA,CACpDO,CAAAA,CAAO,GAAA,CAAIQ,CAAa,CAAA,CACxBN,CAAAA,CAAM,GAAA,CAAIO,CAAY,EACtBL,CAAAA,CAAM,MAAA,CAAO,KACF,CACH,KAAA,CAAAX,CAAAA,CACA,SAAA,CAAWmB,CAAAA,CACX,SAAUhB,CAAAA,CAAQ,QAAA,CAClB,IAAA,CAAMD,CAAAA,CAAI,QACd,CAAA,CACH,EACL,CAAA,CAEMkB,CAAAA,CAAcpB,CAAAA,EACTD,CAAAA,CAAO,IAAA,CAAMsB,CAAAA,EAAaA,CAAAA,GAAarB,CAAK,CAAA,CAGvD,WAAW,gBAAA,CAAiB,UAAA,CAAaK,CAAAA,EAAU,CAC/C,GAAI,CAACD,CAAAA,CAAcC,CAAK,EAAG,OAC3B,IAAMH,CAAAA,CAAM,IAAI,GAAA,CAAIG,CAAAA,CAAM,WAAA,CAAY,GAAG,EAEnCiB,CAAAA,CAAYV,CAAAA,CAAYV,CAAG,CAAA,CACjC,GAAI,CAACoB,CAAAA,EAAa,CAACF,CAAAA,CAAWE,CAAAA,CAAU,KAAK,CAAA,CAAG,OAChD,IAAIC,CAAAA,CAAc,IAAA,CAElBlB,EAAM,SAAA,CAAU,CACZ,MAAA,CAAQ,kBAAA,CACR,gBAAA,CAAkB,SAAY,CAE1B,IAAMmB,GAAab,CAAAA,EAAM,CAAE,KAAA,EAAO,GAAA,EAAO,EAAC,EAAG,MAAA,CAAQO,CAAAA,EAASA,EAAK,GAAA,GAAQ,MAAM,CAAA,CACjFK,CAAAA,CAAc,MAAM1C,CAAAA,CAAa2C,CAAAA,CAAW,CAAE,GAAGb,CAAAA,EAAM,CAAG,MAAA,CAAQJ,CAAAA,EAAO,CAAG,KAAA,CAAOE,CAAAA,EAAM,CAAG,SAAAI,CAAS,CAAC,CAAA,CAGtG,IAAMI,CAAAA,CAAAA,CAAYK,CAAAA,CAAU,KAAA,CAAM,GAAA,EAAO,EAAC,EAAG,MAAA,CAAQJ,CAAAA,EAASA,CAAAA,CAAK,GAAA,GAAQ,KAAK,CAAA,CAIhF,GAHAK,EAAc,MAAM1C,CAAAA,CAAaoC,CAAAA,CAAU,CAAE,GAAGK,CAAAA,CAAW,QAAA,CAAAT,CAAS,CAAC,CAAA,CAGjE,CAACU,CAAAA,CAAa,MAAM,IAAI,KAAA,CAAM,sBAAsB,CAC5D,CAAA,CACA,OAAA,CAAS,SAAY,CAEjB,GAAM,CAAE,OAAA,CAAApB,CAAAA,CAAS,MAAAH,CAAAA,CAAO,MAAA,CAAQe,CAAAA,CAAe,KAAA,CAAOC,CAAa,CAAA,CAAIM,CAAAA,CACjEH,CAAAA,CAAWxC,EAAY,MAAMqB,CAAAA,CAAM,SAAA,EAAW,CAAA,CACpDO,CAAAA,CAAO,GAAA,CAAIQ,CAAa,CAAA,CACxBN,CAAAA,CAAM,GAAA,CAAIO,CAAY,CAAA,CACtBL,CAAAA,CAAM,MAAA,CAAO,KACF,CACH,KAAA,CAAAX,CAAAA,CACA,SAAA,CAAWmB,CAAAA,CACX,QAAA,CAAUhB,CAAAA,CAAQ,QAAA,CAClB,IAAA,CAAMD,EAAI,QACd,CAAA,CACH,EACL,CACJ,CAAC,EACL,CAAC,CAAA,CAGD,IAAMpC,CAAAA,CAAU8C,CAAAA,CAAY,IAAI,GAAA,CAAI,UAAA,CAAW,YAAA,EAAc,GAAA,EAAO,EAAE,CAAC,CAAA,CACvE,OAAI9C,CAAAA,EAASgD,CAAAA,CAAehD,CAAO,CAAA,CAE5B,CACH,OAAQwB,CAAAA,CAAciB,CAAM,CAAA,CAC5B,KAAA,CAAOd,CAAAA,CAASgB,CAAK,CAAA,CACrB,KAAA,CAAOhB,EAASkB,CAAK,CAAA,CACrB,KAAA,CAAAD,CAAAA,CACA,IAAA,CAAAZ,CACJ,CACJ,EC9HO,IAAM2B,CAAAA,CAAoB,IAC7B,OAAO,gBAAA,CAAqB,GAAA,CACtB,cAAgC,gBAAiB,CAK7C,cAAgB,IAAI,GAAA,CAIpB,cAAA,CAAiB,IAAI,GAAA,CAErB,WAAA,EAAc,CAGV,KAAA,CAAM,IAAM,CACR,IAAA,CAAK,gBAAA,GACT,CAAC,EACL,CAEA,gBAAA,EAAmB,CACf,IAAA,IAAWC,CAAAA,IAAS,IAAA,CAAK,aAAA,CAAe,CACpC,GAAM,CAAE,IAAA,CAAAC,EAAM,QAAA,CAAAC,CAAS,CAAA,CAAIF,CAAAA,CAK3B,GAAIC,CAAAA,CAAK,WAAA,CAAa,CAClB,IAAME,CAAAA,CAAUD,CAAAA,EAAAA,CAGhB,GAAI,OAAOC,CAAAA,EAAY,UAAA,CAAY,CAC/B,IAAIC,CAAAA,CAAW,IAAA,CAAK,cAAA,CAAe,GAAA,CAAIH,CAAI,CAAA,CACtCG,CAAAA,GACDA,EAAW,IAAI,GAAA,CACf,IAAA,CAAK,cAAA,CAAe,GAAA,CAAIH,CAAAA,CAAMG,CAAQ,CAAA,CAAA,CAE1CA,EAAS,GAAA,CAAID,CAAO,EACxB,CAGA,IAAA,CAAK,aAAA,CAAc,MAAA,CAAOH,CAAK,EACnC,CACJ,CAIA,IAAA,GAAW,CAACC,CAAAA,CAAMI,CAAS,CAAA,GAAK,KAAK,cAAA,CACjC,GAAI,CAACJ,CAAAA,CAAK,WAAA,CAAa,CACnB,IAAA,IAAWjC,CAAAA,IAAMqC,EAAWrC,CAAAA,EAAAA,CAC5B,IAAA,CAAK,cAAA,CAAe,MAAA,CAAOiC,CAAI,EACnC,CAER,CAEA,KAAA,CAAMA,CAAAA,CAAY,CACd,IAAA,CAAK,OAAA,CAAQA,CAAAA,CAAM,CAAE,SAAA,CAAW,IAAA,CAAM,OAAA,CAAS,IAAK,CAAC,EACzD,CAEA,UAAA,CAAWA,CAAAA,CAAYC,EAAqC,CACxD,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,CAAE,IAAA,CAAAD,CAAAA,CAAM,QAAA,CAAAC,CAAS,CAAC,EAC7C,CAEA,YAAA,CAAaD,CAAAA,CAAYC,CAAAA,CAAsB,CAC3C,IAAIE,EAAW,IAAA,CAAK,cAAA,CAAe,GAAA,CAAIH,CAAI,CAAA,CACtCG,CAAAA,GACDA,CAAAA,CAAW,IAAI,IACf,IAAA,CAAK,cAAA,CAAe,GAAA,CAAIH,CAAAA,CAAMG,CAAQ,CAAA,CAAA,CAE1CA,CAAAA,CAAS,GAAA,CAAIF,CAAQ,EACzB,CACJ,CAAA,CACA,KAAM,CACF,KAAA,EAAQ,CAAC,CACT,cAAe,CAAC,CAChB,UAAA,EAAa,CAAC,CACd,UAAA,EAAa,CAAC,CAClB,GAGGI,CAAAA,CAAmBC,CAAAA,EAAqB,CACjD,IAAA,IAAWN,CAAAA,IAAQM,CAAAA,CAAON,CAAAA,CAAK,MAAA,GACnC,CAAA,CCjFO,IAAMO,CAAAA,CAAkB,mBAAA,CAElBC,CAAAA,CAAmB,IAAM,CAClC,IAAIC,CAAAA,CAAM,EAAA,CAEV,OAAO,CACH,UAAA,CAAY,IAAA,CACZ,MAAA,CAASC,CAAAA,EAAgB,CACrBD,CAAAA,CAAM,CAAA,MAAA,EAAMC,CAAAA,CAAI,QAAA,CAAS,CAAA,CAAG,GAAG,CAAC,CAAA,EACpC,EACA,GAAA,CAAK,IAAMD,CACf,CACJ,CAAA,CCRaE,CAAAA,CAA8B,MAAA,CAAO,GAAA,CAAI,gBAAgB,CAAA,CCNhEC,CAAAA,CAAY,IAAI,OAAA,CAChBC,CAAAA,CAAoB,gFAAA,CAMbC,CAAAA,CAAyB,CAClCd,CAAAA,CACAe,CAAAA,CACAC,CAAAA,CACAC,CAAAA,GACC,CAKD,IAAIC,CAAAA,CAAWN,CAAAA,CAAU,IAAIZ,CAAI,CAAA,CAC5BkB,CAAAA,GACDA,CAAAA,CAAW,IAAI,GAAA,CACfN,CAAAA,CAAU,GAAA,CAAIZ,EAAMkB,CAAQ,CAAA,CAAA,CAKhC,IAAIC,CAAAA,CAAQD,CAAAA,CAAS,GAAA,CAAIH,CAAa,CAAA,CACjCI,CAAAA,GACDA,CAAAA,CAAQF,CAAAA,CACRC,CAAAA,CAAS,GAAA,CAAIH,CAAAA,CAAeI,CAAK,CAAA,CAAA,CAGrC,IAAMC,CAAAA,CAAYP,CAAAA,CAAkB,IAAA,CAAKE,CAAa,CAAA,CAChDM,CAAAA,CAAYF,CAAAA,CAAM,OAAA,CAAQH,CAAM,CAAA,CACtC,OAAIK,CAAAA,GAAc,EAAA,CAAW,IAAM,CAAC,CAAA,CAK5BpF,CAAAA,EAAmB,CACvBkF,CAAAA,CAAME,CAAS,CAAA,CAAI,MAAA,CAAOpF,CAAK,CAAA,CAC/B,IAAMqF,CAAAA,CAAiBH,EAAM,IAAA,CAAK,EAAE,CAAA,CAGpC,GAAI,CAACC,CAAAA,CAAW,CACZpB,CAAAA,CAAK,aAAae,CAAAA,CAAeO,CAAc,CAAA,CAC/C,MACJ,CAGAA,CAAAA,GAAmB,OAAA,EAAW,CAACA,EACzBtB,CAAAA,CAAK,eAAA,CAAgBe,CAAa,CAAA,CAClCf,CAAAA,CAAK,YAAA,CAAae,CAAAA,CAAe,EAAE,EAC7C,CACJ,CAAA,CCrDaQ,CAAAA,CAAe,CAACC,CAAAA,CAAYC,CAAAA,GAA4C,CACjF,IAAMC,CAAAA,CAAiBC,CAAAA,EAAoCA,CAAAA,CAAE,QAAA,GAAa,CAAA,EAAKA,CAAAA,CAAE,QAAA,GAAa,CAAA,CAE1FD,EAAcF,CAAI,CAAA,EAClBC,CAAAA,CAAKD,CAAI,CAAA,CAGb,IAAIrF,CAAAA,CAAuBqF,CAAAA,CAAK,WAChC,KAAOrF,CAAAA,EAAS,CAKZ,GAJIuF,CAAAA,CAAcvF,CAAO,CAAA,EACrBsF,CAAAA,CAAKtF,CAAO,CAAA,CAGZA,CAAAA,CAAQ,UAAA,CAAY,CACpBA,CAAAA,CAAUA,CAAAA,CAAQ,UAAA,CAClB,QACJ,CAGA,KAAOA,CAAAA,EAAWA,CAAAA,GAAYqF,CAAAA,EAAM,CAChC,GAAIrF,CAAAA,CAAQ,WAAA,CAAa,CACrBA,CAAAA,CAAUA,CAAAA,CAAQ,WAAA,CAClB,KACJ,CACAA,CAAAA,CAAUA,CAAAA,CAAQ,WACtB,CAEA,GAAIA,CAAAA,GAAYqF,CAAAA,CACZ,MAER,CACJ,CAAA,CCXaI,CAAAA,CAA2B,CAAC5B,EAAY6B,CAAAA,CAAuBC,CAAAA,GAAmB,CAC3F,IAAMC,CAAAA,CAAsC,EAAA,CAC5C,OAAAR,CAAAA,CAAavB,CAAAA,CAAO7D,CAAAA,EAAY,CAI5B,GAAIA,CAAAA,YAAmB,OAAA,CAAS,CAC5B,IAAM6F,CAAAA,CAAU7F,CAAAA,CAAQ,IAAA,CAExB,GAAI6F,CAAAA,CAAQ,UAAA,CAAW,QAAK,CAAA,CAAG,CAC3B,IAAMC,CAAAA,CAAKD,CAAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,CACpBtB,CAAAA,CAAM,MAAA,CAAO,SAASuB,CAAAA,CAAI,EAAE,CAAA,CAC5BzC,CAAAA,CAAWqC,CAAAA,CAAUnB,CAAG,CAAA,CAE1BlB,CAAAA,EACAuC,EAAe,IAAA,CAAK,CAAE,QAAA,CAAAvC,CAAAA,CAAU,IAAA,CAAM,CAACrD,CAAkB,CAAE,CAAC,EAEpE,CACJ,CAGA,GAAIA,CAAAA,YAAmB,OAAA,CAAS,CAE5B,IAAM+F,EAAQ,CAAC,GAAG/F,CAAAA,CAAQ,UAAU,CAAA,CACpC,IAAA,GAAW,CAAE,IAAA,CAAAgG,EAAM,KAAA,CAAAlG,CAAM,CAAA,GAAKiG,CAAAA,CAAO,CAGjC,GAAIC,CAAAA,CAAK,UAAA,CAAW,QAAK,CAAA,CAAG,CACxB,IAAMzB,CAAAA,CAAM,MAAA,CAAO,QAAA,CAASyB,CAAAA,CAAK,MAAM,CAAC,CAAA,CAAG,EAAE,CAAA,CACvC3C,CAAAA,CAAWqC,CAAAA,CAAUnB,CAAG,CAAA,CAE1BlB,IACAuC,CAAAA,CAAe,IAAA,CAAK,CAAE,QAAA,CAAAvC,CAAAA,CAAU,IAAA,CAAM,CAACrD,CAAO,CAAE,CAAC,CAAA,CACjDA,CAAAA,CAAQ,eAAA,CAAgBgG,CAAI,CAAA,CAAA,CAGhC,QACJ,CAIA,GAAI,CAAClG,CAAAA,CAAM,QAAA,CAAS,QAAK,CAAA,CAAG,SAC5B,IAAMmG,EAAUnG,CAAAA,CAAM,KAAA,CAAMsE,CAAe,CAAA,CAC3C,IAAA,IAAWxB,CAAAA,IAASqD,CAAAA,CAChB,GAAIrD,EAAM,UAAA,CAAW,QAAK,CAAA,CAAG,CACzB,IAAM2B,CAAAA,CAAM,MAAA,CAAO,QAAA,CAAS3B,EAAM,KAAA,CAAM,CAAC,CAAA,CAAG,EAAE,CAAA,CACxCS,CAAAA,CAAWqC,CAAAA,CAAUnB,CAAG,CAAA,CAE9B,GAAIlB,CAAAA,CAAU,CACV,IAAM6C,CAAAA,CAAUvB,CAAAA,CAAuB3E,CAAAA,CAASgG,EAAMpD,CAAAA,CAAOqD,CAAO,CAAA,CACpEL,CAAAA,CAAe,IAAA,CAAK,CAAE,QAAA,CAAAvC,CAAAA,CAAU,KAAM,CAACrD,CAAAA,CAAS,CAAE,OAAA,CAAAkG,CAAQ,CAAC,CAAE,CAAC,EAClE,CACJ,CAER,CAGIP,CAAAA,EACA3F,CAAAA,CAAQ,YAAA,CAAa2F,CAAAA,CAAO,EAAE,EAEtC,CACJ,CAAC,CAAA,CACMC,CACX,CAAA,CC9EMO,CAAAA,CAAgB,IAAI,GAAA,CACpBC,EAAeC,CAAAA,EAAiB,CAClC,IAAMC,CAAAA,CAAWH,CAAAA,CAAc,GAAA,CAAIE,CAAI,CAAA,CACvC,GAAIC,CAAAA,EAAYA,CAAAA,CAAS,aAAA,GAAkB,QAAA,CACvC,OAAOA,CAAAA,CAGX,IAAMC,CAAAA,CAAU,SAAS,aAAA,CAAc,UAAU,CAAA,CACjD,OAAAA,CAAAA,CAAQ,SAAA,CAAYF,CAAAA,CAAK,IAAA,EAAA,CACzBF,CAAAA,CAAc,GAAA,CAAIE,CAAAA,CAAME,CAAO,CAAA,CACxBA,CACX,CAAA,CAEaC,EAA0B,CAACF,CAAAA,CAAoBZ,CAAAA,GAA6C,CACrG,IAAMW,CAAAA,CAAOC,CAAAA,CAAS,IAAA,CAAK,EAAE,CAAA,CACvBG,CAAAA,CAAapC,CAAAA,EAAAA,CAEnB,OAAO,CACH,UAAA,CAAYoC,CAAAA,CACZ,CAACjC,CAAY,EAAG,IAAA,CAChB,OAAA,CAAS,IAAM,CAAA,IAAA,EAAOiC,CAAAA,CAAW,GAAA,EAAK,CAAA,GAAA,CAAA,CACtC,MAAA,CAAQ,IACGH,CAAAA,CACF,MAAA,CAAO,CAAC/E,CAAAA,CAAGmF,IAAMA,CAAAA,CAAI,CAAA,GAAM,CAAC,CAAA,CAC5B,OAAA,CAAQ,CAACC,CAAAA,CAAKpC,CAAAA,GAAQ,CAACoC,CAAAA,CAAKjB,CAAAA,CAAUnB,CAAG,CAAA,EAAG,MAAA,EAAA,EAAY,EAAE,CAAC,EAC3D,IAAA,CAAK,EAAE,CAAA,CAEhB,OAAA,CAAS,CAACV,CAAAA,CAAY+C,CAAAA,GAAQ,CAE1B,GAAI,EAAE/C,CAAAA,YAAgB,OAAA,CAAA,CAAU,OAIhC,IAAMyC,CAAAA,CAAWF,CAAAA,CAAYC,CAAI,CAAA,CAAE,OAAA,CAAQ,SAAA,CAAU,IAAI,CAAA,CAIzD,IAAA,GAAW,CAAE,QAAA,CAAAhD,EAAU,IAAA,CAAAwD,CAAK,CAAA,GAAKpB,CAAAA,CAAyBa,CAAAA,CAAUZ,CAAAA,CAAWkB,CAAAA,EAAK,KAAK,EACrFvD,CAAAA,CAAS,OAAA,CAAQ,GAAGwD,CAAI,CAAA,CAG5BhD,CAAAA,CAAK,WAAA,CAAYyC,CAAQ,EAC7B,CACJ,CACJ,CAAA,CC5CaQ,CAAAA,CAA2BC,CAAAA,EAAgE,CACpG,IAAMN,CAAAA,CAAapC,GAAAA,CACnB,OAAO,CACH,UAAA,CAAYoC,CAAAA,CACZ,OAAA,CAAS,IAAM,CAAA,IAAA,EAAOA,EAAW,GAAA,EAAK,CAAA,GAAA,CAAA,CACtC,MAAA,CAAQ,IAAM,MAAA,CAAOM,CAAa,CAAA,CAClC,QAAS,CAAClD,CAAAA,CAAY,CAAE,OAAA,CAAAqC,CAAQ,CAAA,CAAI,EAAA,GAAO,CAEvC,GAAIrC,CAAAA,YAAgB,OAAA,CAChB,OAAOA,CAAAA,CAAK,WAAA,CAAY,IAAI,KAAK,MAAA,CAAOkD,CAAa,CAAC,CAAC,CAAA,CAIvDlD,CAAAA,YAAgB,OAAA,EAChBqC,CAAAA,GAAUa,CAAa,EAE/B,CACJ,CACJ,CAAA,CChBaC,CAAAA,CAA0BD,CAAAA,EAA0C,CAC7E,IAAMN,EAAapC,CAAAA,EAAAA,CACnB,OAAO,CACH,UAAA,CAAYoC,CAAAA,CACZ,OAAA,CAAS,IAAM,CAAA,IAAA,EAAOA,CAAAA,CAAW,GAAA,EAAK,CAAA,GAAA,CAAA,CACtC,MAAA,CAAQ,IAAM,MAAA,CAAOM,GAAAA,EAAmB,EAAE,CAAA,CAC1C,OAAA,CAAS,CAAClD,CAAAA,CAAY,CAAE,OAAA,CAAAqC,CAAQ,CAAA,CAAI,EAAA,GAAO,CACvC,GAAIrC,CAAAA,YAAgB,OAAA,CAAS,CACzB,IAAMoD,CAAAA,CAAO,IAAI,IAAA,CAAK,MAAA,CAAOF,CAAAA,EAAAA,EAAmB,EAAE,CAAC,CAAA,CACnDlD,CAAAA,CAAK,WAAA,CAAYoD,CAAI,CAAA,CAErB,IAAMC,CAAAA,CAAYH,CAAAA,CAAc,UAAWjH,CAAAA,EAAU,CACjDmH,CAAAA,CAAK,WAAA,CAAc,MAAA,CAAOnH,CAAAA,EAAS,EAAE,EACzC,CAAC,CAAA,CAEGoH,CAAAA,EAAWvD,CAAAA,CAAkB,YAAA,CAAasD,CAAAA,CAAMC,CAAS,EACjE,CAEA,GAAIrD,CAAAA,YAAgB,OAAA,CAAS,CACzBqC,CAAAA,GAAUa,CAAAA,EAAAA,EAAmB,EAAE,CAAA,CAE/B,IAAMG,CAAAA,CAAYH,CAAAA,CAAc,SAAA,CAAWjH,CAAAA,EAAU,CACjDoG,CAAAA,GAAUpG,CAAAA,EAAS,EAAE,EACzB,CAAC,CAAA,CAEGoH,CAAAA,EAAWvD,CAAAA,CAAkB,YAAA,CAAaE,CAAAA,CAAMqD,CAAS,EACjE,CACJ,CACJ,CACJ,CAAA,CChCaC,CAAAA,CAAoBrH,CAAAA,EACtB,CAAC,QAAA,CAAU,SAAA,CAAW,SAAU,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAOA,CAAK,CAAA,CCH7DsH,EAAAA,CAAuBtH,CAAAA,EACzBA,CAAAA,GAAU,IAAA,EAAQ,OAAOA,CAAAA,EAAU,UAAA,EAAc,WAAA,GAAeA,CAAAA,CCH9DuH,EAAAA,CAAkBV,GACpBA,CAAAA,CAAI,OAAA,CAAQ,SAAA,CAAW,GAAG,CAAA,CCQ/BW,EAAAA,CACFjE,CAAAA,EACC,CACD,OAAQ,IAAA,EACJ,KAAK+D,EAAAA,CAAoB/D,CAAQ,CAAA,CAC7B,OAAO2D,CAAAA,CAAuB3D,CAAQ,CAAA,CAC1C,KAAK8D,CAAAA,CAAiB9D,CAAQ,CAAA,EAAKA,CAAAA,EAAY,IAAA,EAC3C,OAAOyD,CAAAA,CAAwBzD,CAAAA,EAAY,EAAE,CAAA,CACjD,QACI,OAAOA,CACf,CACJ,EASakE,CAAAA,CAAiB,CAC1BC,CAAAA,CAAAA,GACGC,CAAAA,GACF,CACD,IAAM/B,CAAAA,CAAwB,GAExBY,CAAAA,CAAWkB,CAAAA,CAAgB,OAAA,CAAQ,CAACE,CAAAA,CAAanD,CAAAA,GAC5C,CACH8C,EAAAA,CAAeK,CAAW,CAAA,CAAA,CACzB,IAAc,CACX,IAAMrE,CAAAA,CAAWiE,EAAAA,CAAsBG,CAAAA,CAAelD,CAAG,CAAC,CAAA,CAC1D,OAAI,YAAA,GAAgBlB,CAAAA,EAChBA,CAAAA,CAAS,UAAA,CAAW,MAAA,CAAO,OAAOkB,CAAG,CAAC,CAAA,CAE1CmB,CAAAA,CAAU,IAAA,CAAKrC,CAAQ,CAAA,CAChBA,CAAAA,CAAS,SACpB,CAAA,GACJ,CACH,CAAA,CAED,OAAOmD,CAAAA,CAAwBF,CAAAA,CAAS,MAAA,CAAQZ,CAAS,CAC7D,CAAA,CCTaiC,CAAAA,CAAmBzG,CAAAA,EAA8D,CAC1F,IAAMuF,EAAapC,CAAAA,EAAAA,CACnB,OAAO,CACH,UAAA,CAAYoC,CAAAA,CACZ,OAAA,CAAS,IAAMA,EAAW,GAAA,EAAA,CAC1B,MAAA,CAAQ,IAAM,EAAA,CACd,OAAA,CAAU5C,CAAAA,EAAe,CACrB,GAAIA,CAAAA,YAAgB,OAAA,CAAS,CACzB,IAAMqD,CAAAA,CAAYhG,CAAAA,CAAQ2C,CAAI,CAAA,CAC1BqD,GAAWvD,CAAAA,CAAkB,YAAA,CAAaE,CAAAA,CAAMqD,CAAS,EACjE,CACJ,CACJ,CACJ,CAAA,CC9CO,IAAMU,EAAAA,CAAmBvE,CAAAA,EAAgC,CAC5D,IAAMiD,CAAAA,CAAW,QAAA,CAAS,cAAc,UAAU,CAAA,CAC5CuB,CAAAA,CAAS,IAAI,OAAA,CAEnB,OAAAvB,CAAAA,CAAS,OAAA,CAAQ,OAAOuB,CAAM,CAAA,CAC9BxE,CAAAA,CAAS,OAAA,CAAQwE,CAAM,CAAA,CAEhB,KAAA,CAAM,IAAA,CAAKvB,EAAS,OAAA,CAAQ,UAAU,CACjD,CAAA,CCqCawB,EAAAA,CAAe,CACxBC,CAAAA,CACAC,CAAAA,CAAyB,IAAM,EAAA,GACpB,CACX,IAAMvB,CAAAA,CAAapC,CAAAA,EAAAA,CACnB,OAAO,CACH,UAAA,CAAYoC,CAAAA,CACZ,OAAA,CAAS,IAAM,CAAA,IAAA,EAAOA,CAAAA,CAAW,GAAA,EAAK,MACtC,MAAA,CAAQ,IAAMuB,CAAAA,EAAAA,CACd,OAAA,CAAUnE,CAAAA,EAAe,CACrB,GAAIA,aAAgB,OAAA,CAAS,CACzB,IAAMqD,CAAAA,CAAYa,CAAAA,CAAOlE,CAAI,CAAA,CACzBqD,CAAAA,EAAWvD,CAAAA,CAAkB,YAAA,CAAaE,CAAAA,CAAMqD,CAAS,EACjE,CACJ,CACJ,CACJ,EC5BO,IAAMe,CAAAA,CAAWtI,CAAAA,EACbmI,EAAAA,CACFjE,CAAAA,EAAS,CACN,IAAIM,CAAAA,CAAmB,EAAA,CAEjB+D,CAAAA,CAAUC,CAAAA,EAAiE,CAC7EjE,CAAAA,CAAgBC,CAAK,CAAA,CAErB,IAAMd,EAAW,OAAO8E,CAAAA,EAAkB,UAAA,CAAaA,CAAAA,EAAAA,CAAkBA,CAAAA,CACzEhE,CAAAA,CAAQyD,EAAAA,CAAgBvE,CAAQ,CAAA,CAEhCQ,CAAAA,CAAK,MAAA,CAAO,GAAGM,CAAK,EACxB,CAAA,CAEA+D,CAAAA,CAAOvI,GAAQ,CAAA,CACf,IAAMyI,CAAAA,CAAYzI,CAAAA,CAAO,SAAA,CAAUuI,CAAM,CAAA,CAEzC,OAAO,IAAM,CACTE,CAAAA,IAAAA,CACAlE,CAAAA,CAAgBC,CAAK,CAAA,CACrBA,CAAAA,CAAQ,GACZ,CACJ,CAAA,CACA,IACWxE,CAAAA,EAAAA,CAAS,MAAA,EAExB,CAAA,CCjEG,IAAM0I,EAAAA,CAAS,CAACC,CAAAA,CAAa,CAAE,KAAA,CAAAC,CAAM,EAAwB,CAAE,KAAA,CAAO,IAAK,CAAA,GACvEC,CAAAA,CAAiB3E,CAAAA,EAAS,CAC7B,IAAM3C,EAAU,IAAM,CAClB,IAAMuH,CAAAA,CAAO5E,CAAAA,CAAK,YAAA,CAAa,MAAM,CAAA,CAC/B6E,EAAc,UAAA,CAAW,YAAA,EAAc,GAAA,CAG7C,GAAI,CAACA,CAAAA,EAAe,CAACD,CAAAA,CAAM,OAC3B,IAAMrG,CAAAA,CAAM,IAAI,GAAA,CAAIsG,CAAW,CAAA,CAC/B7E,CAAAA,CAAK,UAAU,MAAA,CAAOyE,CAAAA,CAAKC,CAAAA,CAAQnG,CAAAA,CAAI,QAAA,GAAaqG,CAAAA,CAAOrG,CAAAA,CAAI,QAAA,CAAS,WAAWqG,CAAI,CAAC,EAC5F,CAAA,CAEA,OAAA,UAAA,CAAW,gBAAA,CAAiB,iBAAA,CAAmBvH,CAAO,EAC/C,IAAM,UAAA,CAAW,mBAAA,CAAoB,iBAAA,CAAmBA,CAAO,CAC1E,CAAC,ECJE,IAAMyH,EAAAA,CAAOzH,CAAAA,GACT,CAAE,GAAA,CAAK,KAAA,CAAgB,OAAA,CAAAA,CAAQ,GAG7B0H,EAAAA,CAAQ1H,CAAAA,GACV,CAAE,GAAA,CAAK,MAAA,CAAiB,OAAA,CAAAA,CAAQ,CAAA,MCR9B2H,EAAAA,CAAU,CAAC,CAAE,GAAA,CAAKC,CAAAA,CAAQ,iBAAA,CAAmBC,CAAc,CAAA,GAAoB,CACxF,IAAMC,CAAAA,CAAmBtG,CAAAA,CAAyBuG,CAAAA,CAAAA,CAAM,CAAA,CAClDjD,CAAAA,CAAO,CAAA,OAAA,EAAU8C,CAAAA,CAAO,KAAK,OAAA,CAAQ,iBAAA,CAAmB,EAAE,CAAA,EAAK,MAAM,CAAA,CAAA,CAE3E,OAAAA,CAAAA,CAAO,MAAM,SAAA,CAAWjG,CAAAA,EAAU,CAC9B,GAAM,CAAE,SAAA,CAAAqG,CAAAA,CAAW,KAAA,CAAAhH,CAAM,CAAA,CAAIW,CAAAA,CACvB5C,CAAAA,CAAOiJ,CAAAA,EAAaD,CAAAA,CAAAA,CAAAA,CAC1B,GAAI,CAAC/G,CAAAA,EAAO,WAAY,OAAO8G,CAAAA,CAAiB,GAAA,CAAI/I,CAAI,CAAA,CAGxD,IAAMkJ,CAAAA,CAASJ,CAAAA,EAAe,OAAA,EAAW,QAAA,CAAS,eAAA,CAClDI,CAAAA,CAAO,KAAA,CAAM,kBAAA,CAAqBnD,CAAAA,CAEX,QAAA,CAAS,oBAAoB,IAAMgD,CAAAA,CAAiB,GAAA,CAAI/I,CAAI,CAAC,CAAA,CACrE,KAAA,CAAM,IAAA,CAAK,IAAM,CACT,CAACiC,CAAAA,CAAM,UAAA,EAAc,EAAE,CAAA,CAAE,IAAA,GACjC,OAAA,CAAQ,CAAC,CAAE,SAAA,CAAAkH,CAAAA,CAAW,GAAGC,CAAM,CAAA,GAAM,CAC5C,QAAA,CAAS,eAAA,CAAgB,OAAA,CAAQD,CAAAA,CAAW,CACxC,aAAA,CAAeC,CAAAA,CAAM,SAAS,OAAA,CAAQ,QAAA,CAAU,CAAA,CAAA,EAAIrD,CAAI,CAAA,CAAA,CAAG,CAAA,EAAG,OAAA,CAAQ,UAAA,CAAY,IAAIA,CAAI,CAAA,CAAA,CAAG,CAAA,CAC7F,GAAGqD,CACP,CAAC,EACL,CAAC,EACL,CAAC,EACL,CAAC,CAAA,CAGMC,CAAAA,CAAQN,CAAgB,CACnC,EC5BO,IAAMO,CAAAA,CAAcC,CAAAA,GAChB,CACH,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,QAAA,CACR,QAAS,6BAAA,CACT,GAAGA,CACP,CAAA,CAAA,CCZG,IAAMC,EAAAA,CAAaC,CAAAA,EACf,CACHH,EAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,QAAS,CAAE,CAAC,CAAA,CAC1C,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,EACDH,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,OAAA,CAAS,CAAE,CAAC,CAAA,CAC1C,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL,CAAA,CAISC,EAAAA,CAAQ,CAACD,CAAAA,CAAkBE,CAAAA,CAA8C,OAAA,GAAY,CAC9F,IAAMC,CAAAA,CAAOD,CAAAA,GAAc,MAAA,EAAUA,CAAAA,GAAc,OAAA,CAAU,GAAA,CAAM,GAAA,CAC7DE,CAAAA,CAAOF,CAAAA,GAAc,OAAA,EAAWA,CAAAA,GAAc,MAAA,CAAS,EAAA,CAAK,GAAA,CAElE,OAAO,CACHL,EAAW,CACP,SAAA,CAAW,CAAC,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYM,CAAI,CAAA,CAAA,EAAIC,CAAI,CAAA,KAAA,CAAQ,CAAA,CAAG,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYD,CAAI,CAAA,GAAA,CAAM,CAAC,EAChG,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAH,CACJ,CAAC,CAAA,CACDH,CAAAA,CAAW,CACP,UAAW,CACP,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYM,CAAI,CAAA,GAAA,CAAM,CAAA,CACnC,CAAE,UAAW,CAAA,SAAA,EAAYA,CAAI,CAAA,CAAA,EAAIC,CAAAA,GAAS,EAAA,CAAK,GAAA,CAAM,EAAE,CAAA,KAAA,CAAQ,CACnE,CAAA,CACA,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAJ,CACJ,CAAC,CACL,CACJ,EAGaK,EAAAA,CAASL,CAAAA,EACX,CACHH,CAAAA,CAAW,CACP,SAAA,CAAW,CACP,CAAE,SAAA,CAAW,aAAA,CAAe,OAAA,CAAS,CAAE,CAAA,CACvC,CAAE,SAAA,CAAW,UAAA,CAAY,QAAS,CAAE,CACxC,CAAA,CACA,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,EACDH,CAAAA,CAAW,CACP,SAAA,CAAW,CACP,CAAE,SAAA,CAAW,UAAA,CAAY,OAAA,CAAS,CAAE,CAAA,CACpC,CAAE,SAAA,CAAW,aAAA,CAAe,OAAA,CAAS,CAAE,CAC3C,CAAA,CACA,QAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL,CAAA,CAISM,EAAAA,CAAQN,CAAAA,EACV,CACHH,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,OAAA,CAAS,CAAE,CAAC,CAAA,CAC1C,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL","file":"index.global.js","sourcesContent":["/** @format */\n\nimport type { Grain, Subscriber } from './grain';\n\n/**\n * A `derived` grain transforms the value of a source grain through a mapping\n * function, producing a new readonly grain of a potentially different type.\n * Like all grains, the value is read by calling it:\n *\n * ```ts\n * const count = grain(5);\n * const isEven = derived(count, n => n % 2 === 0);\n * const value = isEven(); // false\n * ```\n *\n * Reads are always synchronous — the mapping function is applied on the fly.\n * Subscribers are notified whenever the source grain changes.\n */\n\n/**\n * Creates a readonly grain derived from a source grain by applying a\n * transformation function to its value.\n *\n * @template V - The type of value held by the source grain.\n * @template R - The type of value produced by the transformation.\n *\n * @param {Grain<V>} source - The grain to derive from.\n * @param {(value: V) => R} run - A transformation applied to the source value.\n *\n * @returns {Grain<R>} A readonly grain whose value is the result of applying\n * `run` to the current value of `source`. Subscribers are notified whenever\n * the source grain changes.\n *\n * @example\n * ```ts\n * const count = grain(5);\n * const isEven = derived(count, n => n % 2 === 0);\n *\n * isEven.subscribe(value => console.log(`Is even: ${value}`));\n * count.set(3); // Logs: Is even: false\n * count.set(4); // Logs: Is even: true\n * ```\n */\nexport const derived = <V, R>(source: Grain<V>, run: (value: V) => R): Grain<R> => {\n return Object.assign(() => run(source()), {\n subscribe(subscriber: Subscriber<R>) {\n return source.subscribe((value) => {\n subscriber(run(value));\n });\n },\n });\n};\n","/** @format */\n\n/**\n * A `Grain` or `WritableGrain` is a reactive primitive capturing a\n * value via closure. It is basically a getter function accessing the\n * value, with additional methods bolted on.\n *\n * A `Grain`'s value can be read by calling it. It will always return\n * a up to date value, as all values are read synchronously.\n *\n * ```ts\n * const count = grain(0);\n * const value = count(); // value = 0\n * ```\n *\n * This is a core principle of grains & nord.\n *\n * To update the value of a grain, the `set` and `update` methods\n * can be used. Any update to the value is run through the\n * compare fn to determine if subscribers should be notified.\n * If yes, the subscribers are notified in order of subscription.\n */\n\n/**\n * Fn signature used to describe the compareFn used by grains\n * to check for equality. Receives a snapshot of the current and next\n * state. Return false to indicate that the values differ and should\n * trigger an update\n */\ntype CompareFn<V = unknown> = (current: V, next: V) => boolean;\nconst defaultCompareFn = <V = unknown>(current: V, next: V) => Object.is(current, next);\n\n/**\n * A `subscriber` is a callback added when subscribing to a `grain`, allowing to react\n * to changes in the source `grain`s value.\n */\nexport type Subscriber<V = unknown> = (value: V) => void;\n\n/**\n * Function returned by the `subscribe` method of a `grain`, allowing to\n * unsubscribe from listening to changes in the `grain`s value\n */\nexport type Unsubscribe = () => void;\n\n/**\n * The readonly version of a `grain` allows to read the value synchronous as well\n * as subscribe to changes in the `grains` value.\n */\nexport type Grain<V = unknown> = {\n (): V;\n subscribe: (subscriber: Subscriber<V>) => Unsubscribe;\n};\n\n/**\n * The writable version of a `grain` allows to set and update the value in addition\n * to reading and subscribing. The value's are set synchronously.\n */\nexport type WritableGrain<V> = Grain<V> & {\n set: (next: V) => void;\n update: (run: (current: V) => V) => void;\n};\n\n/**\n * Creates a reactive writable grain.\n * A writable grain represents a piece of reactive state\n * that can be subscribed to and updated.\n *\n * @template V - The type of value the grain will hold.\n *\n * @param {V} start - The initial value of the grain.\n * @param {CompareFn<V>} [compareFunc] - An optional function to determine\n * if the value has changed. Defaults to Object.is(). To indicate change, the fn\n * should return `false`\n *\n * @returns {WritableGrain<V>} An fn representing the grain value as a getter.\n * It contains methods to set & update the value as well as subscribe to changes.\n * Grains are always synchronous, there is no batching. To retrieve the value of\n * a grain, it is called like a function.\n *\n * The returned writable grain has the following methods:\n * - `set(value: V)`: Sets a new value for the grain.\n * - `subscribe(subscriber: Subscriber<V>)`: Subscribes to changes.\n * Returns a function to unsubscribe the passed subscriber.\n * - `update(updater: (current: V) => V)`: Updates the value using an updater function.\n *\n * @example\n * ```ts\n * // Setting up a simple subscription and unsubscribing\n * const count = grain(10);\n *\n * const unsubscribe = count.subscribe(value => console.log(value));\n * count.set(20); // Logs: 20\n * unsubscribe(); // Unsubscribes the logging function\n * ```\n *\n * @example\n * ```ts\n * // Updating the grain based on it's current state\n * const count = grain(0);\n *\n * count.subscribe(value => console.log(`Count is now: ${value}`));\n * count.update(currentCount => currentCount + 1); // Logs: Count is now: 1\n * count.update(currentCount => currentCount + 2); // Logs: Count is now: 3\n * ```\n */\nexport const grain = <V = unknown>(start: V, compareFunc: CompareFn<V> = defaultCompareFn): WritableGrain<V> => {\n let _value = start;\n const consumers = new Set<Subscriber<V>>();\n\n const notifyConsumers = () => {\n for (const consumer of Array.from(consumers)) consumer(_value);\n };\n\n const set = (newValue: V) => {\n if (!compareFunc(_value, newValue)) {\n _value = newValue;\n notifyConsumers();\n }\n };\n\n const update = (updater: (current: V) => V) => set(updater(_value));\n\n const subscribe = (subscriber: Subscriber<V>) => {\n consumers.add(subscriber);\n return () => consumers.delete(subscriber);\n };\n\n return Object.assign(() => _value, { set, update, subscribe });\n};\n","/** @format */\n\nimport type { Grain } from './grain';\n\n/**\n * Wraps a (Writable) Grain and exposes it as a readonly variant.\n * Can be called directly to retrieve the value, but no update is\n * possible through the returned value. A grain in its fundamental\n * signature represents a `subscribable`.\n *\n * @template V - The type of value the grain will hold,\n * inferred from the source grain.\n * @param { Grain<V> } source - The grain to shadow.\n * @returns { Grain<V> } - A readonly Grain<V>\n */\nexport const readonly = <V>(source: Grain<V>): Grain<V> => {\n return Object.assign(() => source(), {\n subscribe: source.subscribe,\n });\n};\n","import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = async (hooks: NavigationHook[], context: Omit<NavigationHookContext, 'navigate'>) => {\n for (const { handler } of hooks) {\n const result = await handler({\n ...context,\n navigate: (path: string) => {\n return navigation.navigate(path);\n },\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export const navigate = (path: string) => navigation.navigate(path);\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const redirect = (path: string) => {\n queueMicrotask(() => {\n navigate(path);\n });\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = await resolveHooks(preHooks, { ...next, redirect });\n\n if (!canNavigate) return;\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n\n event.intercept({\n scroll: 'after-transition',\n precommitHandler: async () => {\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = await resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = await resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n if (!canNavigate) throw new Error('Navigation Cancelled');\n },\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","export const lifecycleObserver = new (\n typeof MutationObserver !== 'undefined'\n ? class LifecycleObserver extends MutationObserver {\n // We add all callbacks to the mounting queue, and\n // on trigger check if any of the nodes are connected.\n // if yes, the callbacks get executed and the return\n // added to the unmounts\n pendingMounts = new Set<{ node: Node; callback: () => void | (() => void) }>();\n\n // On trigger, we check all nodes in the map if they are\n // still mounted, and if not, run the unmount callback\n activeUnmounts = new Map<Node, Set<() => void>>();\n\n constructor() {\n // We abuse the mutation observer as basically\n // a signal, triggering our lifecycle logic iteration\n super(() => {\n this.processLifecycle();\n });\n }\n\n processLifecycle() {\n for (const entry of this.pendingMounts) {\n const { node, callback } = entry;\n\n // When connected, we run the callback, remove the\n // entry, and add any eventual cleanup to the\n // unmounts map\n if (node.isConnected) {\n const cleanup = callback();\n\n // If it returned a cleanup, register it\n if (typeof cleanup === 'function') {\n let unmounts = this.activeUnmounts.get(node);\n if (!unmounts) {\n unmounts = new Set();\n this.activeUnmounts.set(node, unmounts);\n }\n unmounts.add(cleanup);\n }\n\n // Remove from pending list (Job Done)\n this.pendingMounts.delete(entry);\n }\n }\n\n // Same for the unmounting entries, we iterate them\n // and execute every unmounting cb where the node is disconnected\n for (const [node, callbacks] of this.activeUnmounts) {\n if (!node.isConnected) {\n for (const fn of callbacks) fn();\n this.activeUnmounts.delete(node);\n }\n }\n }\n\n start(node: Node) {\n this.observe(node, { childList: true, subtree: true });\n }\n\n trackMount(node: Node, callback: () => void | (() => void)) {\n this.pendingMounts.add({ node, callback });\n }\n\n trackUnmount(node: Node, callback: () => void) {\n let unmounts = this.activeUnmounts.get(node);\n if (!unmounts) {\n unmounts = new Set();\n this.activeUnmounts.set(node, unmounts);\n }\n unmounts.add(callback);\n }\n }\n : class {\n start() {}\n trackUnmount() {}\n trackMount() {}\n disconnect() {}\n }\n)();\n\nexport const disconnectNodes = (nodes: Element[]) => {\n for (const node of nodes) node.remove();\n};\n","// A regex used to split attribute strings by the\n// current id format.\nexport const identifierRegex = /<!--(nø-.{6})-->/g;\n\nexport const createIdentifier = () => {\n let _id = '';\n\n return {\n fragmentId: true,\n create: (idx: string) => {\n _id = `nø-${idx.padStart(6, '0')}`;\n },\n get: () => _id,\n };\n};\n","import type { Fragment } from '../internals/fragment';\n\n/**\n * A marker symbol used to identify `ComponentFragment` instances at the\n * type level. Attached to all fragments created by the template parser.\n */\nexport const IS_COMPONENT: unique symbol = Symbol.for('nord.component');\n\n/**\n * A `ComponentFragment` is the primary unit of renderable output in Nord.\n * It extends `Fragment` with a marker symbol that identifies it as the\n * product of the template parser, distinguishing it from lower-level\n * fragments such as directives and structs.\n *\n * All components return a `ComponentFragment`:\n *\n * ```ts\n * const App = (): ComponentFragment => html`<p>Hello</p>`;\n * ```\n */\nexport type ComponentFragment = Fragment & {\n [IS_COMPONENT]: true;\n};\n","const nodeState = new WeakMap<Element, Map<string, string[]>>();\nconst booleanAttributes = /^(disabled|checked|readonly|required|hidden|open|selected|autofocus|multiple)$/;\n\n/**\n * Creates a binding and returns a direct update function.\n * No global IDs required.\n */\nexport const createAttributeBinding = (\n node: Element,\n attributeName: string,\n marker: string, // The specific marker to find (e.g. \"nø-000001\")\n initialParts: string[], // The split array\n) => {\n // We get the current stored binding for the\n // node, allowing us to check all existing\n // bindings for the node. If no binding exist,\n // we create a new one\n let bindings = nodeState.get(node);\n if (!bindings) {\n bindings = new Map<string, string[]>();\n nodeState.set(node, bindings);\n }\n\n // Retrieve the attribute fragments that have\n // been already set.\n let parts = bindings.get(attributeName);\n if (!parts) {\n parts = initialParts;\n bindings.set(attributeName, parts);\n }\n\n const isBoolean = booleanAttributes.test(attributeName);\n const partIndex = parts.indexOf(marker);\n if (partIndex === -1) return () => {};\n\n // We create a fn that acts as binding and is\n // passed back to the hydrator fn allowing to directly\n // bind without any kind of shared update functionality\n return (value: unknown) => {\n parts[partIndex] = String(value);\n const attributeValue = parts.join('');\n\n // Handle non boolean update\n if (!isBoolean) {\n node.setAttribute(attributeName, attributeValue);\n return;\n }\n\n // Handle ugly boolean attribute update\n attributeValue === 'false' || !attributeValue\n ? node.removeAttribute(attributeName)\n : node.setAttribute(attributeName, '');\n };\n};\n","export const iterateNodes = (root: Node, work: (node: Element | Comment) => void) => {\n const shouldProcess = (n: Node): n is Element | Comment => n.nodeType === 1 || n.nodeType === 8;\n\n if (shouldProcess(root)) {\n work(root);\n }\n\n let current: Node | null = root.firstChild;\n while (current) {\n if (shouldProcess(current)) {\n work(current);\n }\n\n if (current.firstChild) {\n current = current.firstChild;\n continue;\n }\n\n // Climb back up until a nextSibling is found or root is reached\n while (current && current !== root) {\n if (current.nextSibling) {\n current = current.nextSibling;\n break;\n }\n current = current.parentNode;\n }\n\n if (current === root) {\n return;\n }\n }\n};\n","import { createAttributeBinding } from '../internals/attribute-bindings';\nimport type { Fragment } from '../internals/fragment';\nimport { identifierRegex } from '../internals/identifier';\nimport { iterateNodes } from '../internals/iterate-nodes';\n\n// To not create a unnecessary closure,\n// we simply store the fragment with it's\n// respective arguments for hydration\n// We can then simply call fragment.hydrate(...args)\ntype HydrationWorkUnit = { fragment: Fragment; args: Parameters<Fragment['hydrate']> };\n\n/**\n * Fn to hydrate a provided node and it's children (until the next component boundary)\n * using the provided `fragments` array. As we place the fragments sequentially, we\n * can safely access them by the encoded index. This allows to safe on map creation\n * and keying overhead.\n *\n * The previous implementation used a TreeWalker, however benchmarking showed\n * that iterating manually is actually faster then the native implementation.\n */\nexport const hydrateComponentTemplate = (node: Node, fragments: Fragment[], scope?: string) => {\n const hydrationUnits: HydrationWorkUnit[] = [];\n iterateNodes(node, (current) => {\n // Comments are handled by finding the\n // correct fragment and simply placing a\n // hydration order.\n if (current instanceof Comment) {\n const content = current.data;\n\n if (content.startsWith('nø-')) {\n const id = content.slice(3); // Remove 'nø-'\n const idx = Number.parseInt(id, 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n hydrationUnits.push({ fragment, args: [current as Comment] });\n }\n }\n }\n\n // --- 2. Element Nodes ---\n if (current instanceof Element) {\n //\n const attrs = [...current.attributes];\n for (const { name, value } of attrs) {\n // If the name starts with nø- we have a directive\n // can process it and then continue directly\n if (name.startsWith('nø-')) {\n const idx = Number.parseInt(name.slice(3), 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n hydrationUnits.push({ fragment, args: [current] });\n current.removeAttribute(name);\n }\n\n continue;\n }\n\n // If the value doesn't include a marker, we skip processing\n // it entirely, which should make this faster\n if (!value.includes('nø-')) continue;\n const matches = value.split(identifierRegex);\n for (const match of matches) {\n if (match.startsWith('nø-')) {\n const idx = Number.parseInt(match.slice(3), 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n const binding = createAttributeBinding(current, name, match, matches);\n hydrationUnits.push({ fragment, args: [current, { binding }] });\n }\n }\n }\n }\n\n // Apply Scope\n if (scope) {\n current.setAttribute(scope, '');\n }\n }\n });\n return hydrationUnits;\n};\n","import { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\nimport { type ComponentFragment, IS_COMPONENT } from './component-fragment';\nimport { hydrateComponentTemplate } from './hydrate-component-template';\n\nconst templateCache = new Map<string, HTMLTemplateElement>();\nconst getTemplate = (html: string) => {\n const template = templateCache.get(html);\n if (template && template.ownerDocument === document) {\n return template;\n }\n\n const created = document.createElement('template');\n created.innerHTML = html.trim();\n templateCache.set(html, created);\n return created;\n};\n\nexport const createComponentFragment = (template: string[], fragments: Fragment[]): ComponentFragment => {\n const html = template.join('');\n const fragmentId = createIdentifier();\n\n return {\n fragmentId: fragmentId,\n [IS_COMPONENT]: true as const,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => {\n return template\n .filter((_, i) => i % 2 === 0) // Keep even indices (Strings only)\n .flatMap((str, idx) => [str, fragments[idx]?.render() ?? ''])\n .join('');\n },\n hydrate: (node: Node, def) => {\n // Bail early if we have a hydration mismatch here\n if (!(node instanceof Comment)) return;\n\n // Retrieve the template, by either creating or\n // cloning it\n const template = getTemplate(html).content.cloneNode(true);\n\n // Hydrate the component template using the fragment,\n // the available fragments and scope the nodes if required\n for (const { fragment, args } of hydrateComponentTemplate(template, fragments, def?.scope)) {\n fragment.hydrate(...args);\n }\n\n node.replaceWith(template);\n },\n };\n};\n","import { type Fragment } from './fragment';\nimport { createIdentifier } from './identifier';\n\n// Creates a primitive fragment, containing a scalar value\n// that get's resolved and rendered only once.\nexport const createPrimitiveFragment = (fragmentValue: boolean | string | number | bigint): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => String(fragmentValue),\n hydrate: (node: Node, { binding } = {}) => {\n // Hydrate the node depending of it's type\n if (node instanceof Comment) {\n return node.replaceWith(new Text(String(fragmentValue)));\n }\n\n // Do the same for attributes\n if (node instanceof Element) {\n binding?.(fragmentValue);\n }\n },\n };\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport type { Subscribable } from '../application/subscribable';\nimport { type Fragment } from './fragment';\nimport { createIdentifier } from './identifier';\n\n// Creates a reactive fragment, that also updates the hydrated\n// node on update of the subscribable\nexport const createReactiveFragment = (fragmentValue: Subscribable): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => String(fragmentValue() ?? ''),\n hydrate: (node: Node, { binding } = {}) => {\n if (node instanceof Comment) {\n const text = new Text(String(fragmentValue() ?? ''));\n node.replaceWith(text);\n\n const onDestroy = fragmentValue.subscribe((value) => {\n text.textContent = String(value ?? '');\n });\n\n if (onDestroy) lifecycleObserver.trackUnmount(text, onDestroy);\n }\n\n if (node instanceof Element) {\n binding?.(fragmentValue() ?? '');\n\n const onDestroy = fragmentValue.subscribe((value) => {\n binding?.(value ?? '');\n });\n\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n };\n};\n","/**\n * Asserts that a given value is a primitive value\n * @param value\n */\nexport const isPrimitiveValue = (value: unknown): value is string | boolean | number | bigint => {\n return ['string', 'boolean', 'number', 'bigint'].includes(typeof value);\n};\n","import type { Subscribable } from '../application/subscribable';\n\nexport const isSubscribableValue = (value: unknown): value is Subscribable => {\n return value !== null && typeof value === 'function' && 'subscribe' in value;\n};\n","export const trimWhitespace = (str: string) => {\n return str.replace(/\\s{2,}/g, ' ');\n};\n","import { createComponentFragment } from '../component/create-component-fragment';\nimport { createPrimitiveFragment } from '../internals/create-primitive-fragment';\nimport { createReactiveFragment } from '../internals/create-reactive-fragment';\nimport { type Fragment } from '../internals/fragment';\nimport { isPrimitiveValue } from '../internals/is-primitive-value';\nimport { isSubscribableValue } from '../internals/is-subscribable-value';\nimport { trimWhitespace } from '../internals/trim-whitespace';\nimport type { Subscribable } from './subscribable';\n\nconst parseTemplateFragment = (\n fragment: string | number | boolean | bigint | null | undefined | Subscribable | Fragment,\n) => {\n switch (true) {\n case isSubscribableValue(fragment):\n return createReactiveFragment(fragment);\n case isPrimitiveValue(fragment) || fragment == null:\n return createPrimitiveFragment(fragment ?? '');\n default:\n return fragment;\n }\n};\n\n/**\n * Parses a provided html string representation into a `ComponentFragment`,\n * which is a basic hydratable fragment to use in templates or applications\n *\n * @param stringFragments\n * @param valueFragments\n */\nexport const templateParser = (\n stringFragments: TemplateStringsArray,\n ...valueFragments: (string | number | boolean | bigint | null | undefined | Subscribable | Fragment)[]\n) => {\n const fragments: Fragment[] = [];\n\n const template = stringFragments.flatMap((strFragment, idx) => {\n return [\n trimWhitespace(strFragment),\n ((): string => {\n const fragment = parseTemplateFragment(valueFragments[idx]);\n if ('fragmentId' in fragment) {\n fragment.fragmentId.create(String(idx));\n }\n fragments.push(fragment);\n return fragment.resolve();\n })(),\n ];\n });\n\n return createComponentFragment(template.flat(), fragments);\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\n\n/**\n * A `createDirective` wraps a handler function into a `Fragment` that can be\n * attached to any element in a template. The handler runs when the element is\n * hydrated and receives the element as its argument.\n *\n * ```ts\n * const color = (color: string) =>\n * createDirective((node) => {\n * node.style.backgroundColor = color;\n * });\n *\n * html`<div ${color('red')}>I'm a red div</div>`;\n * ```\n *\n * If the handler returns a function, it is registered as a cleanup callback\n * and called when the element is removed from the DOM.\n */\n\n/**\n * Creates a directive that runs a handler when the target element is hydrated.\n *\n * @param {(node: Element) => void | (() => void)} handler - A function called\n * with the target element on hydration. May return a cleanup function that runs\n * when the element is removed from the DOM.\n *\n * @returns {Fragment} A fragment representing the directive, attachable to\n * elements in a template.\n *\n * @example\n * ```ts\n * const autofocus = createDirective((node) => {\n * node.focus();\n * });\n *\n * html`<input ${autofocus} type=\"text\" />`;\n * ```\n */\nexport const createDirective = (handler: (node: Element) => void | (() => void)): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => fragmentId.get(),\n render: () => '',\n hydrate: (node: Node) => {\n if (node instanceof Element) {\n const onDestroy = handler(node);\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n } satisfies Fragment;\n};\n","import type { ComponentFragment } from '../component/component-fragment';\n\n/**\n * Method to hydrate a fragment and retrieve it's\n * nodes.\n *\n * @param fragment\n */\nexport const hydrateFragment = (fragment: ComponentFragment) => {\n const template = document.createElement('template');\n const anchor = new Comment();\n\n template.content.append(anchor);\n fragment.hydrate(anchor);\n\n return Array.from(template.content.childNodes) as Element[];\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\n/**\n * `createStruct` is the lower-level counterpart to `createDirective` — where\n * directives target `Element` nodes, structs target `Comment` nodes and are\n * used to manage dynamic regions of the DOM such as conditional blocks,\n * lists, and async content.\n *\n * A struct resolves to an HTML comment anchor in the template, which is then\n * used as a positional reference for inserting and removing nodes at runtime.\n *\n * ```ts\n * const myStruct = createStruct((anchor) => {\n * const node = document.createElement('p');\n * node.textContent = 'Hello';\n * anchor.before(node);\n *\n * return () => node.remove();\n * });\n *\n * html`${myStruct}`;\n * ```\n *\n * If the handler returns a function, it is registered as a cleanup callback\n * and called when the anchor is removed from the DOM.\n */\n\n/**\n * Creates a struct fragment that manages a dynamic DOM region via a comment anchor.\n *\n * @param {(node: Comment) => void | (() => void)} struct - A function called\n * with the comment anchor on hydration. May return a cleanup function that runs\n * when the anchor is removed from the DOM.\n * @param {() => string} [snapshot] - An optional function returning an HTML\n * string for SSR snapshots. Defaults to an empty string.\n *\n * @returns {Fragment} A fragment that resolves to a comment anchor in the\n * template and hydrates the struct when mounted.\n *\n * @example\n * ```ts\n * const myStruct = createStruct(\n * (anchor) => {\n * const node = document.createElement('p');\n * node.textContent = 'Hello';\n * anchor.before(node);\n * return () => node.remove();\n * },\n * () => '<p>Hello</p>',\n * );\n * ```\n */\nexport const createStruct = (\n struct: (node: Comment) => void | (() => void),\n snapshot: () => string = () => '',\n): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => snapshot(),\n hydrate: (node: Node) => {\n if (node instanceof Comment) {\n const onDestroy = struct(node);\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n };\n};\n","import { disconnectNodes } from '../application/lifecycle-observer';\nimport type { Subscribable } from '../application/subscribable';\nimport type { ComponentFragment } from '../component/component-fragment';\nimport { hydrateFragment } from '../internals/hydrate-fragment';\nimport { createStruct } from './create-struct';\n\n/**\n * `$render` is a struct that renders a `ComponentFragment` held by a\n * `Subscribable`, replacing the current nodes whenever the fragment changes.\n *\n * ```ts\n * const view = grain(html`<p>Hello</p>`);\n *\n * html`${$render(view)}`;\n * ```\n *\n * When the subscribable emits a new fragment, the previous nodes are\n * disconnected and replaced with the newly rendered ones. All nodes are\n * cleaned up when the struct is unmounted.\n */\n\n/**\n * Creates a struct that reactively renders a `ComponentFragment` from a\n * subscribable source.\n *\n * @param {Subscribable<ComponentFragment>} source - A subscribable whose\n * value is the `ComponentFragment` to render. The rendered output is updated\n * whenever the source emits a new fragment.\n *\n * @returns {Fragment} A struct fragment that renders and tracks the current\n * fragment from the source.\n *\n * @example\n * ```ts\n * const view = grain(html`<p>Initial</p>`);\n *\n * html`${$render(view)}`;\n *\n * view.set(html`<p>Updated</p>`);\n * ```\n */\nexport const $render = (source: Subscribable<ComponentFragment>) => {\n return createStruct(\n (node) => {\n let nodes: Element[] = [];\n\n const render = (maybeFragment: (() => ComponentFragment) | ComponentFragment) => {\n disconnectNodes(nodes);\n\n const fragment = typeof maybeFragment === 'function' ? maybeFragment() : maybeFragment;\n nodes = hydrateFragment(fragment);\n\n node.before(...nodes);\n };\n\n render(source());\n const ondestroy = source.subscribe(render);\n\n return () => {\n ondestroy?.();\n disconnectNodes(nodes);\n nodes = [];\n };\n },\n () => {\n return source().render();\n },\n );\n};\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook = {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => Promise<boolean | void>;\n};\n\nexport const pre = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
1
+ {"version":3,"sources":["../../../grains/src/derived.ts","../../../grains/src/grain.ts","../../../grains/src/readonly.ts","../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../../nord/src/application/lifecycle-observer.ts","../../../nord/src/internals/identifier.ts","../../../nord/src/component/component-fragment.ts","../../../nord/src/internals/attribute-bindings.ts","../../../nord/src/internals/iterate-nodes.ts","../../../nord/src/component/hydrate-component-template.ts","../../../nord/src/component/create-component-fragment.ts","../../../nord/src/internals/create-primitive-fragment.ts","../../../nord/src/internals/create-reactive-fragment.ts","../../../nord/src/internals/is-primitive-value.ts","../../../nord/src/internals/is-subscribable-value.ts","../../../nord/src/internals/trim-whitespace.ts","../../../nord/src/application/template-parser.ts","../../../nord/src/directives/create-directive.ts","../../../nord/src/internals/hydrate-fragment.ts","../../../nord/src/structs/create-struct.ts","../../../nord/src/structs/render.struct.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["derived","source","run","subscriber","value","defaultCompareFn","current","next","grain","start","compareFunc","_value","consumers","notifyConsumers","consumer","set","newValue","updater","readonly","getFragment","resolved","resolveHooks","hooks","context","handler","navigate","destination","getPathParamGroup","result","_","parameterized","internal","read","p","fn","u","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","V","query","match","state","getURLState","setRouterState","matchedParams","matchedQuery","redirects","redirect","path","preHooks","hook","redirectFn","loadHooks","h","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","lifecycleObserver","entry","node","callback","cleanup","unmounts","callbacks","disconnectNodes","nodes","identifierRegex","createIdentifier","_id","idx","IS_COMPONENT","nodeState","booleanAttributes","createAttributeBinding","attributeName","marker","initialParts","bindings","parts","isBoolean","partIndex","attributeValue","iterateNodes","root","work","shouldProcess","n","hydrateComponentTemplate","fragments","scope","hydrationUnits","content","id","attrs","name","matches","binding","templateCache","getTemplate","html","template","created","createComponentFragment","fragmentId","i","str","def","args","createPrimitiveFragment","fragmentValue","createReactiveFragment","text","onDestroy","isPrimitiveValue","isSubscribableValue","trimWhitespace","parseTemplateFragment","templateParser","stringFragments","valueFragments","strFragment","createDirective","hydrateFragment","anchor","createStruct","struct","snapshot","$render","render","maybeFragment","ondestroy","active","cls","exact","href","pre","post","load","$outlet","router","transitionRef","currentComponent","$","component","target","keyframes","props","oe","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"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","file":"index.global.js","sourcesContent":["/** @format */\n\nimport type { Grain, Subscriber } from './grain';\n\n/**\n * A `derived` grain transforms the value of a source grain through a mapping\n * function, producing a new readonly grain of a potentially different type.\n * Like all grains, the value is read by calling it:\n *\n * ```ts\n * const count = grain(5);\n * const isEven = derived(count, n => n % 2 === 0);\n * const value = isEven(); // false\n * ```\n *\n * Reads are always synchronous — the mapping function is applied on the fly.\n * Subscribers are notified whenever the source grain changes.\n */\n\n/**\n * Creates a readonly grain derived from a source grain by applying a\n * transformation function to its value.\n *\n * @template V - The type of value held by the source grain.\n * @template R - The type of value produced by the transformation.\n *\n * @param {Grain<V>} source - The grain to derive from.\n * @param {(value: V) => R} run - A transformation applied to the source value.\n *\n * @returns {Grain<R>} A readonly grain whose value is the result of applying\n * `run` to the current value of `source`. Subscribers are notified whenever\n * the source grain changes.\n *\n * @example\n * ```ts\n * const count = grain(5);\n * const isEven = derived(count, n => n % 2 === 0);\n *\n * isEven.subscribe(value => console.log(`Is even: ${value}`));\n * count.set(3); // Logs: Is even: false\n * count.set(4); // Logs: Is even: true\n * ```\n */\nexport const derived = <V, R>(source: Grain<V>, run: (value: V) => R): Grain<R> => {\n return Object.assign(() => run(source()), {\n subscribe(subscriber: Subscriber<R>) {\n return source.subscribe((value) => {\n subscriber(run(value));\n });\n },\n });\n};\n","/** @format */\n\n/**\n * A `Grain` or `WritableGrain` is a reactive primitive capturing a\n * value via closure. It is basically a getter function accessing the\n * value, with additional methods bolted on.\n *\n * A `Grain`'s value can be read by calling it. It will always return\n * a up to date value, as all values are read synchronously.\n *\n * ```ts\n * const count = grain(0);\n * const value = count(); // value = 0\n * ```\n *\n * This is a core principle of grains & nord.\n *\n * To update the value of a grain, the `set` and `update` methods\n * can be used. Any update to the value is run through the\n * compare fn to determine if subscribers should be notified.\n * If yes, the subscribers are notified in order of subscription.\n */\n\n/**\n * Fn signature used to describe the compareFn used by grains\n * to check for equality. Receives a snapshot of the current and next\n * state. Return false to indicate that the values differ and should\n * trigger an update\n */\ntype CompareFn<V = unknown> = (current: V, next: V) => boolean;\nconst defaultCompareFn = <V = unknown>(current: V, next: V) => Object.is(current, next);\n\n/**\n * A `subscriber` is a callback added when subscribing to a `grain`, allowing to react\n * to changes in the source `grain`s value.\n */\nexport type Subscriber<V = unknown> = (value: V) => void;\n\n/**\n * Function returned by the `subscribe` method of a `grain`, allowing to\n * unsubscribe from listening to changes in the `grain`s value\n */\nexport type Unsubscribe = () => void;\n\n/**\n * The readonly version of a `grain` allows to read the value synchronous as well\n * as subscribe to changes in the `grains` value.\n */\nexport type Grain<V = unknown> = {\n (): V;\n subscribe: (subscriber: Subscriber<V>) => Unsubscribe;\n};\n\n/**\n * The writable version of a `grain` allows to set and update the value in addition\n * to reading and subscribing. The value's are set synchronously.\n */\nexport type WritableGrain<V> = Grain<V> & {\n set: (next: V) => void;\n update: (run: (current: V) => V) => void;\n};\n\n/**\n * Creates a reactive writable grain.\n * A writable grain represents a piece of reactive state\n * that can be subscribed to and updated.\n *\n * @template V - The type of value the grain will hold.\n *\n * @param {V} start - The initial value of the grain.\n * @param {CompareFn<V>} [compareFunc] - An optional function to determine\n * if the value has changed. Defaults to Object.is(). To indicate change, the fn\n * should return `false`\n *\n * @returns {WritableGrain<V>} An fn representing the grain value as a getter.\n * It contains methods to set & update the value as well as subscribe to changes.\n * Grains are always synchronous, there is no batching. To retrieve the value of\n * a grain, it is called like a function.\n *\n * The returned writable grain has the following methods:\n * - `set(value: V)`: Sets a new value for the grain.\n * - `subscribe(subscriber: Subscriber<V>)`: Subscribes to changes.\n * Returns a function to unsubscribe the passed subscriber.\n * - `update(updater: (current: V) => V)`: Updates the value using an updater function.\n *\n * @example\n * ```ts\n * // Setting up a simple subscription and unsubscribing\n * const count = grain(10);\n *\n * const unsubscribe = count.subscribe(value => console.log(value));\n * count.set(20); // Logs: 20\n * unsubscribe(); // Unsubscribes the logging function\n * ```\n *\n * @example\n * ```ts\n * // Updating the grain based on it's current state\n * const count = grain(0);\n *\n * count.subscribe(value => console.log(`Count is now: ${value}`));\n * count.update(currentCount => currentCount + 1); // Logs: Count is now: 1\n * count.update(currentCount => currentCount + 2); // Logs: Count is now: 3\n * ```\n */\nexport const grain = <V = unknown>(start: V, compareFunc: CompareFn<V> = defaultCompareFn): WritableGrain<V> => {\n let _value = start;\n const consumers = new Set<Subscriber<V>>();\n\n const notifyConsumers = () => {\n for (const consumer of Array.from(consumers)) consumer(_value);\n };\n\n const set = (newValue: V) => {\n if (!compareFunc(_value, newValue)) {\n _value = newValue;\n notifyConsumers();\n }\n };\n\n const update = (updater: (current: V) => V) => set(updater(_value));\n\n const subscribe = (subscriber: Subscriber<V>) => {\n consumers.add(subscriber);\n return () => consumers.delete(subscriber);\n };\n\n return Object.assign(() => _value, { set, update, subscribe });\n};\n","/** @format */\n\nimport type { Grain } from './grain';\n\n/**\n * Wraps a (Writable) Grain and exposes it as a readonly variant.\n * Can be called directly to retrieve the value, but no update is\n * possible through the returned value. A grain in its fundamental\n * signature represents a `subscribable`.\n *\n * @template V - The type of value the grain will hold,\n * inferred from the source grain.\n * @param { Grain<V> } source - The grain to shadow.\n * @returns { Grain<V> } - A readonly Grain<V>\n */\nexport const readonly = <V>(source: Grain<V>): Grain<V> => {\n return Object.assign(() => source(), {\n subscribe: source.subscribe,\n });\n};\n","import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = (hooks: NavigationHook[], context: NavigationHookContext) => {\n for (const { handler } of hooks) {\n const result = handler({\n ...context,\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export type NavigateOptions = string | ({ path: string } & NavigationNavigateOptions);\n\nexport const navigate = (destination: NavigateOptions) => {\n navigation.navigate(\n typeof destination === 'string' ? destination : destination.path,\n typeof destination === 'string' ? {} : (destination ?? {}),\n );\n};\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = resolveHooks(preHooks, { ...next, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n // Run the load hooks\n // LOAD hooks — async, non-blocking for navigation\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...next, redirect });\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = canNavigate && resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n event.preventDefault();\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n event.intercept({\n scroll: 'after-transition',\n // As the handler is not yes baseline as of mid 2026, we cannot\n // use the precommitController. Without it, pre and post hooks need\n // to be resolved synchronously.\n // precommitHandler: async () => {},\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...nextState, redirect });\n\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","export const lifecycleObserver = new (\n typeof MutationObserver !== 'undefined'\n ? class LifecycleObserver extends MutationObserver {\n // We add all callbacks to the mounting queue, and\n // on trigger check if any of the nodes are connected.\n // if yes, the callbacks get executed and the return\n // added to the unmounts\n pendingMounts = new Set<{ node: Node; callback: () => void | (() => void) }>();\n\n // On trigger, we check all nodes in the map if they are\n // still mounted, and if not, run the unmount callback\n activeUnmounts = new Map<Node, Set<() => void>>();\n\n constructor() {\n // We abuse the mutation observer as basically\n // a signal, triggering our lifecycle logic iteration\n super(() => {\n this.processLifecycle();\n });\n }\n\n processLifecycle() {\n for (const entry of this.pendingMounts) {\n const { node, callback } = entry;\n\n // When connected, we run the callback, remove the\n // entry, and add any eventual cleanup to the\n // unmounts map\n if (node.isConnected) {\n const cleanup = callback();\n\n // If it returned a cleanup, register it\n if (typeof cleanup === 'function') {\n let unmounts = this.activeUnmounts.get(node);\n if (!unmounts) {\n unmounts = new Set();\n this.activeUnmounts.set(node, unmounts);\n }\n unmounts.add(cleanup);\n }\n\n // Remove from pending list (Job Done)\n this.pendingMounts.delete(entry);\n }\n }\n\n // Same for the unmounting entries, we iterate them\n // and execute every unmounting cb where the node is disconnected\n for (const [node, callbacks] of this.activeUnmounts) {\n if (!node.isConnected) {\n for (const fn of callbacks) fn();\n this.activeUnmounts.delete(node);\n }\n }\n }\n\n start(node: Node) {\n this.observe(node, { childList: true, subtree: true });\n }\n\n trackMount(node: Node, callback: () => void | (() => void)) {\n this.pendingMounts.add({ node, callback });\n }\n\n trackUnmount(node: Node, callback: () => void) {\n let unmounts = this.activeUnmounts.get(node);\n if (!unmounts) {\n unmounts = new Set();\n this.activeUnmounts.set(node, unmounts);\n }\n unmounts.add(callback);\n }\n }\n : class {\n start() {}\n trackUnmount() {}\n trackMount() {}\n disconnect() {}\n }\n)();\n\nexport const disconnectNodes = (nodes: Element[]) => {\n for (const node of nodes) node.remove();\n};\n","// A regex used to split attribute strings by the\n// current id format.\nexport const identifierRegex = /<!--(nø-.{6})-->/g;\n\nexport const createIdentifier = () => {\n let _id = '';\n\n return {\n fragmentId: true,\n create: (idx: string) => {\n _id = `nø-${idx.padStart(6, '0')}`;\n },\n get: () => _id,\n };\n};\n","import type { Fragment } from '../internals/fragment';\n\n/**\n * A marker symbol used to identify `ComponentFragment` instances at the\n * type level. Attached to all fragments created by the template parser.\n */\nexport const IS_COMPONENT: unique symbol = Symbol.for('nord.component');\n\n/**\n * A `ComponentFragment` is the primary unit of renderable output in Nord.\n * It extends `Fragment` with a marker symbol that identifies it as the\n * product of the template parser, distinguishing it from lower-level\n * fragments such as directives and structs.\n *\n * All components return a `ComponentFragment`:\n *\n * ```ts\n * const App = (): ComponentFragment => html`<p>Hello</p>`;\n * ```\n */\nexport type ComponentFragment = Fragment & {\n [IS_COMPONENT]: true;\n};\n","const nodeState = new WeakMap<Element, Map<string, string[]>>();\nconst booleanAttributes = /^(disabled|checked|readonly|required|hidden|open|selected|autofocus|multiple)$/;\n\n/**\n * Creates a binding and returns a direct update function.\n * No global IDs required.\n */\nexport const createAttributeBinding = (\n node: Element,\n attributeName: string,\n marker: string, // The specific marker to find (e.g. \"nø-000001\")\n initialParts: string[], // The split array\n) => {\n // We get the current stored binding for the\n // node, allowing us to check all existing\n // bindings for the node. If no binding exist,\n // we create a new one\n let bindings = nodeState.get(node);\n if (!bindings) {\n bindings = new Map<string, string[]>();\n nodeState.set(node, bindings);\n }\n\n // Retrieve the attribute fragments that have\n // been already set.\n let parts = bindings.get(attributeName);\n if (!parts) {\n parts = initialParts;\n bindings.set(attributeName, parts);\n }\n\n const isBoolean = booleanAttributes.test(attributeName);\n const partIndex = parts.indexOf(marker);\n if (partIndex === -1) return () => {};\n\n // We create a fn that acts as binding and is\n // passed back to the hydrator fn allowing to directly\n // bind without any kind of shared update functionality\n return (value: unknown) => {\n parts[partIndex] = String(value);\n const attributeValue = parts.join('');\n\n // Handle non boolean update\n if (!isBoolean) {\n node.setAttribute(attributeName, attributeValue);\n return;\n }\n\n // Handle ugly boolean attribute update\n attributeValue === 'false' || !attributeValue\n ? node.removeAttribute(attributeName)\n : node.setAttribute(attributeName, '');\n };\n};\n","export const iterateNodes = (root: Node, work: (node: Element | Comment) => void) => {\n const shouldProcess = (n: Node): n is Element | Comment => n.nodeType === 1 || n.nodeType === 8;\n\n if (shouldProcess(root)) {\n work(root);\n }\n\n let current: Node | null = root.firstChild;\n while (current) {\n if (shouldProcess(current)) {\n work(current);\n }\n\n if (current.firstChild) {\n current = current.firstChild;\n continue;\n }\n\n // Climb back up until a nextSibling is found or root is reached\n while (current && current !== root) {\n if (current.nextSibling) {\n current = current.nextSibling;\n break;\n }\n current = current.parentNode;\n }\n\n if (current === root) {\n return;\n }\n }\n};\n","import { createAttributeBinding } from '../internals/attribute-bindings';\nimport type { Fragment } from '../internals/fragment';\nimport { identifierRegex } from '../internals/identifier';\nimport { iterateNodes } from '../internals/iterate-nodes';\n\n// To not create a unnecessary closure,\n// we simply store the fragment with it's\n// respective arguments for hydration\n// We can then simply call fragment.hydrate(...args)\ntype HydrationWorkUnit = { fragment: Fragment; args: Parameters<Fragment['hydrate']> };\n\n/**\n * Fn to hydrate a provided node and it's children (until the next component boundary)\n * using the provided `fragments` array. As we place the fragments sequentially, we\n * can safely access them by the encoded index. This allows to safe on map creation\n * and keying overhead.\n *\n * The previous implementation used a TreeWalker, however benchmarking showed\n * that iterating manually is actually faster then the native implementation.\n */\nexport const hydrateComponentTemplate = (node: Node, fragments: Fragment[], scope?: string) => {\n const hydrationUnits: HydrationWorkUnit[] = [];\n iterateNodes(node, (current) => {\n // Comments are handled by finding the\n // correct fragment and simply placing a\n // hydration order.\n if (current instanceof Comment) {\n const content = current.data;\n\n if (content.startsWith('nø-')) {\n const id = content.slice(3); // Remove 'nø-'\n const idx = Number.parseInt(id, 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n hydrationUnits.push({ fragment, args: [current as Comment] });\n }\n }\n }\n\n // --- 2. Element Nodes ---\n if (current instanceof Element) {\n //\n const attrs = [...current.attributes];\n for (const { name, value } of attrs) {\n // If the name starts with nø- we have a directive\n // can process it and then continue directly\n if (name.startsWith('nø-')) {\n const idx = Number.parseInt(name.slice(3), 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n hydrationUnits.push({ fragment, args: [current] });\n current.removeAttribute(name);\n }\n\n continue;\n }\n\n // If the value doesn't include a marker, we skip processing\n // it entirely, which should make this faster\n if (!value.includes('nø-')) continue;\n const matches = value.split(identifierRegex);\n for (const match of matches) {\n if (match.startsWith('nø-')) {\n const idx = Number.parseInt(match.slice(3), 10);\n const fragment = fragments[idx];\n\n if (fragment) {\n const binding = createAttributeBinding(current, name, match, matches);\n hydrationUnits.push({ fragment, args: [current, { binding }] });\n }\n }\n }\n }\n\n // Apply Scope\n if (scope) {\n current.setAttribute(scope, '');\n }\n }\n });\n return hydrationUnits;\n};\n","import { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\nimport { type ComponentFragment, IS_COMPONENT } from './component-fragment';\nimport { hydrateComponentTemplate } from './hydrate-component-template';\n\nconst templateCache = new Map<string, HTMLTemplateElement>();\nconst getTemplate = (html: string) => {\n const template = templateCache.get(html);\n if (template && template.ownerDocument === document) {\n return template;\n }\n\n const created = document.createElement('template');\n created.innerHTML = html.trim();\n templateCache.set(html, created);\n return created;\n};\n\nexport const createComponentFragment = (template: string[], fragments: Fragment[]): ComponentFragment => {\n const html = template.join('');\n const fragmentId = createIdentifier();\n\n return {\n fragmentId: fragmentId,\n [IS_COMPONENT]: true as const,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => {\n return template\n .filter((_, i) => i % 2 === 0) // Keep even indices (Strings only)\n .flatMap((str, idx) => [str, fragments[idx]?.render() ?? ''])\n .join('');\n },\n hydrate: (node: Node, def) => {\n // Bail early if we have a hydration mismatch here\n if (!(node instanceof Comment)) return;\n\n // Retrieve the template, by either creating or\n // cloning it\n const template = getTemplate(html).content.cloneNode(true);\n\n // Hydrate the component template using the fragment,\n // the available fragments and scope the nodes if required\n for (const { fragment, args } of hydrateComponentTemplate(template, fragments, def?.scope)) {\n fragment.hydrate(...args);\n }\n\n node.replaceWith(template);\n },\n };\n};\n","import { type Fragment } from './fragment';\nimport { createIdentifier } from './identifier';\n\n// Creates a primitive fragment, containing a scalar value\n// that get's resolved and rendered only once.\nexport const createPrimitiveFragment = (fragmentValue: boolean | string | number | bigint): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => String(fragmentValue),\n hydrate: (node: Node, { binding } = {}) => {\n // Hydrate the node depending of it's type\n if (node instanceof Comment) {\n return node.replaceWith(new Text(String(fragmentValue)));\n }\n\n // Do the same for attributes\n if (node instanceof Element) {\n binding?.(fragmentValue);\n }\n },\n };\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport type { Subscribable } from '../application/subscribable';\nimport { type Fragment } from './fragment';\nimport { createIdentifier } from './identifier';\n\n// Creates a reactive fragment, that also updates the hydrated\n// node on update of the subscribable\nexport const createReactiveFragment = (fragmentValue: Subscribable): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => String(fragmentValue() ?? ''),\n hydrate: (node: Node, { binding } = {}) => {\n if (node instanceof Comment) {\n const text = new Text(String(fragmentValue() ?? ''));\n node.replaceWith(text);\n\n const onDestroy = fragmentValue.subscribe((value) => {\n text.textContent = String(value ?? '');\n });\n\n if (onDestroy) lifecycleObserver.trackUnmount(text, onDestroy);\n }\n\n if (node instanceof Element) {\n binding?.(fragmentValue() ?? '');\n\n const onDestroy = fragmentValue.subscribe((value) => {\n binding?.(value ?? '');\n });\n\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n };\n};\n","/**\n * Asserts that a given value is a primitive value\n * @param value\n */\nexport const isPrimitiveValue = (value: unknown): value is string | boolean | number | bigint => {\n return ['string', 'boolean', 'number', 'bigint'].includes(typeof value);\n};\n","import type { Subscribable } from '../application/subscribable';\n\nexport const isSubscribableValue = (value: unknown): value is Subscribable => {\n return value !== null && typeof value === 'function' && 'subscribe' in value;\n};\n","export const trimWhitespace = (str: string) => {\n return str.replace(/\\s{2,}/g, ' ');\n};\n","import { createComponentFragment } from '../component/create-component-fragment';\nimport { createPrimitiveFragment } from '../internals/create-primitive-fragment';\nimport { createReactiveFragment } from '../internals/create-reactive-fragment';\nimport { type Fragment } from '../internals/fragment';\nimport { isPrimitiveValue } from '../internals/is-primitive-value';\nimport { isSubscribableValue } from '../internals/is-subscribable-value';\nimport { trimWhitespace } from '../internals/trim-whitespace';\nimport type { Subscribable } from './subscribable';\n\nconst parseTemplateFragment = (\n fragment: string | number | boolean | bigint | null | undefined | Subscribable | Fragment,\n) => {\n switch (true) {\n case isSubscribableValue(fragment):\n return createReactiveFragment(fragment);\n case isPrimitiveValue(fragment) || fragment == null:\n return createPrimitiveFragment(fragment ?? '');\n default:\n return fragment;\n }\n};\n\n/**\n * Parses a provided html string representation into a `ComponentFragment`,\n * which is a basic hydratable fragment to use in templates or applications\n *\n * @param stringFragments\n * @param valueFragments\n */\nexport const templateParser = (\n stringFragments: TemplateStringsArray,\n ...valueFragments: (string | number | boolean | bigint | null | undefined | Subscribable | Fragment)[]\n) => {\n const fragments: Fragment[] = [];\n\n const template = stringFragments.flatMap((strFragment, idx) => {\n return [\n trimWhitespace(strFragment),\n ((): string => {\n const fragment = parseTemplateFragment(valueFragments[idx]);\n if ('fragmentId' in fragment) {\n fragment.fragmentId.create(String(idx));\n }\n fragments.push(fragment);\n return fragment.resolve();\n })(),\n ];\n });\n\n return createComponentFragment(template.flat(), fragments);\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\n\n/**\n * A `createDirective` wraps a handler function into a `Fragment` that can be\n * attached to any element in a template. The handler runs when the element is\n * hydrated and receives the element as its argument.\n *\n * ```ts\n * const color = (color: string) =>\n * createDirective((node) => {\n * node.style.backgroundColor = color;\n * });\n *\n * html`<div ${color('red')}>I'm a red div</div>`;\n * ```\n *\n * If the handler returns a function, it is registered as a cleanup callback\n * and called when the element is removed from the DOM.\n */\n\n/**\n * Creates a directive that runs a handler when the target element is hydrated.\n *\n * @param {(node: Element) => void | (() => void)} handler - A function called\n * with the target element on hydration. May return a cleanup function that runs\n * when the element is removed from the DOM.\n *\n * @returns {Fragment} A fragment representing the directive, attachable to\n * elements in a template.\n *\n * @example\n * ```ts\n * const autofocus = createDirective((node) => {\n * node.focus();\n * });\n *\n * html`<input ${autofocus} type=\"text\" />`;\n * ```\n */\nexport const createDirective = (handler: (node: Element) => void | (() => void)): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => fragmentId.get(),\n render: () => '',\n hydrate: (node: Node) => {\n if (node instanceof Element) {\n const onDestroy = handler(node);\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n } satisfies Fragment;\n};\n","import type { ComponentFragment } from '../component/component-fragment';\n\n/**\n * Method to hydrate a fragment and retrieve it's\n * nodes.\n *\n * @param fragment\n */\nexport const hydrateFragment = (fragment: ComponentFragment) => {\n const template = document.createElement('template');\n const anchor = new Comment();\n\n template.content.append(anchor);\n fragment.hydrate(anchor);\n\n return Array.from(template.content.childNodes) as Element[];\n};\n","import { lifecycleObserver } from '../application/lifecycle-observer';\nimport { type Fragment } from '../internals/fragment';\nimport { createIdentifier } from '../internals/identifier';\n/**\n * `createStruct` is the lower-level counterpart to `createDirective` — where\n * directives target `Element` nodes, structs target `Comment` nodes and are\n * used to manage dynamic regions of the DOM such as conditional blocks,\n * lists, and async content.\n *\n * A struct resolves to an HTML comment anchor in the template, which is then\n * used as a positional reference for inserting and removing nodes at runtime.\n *\n * ```ts\n * const myStruct = createStruct((anchor) => {\n * const node = document.createElement('p');\n * node.textContent = 'Hello';\n * anchor.before(node);\n *\n * return () => node.remove();\n * });\n *\n * html`${myStruct}`;\n * ```\n *\n * If the handler returns a function, it is registered as a cleanup callback\n * and called when the anchor is removed from the DOM.\n */\n\n/**\n * Creates a struct fragment that manages a dynamic DOM region via a comment anchor.\n *\n * @param {(node: Comment) => void | (() => void)} struct - A function called\n * with the comment anchor on hydration. May return a cleanup function that runs\n * when the anchor is removed from the DOM.\n * @param {() => string} [snapshot] - An optional function returning an HTML\n * string for SSR snapshots. Defaults to an empty string.\n *\n * @returns {Fragment} A fragment that resolves to a comment anchor in the\n * template and hydrates the struct when mounted.\n *\n * @example\n * ```ts\n * const myStruct = createStruct(\n * (anchor) => {\n * const node = document.createElement('p');\n * node.textContent = 'Hello';\n * anchor.before(node);\n * return () => node.remove();\n * },\n * () => '<p>Hello</p>',\n * );\n * ```\n */\nexport const createStruct = (\n struct: (node: Comment) => void | (() => void),\n snapshot: () => string = () => '',\n): Fragment => {\n const fragmentId = createIdentifier();\n return {\n fragmentId: fragmentId,\n resolve: () => `<!--${fragmentId.get()}-->`,\n render: () => snapshot(),\n hydrate: (node: Node) => {\n if (node instanceof Comment) {\n const onDestroy = struct(node);\n if (onDestroy) lifecycleObserver.trackUnmount(node, onDestroy);\n }\n },\n };\n};\n","import { disconnectNodes } from '../application/lifecycle-observer';\nimport type { Subscribable } from '../application/subscribable';\nimport type { ComponentFragment } from '../component/component-fragment';\nimport { hydrateFragment } from '../internals/hydrate-fragment';\nimport { createStruct } from './create-struct';\n\n/**\n * `$render` is a struct that renders a `ComponentFragment` held by a\n * `Subscribable`, replacing the current nodes whenever the fragment changes.\n *\n * ```ts\n * const view = grain(html`<p>Hello</p>`);\n *\n * html`${$render(view)}`;\n * ```\n *\n * When the subscribable emits a new fragment, the previous nodes are\n * disconnected and replaced with the newly rendered ones. All nodes are\n * cleaned up when the struct is unmounted.\n */\n\n/**\n * Creates a struct that reactively renders a `ComponentFragment` from a\n * subscribable source.\n *\n * @param {Subscribable<ComponentFragment>} source - A subscribable whose\n * value is the `ComponentFragment` to render. The rendered output is updated\n * whenever the source emits a new fragment.\n *\n * @returns {Fragment} A struct fragment that renders and tracks the current\n * fragment from the source.\n *\n * @example\n * ```ts\n * const view = grain(html`<p>Initial</p>`);\n *\n * html`${$render(view)}`;\n *\n * view.set(html`<p>Updated</p>`);\n * ```\n */\nexport const $render = (source: Subscribable<ComponentFragment>) => {\n return createStruct(\n (node) => {\n let nodes: Element[] = [];\n\n const render = (maybeFragment: (() => ComponentFragment) | ComponentFragment) => {\n disconnectNodes(nodes);\n\n const fragment = typeof maybeFragment === 'function' ? maybeFragment() : maybeFragment;\n nodes = hydrateFragment(fragment);\n\n node.before(...nodes);\n };\n\n render(source());\n const ondestroy = source.subscribe(render);\n\n return () => {\n ondestroy?.();\n disconnectNodes(nodes);\n nodes = [];\n };\n },\n () => {\n return source().render();\n },\n );\n};\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook =\n | {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => boolean | void;\n }\n | {\n run: 'load';\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>;\n };\n\nexport const pre = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n\nexport const load = (\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>,\n): NavigationHook => {\n return { run: 'load' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
@@ -1,3 +1,3 @@
1
- 'use strict';var grains=require('@grainular/grains'),nord=require('@grainular/nord');var x=t=>"default"in t?t.default():typeof t=="function"?t():t;var y=async(t,n)=>{for(let{handler:e}of t)if(await e({...n,navigate:s=>navigation.navigate(s)})===false)return false;return true};var w=t=>navigation.navigate(t);var b=t=>Object.fromEntries(Object.entries(t?.pathname?.groups??{}).filter(([n,e])=>e!==void 0));var E=t=>{let n=grains.readonly(t);return Object.assign(n,{select:e=>grains.derived(t,e)})};var C=new Map,L=(t,n)=>{for(let e of n){let r=new URL(e.path,`http://localhost${t}`);C.set(new URLPattern({pathname:r.pathname}),e);}return {match:e=>[...C.entries()].find(([r])=>r.test(e))??null}};var O=t=>t.canIntercept&&!t.hashChange&&!t.downloadRequest&&!t.formData,F=(t,n)=>{let e=grains.grain({}),r=grains.grain({}),{match:s}=L(t,n),m=grains.grain({resolved:null,component:null,path:null,route:null}),c=o=>{let[a,i]=s(o)??[];return !a||!i?null:{params:b(a.exec(o)),query:Object.fromEntries(o.searchParams),resolved:a.pathname,path:o.pathname,pattern:a,route:i,url:o}},l=o=>{queueMicrotask(()=>{w(o);});},v=async o=>{let{pattern:a,route:i,params:f,query:d,url:g}=o,u=(i.use??[]).filter(q=>q.run==="pre");if(!await y(u,{...o,redirect:l}))return;let R=x(await i.component());e.set(f),r.set(d),m.update(()=>({route:i,component:R,resolved:a.pathname,path:g.pathname}));},N=o=>n.some(a=>a===o);navigation.addEventListener("navigate",o=>{if(!O(o))return;let a=new URL(o.destination.url),i=c(a);if(!i||!N(i.route))return;let f=true;o.intercept({scroll:"after-transition",precommitHandler:async()=>{let d=(m().route?.use??[]).filter(u=>u.run==="post");f=await y(d,{...m(),params:e(),query:r(),redirect:l});let g=(i.route.use??[]).filter(u=>u.run==="pre");if(f=await y(g,{...i,redirect:l}),!f)throw new Error("Navigation Cancelled")},handler:async()=>{let{pattern:d,route:g,params:u,query:H}=i,R=x(await g.component());e.set(u),r.set(H),m.update(()=>({route:g,component:R,resolved:d.pathname,path:a.pathname}));}});});let h=c(new URL(navigation.currentEntry?.url??""));return h&&v(h),{params:E(e),query:grains.readonly(r),state:grains.readonly(m),match:s,base:t}};var M=(t,{exact:n}={exact:true})=>nord.createDirective(e=>{let r=()=>{let s=e.getAttribute("href"),m=navigation.currentEntry?.url;if(!m||!s)return;let c=new URL(m);e.classList.toggle(t,n?c.pathname===s:c.pathname.startsWith(s));};return navigation.addEventListener("navigatesuccess",r),()=>navigation.removeEventListener("navigatesuccess",r)});var j=t=>({run:"pre",handler:t}),z=t=>({run:"post",handler:t});var K=({for:t,transitionElement:n})=>{let e=grains.grain(nord.html``),r=`outlet-${t.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return t.state.subscribe(s=>{let{component:m,route:c}=s,l=m??nord.html``;if(!c?.transition)return e.set(l);let v=n?.current??document.documentElement;v.style.viewTransitionName=r,document.startViewTransition(()=>e.set(l)).ready.then(()=>{[c.transition??[]].flat().forEach(({keyframes:o,...a})=>{document.documentElement.animate(o,{pseudoElement:a.element?.replace("(root)",`(${r})`)?.replace("(outlet)",`(${r})`),...a});});});}),nord.$render(e)};var p=t=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...t});var D=t=>[p({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:t})],Q=(t,n="right")=>{let e=n==="left"||n==="right"?"X":"Y",r=n==="right"||n==="down"?"":"-";return [p({keyframes:[{transform:`translate${e}(${r}100%)`},{transform:`translate${e}(0)`}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{transform:`translate${e}(0)`},{transform:`translate${e}(${r===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:t})]},_=t=>[p({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:t})],I=t=>[p({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t})];
2
- exports.$outlet=K;exports.active=M;exports.createRouter=F;exports.crossFade=D;exports.fade=I;exports.navigate=w;exports.post=z;exports.pre=j;exports.scale=_;exports.slide=Q;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var grains=require('@grainular/grains'),nord=require('@grainular/nord');var C=t=>"default"in t?t.default():typeof t=="function"?t():t;var f=(t,o)=>{for(let{handler:e}of t)if(e({...o})===false)return false;return true};var w=t=>{navigation.navigate(typeof t=="string"?t:t.path,typeof t=="string"?{}:t??{});};var L=t=>Object.fromEntries(Object.entries(t?.pathname?.groups??{}).filter(([o,e])=>e!==void 0));var P=t=>{let o=grains.readonly(t);return Object.assign(o,{select:e=>grains.derived(t,e)})};var O=new Map,$=(t,o)=>{for(let e of o){let r=new URL(e.path,`http://localhost${t}`);O.set(new URLPattern({pathname:r.pathname}),e);}return {match:e=>[...O.entries()].find(([r])=>r.test(e))??null}};var j=t=>t.canIntercept&&!t.hashChange&&!t.downloadRequest&&!t.formData,z=(t,o)=>{let e=grains.grain({}),r=grains.grain({}),{match:u}=$(t,o),c=grains.grain({resolved:null,component:null,path:null,route:null}),m=n=>{let[i,a]=u(n)??[];return !i||!a?null:{params:L(i.exec(n)),query:Object.fromEntries(n.searchParams),resolved:i.pathname,path:n.pathname,pattern:i,route:a,url:n}},h=async n=>{let{pattern:i,route:a,params:g,query:d,url:v}=n,y=new Set,x=p=>{y.add(()=>queueMicrotask(()=>{w({path:p,history:"replace"});}));},s=(a.use??[]).filter(p=>p.run==="pre");if(!f(s,{...n,redirect:x})){let[p]=y.values();return y.clear(),p?.()}let H=(a.use??[]).filter(p=>p.run==="load");f(H,{...n,redirect:x});let b=C(await a.component());e.set(g),r.set(d),c.update(()=>({route:a,component:b,resolved:i.pathname,path:v.pathname}));},k=n=>o.some(i=>i===n);navigation.addEventListener("navigate",n=>{if(!j(n))return;let i=new URL(n.destination.url),a=m(i);if(!a||!k(a.route))return;let g=true,d=new Set,v=s=>{d.add(()=>queueMicrotask(()=>{w({path:s,history:"replace"});}));},y=(c().route?.use??[]).filter(s=>s.run==="post");g=f(y,{...c(),params:e(),query:r(),redirect:v});let x=(a.route.use??[]).filter(s=>s.run==="pre");if(g=g&&f(x,{...a,redirect:v}),!g){n.preventDefault();let[s]=d.values();return d.clear(),s?.()}n.intercept({scroll:"after-transition",handler:async()=>{let{pattern:s,route:R,params:H,query:b}=a,p=C(await R.component()),U=(R.use??[]).filter(F=>F.run==="load");f(U,{...a,redirect:v}),e.set(H),r.set(b),c.update(()=>({route:R,component:p,resolved:s.pathname,path:i.pathname}));}});});let N=m(new URL(navigation.currentEntry?.url??""));return N&&h(N),{params:P(e),query:grains.readonly(r),state:grains.readonly(c),match:u,base:t}};var A=(t,{exact:o}={exact:true})=>nord.createDirective(e=>{let r=()=>{let u=e.getAttribute("href"),c=navigation.currentEntry?.url;if(!c||!u)return;let m=new URL(c);e.classList.toggle(t,o?m.pathname===u:m.pathname.startsWith(u));};return navigation.addEventListener("navigatesuccess",r),()=>navigation.removeEventListener("navigatesuccess",r)});var D=t=>({run:"pre",handler:t}),K=t=>({run:"post",handler:t}),Q=t=>({run:"load",handler:t});var V=({for:t,transitionElement:o})=>{let e=grains.grain(nord.html``),r=`outlet-${t.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return t.state.subscribe(u=>{let{component:c,route:m}=u,h=c??nord.html``;if(!m?.transition)return e.set(h);let k=o?.current??document.documentElement;k.style.viewTransitionName=r,document.startViewTransition(()=>e.set(h)).ready.then(()=>{[m.transition??[]].flat().forEach(({keyframes:i,...a})=>{document.documentElement.animate(i,{pseudoElement:a.element?.replace("(root)",`(${r})`)?.replace("(outlet)",`(${r})`),...a});});});}),nord.$render(e)};var l=t=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...t});var W=t=>[l({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:t})],X=(t,o="right")=>{let e=o==="left"||o==="right"?"X":"Y",r=o==="right"||o==="down"?"":"-";return [l({keyframes:[{transform:`translate${e}(${r}100%)`},{transform:`translate${e}(0)`}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{transform:`translate${e}(0)`},{transform:`translate${e}(${r===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:t})]},Y=t=>[l({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:t})],Z=t=>[l({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t})];
2
+ exports.$outlet=V;exports.active=A;exports.createRouter=z;exports.crossFade=W;exports.fade=Z;exports.load=Q;exports.navigate=w;exports.post=K;exports.pre=D;exports.scale=Y;exports.slide=X;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["getFragment","resolved","resolveHooks","hooks","context","handler","path","navigate","getPathParamGroup","result","_","value","parameterized","internal","read","readonly","fn","derived","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","grain","query","match","state","getURLState","redirect","setRouterState","next","matchedParams","matchedQuery","preHooks","hook","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","current","active","cls","exact","createDirective","node","href","destination","pre","post","$outlet","router","transitionRef","currentComponent","html","name","component","target","keyframes","props","$render","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = async (hooks: NavigationHook[], context: Omit<NavigationHookContext, 'navigate'>) => {\n for (const { handler } of hooks) {\n const result = await handler({\n ...context,\n navigate: (path: string) => {\n return navigation.navigate(path);\n },\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export const navigate = (path: string) => navigation.navigate(path);\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const redirect = (path: string) => {\n queueMicrotask(() => {\n navigate(path);\n });\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = await resolveHooks(preHooks, { ...next, redirect });\n\n if (!canNavigate) return;\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n\n event.intercept({\n scroll: 'after-transition',\n precommitHandler: async () => {\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = await resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = await resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n if (!canNavigate) throw new Error('Navigation Cancelled');\n },\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook = {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => Promise<boolean | void>;\n};\n\nexport const pre = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
1
+ {"version":3,"sources":["../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["getFragment","resolved","resolveHooks","hooks","context","handler","navigate","destination","getPathParamGroup","result","_","value","parameterized","internal","read","readonly","fn","derived","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","grain","query","match","state","getURLState","setRouterState","next","matchedParams","matchedQuery","redirects","redirect","path","preHooks","hook","redirectFn","loadHooks","h","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","current","active","cls","exact","createDirective","node","href","pre","post","load","$outlet","router","transitionRef","currentComponent","html","name","component","target","keyframes","props","$render","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"qFAEO,IAAMA,CAAAA,CAAeC,CAAAA,EACpB,SAAA,GAAaA,CAAAA,CACNA,CAAAA,CAAS,OAAA,GAGhB,OAAOA,CAAAA,EAAa,UAAA,CACbA,CAAAA,EAAS,CAGbA,CAAAA,CCTJ,IAAMC,CAAAA,CAAe,CAACC,CAAAA,CAAyBC,CAAAA,GAAmC,CACrF,IAAA,GAAW,CAAE,OAAA,CAAAC,CAAQ,IAAKF,CAAAA,CAMtB,GALeE,CAAAA,CAAQ,CACnB,GAAGD,CACP,CAAC,CAAA,GAGc,KAAA,CAAO,OAAO,MAAA,CAGjC,OAAO,KACX,CAAA,CCXO,IAAME,CAAAA,CAAYC,GAAiC,CACtD,UAAA,CAAW,QAAA,CACP,OAAOA,CAAAA,EAAgB,QAAA,CAAWA,CAAAA,CAAcA,CAAAA,CAAY,IAAA,CAC5D,OAAOA,CAAAA,EAAgB,QAAA,CAAW,EAAC,CAAKA,CAAAA,EAAe,EAC3D,EACJ,ECPO,IAAMC,CAAAA,CAAqBC,CAAAA,EACvB,MAAA,CAAO,WAAA,CACV,MAAA,CAAO,OAAA,CAAQA,CAAAA,EAAQ,QAAA,EAAU,MAAA,EAAU,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,CAACC,CAAAA,CAAGC,CAAK,CAAA,GACrDA,CAAAA,GAAU,MACpB,CACL,CAAA,CCHG,IAAMC,CAAAA,CAAiBC,GAA4C,CACtE,IAAMC,CAAAA,CAAOC,eAAAA,CAASF,CAAQ,CAAA,CAE9B,OAAO,MAAA,CAAO,MAAA,CAAOC,CAAAA,CAAM,CACvB,MAAA,CAA2BE,CAAAA,EAChBC,cAAAA,CAAQJ,CAAAA,CAAUG,CAAgD,CAEjF,CAAC,CACL,CAAA,CCRO,IAAME,CAAAA,CAAW,IAAI,GAAA,CAEfC,CAAAA,CAAuB,CAACC,CAAAA,CAAcC,CAAAA,GAAoB,CACnE,IAAA,IAAWC,CAAAA,IAASD,CAAAA,CAAQ,CACxB,IAAME,EAAa,IAAI,GAAA,CAAID,CAAAA,CAAM,IAAA,CAAM,CAAA,gBAAA,EAAmBF,CAAI,CAAA,CAAE,CAAA,CAChEF,CAAAA,CAAS,GAAA,CAAI,IAAI,UAAA,CAAW,CAAE,QAAA,CAAUK,CAAAA,CAAW,QAAS,CAAC,CAAA,CAAGD,CAAK,EACzE,CAEA,OAAO,CACH,KAAA,CAAQE,CAAAA,EACG,CAAC,GAAGN,CAAAA,CAAS,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAACO,CAAO,CAAA,GAAMA,CAAAA,CAAQ,IAAA,CAAKD,CAAG,CAAC,CAAA,EAAK,IAEjF,CACJ,CAAA,CCEA,IAAME,CAAAA,CAAiBC,CAAAA,EACZA,CAAAA,CAAM,YAAA,EAAgB,CAACA,EAAM,UAAA,EAAc,CAACA,CAAAA,CAAM,eAAA,EAAmB,CAACA,CAAAA,CAAM,QAAA,CAG1EC,CAAAA,CAAe,CAACR,CAAAA,CAAcC,CAAAA,GAAoB,CAC3D,IAAMQ,CAAAA,CAASC,YAAAA,CAAM,EAAE,EACjBC,CAAAA,CAAQD,YAAAA,CAA8B,EAAE,CAAA,CAExC,CAAE,KAAA,CAAAE,CAAM,CAAA,CAAIb,CAAAA,CAAqBC,CAAAA,CAAMC,CAAM,CAAA,CAC7CY,CAAAA,CAAQH,YAAAA,CAA2B,CAAE,SAAU,IAAA,CAAM,SAAA,CAAW,IAAA,CAAM,IAAA,CAAM,IAAA,CAAM,KAAA,CAAO,IAAK,CAAC,CAAA,CAE/FI,CAAAA,CAAeV,CAAAA,EAAa,CAC9B,GAAM,CAACC,CAAAA,CAASH,CAAK,EAAIU,CAAAA,CAAMR,CAAG,CAAA,EAAK,EAAC,CACxC,OAAI,CAACC,CAAAA,EAAW,CAACH,CAAAA,CAAc,IAAA,CAExB,CACH,MAAA,CAAQd,CAAAA,CAAkBiB,CAAAA,CAAQ,IAAA,CAAKD,CAAG,CAAC,CAAA,CAC3C,KAAA,CAAO,MAAA,CAAO,WAAA,CAAYA,CAAAA,CAAI,YAAY,CAAA,CAC1C,SAAUC,CAAAA,CAAQ,QAAA,CAClB,IAAA,CAAMD,CAAAA,CAAI,QAAA,CACV,OAAA,CAASC,CAAAA,CACT,KAAA,CAAOH,EACP,GAAA,CAAKE,CACT,CACJ,CAAA,CAEMW,CAAAA,CAAiB,MAAOC,CAAAA,EAAsD,CAChF,GAAM,CAAE,OAAA,CAAAX,CAAAA,CAAS,KAAA,CAAAH,CAAAA,CAAO,MAAA,CAAQe,CAAAA,CAAe,MAAOC,CAAAA,CAAc,GAAA,CAAAd,CAAI,CAAA,CAAIY,CAAAA,CAEtEG,CAAAA,CAAY,IAAI,GAAA,CAChBC,CAAAA,CAAYC,CAAAA,EAAiB,CAC/BF,CAAAA,CAAU,GAAA,CAAI,IACV,cAAA,CAAe,IAAM,CACjBjC,CAAAA,CAAS,CAAE,IAAA,CAAAmC,CAAAA,CAAM,OAAA,CAAS,SAAU,CAAC,EACzC,CAAC,CACL,EACJ,CAAA,CAGMC,CAAAA,CAAAA,CAAYpB,CAAAA,CAAM,GAAA,EAAO,IAAI,MAAA,CAAQqB,CAAAA,EAASA,CAAAA,CAAK,GAAA,GAAQ,KAAK,CAAA,CAMtE,GAAI,CALgBzC,EAAawC,CAAAA,CAAU,CAAE,GAAGN,CAAAA,CAAM,QAAA,CAAAI,CAAS,CAAC,CAAA,CAK9C,CACd,GAAM,CAACI,CAAU,CAAA,CAAIL,CAAAA,CAAU,MAAA,EAAO,CACtC,OAAAA,CAAAA,CAAU,KAAA,EAAM,CACTK,CAAAA,IACX,CAIA,IAAMC,CAAAA,CAAAA,CAAavB,EAAM,GAAA,EAAO,EAAC,EAAG,MAAA,CAAQwB,CAAAA,EAAMA,CAAAA,CAAE,GAAA,GAAQ,MAAM,CAAA,CAClE5C,CAAAA,CAAa2C,CAAAA,CAAW,CAAE,GAAGT,CAAAA,CAAM,QAAA,CAAAI,CAAS,CAAC,CAAA,CAE7C,IAAMO,CAAAA,CAAW/C,CAAAA,CAAY,MAAMsB,CAAAA,CAAM,SAAA,EAAW,CAAA,CACpDO,CAAAA,CAAO,GAAA,CAAIQ,CAAa,CAAA,CACxBN,CAAAA,CAAM,GAAA,CAAIO,CAAY,EACtBL,CAAAA,CAAM,MAAA,CAAO,KACF,CACH,KAAA,CAAAX,CAAAA,CACA,SAAA,CAAWyB,CAAAA,CACX,SAAUtB,CAAAA,CAAQ,QAAA,CAClB,IAAA,CAAMD,CAAAA,CAAI,QACd,CAAA,CACH,EACL,CAAA,CAEMwB,EAAc1B,CAAAA,EACTD,CAAAA,CAAO,IAAA,CAAM4B,CAAAA,EAAaA,CAAAA,GAAa3B,CAAK,CAAA,CAGvD,UAAA,CAAW,gBAAA,CAAiB,UAAA,CAAaK,CAAAA,EAAU,CAC/C,GAAI,CAACD,CAAAA,CAAcC,CAAK,EAAG,OAC3B,IAAMH,CAAAA,CAAM,IAAI,GAAA,CAAIG,CAAAA,CAAM,WAAA,CAAY,GAAG,CAAA,CAEnCuB,CAAAA,CAAYhB,CAAAA,CAAYV,CAAG,CAAA,CACjC,GAAI,CAAC0B,CAAAA,EAAa,CAACF,CAAAA,CAAWE,CAAAA,CAAU,KAAK,CAAA,CAAG,OAChD,IAAIC,CAAAA,CAAc,IAAA,CACZZ,CAAAA,CAAY,IAAI,GAAA,CAChBC,CAAAA,CAAYC,CAAAA,EAAiB,CAC/BF,CAAAA,CAAU,GAAA,CAAI,IACV,cAAA,CAAe,IAAM,CACjBjC,CAAAA,CAAS,CAAE,IAAA,CAAAmC,CAAAA,CAAM,OAAA,CAAS,SAAU,CAAC,EACzC,CAAC,CACL,EACJ,CAAA,CAGMW,CAAAA,CAAAA,CAAanB,CAAAA,GAAQ,KAAA,EAAO,GAAA,EAAO,EAAC,EAAG,MAAA,CAAQU,CAAAA,EAASA,CAAAA,CAAK,GAAA,GAAQ,MAAM,CAAA,CACjFQ,CAAAA,CAAcjD,CAAAA,CAAakD,CAAAA,CAAW,CAAE,GAAGnB,CAAAA,GAAS,MAAA,CAAQJ,CAAAA,EAAO,CAAG,KAAA,CAAOE,CAAAA,EAAM,CAAG,QAAA,CAAAS,CAAS,CAAC,CAAA,CAGhG,IAAME,CAAAA,CAAAA,CAAYQ,CAAAA,CAAU,KAAA,CAAM,GAAA,EAAO,IAAI,MAAA,CAAQP,CAAAA,EAASA,CAAAA,CAAK,GAAA,GAAQ,KAAK,CAAA,CAMhF,GALAQ,CAAAA,CAAcA,CAAAA,EAAejD,CAAAA,CAAawC,CAAAA,CAAU,CAAE,GAAGQ,CAAAA,CAAW,QAAA,CAAAV,CAAS,CAAC,CAAA,CAK1E,CAACW,CAAAA,CAAa,CACdxB,CAAAA,CAAM,cAAA,EAAe,CACrB,GAAM,CAACiB,CAAU,CAAA,CAAIL,CAAAA,CAAU,MAAA,EAAO,CACtC,OAAAA,CAAAA,CAAU,KAAA,GACHK,CAAAA,IACX,CAEAjB,CAAAA,CAAM,SAAA,CAAU,CACZ,MAAA,CAAQ,kBAAA,CAKR,OAAA,CAAS,SAAY,CAEjB,GAAM,CAAE,OAAA,CAAAF,CAAAA,CAAS,KAAA,CAAAH,EAAO,MAAA,CAAQe,CAAAA,CAAe,KAAA,CAAOC,CAAa,CAAA,CAAIY,CAAAA,CACjEH,CAAAA,CAAW/C,CAAAA,CAAY,MAAMsB,CAAAA,CAAM,SAAA,EAAW,CAAA,CAE9CuB,CAAAA,CAAAA,CAAavB,CAAAA,CAAM,GAAA,EAAO,EAAC,EAAG,MAAA,CAAQwB,CAAAA,EAAMA,CAAAA,CAAE,GAAA,GAAQ,MAAM,CAAA,CAClE5C,CAAAA,CAAa2C,CAAAA,CAAW,CAAE,GAAGK,CAAAA,CAAW,QAAA,CAAAV,CAAS,CAAC,CAAA,CAElDX,EAAO,GAAA,CAAIQ,CAAa,CAAA,CACxBN,CAAAA,CAAM,GAAA,CAAIO,CAAY,CAAA,CACtBL,CAAAA,CAAM,MAAA,CAAO,KACF,CACH,KAAA,CAAAX,CAAAA,CACA,SAAA,CAAWyB,CAAAA,CACX,QAAA,CAAUtB,EAAQ,QAAA,CAClB,IAAA,CAAMD,CAAAA,CAAI,QACd,CAAA,CACH,EACL,CACJ,CAAC,EACL,CAAC,CAAA,CAGD,IAAM6B,CAAAA,CAAUnB,CAAAA,CAAY,IAAI,GAAA,CAAI,WAAW,YAAA,EAAc,GAAA,EAAO,EAAE,CAAC,CAAA,CACvE,OAAImB,CAAAA,EAASlB,CAAAA,CAAekB,CAAO,CAAA,CAE5B,CACH,MAAA,CAAQzC,CAAAA,CAAciB,CAAM,CAAA,CAC5B,KAAA,CAAOd,gBAASgB,CAAK,CAAA,CACrB,KAAA,CAAOhB,eAAAA,CAASkB,CAAK,CAAA,CACrB,KAAA,CAAAD,CAAAA,CACA,IAAA,CAAAZ,CACJ,CACJ,MCjKakC,CAAAA,CAAS,CAACC,CAAAA,CAAa,CAAE,KAAA,CAAAC,CAAM,CAAA,CAAwB,CAAE,MAAO,IAAK,CAAA,GACvEC,oBAAAA,CAAiBC,CAAAA,EAAS,CAC7B,IAAMrD,CAAAA,CAAU,IAAM,CAClB,IAAMsD,CAAAA,CAAOD,CAAAA,CAAK,YAAA,CAAa,MAAM,CAAA,CAC/BnD,CAAAA,CAAc,UAAA,CAAW,YAAA,EAAc,GAAA,CAG7C,GAAI,CAACA,CAAAA,EAAe,CAACoD,CAAAA,CAAM,OAC3B,IAAMnC,CAAAA,CAAM,IAAI,GAAA,CAAIjB,CAAW,CAAA,CAC/BmD,CAAAA,CAAK,SAAA,CAAU,MAAA,CAAOH,CAAAA,CAAKC,CAAAA,CAAQhC,CAAAA,CAAI,QAAA,GAAamC,CAAAA,CAAOnC,CAAAA,CAAI,QAAA,CAAS,UAAA,CAAWmC,CAAI,CAAC,EAC5F,CAAA,CAEA,OAAA,UAAA,CAAW,gBAAA,CAAiB,iBAAA,CAAmBtD,CAAO,CAAA,CAC/C,IAAM,UAAA,CAAW,mBAAA,CAAoB,iBAAA,CAAmBA,CAAO,CAC1E,CAAC,MCCQuD,CAAAA,CAAOvD,CAAAA,GACT,CAAE,GAAA,CAAK,KAAA,CAAgB,OAAA,CAAAA,CAAQ,CAAA,CAAA,CAG7BwD,EAAQxD,CAAAA,GACV,CAAE,GAAA,CAAK,MAAA,CAAiB,OAAA,CAAAA,CAAQ,CAAA,CAAA,CAG9ByD,CAAAA,CACTzD,IAEO,CAAE,GAAA,CAAK,MAAA,CAAiB,OAAA,CAAAA,CAAQ,CAAA,MCnB9B0D,CAAAA,CAAU,CAAC,CAAE,GAAA,CAAKC,CAAAA,CAAQ,iBAAA,CAAmBC,CAAc,CAAA,GAAoB,CACxF,IAAMC,CAAAA,CAAmBpC,YAAAA,CAAyBqC,SAAAA,CAAAA,CAAM,CAAA,CAClDC,CAAAA,CAAO,CAAA,OAAA,EAAUJ,EAAO,IAAA,CAAK,OAAA,CAAQ,iBAAA,CAAmB,EAAE,CAAA,EAAK,MAAM,CAAA,CAAA,CAE3E,OAAAA,CAAAA,CAAO,KAAA,CAAM,SAAA,CAAW/B,CAAAA,EAAU,CAC9B,GAAM,CAAE,SAAA,CAAAoC,EAAW,KAAA,CAAA/C,CAAM,CAAA,CAAIW,CAAAA,CACvBG,CAAAA,CAAOiC,CAAAA,EAAaF,SAAAA,CAAAA,CAAAA,CAC1B,GAAI,CAAC7C,CAAAA,EAAO,UAAA,CAAY,OAAO4C,CAAAA,CAAiB,GAAA,CAAI9B,CAAI,CAAA,CAGxD,IAAMkC,EAASL,CAAAA,EAAe,OAAA,EAAW,QAAA,CAAS,eAAA,CAClDK,CAAAA,CAAO,KAAA,CAAM,kBAAA,CAAqBF,CAAAA,CAEX,QAAA,CAAS,mBAAA,CAAoB,IAAMF,CAAAA,CAAiB,GAAA,CAAI9B,CAAI,CAAC,CAAA,CACrE,MAAM,IAAA,CAAK,IAAM,CACT,CAACd,CAAAA,CAAM,UAAA,EAAc,EAAE,CAAA,CAAE,IAAA,EAAK,CACtC,OAAA,CAAQ,CAAC,CAAE,SAAA,CAAAiD,CAAAA,CAAW,GAAGC,CAAM,CAAA,GAAM,CAC5C,QAAA,CAAS,eAAA,CAAgB,OAAA,CAAQD,CAAAA,CAAW,CACxC,aAAA,CAAeC,CAAAA,CAAM,OAAA,EAAS,OAAA,CAAQ,QAAA,CAAU,CAAA,CAAA,EAAIJ,CAAI,CAAA,CAAA,CAAG,GAAG,OAAA,CAAQ,UAAA,CAAY,CAAA,CAAA,EAAIA,CAAI,CAAA,CAAA,CAAG,CAAA,CAC7F,GAAGI,CACP,CAAC,EACL,CAAC,EACL,CAAC,EACL,CAAC,CAAA,CAGMC,YAAAA,CAAQP,CAAgB,CACnC,EC5BO,IAAMQ,CAAAA,CAAcC,CAAAA,GAChB,CACH,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,6BAAA,CACT,GAAGA,CACP,CAAA,CAAA,CCZG,IAAMC,EAAaC,CAAAA,EACf,CACHH,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,OAAA,CAAS,CAAE,CAAC,CAAA,CAC1C,OAAA,CAAS,8BACT,QAAA,CAAAG,CACJ,CAAC,CAAA,CACDH,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,OAAA,CAAS,CAAE,CAAC,EAC1C,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL,CAAA,CAISC,CAAAA,CAAQ,CAACD,CAAAA,CAAkBE,CAAAA,CAA8C,OAAA,GAAY,CAC9F,IAAMC,CAAAA,CAAOD,CAAAA,GAAc,MAAA,EAAUA,IAAc,OAAA,CAAU,GAAA,CAAM,GAAA,CAC7DE,CAAAA,CAAOF,CAAAA,GAAc,OAAA,EAAWA,CAAAA,GAAc,MAAA,CAAS,EAAA,CAAK,GAAA,CAElE,OAAO,CACHL,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYM,CAAI,CAAA,CAAA,EAAIC,CAAI,CAAA,KAAA,CAAQ,CAAA,CAAG,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYD,CAAI,CAAA,GAAA,CAAM,CAAC,CAAA,CAChG,OAAA,CAAS,6BAAA,CACT,SAAAH,CACJ,CAAC,CAAA,CACDH,CAAAA,CAAW,CACP,SAAA,CAAW,CACP,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYM,CAAI,CAAA,GAAA,CAAM,CAAA,CACnC,CAAE,SAAA,CAAW,CAAA,SAAA,EAAYA,CAAI,CAAA,CAAA,EAAIC,CAAAA,GAAS,EAAA,CAAK,GAAA,CAAM,EAAE,CAAA,KAAA,CAAQ,CACnE,CAAA,CACA,QAAS,6BAAA,CACT,QAAA,CAAAJ,CACJ,CAAC,CACL,CACJ,CAAA,CAGaK,CAAAA,CAASL,GACX,CACHH,CAAAA,CAAW,CACP,SAAA,CAAW,CACP,CAAE,SAAA,CAAW,aAAA,CAAe,OAAA,CAAS,CAAE,CAAA,CACvC,CAAE,SAAA,CAAW,UAAA,CAAY,OAAA,CAAS,CAAE,CACxC,CAAA,CACA,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CAAA,CACDH,CAAAA,CAAW,CACP,SAAA,CAAW,CACP,CAAE,SAAA,CAAW,UAAA,CAAY,OAAA,CAAS,CAAE,EACpC,CAAE,SAAA,CAAW,aAAA,CAAe,OAAA,CAAS,CAAE,CAC3C,CAAA,CACA,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL,CAAA,CAISM,CAAAA,CAAQN,CAAAA,EACV,CACHH,CAAAA,CAAW,CACP,SAAA,CAAW,CAAC,CAAE,OAAA,CAAS,CAAE,CAAA,CAAG,CAAE,OAAA,CAAS,CAAE,CAAC,CAAA,CAC1C,OAAA,CAAS,6BAAA,CACT,QAAA,CAAAG,CACJ,CAAC,CACL","file":"index.cjs","sourcesContent":["import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = (hooks: NavigationHook[], context: NavigationHookContext) => {\n for (const { handler } of hooks) {\n const result = handler({\n ...context,\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export type NavigateOptions = string | ({ path: string } & NavigationNavigateOptions);\n\nexport const navigate = (destination: NavigateOptions) => {\n navigation.navigate(\n typeof destination === 'string' ? destination : destination.path,\n typeof destination === 'string' ? {} : (destination ?? {}),\n );\n};\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = resolveHooks(preHooks, { ...next, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n // Run the load hooks\n // LOAD hooks — async, non-blocking for navigation\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...next, redirect });\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = canNavigate && resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n event.preventDefault();\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n event.intercept({\n scroll: 'after-transition',\n // As the handler is not yes baseline as of mid 2026, we cannot\n // use the precommitController. Without it, pre and post hooks need\n // to be resolved synchronously.\n // precommitHandler: async () => {},\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...nextState, redirect });\n\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook =\n | {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => boolean | void;\n }\n | {\n run: 'load';\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>;\n };\n\nexport const pre = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n\nexport const load = (\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>,\n): NavigationHook => {\n return { run: 'load' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
package/dist/esm/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import {grain,readonly,derived}from'@grainular/grains';import {createDirective,html,$render}from'@grainular/nord';var x=t=>"default"in t?t.default():typeof t=="function"?t():t;var y=async(t,n)=>{for(let{handler:e}of t)if(await e({...n,navigate:s=>navigation.navigate(s)})===false)return false;return true};var w=t=>navigation.navigate(t);var b=t=>Object.fromEntries(Object.entries(t?.pathname?.groups??{}).filter(([n,e])=>e!==void 0));var E=t=>{let n=readonly(t);return Object.assign(n,{select:e=>derived(t,e)})};var C=new Map,L=(t,n)=>{for(let e of n){let r=new URL(e.path,`http://localhost${t}`);C.set(new URLPattern({pathname:r.pathname}),e);}return {match:e=>[...C.entries()].find(([r])=>r.test(e))??null}};var O=t=>t.canIntercept&&!t.hashChange&&!t.downloadRequest&&!t.formData,F=(t,n)=>{let e=grain({}),r=grain({}),{match:s}=L(t,n),m=grain({resolved:null,component:null,path:null,route:null}),c=o=>{let[a,i]=s(o)??[];return !a||!i?null:{params:b(a.exec(o)),query:Object.fromEntries(o.searchParams),resolved:a.pathname,path:o.pathname,pattern:a,route:i,url:o}},l=o=>{queueMicrotask(()=>{w(o);});},v=async o=>{let{pattern:a,route:i,params:f,query:d,url:g}=o,u=(i.use??[]).filter(q=>q.run==="pre");if(!await y(u,{...o,redirect:l}))return;let R=x(await i.component());e.set(f),r.set(d),m.update(()=>({route:i,component:R,resolved:a.pathname,path:g.pathname}));},N=o=>n.some(a=>a===o);navigation.addEventListener("navigate",o=>{if(!O(o))return;let a=new URL(o.destination.url),i=c(a);if(!i||!N(i.route))return;let f=true;o.intercept({scroll:"after-transition",precommitHandler:async()=>{let d=(m().route?.use??[]).filter(u=>u.run==="post");f=await y(d,{...m(),params:e(),query:r(),redirect:l});let g=(i.route.use??[]).filter(u=>u.run==="pre");if(f=await y(g,{...i,redirect:l}),!f)throw new Error("Navigation Cancelled")},handler:async()=>{let{pattern:d,route:g,params:u,query:H}=i,R=x(await g.component());e.set(u),r.set(H),m.update(()=>({route:g,component:R,resolved:d.pathname,path:a.pathname}));}});});let h=c(new URL(navigation.currentEntry?.url??""));return h&&v(h),{params:E(e),query:readonly(r),state:readonly(m),match:s,base:t}};var M=(t,{exact:n}={exact:true})=>createDirective(e=>{let r=()=>{let s=e.getAttribute("href"),m=navigation.currentEntry?.url;if(!m||!s)return;let c=new URL(m);e.classList.toggle(t,n?c.pathname===s:c.pathname.startsWith(s));};return navigation.addEventListener("navigatesuccess",r),()=>navigation.removeEventListener("navigatesuccess",r)});var j=t=>({run:"pre",handler:t}),z=t=>({run:"post",handler:t});var K=({for:t,transitionElement:n})=>{let e=grain(html``),r=`outlet-${t.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return t.state.subscribe(s=>{let{component:m,route:c}=s,l=m??html``;if(!c?.transition)return e.set(l);let v=n?.current??document.documentElement;v.style.viewTransitionName=r,document.startViewTransition(()=>e.set(l)).ready.then(()=>{[c.transition??[]].flat().forEach(({keyframes:o,...a})=>{document.documentElement.animate(o,{pseudoElement:a.element?.replace("(root)",`(${r})`)?.replace("(outlet)",`(${r})`),...a});});});}),$render(e)};var p=t=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...t});var D=t=>[p({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:t})],Q=(t,n="right")=>{let e=n==="left"||n==="right"?"X":"Y",r=n==="right"||n==="down"?"":"-";return [p({keyframes:[{transform:`translate${e}(${r}100%)`},{transform:`translate${e}(0)`}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{transform:`translate${e}(0)`},{transform:`translate${e}(${r===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:t})]},_=t=>[p({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:t}),p({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:t})],I=t=>[p({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t})];
2
- export{K as $outlet,M as active,F as createRouter,D as crossFade,I as fade,w as navigate,z as post,j as pre,_ as scale,Q as slide};//# sourceMappingURL=index.js.map
1
+ import {grain,readonly,derived}from'@grainular/grains';import {createDirective,html,$render}from'@grainular/nord';var C=t=>"default"in t?t.default():typeof t=="function"?t():t;var f=(t,o)=>{for(let{handler:e}of t)if(e({...o})===false)return false;return true};var w=t=>{navigation.navigate(typeof t=="string"?t:t.path,typeof t=="string"?{}:t??{});};var L=t=>Object.fromEntries(Object.entries(t?.pathname?.groups??{}).filter(([o,e])=>e!==void 0));var P=t=>{let o=readonly(t);return Object.assign(o,{select:e=>derived(t,e)})};var O=new Map,$=(t,o)=>{for(let e of o){let r=new URL(e.path,`http://localhost${t}`);O.set(new URLPattern({pathname:r.pathname}),e);}return {match:e=>[...O.entries()].find(([r])=>r.test(e))??null}};var j=t=>t.canIntercept&&!t.hashChange&&!t.downloadRequest&&!t.formData,z=(t,o)=>{let e=grain({}),r=grain({}),{match:u}=$(t,o),c=grain({resolved:null,component:null,path:null,route:null}),m=n=>{let[i,a]=u(n)??[];return !i||!a?null:{params:L(i.exec(n)),query:Object.fromEntries(n.searchParams),resolved:i.pathname,path:n.pathname,pattern:i,route:a,url:n}},h=async n=>{let{pattern:i,route:a,params:g,query:d,url:v}=n,y=new Set,x=p=>{y.add(()=>queueMicrotask(()=>{w({path:p,history:"replace"});}));},s=(a.use??[]).filter(p=>p.run==="pre");if(!f(s,{...n,redirect:x})){let[p]=y.values();return y.clear(),p?.()}let H=(a.use??[]).filter(p=>p.run==="load");f(H,{...n,redirect:x});let b=C(await a.component());e.set(g),r.set(d),c.update(()=>({route:a,component:b,resolved:i.pathname,path:v.pathname}));},k=n=>o.some(i=>i===n);navigation.addEventListener("navigate",n=>{if(!j(n))return;let i=new URL(n.destination.url),a=m(i);if(!a||!k(a.route))return;let g=true,d=new Set,v=s=>{d.add(()=>queueMicrotask(()=>{w({path:s,history:"replace"});}));},y=(c().route?.use??[]).filter(s=>s.run==="post");g=f(y,{...c(),params:e(),query:r(),redirect:v});let x=(a.route.use??[]).filter(s=>s.run==="pre");if(g=g&&f(x,{...a,redirect:v}),!g){n.preventDefault();let[s]=d.values();return d.clear(),s?.()}n.intercept({scroll:"after-transition",handler:async()=>{let{pattern:s,route:R,params:H,query:b}=a,p=C(await R.component()),U=(R.use??[]).filter(F=>F.run==="load");f(U,{...a,redirect:v}),e.set(H),r.set(b),c.update(()=>({route:R,component:p,resolved:s.pathname,path:i.pathname}));}});});let N=m(new URL(navigation.currentEntry?.url??""));return N&&h(N),{params:P(e),query:readonly(r),state:readonly(c),match:u,base:t}};var A=(t,{exact:o}={exact:true})=>createDirective(e=>{let r=()=>{let u=e.getAttribute("href"),c=navigation.currentEntry?.url;if(!c||!u)return;let m=new URL(c);e.classList.toggle(t,o?m.pathname===u:m.pathname.startsWith(u));};return navigation.addEventListener("navigatesuccess",r),()=>navigation.removeEventListener("navigatesuccess",r)});var D=t=>({run:"pre",handler:t}),K=t=>({run:"post",handler:t}),Q=t=>({run:"load",handler:t});var V=({for:t,transitionElement:o})=>{let e=grain(html``),r=`outlet-${t.base.replace(/[^a-zA-Z0-9-_]/g,"")||"root"}`;return t.state.subscribe(u=>{let{component:c,route:m}=u,h=c??html``;if(!m?.transition)return e.set(h);let k=o?.current??document.documentElement;k.style.viewTransitionName=r,document.startViewTransition(()=>e.set(h)).ready.then(()=>{[m.transition??[]].flat().forEach(({keyframes:i,...a})=>{document.documentElement.animate(i,{pseudoElement:a.element?.replace("(root)",`(${r})`)?.replace("(outlet)",`(${r})`),...a});});});}),$render(e)};var l=t=>({delay:0,easing:"linear",element:"::view-transition-new(root)",...t});var W=t=>[l({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{opacity:1},{opacity:0}],element:"::view-transition-old(root)",duration:t})],X=(t,o="right")=>{let e=o==="left"||o==="right"?"X":"Y",r=o==="right"||o==="down"?"":"-";return [l({keyframes:[{transform:`translate${e}(${r}100%)`},{transform:`translate${e}(0)`}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{transform:`translate${e}(0)`},{transform:`translate${e}(${r===""?"-":""}100%)`}],element:"::view-transition-old(root)",duration:t})]},Y=t=>[l({keyframes:[{transform:"scale(0.95)",opacity:0},{transform:"scale(1)",opacity:1}],element:"::view-transition-new(root)",duration:t}),l({keyframes:[{transform:"scale(1)",opacity:1},{transform:"scale(0.95)",opacity:0}],element:"::view-transition-old(root)",duration:t})],Z=t=>[l({keyframes:[{opacity:0},{opacity:1}],element:"::view-transition-new(root)",duration:t})];
2
+ export{V as $outlet,A as active,z as createRouter,W as crossFade,Z as fade,Q as load,w as navigate,K as post,D as pre,Y as scale,X as slide};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["getFragment","resolved","resolveHooks","hooks","context","handler","path","navigate","getPathParamGroup","result","_","value","parameterized","internal","read","readonly","fn","derived","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","grain","query","match","state","getURLState","redirect","setRouterState","next","matchedParams","matchedQuery","preHooks","hook","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","current","active","cls","exact","createDirective","node","href","destination","pre","post","$outlet","router","transitionRef","currentComponent","html","name","component","target","keyframes","props","$render","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"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","file":"index.js","sourcesContent":["import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = async (hooks: NavigationHook[], context: Omit<NavigationHookContext, 'navigate'>) => {\n for (const { handler } of hooks) {\n const result = await handler({\n ...context,\n navigate: (path: string) => {\n return navigation.navigate(path);\n },\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export const navigate = (path: string) => navigation.navigate(path);\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const redirect = (path: string) => {\n queueMicrotask(() => {\n navigate(path);\n });\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = await resolveHooks(preHooks, { ...next, redirect });\n\n if (!canNavigate) return;\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n\n event.intercept({\n scroll: 'after-transition',\n precommitHandler: async () => {\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = await resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = await resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n if (!canNavigate) throw new Error('Navigation Cancelled');\n },\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook = {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => Promise<boolean | void>;\n};\n\nexport const pre = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => Promise<boolean | void>): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
1
+ {"version":3,"sources":["../../src/lib/fragments.ts","../../src/lib/hooks/resolve-hook.ts","../../src/lib/navigate.ts","../../src/lib/params/get-path-param-group.ts","../../src/lib/params/parameterized.ts","../../src/lib/pattern-matcher.ts","../../src/lib/create-router.ts","../../src/lib/directives/active.ts","../../src/lib/hooks/hooks.ts","../../src/lib/outlet.ts","../../src/lib/transitions/transition.ts","../../src/lib/transitions/prefabs.ts"],"names":["getFragment","resolved","resolveHooks","hooks","context","handler","navigate","destination","getPathParamGroup","result","_","value","parameterized","internal","read","readonly","fn","derived","registry","createPatternMatcher","base","routes","route","normalized","url","pattern","isRouterEvent","event","createRouter","params","grain","query","match","state","getURLState","setRouterState","next","matchedParams","matchedQuery","redirects","redirect","path","preHooks","hook","redirectFn","loadHooks","h","fragment","isOwnRoute","ownRoute","nextState","canNavigate","postHooks","current","active","cls","exact","createDirective","node","href","pre","post","load","$outlet","router","transitionRef","currentComponent","html","name","component","target","keyframes","props","$render","transition","setup","crossFade","duration","slide","direction","axis","sign","scale","fade"],"mappings":"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","file":"index.js","sourcesContent":["import type { Route } from './route';\n\nexport const getFragment = (resolved: Awaited<ReturnType<Route['component']>>) => {\n if ('default' in resolved) {\n return resolved.default();\n }\n\n if (typeof resolved === 'function') {\n return resolved();\n }\n\n return resolved;\n};\n","import type { NavigationHook, NavigationHookContext } from './hooks';\n\nexport const resolveHooks = (hooks: NavigationHook[], context: NavigationHookContext) => {\n for (const { handler } of hooks) {\n const result = handler({\n ...context,\n });\n\n // Bail if a hook returns false explicitly\n if (result === false) return false;\n }\n\n return true;\n};\n","export type NavigateOptions = string | ({ path: string } & NavigationNavigateOptions);\n\nexport const navigate = (destination: NavigateOptions) => {\n navigation.navigate(\n typeof destination === 'string' ? destination : destination.path,\n typeof destination === 'string' ? {} : (destination ?? {}),\n );\n};\n","export const getPathParamGroup = (result: URLPatternResult | null) => {\n return Object.fromEntries(\n Object.entries(result?.pathname?.groups ?? {}).filter(([_, value]) => {\n return value !== undefined;\n }),\n ) as Record<string, string>;\n};\n","import { derived, type Grain, readonly } from '@grainular/grains';\n\nexport const parameterized = (internal: Grain<Record<string, string>>) => {\n const read = readonly(internal);\n\n return Object.assign(read, {\n select: <K extends string>(fn: (params: Record<K, string>) => string) => {\n return derived(internal, fn as (params: Record<string, string>) => string);\n },\n });\n};\n","import type { Route } from './route';\n\nexport const registry = new Map<URLPattern, Route>();\n\nexport const createPatternMatcher = (base: string, routes: Route[]) => {\n for (const route of routes) {\n const normalized = new URL(route.path, `http://localhost${base}`);\n registry.set(new URLPattern({ pathname: normalized.pathname }), route);\n }\n\n return {\n match: (url: URL) => {\n return [...registry.entries()].find(([pattern]) => pattern.test(url)) ?? null;\n },\n };\n};\n","import { grain, readonly } from '@grainular/grains';\nimport type { ComponentFragment } from '@grainular/nord';\nimport { getFragment } from './fragments';\nimport { resolveHooks } from './hooks/resolve-hook';\nimport { navigate } from './navigate';\nimport { getPathParamGroup } from './params/get-path-param-group';\nimport { parameterized } from './params/parameterized';\nimport { createPatternMatcher } from './pattern-matcher';\nimport type { Route } from './route';\n\ntype RouterStateSnapshot = {\n path: string | null;\n resolved: string | null;\n component: ComponentFragment | null;\n route: Route | null;\n};\n\nconst isRouterEvent = (event: NavigateEvent) => {\n return event.canIntercept && !event.hashChange && !event.downloadRequest && !event.formData;\n};\n\nexport const createRouter = (base: string, routes: Route[]) => {\n const params = grain({});\n const query = grain<Record<string, string>>({});\n\n const { match } = createPatternMatcher(base, routes);\n const state = grain<RouterStateSnapshot>({ resolved: null, component: null, path: null, route: null });\n\n const getURLState = (url: URL) => {\n const [pattern, route] = match(url) ?? [];\n if (!pattern || !route) return null;\n\n return {\n params: getPathParamGroup(pattern.exec(url)),\n query: Object.fromEntries(url.searchParams),\n resolved: pattern.pathname,\n path: url.pathname,\n pattern: pattern,\n route: route,\n url: url,\n };\n };\n\n const setRouterState = async (next: NonNullable<ReturnType<typeof getURLState>>) => {\n const { pattern, route, params: matchedParams, query: matchedQuery, url } = next;\n\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run pre hooks\n const preHooks = (route.use ?? []).filter((hook) => hook.run === 'pre');\n const canNavigate = resolveHooks(preHooks, { ...next, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n // Run the load hooks\n // LOAD hooks — async, non-blocking for navigation\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...next, redirect });\n\n const fragment = getFragment(await route.component());\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n };\n\n const isOwnRoute = (route: Route) => {\n return routes.some((ownRoute) => ownRoute === route);\n };\n\n navigation.addEventListener('navigate', (event) => {\n if (!isRouterEvent(event)) return;\n const url = new URL(event.destination.url);\n\n const nextState = getURLState(url);\n if (!nextState || !isOwnRoute(nextState.route)) return;\n let canNavigate = true;\n const redirects = new Set<() => void>();\n const redirect = (path: string) => {\n redirects.add(() =>\n queueMicrotask(() => {\n navigate({ path, history: 'replace' });\n }),\n );\n };\n\n // Run all post hooks of the previous route\n const postHooks = (state().route?.use ?? []).filter((hook) => hook.run === 'post');\n canNavigate = resolveHooks(postHooks, { ...state(), params: params(), query: query(), redirect });\n\n // Run pre hooks\n const preHooks = (nextState.route.use ?? []).filter((hook) => hook.run === 'pre');\n canNavigate = canNavigate && resolveHooks(preHooks, { ...nextState, redirect });\n\n // Cancel navigation based on hook result\n // We redirect to the first stored redirect\n // handler, and loose all others\n if (!canNavigate) {\n event.preventDefault();\n const [redirectFn] = redirects.values();\n redirects.clear();\n return redirectFn?.();\n }\n\n event.intercept({\n scroll: 'after-transition',\n // As the handler is not yes baseline as of mid 2026, we cannot\n // use the precommitController. Without it, pre and post hooks need\n // to be resolved synchronously.\n // precommitHandler: async () => {},\n handler: async () => {\n // update router state & post hooks\n const { pattern, route, params: matchedParams, query: matchedQuery } = nextState;\n const fragment = getFragment(await route.component());\n\n const loadHooks = (route.use ?? []).filter((h) => h.run === 'load');\n resolveHooks(loadHooks, { ...nextState, redirect });\n\n params.set(matchedParams);\n query.set(matchedQuery);\n state.update(() => {\n return {\n route,\n component: fragment,\n resolved: pattern.pathname,\n path: url.pathname,\n };\n });\n },\n });\n });\n\n // Get the initial route set and set the routerState\n const current = getURLState(new URL(navigation.currentEntry?.url ?? ''));\n if (current) setRouterState(current);\n\n return {\n params: parameterized(params),\n query: readonly(query),\n state: readonly(state),\n match,\n base,\n };\n};\n\nexport type Router = Omit<ReturnType<typeof createRouter>, 'match' | 'params' | 'query'>;\n","import { createDirective } from '@grainular/nord';\n\nexport const active = (cls: string, { exact }: { exact: boolean } = { exact: true }) => {\n return createDirective((node) => {\n const handler = () => {\n const href = node.getAttribute('href');\n const destination = navigation.currentEntry?.url;\n\n // Should both be not possible, but alas.\n if (!destination || !href) return;\n const url = new URL(destination);\n node.classList.toggle(cls, exact ? url.pathname === href : url.pathname.startsWith(href));\n };\n\n navigation.addEventListener('navigatesuccess', handler);\n return () => navigation.removeEventListener('navigatesuccess', handler);\n });\n};\n","export type NavigationHookContext = {\n path: string | null;\n resolved: string | null;\n params: Record<string, string>;\n query: Record<string, string>;\n redirect: (path: string) => void;\n};\nexport type NavigationHook =\n | {\n run: 'pre' | 'post';\n handler: (ctx: NavigationHookContext) => boolean | void;\n }\n | {\n run: 'load';\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>;\n };\n\nexport const pre = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'pre' as const, handler };\n};\n\nexport const post = (handler: (ctx: NavigationHookContext) => boolean | void): NavigationHook => {\n return { run: 'post' as const, handler };\n};\n\nexport const load = (\n handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>,\n): NavigationHook => {\n return { run: 'load' as const, handler };\n};\n","import { grain } from '@grainular/grains';\nimport { $render, type ComponentFragment, html, type Ref } from '@grainular/nord';\nimport type { Router } from './create-router';\n\ntype OutletConfig = {\n for: Router;\n transitionElement?: Ref<HTMLElement>; // user provides the element to transition\n};\n\nexport const $outlet = ({ for: router, transitionElement: transitionRef }: OutletConfig) => {\n const currentComponent = grain<ComponentFragment>(html``);\n const name = `outlet-${router.base.replace(/[^a-zA-Z0-9-_]/g, '') || 'root'}`;\n\n router.state.subscribe((state) => {\n const { component, route } = state;\n const next = component ?? html``;\n if (!route?.transition) return currentComponent.set(next);\n\n // Apply view-transition-name to user's element or fall back to documentElement\n const target = transitionRef?.current ?? document.documentElement;\n target.style.viewTransitionName = name;\n\n const viewTransition = document.startViewTransition(() => currentComponent.set(next));\n viewTransition.ready.then(() => {\n const animations = [route.transition ?? []].flat();\n animations.forEach(({ keyframes, ...props }) => {\n document.documentElement.animate(keyframes, {\n pseudoElement: props.element?.replace('(root)', `(${name})`)?.replace('(outlet)', `(${name})`),\n ...props,\n });\n });\n });\n });\n\n // No wrapper div at all — just $render directly\n return $render(currentComponent);\n};\n","export type Transition = {\n keyframes: Keyframe[];\n duration: number;\n delay?: number;\n easing?: string;\n element?: '::view-transition-new(root)' | '::view-transition-old(root)' | string;\n};\n\nexport const transition = (setup: Transition): Required<Transition> => {\n return {\n delay: 0,\n easing: 'linear',\n element: '::view-transition-new(root)',\n ...setup,\n };\n};\n","import { transition } from './transition';\n\nexport const crossFade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// slide in from a direction\nexport const slide = (duration: number, direction: 'left' | 'right' | 'up' | 'down' = 'right') => {\n const axis = direction === 'left' || direction === 'right' ? 'X' : 'Y';\n const sign = direction === 'right' || direction === 'down' ? '' : '-';\n\n return [\n transition({\n keyframes: [{ transform: `translate${axis}(${sign}100%)` }, { transform: `translate${axis}(0)` }],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: `translate${axis}(0)` },\n { transform: `translate${axis}(${sign === '' ? '-' : ''}100%)` },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// scale up, good for modals/detail views\nexport const scale = (duration: number) => {\n return [\n transition({\n keyframes: [\n { transform: 'scale(0.95)', opacity: 0 },\n { transform: 'scale(1)', opacity: 1 },\n ],\n element: '::view-transition-new(root)',\n duration,\n }),\n transition({\n keyframes: [\n { transform: 'scale(1)', opacity: 1 },\n { transform: 'scale(0.95)', opacity: 0 },\n ],\n element: '::view-transition-old(root)',\n duration,\n }),\n ];\n};\n\n// just fade the new in, old stays — subtle\nexport const fade = (duration: number) => {\n return [\n transition({\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\n element: '::view-transition-new(root)',\n duration,\n }),\n ];\n};\n"]}
@@ -10,10 +10,14 @@ type NavigationHookContext = {
10
10
  };
11
11
  type NavigationHook = {
12
12
  run: 'pre' | 'post';
13
- handler: (ctx: NavigationHookContext) => Promise<boolean | void>;
13
+ handler: (ctx: NavigationHookContext) => boolean | void;
14
+ } | {
15
+ run: 'load';
16
+ handler: (ctx: Omit<NavigationHookContext, 'redirect'>) => Promise<boolean | void>;
14
17
  };
15
- declare const pre: (handler: (ctx: NavigationHookContext) => Promise<boolean | void>) => NavigationHook;
16
- declare const post: (handler: (ctx: NavigationHookContext) => Promise<boolean | void>) => NavigationHook;
18
+ declare const pre: (handler: (ctx: NavigationHookContext) => boolean | void) => NavigationHook;
19
+ declare const post: (handler: (ctx: NavigationHookContext) => boolean | void) => NavigationHook;
20
+ declare const load: (handler: (ctx: Omit<NavigationHookContext, "redirect">) => Promise<boolean | void>) => NavigationHook;
17
21
 
18
22
  type Transition = {
19
23
  keyframes: Keyframe[];
@@ -65,7 +69,10 @@ declare const active: (cls: string, { exact }?: {
65
69
  }) => void;
66
70
  };
67
71
 
68
- declare const navigate: (path: string) => NavigationResult;
72
+ type NavigateOptions = string | ({
73
+ path: string;
74
+ } & NavigationNavigateOptions);
75
+ declare const navigate: (destination: NavigateOptions) => void;
69
76
 
70
77
  type OutletConfig = {
71
78
  for: Router;
@@ -90,4 +97,4 @@ declare const slide: (duration: number, direction?: "left" | "right" | "up" | "d
90
97
  declare const scale: (duration: number) => Required<Transition>[];
91
98
  declare const fade: (duration: number) => Required<Transition>[];
92
99
 
93
- export { $outlet, type NavigationHook, type NavigationHookContext, active, createRouter, crossFade, fade, navigate, post, pre, scale, slide };
100
+ export { $outlet, type NavigationHook, type NavigationHookContext, active, createRouter, crossFade, fade, load, navigate, post, pre, scale, slide };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grainular/router",
3
- "version": "2.0.0-next.6",
3
+ "version": "2.0.0-next.8",
4
4
  "type": "module",
5
5
  "packageManager": "bun@1.2.7",
6
6
  "main": "./dist/cjs/index.js",