@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 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, WebComponent as S, jsx as f } from "@wsxjs/wsx-core";
2
- const Y = ":host{display:block;width:100%;height:100%}.router-outlet{width:100%;height:100%}";
3
- var Z = Object.create, R = Object.defineProperty, tt = Object.getOwnPropertyDescriptor, O = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), N = (e) => {
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 ? R(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, et = (e, t) => R(e, "name", { value: t, configurable: !0 }), rt = (e) => [, , , Z((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, it = (e, t, r, i, o) => ({ kind: ot[e], name: t, metadata: i, addInitializer: (n) => r._ ? N("Already initialized") : o.push(z(n || null)) }), nt = (e, t) => j(t, O("metadata"), e[3]), st = (e, t, r, i) => {
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
- }, at = (e, t, r, i, o, n) => {
9
- var s, l, c, a = t & 7, h = !1, v = 0, w = e[v] || (e[v] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && tt(o, r));
10
- et(o, r);
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 = it(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, z(s) && (o = s);
13
- return nt(e, o), d && R(o, r, d), h ? a ^ 4 ? n : d : o;
14
- }, g = (e, t, r) => j(e, typeof t != "symbol" ? t + "" : t, r), D, C, F;
15
- const p = y("WsxRouter");
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 = S) {
17
+ class $ extends (F = I) {
18
18
  constructor() {
19
- super({ styles: Y }), g(this, "views", /* @__PURE__ */ new Map()), g(this, "currentView", null), g(this, "handleRouteChange", () => {
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
- p.debug(`Route changed to: ${t}`), this.currentView && (this.currentView.style.display = "none", p.debug("Hiding previous view"));
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, p.debug(`Showing view for route: ${r.getAttribute("route")}`);
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
- p.warn(`No view found for path: ${t}`);
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
- }), g(this, "interceptLinks", (t) => {
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__ */ f("div", { class: "router-outlet" }, /* @__PURE__ */ f("slot", null));
47
+ return /* @__PURE__ */ _("div", { class: "router-outlet" });
45
48
  }
46
49
  onConnected() {
47
- p.debug("WsxRouter connected to DOM"), this.collectViews(), p.debug("WsxRouter collected views:", this.views.size), window.addEventListener("popstate", this.handleRouteChange), this.addEventListener("click", this.interceptLinks), this.handleRouteChange();
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
- var o;
54
- const t = (o = this.shadowRoot) == null ? void 0 : o.querySelector("slot");
55
- if (!t) {
56
- p.error("WsxRouter: No slot found");
57
- return;
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 = rt(F);
94
- $ = at(C, 0, "WsxRouter", D, $);
92
+ C = it(F);
93
+ $ = ct(C, 0, "WsxRouter", D, $);
95
94
  st(C, 1, $);
96
- const ct = ":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}}";
97
- var lt = Object.create, A = Object.defineProperty, ht = Object.getOwnPropertyDescriptor, U = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), M = (e) => {
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
- }, q = (e, t, r) => t in e ? A(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, dt = (e, t) => A(e, "name", { value: t, configurable: !0 }), ut = (e) => [, , , lt((e == null ? void 0 : e[U("metadata")]) ?? null)], pt = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], V = (e) => e !== void 0 && typeof e != "function" ? M("Function expected") : e, vt = (e, t, r, i, o) => ({ kind: pt[e], name: t, metadata: i, addInitializer: (n) => r._ ? M("Already initialized") : o.push(V(n || null)) }), mt = (e, t) => q(t, U("metadata"), e[3]), wt = (e, t, r, i) => {
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
- }, ft = (e, t, r, i, o, n) => {
103
- var s, l, c, a = t & 7, h = !1, v = 0, w = e[v] || (e[v] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && ht(o, r));
104
- dt(o, r);
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 = vt(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, V(s) && (o = s);
107
- return mt(e, o), d && A(o, r, d), h ? a ^ 4 ? n : d : o;
108
- }, _ = (e, t, r) => q(e, typeof t != "symbol" ? t + "" : t, r), Q, P, T;
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 = S) {
110
+ class b extends (T = I) {
112
111
  constructor() {
113
112
  super({
114
- styles: ct,
113
+ styles: lt,
115
114
  styleName: "wsx-view"
116
- }), _(this, "component", null), _(this, "params", {}), _(this, "componentInstance", null);
115
+ }), g(this, "component", null), g(this, "params", {}), g(this, "componentInstance", null);
117
116
  }
118
117
  render() {
119
- return /* @__PURE__ */ f("div", { class: "route-view", part: "view" });
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(([n, s]) => {
144
- this.componentInstance.setAttribute(n, s);
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 = (o = this.shadowRoot) == null ? void 0 : o.querySelector(".route-view");
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
- P = ut(T);
154
- b = ft(P, 0, "WsxView", Q, b);
155
- _(b, "observedAttributes", ["route", "component", "params"]);
156
- wt(P, 1, b);
157
- const gt = ':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)}';
158
- var _t = Object.create, L = Object.defineProperty, bt = Object.getOwnPropertyDescriptor, H = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), J = (e) => {
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 ? L(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, xt = (e, t) => L(e, "name", { value: t, configurable: !0 }), yt = (e) => [, , , _t((e == null ? void 0 : e[H("metadata")]) ?? null)], kt = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], G = (e) => e !== void 0 && typeof e != "function" ? J("Function expected") : e, $t = (e, t, r, i, o) => ({ kind: kt[e], name: t, metadata: i, addInitializer: (n) => r._ ? J("Already initialized") : o.push(G(n || null)) }), Et = (e, t) => B(t, H("metadata"), e[3]), St = (e, t, r, i) => {
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, v = 0, w = e[v] || (e[v] = []), d = a && (o = o.prototype, a < 5 && (a > 3 || !h) && bt(o, r));
165
- xt(o, r);
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 = $t(a, r, l = {}, e[3], w), s = (0, i[u])(o, c), l._ = 1, G(s) && (o = s);
168
- return Et(e, o), d && L(o, r, d), h ? a ^ 4 ? n : d : o;
169
- }, m = (e, t, r) => B(e, typeof t != "symbol" ? t + "" : t, r), K, W, X;
170
- const I = y("WsxLink");
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 = S) {
170
+ class x extends (X = Y) {
173
171
  constructor() {
174
172
  super({
175
- styles: gt,
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
- I.warn("No 'to' attribute specified");
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")), I.debug(`Navigated to: ${this.to}`);
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__ */ f("a", { href: this.to, class: "wsx-link", onClick: this.handleClick, part: "link" }, /* @__PURE__ */ f("slot", null));
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
- W = yt(X);
236
- x = Rt(W, 0, "WsxLink", K, x);
233
+ L = kt(X);
234
+ x = Rt(L, 0, "WsxLink", K, x);
237
235
  m(x, "observedAttributes", ["to", "replace", "active-class", "exact"]);
238
- St(W, 1, x);
239
- const Ct = y("RouterUtils");
240
- class Pt {
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")), Ct.debug(`Navigated to: ${t} (replace: ${r})`);
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
- Pt as RouterUtils,
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
- "name": "@wsxjs/wsx-router",
3
- "version": "0.0.5",
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"
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 { WebComponent, autoRegister, createLogger } from "@wsxjs/wsx-core";
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 WebComponent {
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({ styles });
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
- <slot></slot>
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
- // Get the slot element
65
- const slot = this.shadowRoot?.querySelector("slot");
66
- if (!slot) {
67
- logger.error("WsxRouter: No slot found");
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 { WebComponent, autoRegister, createLogger } from "@wsxjs/wsx-core";
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 WebComponent {
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 <div class="route-view" part="view"></div>;
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.shadowRoot?.querySelector(".route-view");
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.