@wsxjs/wsx-router 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.js +71 -73
- package/package.json +61 -61
- package/src/WsxRouter.wsx +11 -16
- package/src/WsxView.wsx +8 -4
- package/LICENSE +0 -21
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("@wsxjs/wsx-core"),G=":host{display:block;width:100%;height:100%}.router-outlet{width:100%;height:100%}";var K=Object.create,$=Object.defineProperty,X=Object.getOwnPropertyDescriptor,L=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),P=e=>{throw TypeError(e)},I=(e,t,r)=>t in e?$(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,Y=(e,t)=>$(e,"name",{value:t,configurable:!0}),Z=e=>[,,,K((e==null?void 0:e[L("metadata")])??null)],tt=["class","method","getter","setter","accessor","field","value","get","set"],O=e=>e!==void 0&&typeof e!="function"?P("Function expected"):e,et=(e,t,r,i,o)=>({kind:tt[e],name:t,metadata:i,addInitializer:n=>r._?P("Already initialized"):o.push(O(n||null))}),rt=(e,t)=>I(t,L("metadata"),e[3]),ot=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},it=(e,t,r,i,o,n)=>{var s,h,c,a=t&7,d=!1,m=0,f=e[m]||(e[m]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&X(o,r));Y(o,r);for(var p=i.length-1;p>=0;p--)c=et(a,r,h={},e[3],f),s=(0,i[p])(o,c),h._=1,O(s)&&(o=s);return rt(e,o),u&&$(o,r,u),d?a^4?n:u:o},b=(e,t,r)=>I(e,typeof t!="symbol"?t+"":t,r),j,E,N;const v=l.createLogger("WsxRouter");j=[l.autoRegister({tagName:"wsx-router"})];class y extends(N=l.WebComponent){constructor(){super({styles:G}),b(this,"views",new Map),b(this,"currentView",null),b(this,"handleRouteChange",()=>{const t=window.location.pathname;v.debug(`Route changed to: ${t}`),this.currentView&&(this.currentView.style.display="none",v.debug("Hiding previous view"));const r=this.matchRoute(t);if(r){r.style.display="block",this.currentView=r,v.debug(`Showing view for route: ${r.getAttribute("route")}`);const i=this.extractParams(r.getAttribute("route")||"/",t);i&&r.setAttribute("params",JSON.stringify(i))}else v.warn(`No view found for path: ${t}`);this.dispatchEvent(new CustomEvent("route-changed",{detail:{path:t,view:r},bubbles:!0,composed:!0}))}),b(this,"interceptLinks",t=>{const r=t.target.closest("a");if(!r)return;const i=r.getAttribute("href");!i||i.startsWith("http")||i.startsWith("#")||(t.preventDefault(),this.navigate(i))})}render(){return l.jsx("div",{class:"router-outlet"},l.jsx("slot",null))}onConnected(){v.debug("WsxRouter connected to DOM"),this.collectViews(),v.debug("WsxRouter collected views:",this.views.size),window.addEventListener("popstate",this.handleRouteChange),this.addEventListener("click",this.interceptLinks),this.handleRouteChange()}onDisconnected(){window.removeEventListener("popstate",this.handleRouteChange)}collectViews(){var o;const t=(o=this.shadowRoot)==null?void 0:o.querySelector("slot");if(!t){v.error("WsxRouter: No slot found");return}const i=t.assignedElements().filter(n=>n.tagName.toLowerCase()==="wsx-view");v.debug("WsxRouter found views:",i.length),i.forEach(n=>{const s=n.getAttribute("route")||"/";this.views.set(s,n),n.style.display="none",v.debug(`WsxRouter hiding view for route: ${s}`)})}matchRoute(t){if(this.views.has(t))return this.views.get(t);for(const[r,i]of this.views)if(r.includes(":")){const o=r.replace(/:[^/]+/g,"([^/]+)");if(new RegExp(`^${o}$`).test(t))return i}return this.views.get("*")||null}extractParams(t,r){var c;if(!t.includes(":"))return null;const i=((c=t.match(/:([^/]+)/g))==null?void 0:c.map(a=>a.slice(1)))||[],o=t.replace(/:[^/]+/g,"([^/]+)"),n=new RegExp(`^${o}$`),s=r.match(n);if(!s||!i.length)return null;const h={};return i.forEach((a,d)=>{h[a]=s[d+1]}),h}navigate(t){window.history.pushState(null,"",t),this.handleRouteChange()}}E=Z(N);y=it(E,0,"WsxRouter",j,y);ot(E,1,y);const nt=":host{display:block;width:100%;height:100%}.route-view{width:100%;height:100%;position:relative}:host([loading]) .route-view{opacity:.5;transition:opacity .3s ease}:host([error]) .route-view{border:1px solid var(--error-color, #ff0000);padding:1rem}.route-view.entering{animation:fadeIn .3s ease-out}.route-view.leaving{animation:fadeOut .3s ease-in}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}";var st=Object.create,R=Object.defineProperty,at=Object.getOwnPropertyDescriptor,z=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),D=e=>{throw TypeError(e)},F=(e,t,r)=>t in e?R(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,ct=(e,t)=>R(e,"name",{value:t,configurable:!0}),lt=e=>[,,,st((e==null?void 0:e[z("metadata")])??null)],ht=["class","method","getter","setter","accessor","field","value","get","set"],U=e=>e!==void 0&&typeof e!="function"?D("Function expected"):e,dt=(e,t,r,i,o)=>({kind:ht[e],name:t,metadata:i,addInitializer:n=>r._?D("Already initialized"):o.push(U(n||null))}),ut=(e,t)=>F(t,z("metadata"),e[3]),pt=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},vt=(e,t,r,i,o,n)=>{var s,h,c,a=t&7,d=!1,m=0,f=e[m]||(e[m]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&at(o,r));ct(o,r);for(var p=i.length-1;p>=0;p--)c=dt(a,r,h={},e[3],f),s=(0,i[p])(o,c),h._=1,U(s)&&(o=s);return ut(e,o),u&&R(o,r,u),d?a^4?n:u:o},x=(e,t,r)=>F(e,typeof t!="symbol"?t+"":t,r),M,S,q;const k=l.createLogger("WsxView");M=[l.autoRegister({tagName:"wsx-view"})];class g extends(q=l.WebComponent){constructor(){super({styles:nt,styleName:"wsx-view"}),x(this,"component",null),x(this,"params",{}),x(this,"componentInstance",null)}render(){return l.jsx("div",{class:"route-view",part:"view"})}onConnected(){const t=this.getAttribute("component");t&&!this.componentInstance&&this.loadComponent(t)}onAttributeChanged(t,r,i){if(t==="component"&&i&&!this.componentInstance)this.loadComponent(i);else if(t==="params"&&this.componentInstance)try{this.params=JSON.parse(i),Object.entries(this.params).forEach(([o,n])=>{this.componentInstance.setAttribute(o,n)})}catch(o){k.error("Failed to parse params:",o)}}async loadComponent(t){var o;if(this.componentInstance&&(this.componentInstance.remove(),this.componentInstance=null),!customElements.get(t)){k.warn(`Component ${t} not found in customElements registry`);return}this.componentInstance=document.createElement(t),Object.keys(this.params).length>0&&Object.entries(this.params).forEach(([n,s])=>{this.componentInstance.setAttribute(n,s)});const i=(o=this.shadowRoot)==null?void 0:o.querySelector(".route-view");i?i.appendChild(this.componentInstance):k.error("Route view container not found")}onDisconnected(){this.componentInstance&&(this.componentInstance.remove(),this.componentInstance=null)}}S=lt(q);g=vt(S,0,"WsxView",M,g);x(g,"observedAttributes",["route","component","params"]);pt(S,1,g);const mt=':host{display:inline-block;min-width:fit-content;min-height:fit-content;width:auto;height:auto}.wsx-link{color:var(--link-color, #007bff);text-decoration:var(--link-decoration, underline);cursor:pointer;transition:color .2s ease;display:inline-block;min-height:1.2em;line-height:1.2}.wsx-link:hover{color:var(--link-hover-color, #0056b3);text-decoration:var(--link-hover-decoration, underline)}.wsx-link:focus{outline:2px solid var(--link-focus-color, #007bff);outline-offset:2px}.wsx-link.active{color:var(--link-active-color, #6c757d);font-weight:var(--link-active-weight, bold)}:host([disabled]) .wsx-link{color:var(--link-disabled-color, #6c757d);cursor:not-allowed;pointer-events:none}:host([external]) .wsx-link:after{content:"↗";font-size:.8em;margin-left:.2em;opacity:.7}:host([variant="button"]) .wsx-link{background-color:var(--button-bg, #007bff);color:var(--button-color, white);padding:.5rem 1rem;border-radius:.25rem;text-decoration:none;display:inline-block}:host([variant="button"]) .wsx-link:hover{background-color:var(--button-hover-bg, #0056b3);color:var(--button-hover-color, white)}:host([variant="tab"]) .wsx-link{padding:.5rem 1rem;border-bottom:2px solid transparent;text-decoration:none}:host([variant="tab"]) .wsx-link.active{border-bottom-color:var(--tab-active-border, #007bff)}';var wt=Object.create,C=Object.defineProperty,ft=Object.getOwnPropertyDescriptor,V=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),T=e=>{throw TypeError(e)},Q=(e,t,r)=>t in e?C(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,gt=(e,t)=>C(e,"name",{value:t,configurable:!0}),_t=e=>[,,,wt((e==null?void 0:e[V("metadata")])??null)],bt=["class","method","getter","setter","accessor","field","value","get","set"],H=e=>e!==void 0&&typeof e!="function"?T("Function expected"):e,xt=(e,t,r,i,o)=>({kind:bt[e],name:t,metadata:i,addInitializer:n=>r._?T("Already initialized"):o.push(H(n||null))}),yt=(e,t)=>Q(t,V("metadata"),e[3]),kt=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},$t=(e,t,r,i,o,n)=>{var s,h,c,a=t&7,d=!1,m=0,f=e[m]||(e[m]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&ft(o,r));gt(o,r);for(var p=i.length-1;p>=0;p--)c=xt(a,r,h={},e[3],f),s=(0,i[p])(o,c),h._=1,H(s)&&(o=s);return yt(e,o),u&&C(o,r,u),d?a^4?n:u:o},w=(e,t,r)=>Q(e,typeof t!="symbol"?t+"":t,r),J,W,B;const A=l.createLogger("WsxLink");J=[l.autoRegister({tagName:"wsx-link"})];class _ extends(B=l.WebComponent){constructor(){super({styles:mt,styleName:"wsx-link"}),w(this,"to",""),w(this,"replace",!1),w(this,"activeClass","active"),w(this,"exact",!1),w(this,"handleClick",t=>{if(t.preventDefault(),!this.to){A.warn("No 'to' attribute specified");return}if(this.isExternalLink(this.to)){window.open(this.to,"_blank");return}this.replace?window.history.replaceState(null,"",this.to):window.history.pushState(null,"",this.to),window.dispatchEvent(new PopStateEvent("popstate")),A.debug(`Navigated to: ${this.to}`)}),w(this,"updateActiveState",()=>{var o;const t=window.location.pathname,r=this.exact?t===this.to:t.startsWith(this.to)&&this.to!=="/",i=(o=this.shadowRoot)==null?void 0:o.querySelector("a");i&&(r?(i.classList.add(this.activeClass),this.setAttribute("active","")):(i.classList.remove(this.activeClass),this.removeAttribute("active")))})}render(){return l.jsx("a",{href:this.to,class:"wsx-link",onClick:this.handleClick,part:"link"},l.jsx("slot",null))}onConnected(){this.to=this.getAttribute("to")||"",this.replace=this.hasAttribute("replace"),this.activeClass=this.getAttribute("active-class")||"active",this.exact=this.hasAttribute("exact");const t=this.shadowRoot.querySelector(".wsx-link");t&&(t.href=this.to),window.addEventListener("popstate",this.updateActiveState),document.addEventListener("route-changed",this.updateActiveState),this.updateActiveState()}onDisconnected(){window.removeEventListener("popstate",this.updateActiveState),document.removeEventListener("route-changed",this.updateActiveState)}onAttributeChanged(t,r,i){switch(t){case"to":this.to=i||"",this.rerender(),this.updateActiveState();break;case"replace":this.replace=i!==null&&i!=="false";break;case"active-class":this.activeClass=i||"active",this.updateActiveState();break;case"exact":this.exact=i!==null&&i!=="false",this.updateActiveState();break}}isExternalLink(t){return t.startsWith("http://")||t.startsWith("https://")||t.startsWith("mailto:")||t.startsWith("tel:")}navigate(){this.to&&this.handleClick(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}}W=_t(B);_=$t(W,0,"WsxLink",J,_);w(_,"observedAttributes",["to","replace","active-class","exact"]);kt(W,1,_);const Et=l.createLogger("RouterUtils");class Rt{static navigate(t,r=!1){r?window.history.replaceState(null,"",t):window.history.pushState(null,"",t),window.dispatchEvent(new PopStateEvent("popstate")),Et.debug(`Navigated to: ${t} (replace: ${r})`)}static getCurrentRoute(){const t=new URL(window.location.href);return{path:t.pathname,params:{},query:Object.fromEntries(t.searchParams.entries()),hash:t.hash.slice(1)}}static parseRoute(t,r){var i;if(t===r)return{route:t,params:{},exact:!0};if(t==="*")return{route:t,params:{},exact:!1};if(t.includes(":")){const o=((i=t.match(/:([^/]+)/g))==null?void 0:i.map(c=>c.slice(1)))||[],n=t.replace(/:[^/]+/g,"([^/]+)"),s=new RegExp(`^${n}$`),h=r.match(s);if(h&&o.length>0){const c={};return o.forEach((a,d)=>{c[a]=h[d+1]}),{route:t,params:c,exact:!0}}}if(t.endsWith("/*")){const o=t.slice(0,-2);if(r.startsWith(o))return{route:t,params:{},exact:!1}}return null}static buildPath(t,r={}){let i=t;return Object.entries(r).forEach(([o,n])=>{i=i.replace(`:${o}`,encodeURIComponent(n))}),i}static isRouteActive(t,r=!1){const i=window.location.pathname;return r?i===t:t==="/"?i==="/":i.startsWith(t)}static getRouteDepth(t){return t.split("/").filter(r=>r.length>0).length}static getParentRoute(t){const r=t.split("/").filter(i=>i.length>0);return r.length<=1?"/":(r.pop(),"/"+r.join("/"))}static joinPaths(...t){return t.map(r=>r.replace(/^\/+|\/+$/g,"")).filter(r=>r.length>0).join("/").replace(/^/,"/")}static isExternalUrl(t){return/^https?:\/\//.test(t)||/^mailto:/.test(t)||/^tel:/.test(t)}static getQueryParam(t){return new URL(window.location.href).searchParams.get(t)}static setQueryParam(t,r,i=!1){const o=new URL(window.location.href);o.searchParams.set(t,r);const n=o.pathname+o.search+o.hash;this.navigate(n,i)}static removeQueryParam(t,r=!1){const i=new URL(window.location.href);i.searchParams.delete(t);const o=i.pathname+i.search+i.hash;this.navigate(o,r)}static goBack(){window.history.back()}static goForward(){window.history.forward()}static replace(t){this.navigate(t,!0)}static getHistoryLength(){return window.history.length}static onRouteChange(t){const r=()=>{const i=this.getCurrentRoute();t(i)};return window.addEventListener("popstate",r),document.addEventListener("route-changed",r),()=>{window.removeEventListener("popstate",r),document.removeEventListener("route-changed",r)}}}exports.RouterUtils=Rt;exports.WsxLink=_;exports.WsxRouter=y;exports.WsxView=g;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("@wsxjs/wsx-core"),G=":host{display:block;width:100%;height:100%}.router-outlet{width:100%;height:100%}";var K=Object.create,$=Object.defineProperty,X=Object.getOwnPropertyDescriptor,P=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),W=e=>{throw TypeError(e)},I=(e,t,r)=>t in e?$(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,Y=(e,t)=>$(e,"name",{value:t,configurable:!0}),Z=e=>[,,,K((e==null?void 0:e[P("metadata")])??null)],tt=["class","method","getter","setter","accessor","field","value","get","set"],O=e=>e!==void 0&&typeof e!="function"?W("Function expected"):e,et=(e,t,r,i,o)=>({kind:tt[e],name:t,metadata:i,addInitializer:n=>r._?W("Already initialized"):o.push(O(n||null))}),rt=(e,t)=>I(t,P("metadata"),e[3]),it=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},ot=(e,t,r,i,o,n)=>{var s,l,c,a=t&7,d=!1,v=0,f=e[v]||(e[v]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&X(o,r));Y(o,r);for(var p=i.length-1;p>=0;p--)c=et(a,r,l={},e[3],f),s=(0,i[p])(o,c),l._=1,O(s)&&(o=s);return rt(e,o),u&&$(o,r,u),d?a^4?n:u:o},b=(e,t,r)=>I(e,typeof t!="symbol"?t+"":t,r),j,E,N;const m=h.createLogger("WsxRouter");j=[h.autoRegister({tagName:"wsx-router"})];class y extends(N=h.LightComponent){constructor(){super({styles:G,styleName:"wsx-router"}),b(this,"views",new Map),b(this,"currentView",null),b(this,"handleRouteChange",()=>{const t=window.location.pathname;m.debug(`Route changed to: ${t}`),this.currentView&&(this.currentView.style.display="none",m.debug("Hiding previous view"));const r=this.matchRoute(t);if(r){r.style.display="block",this.currentView=r,m.debug(`Showing view for route: ${r.getAttribute("route")}`);const i=this.extractParams(r.getAttribute("route")||"/",t);i&&r.setAttribute("params",JSON.stringify(i))}else m.warn(`No view found for path: ${t}`);this.dispatchEvent(new CustomEvent("route-changed",{detail:{path:t,view:r},bubbles:!0,composed:!0}))}),b(this,"interceptLinks",t=>{const r=t.target.closest("a");if(!r)return;const i=r.getAttribute("href");!i||i.startsWith("http")||i.startsWith("#")||(t.preventDefault(),this.navigate(i))})}render(){return h.jsx("div",{class:"router-outlet"})}onConnected(){m.debug("WsxRouter connected to DOM"),this.collectViews(),m.debug("WsxRouter collected views:",this.views.size),window.addEventListener("popstate",this.handleRouteChange),this.addEventListener("click",this.interceptLinks),this.handleRouteChange()}onDisconnected(){window.removeEventListener("popstate",this.handleRouteChange)}collectViews(){const t=Array.from(this.children).filter(r=>r.tagName.toLowerCase()==="wsx-view");m.debug("WsxRouter found views:",t.length),t.forEach(r=>{const i=r.getAttribute("route")||"/";this.views.set(i,r),r.style.display="none",m.debug(`WsxRouter hiding view for route: ${i}`)})}matchRoute(t){if(this.views.has(t))return this.views.get(t);for(const[r,i]of this.views)if(r.includes(":")){const o=r.replace(/:[^/]+/g,"([^/]+)");if(new RegExp(`^${o}$`).test(t))return i}return this.views.get("*")||null}extractParams(t,r){var c;if(!t.includes(":"))return null;const i=((c=t.match(/:([^/]+)/g))==null?void 0:c.map(a=>a.slice(1)))||[],o=t.replace(/:[^/]+/g,"([^/]+)"),n=new RegExp(`^${o}$`),s=r.match(n);if(!s||!i.length)return null;const l={};return i.forEach((a,d)=>{l[a]=s[d+1]}),l}navigate(t){window.history.pushState(null,"",t),this.handleRouteChange()}}E=Z(N);y=ot(E,0,"WsxRouter",j,y);it(E,1,y);const nt=":host{display:block;width:100%;height:100%}.route-view{width:100%;height:100%;position:relative}:host([loading]) .route-view{opacity:.5;transition:opacity .3s ease}:host([error]) .route-view{border:1px solid var(--error-color, #ff0000);padding:1rem}.route-view.entering{animation:fadeIn .3s ease-out}.route-view.leaving{animation:fadeOut .3s ease-in}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}";var at=Object.create,S=Object.defineProperty,st=Object.getOwnPropertyDescriptor,z=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),D=e=>{throw TypeError(e)},F=(e,t,r)=>t in e?S(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,ct=(e,t)=>S(e,"name",{value:t,configurable:!0}),lt=e=>[,,,at((e==null?void 0:e[z("metadata")])??null)],ht=["class","method","getter","setter","accessor","field","value","get","set"],U=e=>e!==void 0&&typeof e!="function"?D("Function expected"):e,dt=(e,t,r,i,o)=>({kind:ht[e],name:t,metadata:i,addInitializer:n=>r._?D("Already initialized"):o.push(U(n||null))}),ut=(e,t)=>F(t,z("metadata"),e[3]),pt=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},vt=(e,t,r,i,o,n)=>{var s,l,c,a=t&7,d=!1,v=0,f=e[v]||(e[v]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&st(o,r));ct(o,r);for(var p=i.length-1;p>=0;p--)c=dt(a,r,l={},e[3],f),s=(0,i[p])(o,c),l._=1,U(s)&&(o=s);return ut(e,o),u&&S(o,r,u),d?a^4?n:u:o},x=(e,t,r)=>F(e,typeof t!="symbol"?t+"":t,r),M,R,V;const k=h.createLogger("WsxView");M=[h.autoRegister({tagName:"wsx-view"})];class g extends(V=h.LightComponent){constructor(){super({styles:nt,styleName:"wsx-view"}),x(this,"component",null),x(this,"params",{}),x(this,"componentInstance",null)}render(){return h.jsx("div",{class:"route-view"})}onConnected(){const t=this.getAttribute("component");t&&!this.componentInstance&&this.loadComponent(t)}onAttributeChanged(t,r,i){if(t==="component"&&i&&!this.componentInstance)this.loadComponent(i);else if(t==="params"&&this.componentInstance)try{this.params=JSON.parse(i),Object.entries(this.params).forEach(([o,n])=>{this.componentInstance.setAttribute(o,n)})}catch(o){k.error("Failed to parse params:",o)}}async loadComponent(t){if(this.componentInstance&&(this.componentInstance.remove(),this.componentInstance=null),!customElements.get(t)){k.warn(`Component ${t} not found in customElements registry`);return}this.componentInstance=document.createElement(t),Object.keys(this.params).length>0&&Object.entries(this.params).forEach(([o,n])=>{this.componentInstance.setAttribute(o,n)});const i=this.querySelector(".route-view");i?i.appendChild(this.componentInstance):k.error("Route view container not found")}onDisconnected(){this.componentInstance&&(this.componentInstance.remove(),this.componentInstance=null)}}R=lt(V);g=vt(R,0,"WsxView",M,g);x(g,"observedAttributes",["route","component","params"]);pt(R,1,g);const mt=':host{display:inline-block;min-width:fit-content;min-height:fit-content;width:auto;height:auto}.wsx-link{color:var(--link-color, #007bff);text-decoration:var(--link-decoration, underline);cursor:pointer;transition:color .2s ease;display:inline-block;min-height:1.2em;line-height:1.2}.wsx-link:hover{color:var(--link-hover-color, #0056b3);text-decoration:var(--link-hover-decoration, underline)}.wsx-link:focus{outline:2px solid var(--link-focus-color, #007bff);outline-offset:2px}.wsx-link.active{color:var(--link-active-color, #6c757d);font-weight:var(--link-active-weight, bold)}:host([disabled]) .wsx-link{color:var(--link-disabled-color, #6c757d);cursor:not-allowed;pointer-events:none}:host([external]) .wsx-link:after{content:"↗";font-size:.8em;margin-left:.2em;opacity:.7}:host([variant="button"]) .wsx-link{background-color:var(--button-bg, #007bff);color:var(--button-color, white);padding:.5rem 1rem;border-radius:.25rem;text-decoration:none;display:inline-block}:host([variant="button"]) .wsx-link:hover{background-color:var(--button-hover-bg, #0056b3);color:var(--button-hover-color, white)}:host([variant="tab"]) .wsx-link{padding:.5rem 1rem;border-bottom:2px solid transparent;text-decoration:none}:host([variant="tab"]) .wsx-link.active{border-bottom-color:var(--tab-active-border, #007bff)}';var wt=Object.create,C=Object.defineProperty,ft=Object.getOwnPropertyDescriptor,q=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),T=e=>{throw TypeError(e)},Q=(e,t,r)=>t in e?C(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,gt=(e,t)=>C(e,"name",{value:t,configurable:!0}),_t=e=>[,,,wt((e==null?void 0:e[q("metadata")])??null)],bt=["class","method","getter","setter","accessor","field","value","get","set"],H=e=>e!==void 0&&typeof e!="function"?T("Function expected"):e,xt=(e,t,r,i,o)=>({kind:bt[e],name:t,metadata:i,addInitializer:n=>r._?T("Already initialized"):o.push(H(n||null))}),yt=(e,t)=>Q(t,q("metadata"),e[3]),kt=(e,t,r,i)=>{for(var o=0,n=e[t>>1],s=n&&n.length;o<s;o++)n[o].call(r);return i},$t=(e,t,r,i,o,n)=>{var s,l,c,a=t&7,d=!1,v=0,f=e[v]||(e[v]=[]),u=a&&(o=o.prototype,a<5&&(a>3||!d)&&ft(o,r));gt(o,r);for(var p=i.length-1;p>=0;p--)c=xt(a,r,l={},e[3],f),s=(0,i[p])(o,c),l._=1,H(s)&&(o=s);return yt(e,o),u&&C(o,r,u),d?a^4?n:u:o},w=(e,t,r)=>Q(e,typeof t!="symbol"?t+"":t,r),J,L,B;const A=h.createLogger("WsxLink");J=[h.autoRegister({tagName:"wsx-link"})];class _ extends(B=h.WebComponent){constructor(){super({styles:mt,styleName:"wsx-link"}),w(this,"to",""),w(this,"replace",!1),w(this,"activeClass","active"),w(this,"exact",!1),w(this,"handleClick",t=>{if(t.preventDefault(),!this.to){A.warn("No 'to' attribute specified");return}if(this.isExternalLink(this.to)){window.open(this.to,"_blank");return}this.replace?window.history.replaceState(null,"",this.to):window.history.pushState(null,"",this.to),window.dispatchEvent(new PopStateEvent("popstate")),A.debug(`Navigated to: ${this.to}`)}),w(this,"updateActiveState",()=>{var o;const t=window.location.pathname,r=this.exact?t===this.to:t.startsWith(this.to)&&this.to!=="/",i=(o=this.shadowRoot)==null?void 0:o.querySelector("a");i&&(r?(i.classList.add(this.activeClass),this.setAttribute("active","")):(i.classList.remove(this.activeClass),this.removeAttribute("active")))})}render(){return h.jsx("a",{href:this.to,class:"wsx-link",onClick:this.handleClick,part:"link"},h.jsx("slot",null))}onConnected(){this.to=this.getAttribute("to")||"",this.replace=this.hasAttribute("replace"),this.activeClass=this.getAttribute("active-class")||"active",this.exact=this.hasAttribute("exact");const t=this.shadowRoot.querySelector(".wsx-link");t&&(t.href=this.to),window.addEventListener("popstate",this.updateActiveState),document.addEventListener("route-changed",this.updateActiveState),this.updateActiveState()}onDisconnected(){window.removeEventListener("popstate",this.updateActiveState),document.removeEventListener("route-changed",this.updateActiveState)}onAttributeChanged(t,r,i){switch(t){case"to":this.to=i||"",this.rerender(),this.updateActiveState();break;case"replace":this.replace=i!==null&&i!=="false";break;case"active-class":this.activeClass=i||"active",this.updateActiveState();break;case"exact":this.exact=i!==null&&i!=="false",this.updateActiveState();break}}isExternalLink(t){return t.startsWith("http://")||t.startsWith("https://")||t.startsWith("mailto:")||t.startsWith("tel:")}navigate(){this.to&&this.handleClick(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}}L=_t(B);_=$t(L,0,"WsxLink",J,_);w(_,"observedAttributes",["to","replace","active-class","exact"]);kt(L,1,_);const Et=h.createLogger("RouterUtils");class St{static navigate(t,r=!1){r?window.history.replaceState(null,"",t):window.history.pushState(null,"",t),window.dispatchEvent(new PopStateEvent("popstate")),Et.debug(`Navigated to: ${t} (replace: ${r})`)}static getCurrentRoute(){const t=new URL(window.location.href);return{path:t.pathname,params:{},query:Object.fromEntries(t.searchParams.entries()),hash:t.hash.slice(1)}}static parseRoute(t,r){var i;if(t===r)return{route:t,params:{},exact:!0};if(t==="*")return{route:t,params:{},exact:!1};if(t.includes(":")){const o=((i=t.match(/:([^/]+)/g))==null?void 0:i.map(c=>c.slice(1)))||[],n=t.replace(/:[^/]+/g,"([^/]+)"),s=new RegExp(`^${n}$`),l=r.match(s);if(l&&o.length>0){const c={};return o.forEach((a,d)=>{c[a]=l[d+1]}),{route:t,params:c,exact:!0}}}if(t.endsWith("/*")){const o=t.slice(0,-2);if(r.startsWith(o))return{route:t,params:{},exact:!1}}return null}static buildPath(t,r={}){let i=t;return Object.entries(r).forEach(([o,n])=>{i=i.replace(`:${o}`,encodeURIComponent(n))}),i}static isRouteActive(t,r=!1){const i=window.location.pathname;return r?i===t:t==="/"?i==="/":i.startsWith(t)}static getRouteDepth(t){return t.split("/").filter(r=>r.length>0).length}static getParentRoute(t){const r=t.split("/").filter(i=>i.length>0);return r.length<=1?"/":(r.pop(),"/"+r.join("/"))}static joinPaths(...t){return t.map(r=>r.replace(/^\/+|\/+$/g,"")).filter(r=>r.length>0).join("/").replace(/^/,"/")}static isExternalUrl(t){return/^https?:\/\//.test(t)||/^mailto:/.test(t)||/^tel:/.test(t)}static getQueryParam(t){return new URL(window.location.href).searchParams.get(t)}static setQueryParam(t,r,i=!1){const o=new URL(window.location.href);o.searchParams.set(t,r);const n=o.pathname+o.search+o.hash;this.navigate(n,i)}static removeQueryParam(t,r=!1){const i=new URL(window.location.href);i.searchParams.delete(t);const o=i.pathname+i.search+i.hash;this.navigate(o,r)}static goBack(){window.history.back()}static goForward(){window.history.forward()}static replace(t){this.navigate(t,!0)}static getHistoryLength(){return window.history.length}static onRouteChange(t){const r=()=>{const i=this.getCurrentRoute();t(i)};return window.addEventListener("popstate",r),document.addEventListener("route-changed",r),()=>{window.removeEventListener("popstate",r),document.removeEventListener("route-changed",r)}}}exports.RouterUtils=St;exports.WsxLink=_;exports.WsxRouter=y;exports.WsxView=g;
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
import { createLogger as y, autoRegister as E,
|
|
2
|
-
const
|
|
3
|
-
var
|
|
1
|
+
import { createLogger as y, autoRegister as E, LightComponent as I, jsx as _, WebComponent as Y } from "@wsxjs/wsx-core";
|
|
2
|
+
const Z = ":host{display:block;width:100%;height:100%}.router-outlet{width:100%;height:100%}";
|
|
3
|
+
var tt = Object.create, S = Object.defineProperty, et = Object.getOwnPropertyDescriptor, O = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), N = (e) => {
|
|
4
4
|
throw TypeError(e);
|
|
5
|
-
}, j = (e, t, r) => t in e ?
|
|
5
|
+
}, j = (e, t, r) => t in e ? S(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, rt = (e, t) => S(e, "name", { value: t, configurable: !0 }), it = (e) => [, , , tt((e == null ? void 0 : e[O("metadata")]) ?? null)], ot = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], z = (e) => e !== void 0 && typeof e != "function" ? N("Function expected") : e, nt = (e, t, r, i, o) => ({ kind: ot[e], name: t, metadata: i, addInitializer: (n) => r._ ? N("Already initialized") : o.push(z(n || null)) }), at = (e, t) => j(t, O("metadata"), e[3]), st = (e, t, r, i) => {
|
|
6
6
|
for (var o = 0, n = e[t >> 1], s = n && n.length; o < s; o++) n[o].call(r);
|
|
7
7
|
return i;
|
|
8
|
-
},
|
|
9
|
-
var s, l, c, a = t & 7, h = !1,
|
|
10
|
-
|
|
8
|
+
}, ct = (e, t, r, i, o, n) => {
|
|
9
|
+
var s, l, c, a = t & 7, h = !1, p = 0, w = e[p] || (e[p] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && et(o, r));
|
|
10
|
+
rt(o, r);
|
|
11
11
|
for (var u = i.length - 1; u >= 0; u--)
|
|
12
|
-
c =
|
|
13
|
-
return
|
|
14
|
-
},
|
|
15
|
-
const
|
|
12
|
+
c = nt(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, z(s) && (o = s);
|
|
13
|
+
return at(e, o), d && S(o, r, d), h ? a ^ 4 ? n : d : o;
|
|
14
|
+
}, f = (e, t, r) => j(e, typeof t != "symbol" ? t + "" : t, r), D, C, F;
|
|
15
|
+
const v = y("WsxRouter");
|
|
16
16
|
D = [E({ tagName: "wsx-router" })];
|
|
17
|
-
class $ extends (F =
|
|
17
|
+
class $ extends (F = I) {
|
|
18
18
|
constructor() {
|
|
19
|
-
super({
|
|
19
|
+
super({
|
|
20
|
+
styles: Z,
|
|
21
|
+
styleName: "wsx-router"
|
|
22
|
+
}), f(this, "views", /* @__PURE__ */ new Map()), f(this, "currentView", null), f(this, "handleRouteChange", () => {
|
|
20
23
|
const t = window.location.pathname;
|
|
21
|
-
|
|
24
|
+
v.debug(`Route changed to: ${t}`), this.currentView && (this.currentView.style.display = "none", v.debug("Hiding previous view"));
|
|
22
25
|
const r = this.matchRoute(t);
|
|
23
26
|
if (r) {
|
|
24
|
-
r.style.display = "block", this.currentView = r,
|
|
27
|
+
r.style.display = "block", this.currentView = r, v.debug(`Showing view for route: ${r.getAttribute("route")}`);
|
|
25
28
|
const i = this.extractParams(r.getAttribute("route") || "/", t);
|
|
26
29
|
i && r.setAttribute("params", JSON.stringify(i));
|
|
27
30
|
} else
|
|
28
|
-
|
|
31
|
+
v.warn(`No view found for path: ${t}`);
|
|
29
32
|
this.dispatchEvent(
|
|
30
33
|
new CustomEvent("route-changed", {
|
|
31
34
|
detail: { path: t, view: r },
|
|
@@ -33,7 +36,7 @@ class $ extends (F = S) {
|
|
|
33
36
|
composed: !0
|
|
34
37
|
})
|
|
35
38
|
);
|
|
36
|
-
}),
|
|
39
|
+
}), f(this, "interceptLinks", (t) => {
|
|
37
40
|
const r = t.target.closest("a");
|
|
38
41
|
if (!r) return;
|
|
39
42
|
const i = r.getAttribute("href");
|
|
@@ -41,25 +44,21 @@ class $ extends (F = S) {
|
|
|
41
44
|
});
|
|
42
45
|
}
|
|
43
46
|
render() {
|
|
44
|
-
return /* @__PURE__ */
|
|
47
|
+
return /* @__PURE__ */ _("div", { class: "router-outlet" });
|
|
45
48
|
}
|
|
46
49
|
onConnected() {
|
|
47
|
-
|
|
50
|
+
v.debug("WsxRouter connected to DOM"), this.collectViews(), v.debug("WsxRouter collected views:", this.views.size), window.addEventListener("popstate", this.handleRouteChange), this.addEventListener("click", this.interceptLinks), this.handleRouteChange();
|
|
48
51
|
}
|
|
49
52
|
onDisconnected() {
|
|
50
53
|
window.removeEventListener("popstate", this.handleRouteChange);
|
|
51
54
|
}
|
|
52
55
|
collectViews() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const i = t.assignedElements().filter((n) => n.tagName.toLowerCase() === "wsx-view");
|
|
60
|
-
p.debug("WsxRouter found views:", i.length), i.forEach((n) => {
|
|
61
|
-
const s = n.getAttribute("route") || "/";
|
|
62
|
-
this.views.set(s, n), n.style.display = "none", p.debug(`WsxRouter hiding view for route: ${s}`);
|
|
56
|
+
const t = Array.from(this.children).filter(
|
|
57
|
+
(r) => r.tagName.toLowerCase() === "wsx-view"
|
|
58
|
+
);
|
|
59
|
+
v.debug("WsxRouter found views:", t.length), t.forEach((r) => {
|
|
60
|
+
const i = r.getAttribute("route") || "/";
|
|
61
|
+
this.views.set(i, r), r.style.display = "none", v.debug(`WsxRouter hiding view for route: ${i}`);
|
|
63
62
|
});
|
|
64
63
|
}
|
|
65
64
|
matchRoute(t) {
|
|
@@ -90,33 +89,33 @@ class $ extends (F = S) {
|
|
|
90
89
|
window.history.pushState(null, "", t), this.handleRouteChange();
|
|
91
90
|
}
|
|
92
91
|
}
|
|
93
|
-
C =
|
|
94
|
-
$ =
|
|
92
|
+
C = it(F);
|
|
93
|
+
$ = ct(C, 0, "WsxRouter", D, $);
|
|
95
94
|
st(C, 1, $);
|
|
96
|
-
const
|
|
97
|
-
var
|
|
95
|
+
const lt = ":host{display:block;width:100%;height:100%}.route-view{width:100%;height:100%;position:relative}:host([loading]) .route-view{opacity:.5;transition:opacity .3s ease}:host([error]) .route-view{border:1px solid var(--error-color, #ff0000);padding:1rem}.route-view.entering{animation:fadeIn .3s ease-out}.route-view.leaving{animation:fadeOut .3s ease-in}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}";
|
|
96
|
+
var ht = Object.create, R = Object.defineProperty, dt = Object.getOwnPropertyDescriptor, U = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), M = (e) => {
|
|
98
97
|
throw TypeError(e);
|
|
99
|
-
},
|
|
98
|
+
}, V = (e, t, r) => t in e ? R(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, ut = (e, t) => R(e, "name", { value: t, configurable: !0 }), pt = (e) => [, , , ht((e == null ? void 0 : e[U("metadata")]) ?? null)], vt = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], q = (e) => e !== void 0 && typeof e != "function" ? M("Function expected") : e, mt = (e, t, r, i, o) => ({ kind: vt[e], name: t, metadata: i, addInitializer: (n) => r._ ? M("Already initialized") : o.push(q(n || null)) }), wt = (e, t) => V(t, U("metadata"), e[3]), ft = (e, t, r, i) => {
|
|
100
99
|
for (var o = 0, n = e[t >> 1], s = n && n.length; o < s; o++) n[o].call(r);
|
|
101
100
|
return i;
|
|
102
|
-
},
|
|
103
|
-
var s, l, c, a = t & 7, h = !1,
|
|
104
|
-
|
|
101
|
+
}, gt = (e, t, r, i, o, n) => {
|
|
102
|
+
var s, l, c, a = t & 7, h = !1, p = 0, w = e[p] || (e[p] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && dt(o, r));
|
|
103
|
+
ut(o, r);
|
|
105
104
|
for (var u = i.length - 1; u >= 0; u--)
|
|
106
|
-
c =
|
|
107
|
-
return
|
|
108
|
-
},
|
|
105
|
+
c = mt(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, q(s) && (o = s);
|
|
106
|
+
return wt(e, o), d && R(o, r, d), h ? a ^ 4 ? n : d : o;
|
|
107
|
+
}, g = (e, t, r) => V(e, typeof t != "symbol" ? t + "" : t, r), Q, A, T;
|
|
109
108
|
const k = y("WsxView");
|
|
110
109
|
Q = [E({ tagName: "wsx-view" })];
|
|
111
|
-
class b extends (T =
|
|
110
|
+
class b extends (T = I) {
|
|
112
111
|
constructor() {
|
|
113
112
|
super({
|
|
114
|
-
styles:
|
|
113
|
+
styles: lt,
|
|
115
114
|
styleName: "wsx-view"
|
|
116
|
-
}),
|
|
115
|
+
}), g(this, "component", null), g(this, "params", {}), g(this, "componentInstance", null);
|
|
117
116
|
}
|
|
118
117
|
render() {
|
|
119
|
-
return /* @__PURE__ */
|
|
118
|
+
return /* @__PURE__ */ _("div", { class: "route-view" });
|
|
120
119
|
}
|
|
121
120
|
onConnected() {
|
|
122
121
|
const t = this.getAttribute("component");
|
|
@@ -135,55 +134,54 @@ class b extends (T = S) {
|
|
|
135
134
|
}
|
|
136
135
|
}
|
|
137
136
|
async loadComponent(t) {
|
|
138
|
-
var o;
|
|
139
137
|
if (this.componentInstance && (this.componentInstance.remove(), this.componentInstance = null), !customElements.get(t)) {
|
|
140
138
|
k.warn(`Component ${t} not found in customElements registry`);
|
|
141
139
|
return;
|
|
142
140
|
}
|
|
143
|
-
this.componentInstance = document.createElement(t), Object.keys(this.params).length > 0 && Object.entries(this.params).forEach(([
|
|
144
|
-
this.componentInstance.setAttribute(
|
|
141
|
+
this.componentInstance = document.createElement(t), Object.keys(this.params).length > 0 && Object.entries(this.params).forEach(([o, n]) => {
|
|
142
|
+
this.componentInstance.setAttribute(o, n);
|
|
145
143
|
});
|
|
146
|
-
const i =
|
|
144
|
+
const i = this.querySelector(".route-view");
|
|
147
145
|
i ? i.appendChild(this.componentInstance) : k.error("Route view container not found");
|
|
148
146
|
}
|
|
149
147
|
onDisconnected() {
|
|
150
148
|
this.componentInstance && (this.componentInstance.remove(), this.componentInstance = null);
|
|
151
149
|
}
|
|
152
150
|
}
|
|
153
|
-
|
|
154
|
-
b =
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
var
|
|
151
|
+
A = pt(T);
|
|
152
|
+
b = gt(A, 0, "WsxView", Q, b);
|
|
153
|
+
g(b, "observedAttributes", ["route", "component", "params"]);
|
|
154
|
+
ft(A, 1, b);
|
|
155
|
+
const _t = ':host{display:inline-block;min-width:fit-content;min-height:fit-content;width:auto;height:auto}.wsx-link{color:var(--link-color, #007bff);text-decoration:var(--link-decoration, underline);cursor:pointer;transition:color .2s ease;display:inline-block;min-height:1.2em;line-height:1.2}.wsx-link:hover{color:var(--link-hover-color, #0056b3);text-decoration:var(--link-hover-decoration, underline)}.wsx-link:focus{outline:2px solid var(--link-focus-color, #007bff);outline-offset:2px}.wsx-link.active{color:var(--link-active-color, #6c757d);font-weight:var(--link-active-weight, bold)}:host([disabled]) .wsx-link{color:var(--link-disabled-color, #6c757d);cursor:not-allowed;pointer-events:none}:host([external]) .wsx-link:after{content:"↗";font-size:.8em;margin-left:.2em;opacity:.7}:host([variant="button"]) .wsx-link{background-color:var(--button-bg, #007bff);color:var(--button-color, white);padding:.5rem 1rem;border-radius:.25rem;text-decoration:none;display:inline-block}:host([variant="button"]) .wsx-link:hover{background-color:var(--button-hover-bg, #0056b3);color:var(--button-hover-color, white)}:host([variant="tab"]) .wsx-link{padding:.5rem 1rem;border-bottom:2px solid transparent;text-decoration:none}:host([variant="tab"]) .wsx-link.active{border-bottom-color:var(--tab-active-border, #007bff)}';
|
|
156
|
+
var bt = Object.create, P = Object.defineProperty, xt = Object.getOwnPropertyDescriptor, H = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), J = (e) => {
|
|
159
157
|
throw TypeError(e);
|
|
160
|
-
}, B = (e, t, r) => t in e ?
|
|
158
|
+
}, B = (e, t, r) => t in e ? P(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, yt = (e, t) => P(e, "name", { value: t, configurable: !0 }), kt = (e) => [, , , bt((e == null ? void 0 : e[H("metadata")]) ?? null)], $t = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], G = (e) => e !== void 0 && typeof e != "function" ? J("Function expected") : e, Et = (e, t, r, i, o) => ({ kind: $t[e], name: t, metadata: i, addInitializer: (n) => r._ ? J("Already initialized") : o.push(G(n || null)) }), St = (e, t) => B(t, H("metadata"), e[3]), Ct = (e, t, r, i) => {
|
|
161
159
|
for (var o = 0, n = e[t >> 1], s = n && n.length; o < s; o++) n[o].call(r);
|
|
162
160
|
return i;
|
|
163
161
|
}, Rt = (e, t, r, i, o, n) => {
|
|
164
|
-
var s, l, c, a = t & 7, h = !1,
|
|
165
|
-
|
|
162
|
+
var s, l, c, a = t & 7, h = !1, p = 0, w = e[p] || (e[p] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && xt(o, r));
|
|
163
|
+
yt(o, r);
|
|
166
164
|
for (var u = i.length - 1; u >= 0; u--)
|
|
167
|
-
c =
|
|
168
|
-
return
|
|
169
|
-
}, m = (e, t, r) => B(e, typeof t != "symbol" ? t + "" : t, r), K,
|
|
170
|
-
const
|
|
165
|
+
c = Et(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, G(s) && (o = s);
|
|
166
|
+
return St(e, o), d && P(o, r, d), h ? a ^ 4 ? n : d : o;
|
|
167
|
+
}, m = (e, t, r) => B(e, typeof t != "symbol" ? t + "" : t, r), K, L, X;
|
|
168
|
+
const W = y("WsxLink");
|
|
171
169
|
K = [E({ tagName: "wsx-link" })];
|
|
172
|
-
class x extends (X =
|
|
170
|
+
class x extends (X = Y) {
|
|
173
171
|
constructor() {
|
|
174
172
|
super({
|
|
175
|
-
styles:
|
|
173
|
+
styles: _t,
|
|
176
174
|
styleName: "wsx-link"
|
|
177
175
|
}), m(this, "to", ""), m(this, "replace", !1), m(this, "activeClass", "active"), m(this, "exact", !1), m(this, "handleClick", (t) => {
|
|
178
176
|
if (t.preventDefault(), !this.to) {
|
|
179
|
-
|
|
177
|
+
W.warn("No 'to' attribute specified");
|
|
180
178
|
return;
|
|
181
179
|
}
|
|
182
180
|
if (this.isExternalLink(this.to)) {
|
|
183
181
|
window.open(this.to, "_blank");
|
|
184
182
|
return;
|
|
185
183
|
}
|
|
186
|
-
this.replace ? window.history.replaceState(null, "", this.to) : window.history.pushState(null, "", this.to), window.dispatchEvent(new PopStateEvent("popstate")),
|
|
184
|
+
this.replace ? window.history.replaceState(null, "", this.to) : window.history.pushState(null, "", this.to), window.dispatchEvent(new PopStateEvent("popstate")), W.debug(`Navigated to: ${this.to}`);
|
|
187
185
|
}), m(this, "updateActiveState", () => {
|
|
188
186
|
var o;
|
|
189
187
|
const t = window.location.pathname, r = this.exact ? t === this.to : t.startsWith(this.to) && this.to !== "/", i = (o = this.shadowRoot) == null ? void 0 : o.querySelector("a");
|
|
@@ -191,7 +189,7 @@ class x extends (X = S) {
|
|
|
191
189
|
});
|
|
192
190
|
}
|
|
193
191
|
render() {
|
|
194
|
-
return /* @__PURE__ */
|
|
192
|
+
return /* @__PURE__ */ _("a", { href: this.to, class: "wsx-link", onClick: this.handleClick, part: "link" }, /* @__PURE__ */ _("slot", null));
|
|
195
193
|
}
|
|
196
194
|
onConnected() {
|
|
197
195
|
this.to = this.getAttribute("to") || "", this.replace = this.hasAttribute("replace"), this.activeClass = this.getAttribute("active-class") || "active", this.exact = this.hasAttribute("exact");
|
|
@@ -232,17 +230,17 @@ class x extends (X = S) {
|
|
|
232
230
|
);
|
|
233
231
|
}
|
|
234
232
|
}
|
|
235
|
-
|
|
236
|
-
x = Rt(
|
|
233
|
+
L = kt(X);
|
|
234
|
+
x = Rt(L, 0, "WsxLink", K, x);
|
|
237
235
|
m(x, "observedAttributes", ["to", "replace", "active-class", "exact"]);
|
|
238
|
-
|
|
239
|
-
const
|
|
240
|
-
class
|
|
236
|
+
Ct(L, 1, x);
|
|
237
|
+
const At = y("RouterUtils");
|
|
238
|
+
class Lt {
|
|
241
239
|
/**
|
|
242
240
|
* 编程式导航
|
|
243
241
|
*/
|
|
244
242
|
static navigate(t, r = !1) {
|
|
245
|
-
r ? window.history.replaceState(null, "", t) : window.history.pushState(null, "", t), window.dispatchEvent(new PopStateEvent("popstate")),
|
|
243
|
+
r ? window.history.replaceState(null, "", t) : window.history.pushState(null, "", t), window.dispatchEvent(new PopStateEvent("popstate")), At.debug(`Navigated to: ${t} (replace: ${r})`);
|
|
246
244
|
}
|
|
247
245
|
/**
|
|
248
246
|
* 获取当前路由信息
|
|
@@ -402,7 +400,7 @@ class Pt {
|
|
|
402
400
|
}
|
|
403
401
|
}
|
|
404
402
|
export {
|
|
405
|
-
|
|
403
|
+
Lt as RouterUtils,
|
|
406
404
|
x as WsxLink,
|
|
407
405
|
$ as WsxRouter,
|
|
408
406
|
b as WsxView
|
package/package.json
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
"name": "@wsxjs/wsx-router",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "WSX Router - Native History API-based routing for WSX Framework",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.cjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src",
|
|
17
|
+
"!**/__tests__",
|
|
18
|
+
"!**/test"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "vite build",
|
|
22
|
+
"build:dev": "NODE_ENV=development vite build",
|
|
23
|
+
"dev": "NODE_ENV=development vite build --watch",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"test": "vitest",
|
|
26
|
+
"test:ui": "vitest --ui",
|
|
27
|
+
"test:coverage": "vitest --coverage",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"lint": "eslint .",
|
|
30
|
+
"lint:fix": "eslint . --fix"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@wsxjs/wsx-core": "workspace:*"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@wsxjs/eslint-plugin-wsx": "workspace:*",
|
|
37
|
+
"@wsxjs/wsx-vite-plugin": "workspace:*",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
|
39
|
+
"@typescript-eslint/parser": "^8.37.0",
|
|
40
|
+
"@vitest/ui": "^2.1.8",
|
|
41
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
42
|
+
"eslint": "^9.31.0",
|
|
43
|
+
"jsdom": "^26.0.0",
|
|
44
|
+
"typescript": "^5.0.0",
|
|
45
|
+
"vite": "^5.4.19",
|
|
46
|
+
"vitest": "^2.1.8"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"wsx",
|
|
50
|
+
"router",
|
|
51
|
+
"web-components",
|
|
52
|
+
"history-api",
|
|
53
|
+
"navigation",
|
|
54
|
+
"spa"
|
|
55
|
+
],
|
|
56
|
+
"author": "WSX Framework Team",
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/wsxjs/wsxjs.git",
|
|
61
|
+
"directory": "packages/wsx-router"
|
|
12
62
|
}
|
|
13
|
-
|
|
14
|
-
"files": [
|
|
15
|
-
"dist",
|
|
16
|
-
"src",
|
|
17
|
-
"!**/__tests__",
|
|
18
|
-
"!**/test"
|
|
19
|
-
],
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@wsxjs/wsx-core": "0.0.5"
|
|
22
|
-
},
|
|
23
|
-
"devDependencies": {
|
|
24
|
-
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
|
25
|
-
"@typescript-eslint/parser": "^8.37.0",
|
|
26
|
-
"@vitest/ui": "^2.1.8",
|
|
27
|
-
"@vitest/coverage-v8": "^2.1.8",
|
|
28
|
-
"eslint": "^9.31.0",
|
|
29
|
-
"jsdom": "^26.0.0",
|
|
30
|
-
"typescript": "^5.0.0",
|
|
31
|
-
"vite": "^5.4.19",
|
|
32
|
-
"vitest": "^2.1.8",
|
|
33
|
-
"@wsxjs/wsx-vite-plugin": "0.0.5",
|
|
34
|
-
"@wsxjs/eslint-plugin-wsx": "0.0.5"
|
|
35
|
-
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
"wsx",
|
|
38
|
-
"router",
|
|
39
|
-
"web-components",
|
|
40
|
-
"history-api",
|
|
41
|
-
"navigation",
|
|
42
|
-
"spa"
|
|
43
|
-
],
|
|
44
|
-
"author": "WSX Framework Team",
|
|
45
|
-
"license": "MIT",
|
|
46
|
-
"repository": {
|
|
47
|
-
"type": "git",
|
|
48
|
-
"url": "https://github.com/wsxjs/wsxjs.git",
|
|
49
|
-
"directory": "packages/wsx-router"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build": "vite build",
|
|
53
|
-
"build:dev": "NODE_ENV=development vite build",
|
|
54
|
-
"dev": "NODE_ENV=development vite build --watch",
|
|
55
|
-
"clean": "rm -rf dist",
|
|
56
|
-
"test": "vitest",
|
|
57
|
-
"test:ui": "vitest --ui",
|
|
58
|
-
"test:coverage": "vitest --coverage",
|
|
59
|
-
"typecheck": "tsc --noEmit",
|
|
60
|
-
"lint": "eslint .",
|
|
61
|
-
"lint:fix": "eslint . --fix"
|
|
62
|
-
}
|
|
63
|
-
}
|
|
63
|
+
}
|
package/src/WsxRouter.wsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @jsxImportSource @wsxjs/wsx-core */
|
|
2
|
-
import {
|
|
2
|
+
import { LightComponent, autoRegister, createLogger } from "@wsxjs/wsx-core";
|
|
3
3
|
import styles from "./WsxRouter.css?inline";
|
|
4
4
|
|
|
5
5
|
const logger = createLogger("WsxRouter");
|
|
@@ -23,18 +23,21 @@ const logger = createLogger("WsxRouter");
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
@autoRegister({ tagName: "wsx-router" })
|
|
26
|
-
export default class WsxRouter extends
|
|
26
|
+
export default class WsxRouter extends LightComponent {
|
|
27
27
|
private views: Map<string, HTMLElement> = new Map();
|
|
28
28
|
private currentView: HTMLElement | null = null;
|
|
29
29
|
|
|
30
30
|
constructor() {
|
|
31
|
-
super({
|
|
31
|
+
super({
|
|
32
|
+
styles,
|
|
33
|
+
styleName: "wsx-router",
|
|
34
|
+
});
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
render() {
|
|
35
38
|
return (
|
|
36
39
|
<div class="router-outlet">
|
|
37
|
-
|
|
40
|
+
{/* In Light DOM, slot is just a placeholder - content is accessed via this.children */}
|
|
38
41
|
</div>
|
|
39
42
|
);
|
|
40
43
|
}
|
|
@@ -61,18 +64,10 @@ export default class WsxRouter extends WebComponent {
|
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
private collectViews() {
|
|
64
|
-
//
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Get slotted elements (light DOM children)
|
|
72
|
-
const slottedElements = slot.assignedElements();
|
|
73
|
-
|
|
74
|
-
// Filter for wsx-view elements
|
|
75
|
-
const views = slottedElements.filter((el) => el.tagName.toLowerCase() === "wsx-view");
|
|
67
|
+
// In Light DOM, directly access child elements
|
|
68
|
+
const views = Array.from(this.children).filter(
|
|
69
|
+
(el) => el.tagName.toLowerCase() === "wsx-view"
|
|
70
|
+
);
|
|
76
71
|
logger.debug("WsxRouter found views:", views.length);
|
|
77
72
|
|
|
78
73
|
views.forEach((view) => {
|
package/src/WsxView.wsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @jsxImportSource @wsxjs/wsx-core */
|
|
2
|
-
import {
|
|
2
|
+
import { LightComponent, autoRegister, createLogger } from "@wsxjs/wsx-core";
|
|
3
3
|
import styles from "./WsxView.css?inline";
|
|
4
4
|
|
|
5
5
|
const logger = createLogger("WsxView");
|
|
@@ -18,7 +18,7 @@ const logger = createLogger("WsxView");
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
@autoRegister({ tagName: "wsx-view" })
|
|
21
|
-
export default class WsxView extends
|
|
21
|
+
export default class WsxView extends LightComponent {
|
|
22
22
|
static observedAttributes = ["route", "component", "params"];
|
|
23
23
|
|
|
24
24
|
private component: string | null = null;
|
|
@@ -33,7 +33,11 @@ export default class WsxView extends WebComponent {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
render() {
|
|
36
|
-
return
|
|
36
|
+
return (
|
|
37
|
+
<div class="route-view">
|
|
38
|
+
{/* Light DOM container for dynamically loaded components */}
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
protected onConnected() {
|
|
@@ -84,7 +88,7 @@ export default class WsxView extends WebComponent {
|
|
|
84
88
|
});
|
|
85
89
|
}
|
|
86
90
|
|
|
87
|
-
const container = this.
|
|
91
|
+
const container = this.querySelector(".route-view");
|
|
88
92
|
if (container) {
|
|
89
93
|
container.appendChild(this.componentInstance);
|
|
90
94
|
} else {
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 WSX Framework Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|