@cruxjs/client 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div align="center">
|
|
11
|
-
<img src="https://img.shields.io/badge/v-0.3.
|
|
11
|
+
<img src="https://img.shields.io/badge/v-0.3.2-black"/>
|
|
12
12
|
<a href="https://github.com/cruxjs-org"><img src="https://img.shields.io/badge/🔥-@cruxjs-black"/></a>
|
|
13
13
|
<br>
|
|
14
14
|
<img src="https://img.shields.io/badge/coverage-~%25-brightgreen" alt="Test Coverage" />
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var signals=require('@minejs/signals'),jsx=require('@minejs/jsx'),browser=require('@minejs/browser'),i18n=require('@minejs/i18n');var l=class extends Error{constructor(e,r,o){super(r);this.code=e;this.cause=o;this.name="NavigationError";}};var h=class{constructor(t,e=null,r=new Map,o,n=false){this.segment=t;this.route=e;this.children=r;this.paramName=o;this.isWildcard=n;}},y=class{constructor(){this.root=new h("");this.wildcardRoute=null;}addRoute(t,e=""){let r=e+t.path;if(r==="/*"||r==="*"){this.wildcardRoute=t;return}let o=r.split("/").filter(Boolean),n=this.root;for(let a of o){let c=a.startsWith(":"),s=c?":param":a;n.children.has(s)||n.children.set(s,new h(a,null,new Map,c?a.slice(1):void 0)),n=n.children.get(s);}n.route=t,t.children&&t.children.forEach(a=>this.addRoute(a,r));}match(t){let e=t.split("/").filter(Boolean),r={},o=this.root,n=null;for(let c of e)if(o.children.has(c))o=o.children.get(c);else if(o.children.has(":param")){let s=o.children.get(":param");r[s.paramName]=decodeURIComponent(c),o=s;}else {n=this.wildcardRoute;break}if(n=n||o.route,!n)return null;let a=new URL(window.location.href);return {path:t,params:r,query:a.searchParams,hash:a.hash.slice(1),route:n}}},m=class{constructor(t){this.matcher=new y;this.currentRoute=signals.signal(null);this.isNavigating=signals.signal(false);this.loaderData=signals.signal(null);this.error=signals.signal(null);this.history=[];this.historyIndex=0;this.maxHistory=50;this.beforeEachGuards=[];this.afterEachGuards=[];this.onErrorHandlers=[];this.config={mode:"history",base:"",scrollBehavior:"auto",...t},t.onError&&this.onErrorHandlers.push(t.onError),t.routes.forEach(e=>this.matcher.addRoute(e)),this.setupListeners(),this.performNavigation(window.location.pathname+window.location.search);}emitError(t){this.error.set(t),this.onErrorHandlers.forEach(e=>e(t));}setupListeners(){this.config.mode==="history"?window.addEventListener("popstate",()=>{this.handleNavigation(window.location.pathname+window.location.search);}):window.addEventListener("hashchange",()=>{let t=window.location.hash.slice(1);this.handleNavigation(t||"/");}),document.addEventListener("click",t=>{let e=t.target.closest("a");if(!e||!e.href)return;let r=new URL(e.href);r.origin===window.location.origin&&(e.hasAttribute("data-external")||e.getAttribute("target")!=="_blank"&&(t.ctrlKey||t.metaKey||t.shiftKey||(t.preventDefault(),this.push(r.pathname+r.search))));});}performNavigation(t,e={}){try{let[r,o]=t.split("?"),n=new URL("http://localhost"+r+(o?"?"+o:""));this.config.allowedQueryParams&&this.config.allowedQueryParams.length>0&&Array.from(n.searchParams.keys()).forEach(p=>{this.config.allowedQueryParams.some(f=>typeof f=="string"?f===p:f.test(p))||n.searchParams.delete(p);});let a=n.searchParams.toString(),c=r+(a?"?"+a:""),s=this.matcher.match(r);if(!s){let w=new l("ROUTE_NOT_FOUND",`No route matched: ${r}`);this.emitError(w);return}if(this.config.mode==="history"?e.replace?window.history.replaceState(e.state||{},"",c):window.history.pushState(e.state||{},"",c):window.location.hash=c,s.query=n.searchParams,s.path=r,this.checkSyncGuards(s,this.currentRoute())===!1){window.history.back();return}this.error.set(null),this.currentRoute.set(s),this.handleScroll(e.scroll),this.updateMetaTags(s.route.meta),this.pruneHistory(),this.history.push(s),this.historyIndex=this.history.length-1,this.runAsyncNavigation(t,s,e);}catch(r){let o=new l("GUARD_ERROR","Navigation failed: "+String(r),r instanceof Error?r:void 0);this.emitError(o);}}updateMetaTags(t){if(t&&(t.title&&(document.title=t.title),t.description)){let e=document.querySelector('meta[name="description"]');if(e)e.content=t.description;else {let r=document.createElement("meta");r.name="description",r.content=t.description,document.head.appendChild(r);}}}pruneHistory(){this.history.length>this.maxHistory&&(this.history=this.history.slice(-this.maxHistory),this.historyIndex=this.history.length-1);}checkSyncGuards(t,e){if(this.beforeEachGuards.length!==0){for(let r of this.beforeEachGuards){let o=r(t,e);if(o instanceof Promise)return;if(o===false)return false}return true}}async runAsyncNavigation(t,e,r){try{if(!await this.runBeforeEachGuards(e,e)){this.currentRoute.set(null),this.history.pop(),this.historyIndex=Math.max(-1,this.history.length-1),window.history.back();return}let n=e;this.isNavigating.set(!0);try{if(e.route.loader){let a={params:e.params,query:e.query,request:new Request(window.location.href),pathname:t};try{let c=await e.route.loader(a);this.loaderData.set(c);}catch(c){let s=new l("LOADER_ERROR",`Failed to load data for ${t}`,c instanceof Error?c:void 0);throw this.emitError(s),s}}else this.loaderData.set(null);this.runAfterEachGuards(e,n);}finally{this.isNavigating.set(!1);}}catch(o){if(o instanceof l)throw o;let n=new l("GUARD_ERROR","Async navigation failed",o instanceof Error?o:void 0);this.emitError(n);}}async handleNavigation(t,e={}){this.performNavigation(t,e);}async runBeforeEachGuards(t,e){for(let r of this.beforeEachGuards)if(await r(t,e)===false)return false;return true}runAfterEachGuards(t,e){this.afterEachGuards.forEach(r=>r(t,e));}handleScroll(t){if(t===false)return;let e=typeof t=="string"?t:this.config.scrollBehavior;typeof window<"u"&&window.scrollTo&&window.scrollTo({top:0,left:0,behavior:e==="smooth"?"smooth":"auto"});}push(t,e={}){this.handleNavigation(t,{...e,replace:false});}replace(t,e={}){this.handleNavigation(t,{...e,replace:true});}back(){window.history.back();}forward(){window.history.forward();}go(t){window.history.go(t);}isActive(t,e=false){let r=this.currentRoute();return r?e?r.path===t:r.path.startsWith(t):false}getParams(){return this.currentRoute()?.params||{}}getQuery(){return this.currentRoute()?.query||new URLSearchParams}beforeEach(t){return this.beforeEachGuards.push(t),()=>{let e=this.beforeEachGuards.indexOf(t);e>-1&&this.beforeEachGuards.splice(e,1);}}afterEach(t){return this.afterEachGuards.push(t),()=>{let e=this.afterEachGuards.indexOf(t);e>-1&&this.afterEachGuards.splice(e,1);}}onError(t){return this.onErrorHandlers.push(t),()=>{let e=this.onErrorHandlers.indexOf(t);e>-1&&this.onErrorHandlers.splice(e,1);}}addAllowedQueryParam(t){this.config.allowedQueryParams||(this.config.allowedQueryParams=[]),this.config.allowedQueryParams.push(t);}async reload(){let t=this.currentRoute();if(t){let e=t.query.toString(),r=t.path+(e?"?"+e:"");await this.handleNavigation(r,{replace:true});}}destroy(){this.history=[],this.beforeEachGuards=[],this.afterEachGuards=[],this.onErrorHandlers=[],this.currentRoute.set(null),this.loaderData.set(null),this.error.set(null);}},E=null;function b(i){return E=new m(i),E}var x,d=class{constructor(t){this.lifecycle="booting";this.hooks={};this.extensions=[];this.routeComponents={};this.currentPathSignal=signals.signal(window.location.pathname??"/");this.config=t,this.debug=t.debug??false,this.log("[INIT] Creating ClientManager"),t.lifecycle&&(this.hooks={...t.lifecycle}),this.extensions=t.extensions??[],this.routeComponents=t.routes,this.eventsManager=new browser.EventsManager,this.windowManager=new browser.WindowManager;let e=Object.entries(t.routes).map(([r,o])=>({path:r,component:o}));this.router=b({routes:e,notFoundComponent:t.notFoundComponent,allowedQueryParams:t.allowedQueryParams}),this.router.afterEach(r=>{this.currentPathSignal.set(r.path);}),x=this,this.log("[INIT] ClientManager created");}on(t,e,r,o){return typeof t=="string"&&t.startsWith("on")?(this.hooks[t]=e,this):this.eventsManager.on(t,e,r,o)}async boot(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Already booted or destroyed");return}this.log("\u26A1 Phase: BOOT");try{for(let t of this.extensions)t.onBoot&&(this.log(`\u2192 Extension onBoot: ${t.name}`),await t.onBoot({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onBoot&&(this.log("\u2192 Calling onBoot hook"),await this.hooks.onBoot()),this.log("\u2713 BOOT phase complete");}catch(t){throw console.error("[ClientManager] Boot failed:",t),t}}async ready(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Cannot ready - not in booting phase");return}this.log("\u26A1 Phase: READY");try{let t="body";document.querySelector(t).id="root",this.mount(t),this.log("\u2192 Router mounted");for(let e of this.extensions)e.onReady&&(this.log(`\u2192 Extension onReady: ${e.name}`),await e.onReady({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onReady&&(this.log("\u2192 Calling onReady hook"),await this.hooks.onReady()),this.lifecycle="ready",this.log("\u2713 READY phase complete"),this.log("\u2713 App is ready!");}catch(t){throw console.error("[ClientManager] Ready failed:",t),t}}async destroy(){if(this.lifecycle==="destroyed"){console.warn("[ClientManager] Already destroyed");return}this.lifecycle="destroying",this.log("\u26A1 Phase: DESTROY");try{for(let t=this.extensions.length-1;t>=0;t--){let e=this.extensions[t];e.onDestroy&&(this.log(`\u2192 Extension onDestroy: ${e.name}`),await e.onDestroy({debug:this.debug,config:{},cconfig:this.config}));}this.hooks.onDestroy&&(this.log("\u2192 Calling onDestroy hook"),await this.hooks.onDestroy()),this.eventsManager.destroy(),this.windowManager.destroy(),this.lifecycle="destroyed",this.log("\u2713 DESTROY phase complete");}catch(t){throw console.error("[ClientManager] Destroy failed:",t),t}}navigate(t){this.router.push(t);}mount(t){let e=typeof t=="string"?document.querySelector(t):t;if(!e){console.warn("[ClientManager] Mount target not found:",t);return}let r=e;if(this.config.rootLayout)try{let o=this.config.rootLayout();if(o){jsx.mount(o,e),this.log("\u2192 Root layout mounted");let n=e.querySelector("#main-overlay");n?r=n:console.warn("[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.");}}catch(o){console.error("[ClientManager] Error rendering root layout:",o),e.innerHTML="<p>Error loading root layout</p>";return}signals.effect(()=>{let o=this.currentPathSignal(),n=this.routeComponents[o]||this.config.notFoundComponent||null;if(r.innerHTML="",n)try{let a=n();a&&jsx.mount(a,r);}catch(a){console.error("[ClientManager] Error rendering component:",o,a),r.innerHTML="<p>Error loading component</p>";}else r.innerHTML="<p>No component found for this route</p>";this.log(`\u2192 Route changed to: ${o}`);}),this.log("\u2192 Routing setup complete");}getCurrentPath(){return this.currentPathSignal}createLinkHandler(t){return e=>{e.preventDefault(),this.navigate(t);}}getRouter(){return this.router}off(t,e,r){this.eventsManager.off(t,e,r);}getEventsManager(){return this.eventsManager}getViewport(){return this.windowManager.getViewport()}getWindowManager(){return this.windowManager}getI18n(){return window.__i18n}t(t,e,r){return window.__i18n?window.__i18n.t(t,e)??r??t:(console.warn("[ClientManager] i18n not initialized. Using default value or key."),r??t)}getPhase(){return this.lifecycle}isReady(){return this.lifecycle==="ready"}log(t){this.debug&&console.log(`[ClientManager] ${t}`);}},v=()=>x,g=()=>v()?.getRouter(),W=()=>g()?.back(),$=()=>g()?.forward(),j=i=>g()?.push(i),K=i=>g()?.replace(i),R=()=>v()?.getI18n(),Y=()=>R()?.getLanguage(),J=i=>R()?.setLanguage(i),z=(i,t,e)=>v()?.t(i,t,e),X=(i,t,e,r)=>R()?.tLang(i,t,e,r)??r??t;async function et(i){let t=document.querySelector('meta[name="app-i18n"]');if(t){let r=JSON.parse(t.getAttribute("content")||"{}");i.i18n=r;}let e=new d(i);return window.__i18n=await i18n.setupI18n(i.i18n||{defaultLanguage:"en",supportedLanguages:["en"]}),e.boot(),e.ready(),window.addEventListener("beforeunload",async()=>{await e.destroy();}),e}
|
|
2
|
-
exports.CM=v;exports.ClientManager=
|
|
1
|
+
'use strict';var signals=require('@minejs/signals'),jsx=require('@minejs/jsx'),browser=require('@minejs/browser'),i18n=require('@minejs/i18n');var l=class extends Error{constructor(e,r,o){super(r);this.code=e;this.cause=o;this.name="NavigationError";}};var d=class{constructor(t,e=null,r=new Map,o,n=false){this.segment=t;this.route=e;this.children=r;this.paramName=o;this.isWildcard=n;}},y=class{constructor(){this.root=new d("");this.wildcardRoute=null;}addRoute(t,e=""){let r=e+t.path;if(r==="/*"||r==="*"){this.wildcardRoute=t;return}let o=r.split("/").filter(Boolean),n=this.root;for(let a of o){let c=a.startsWith(":"),s=c?":param":a;n.children.has(s)||n.children.set(s,new d(a,null,new Map,c?a.slice(1):void 0)),n=n.children.get(s);}n.route=t,t.children&&t.children.forEach(a=>this.addRoute(a,r));}match(t){let e=t.split("/").filter(Boolean),r={},o=this.root,n=null;for(let c of e)if(o.children.has(c))o=o.children.get(c);else if(o.children.has(":param")){let s=o.children.get(":param");r[s.paramName]=decodeURIComponent(c),o=s;}else {n=this.wildcardRoute;break}if(n=n||o.route,!n)return null;let a=new URL(window.location.href);return {path:t,params:r,query:a.searchParams,hash:a.hash.slice(1),route:n}}},m=class{constructor(t){this.matcher=new y;this.currentRoute=signals.signal(null);this.isNavigating=signals.signal(false);this.loaderData=signals.signal(null);this.error=signals.signal(null);this.history=[];this.historyIndex=0;this.maxHistory=50;this.beforeEachGuards=[];this.afterEachGuards=[];this.onErrorHandlers=[];this.config={mode:"history",base:"",scrollBehavior:"auto",...t},t.onError&&this.onErrorHandlers.push(t.onError),t.routes.forEach(e=>this.matcher.addRoute(e)),this.setupListeners(),this.performNavigation(window.location.pathname+window.location.search);}emitError(t){this.error.set(t),this.onErrorHandlers.forEach(e=>e(t));}setupListeners(){this.config.mode==="history"?window.addEventListener("popstate",()=>{this.handleNavigation(window.location.pathname+window.location.search);}):window.addEventListener("hashchange",()=>{let t=window.location.hash.slice(1);this.handleNavigation(t||"/");}),document.addEventListener("click",t=>{let e=t.target.closest("a");if(!e||!e.href)return;let r=new URL(e.href);r.origin===window.location.origin&&(e.hasAttribute("data-external")||e.getAttribute("target")!=="_blank"&&(t.ctrlKey||t.metaKey||t.shiftKey||(t.preventDefault(),this.push(r.pathname+r.search))));});}performNavigation(t,e={}){try{let[r,o]=t.split("?"),n=new URL("http://localhost"+r+(o?"?"+o:""));this.config.allowedQueryParams&&this.config.allowedQueryParams.length>0&&Array.from(n.searchParams.keys()).forEach(p=>{this.config.allowedQueryParams.some(f=>typeof f=="string"?f===p:f.test(p))||n.searchParams.delete(p);});let a=n.searchParams.toString(),c=r+(a?"?"+a:""),s=this.matcher.match(r);if(!s){let w=new l("ROUTE_NOT_FOUND",`No route matched: ${r}`);this.emitError(w);return}if(this.config.mode==="history"?e.replace?window.history.replaceState(e.state||{},"",c):window.history.pushState(e.state||{},"",c):window.location.hash=c,s.query=n.searchParams,s.path=r,this.checkSyncGuards(s,this.currentRoute())===!1){window.history.back();return}this.error.set(null),this.currentRoute.set(s),this.handleScroll(e.scroll),this.updateMetaTags(s.route.meta),this.pruneHistory(),this.history.push(s),this.historyIndex=this.history.length-1,this.runAsyncNavigation(t,s,e);}catch(r){let o=new l("GUARD_ERROR","Navigation failed: "+String(r),r instanceof Error?r:void 0);this.emitError(o);}}updateMetaTags(t){if(t&&(t.title&&(document.title=t.title),t.description)){let e=document.querySelector('meta[name="description"]');if(e)e.content=t.description;else {let r=document.createElement("meta");r.name="description",r.content=t.description,document.head.appendChild(r);}}}pruneHistory(){this.history.length>this.maxHistory&&(this.history=this.history.slice(-this.maxHistory),this.historyIndex=this.history.length-1);}checkSyncGuards(t,e){if(this.beforeEachGuards.length!==0){for(let r of this.beforeEachGuards){let o=r(t,e);if(o instanceof Promise)return;if(o===false)return false}return true}}async runAsyncNavigation(t,e,r){try{if(!await this.runBeforeEachGuards(e,e)){this.currentRoute.set(null),this.history.pop(),this.historyIndex=Math.max(-1,this.history.length-1),window.history.back();return}let n=e;this.isNavigating.set(!0);try{if(e.route.loader){let a={params:e.params,query:e.query,request:new Request(window.location.href),pathname:t};try{let c=await e.route.loader(a);this.loaderData.set(c);}catch(c){let s=new l("LOADER_ERROR",`Failed to load data for ${t}`,c instanceof Error?c:void 0);throw this.emitError(s),s}}else this.loaderData.set(null);this.runAfterEachGuards(e,n);}finally{this.isNavigating.set(!1);}}catch(o){if(o instanceof l)throw o;let n=new l("GUARD_ERROR","Async navigation failed",o instanceof Error?o:void 0);this.emitError(n);}}async handleNavigation(t,e={}){this.performNavigation(t,e);}async runBeforeEachGuards(t,e){for(let r of this.beforeEachGuards)if(await r(t,e)===false)return false;return true}runAfterEachGuards(t,e){this.afterEachGuards.forEach(r=>r(t,e));}handleScroll(t){if(t===false)return;let e=typeof t=="string"?t:this.config.scrollBehavior;typeof window<"u"&&window.scrollTo&&window.scrollTo({top:0,left:0,behavior:e==="smooth"?"smooth":"auto"});}push(t,e={}){this.handleNavigation(t,{...e,replace:false});}replace(t,e={}){this.handleNavigation(t,{...e,replace:true});}back(){window.history.back();}forward(){window.history.forward();}go(t){window.history.go(t);}isActive(t,e=false){let r=this.currentRoute();return r?e?r.path===t:r.path.startsWith(t):false}getParams(){return this.currentRoute()?.params||{}}getQuery(){return this.currentRoute()?.query||new URLSearchParams}beforeEach(t){return this.beforeEachGuards.push(t),()=>{let e=this.beforeEachGuards.indexOf(t);e>-1&&this.beforeEachGuards.splice(e,1);}}afterEach(t){return this.afterEachGuards.push(t),()=>{let e=this.afterEachGuards.indexOf(t);e>-1&&this.afterEachGuards.splice(e,1);}}onError(t){return this.onErrorHandlers.push(t),()=>{let e=this.onErrorHandlers.indexOf(t);e>-1&&this.onErrorHandlers.splice(e,1);}}addAllowedQueryParam(t){this.config.allowedQueryParams||(this.config.allowedQueryParams=[]),this.config.allowedQueryParams.push(t);}visit(t,e){e??true?window.open(t,"_blank"):window.location.href=t;}async reload(){let t=this.currentRoute();if(t){let e=t.query.toString(),r=t.path+(e?"?"+e:"");await this.handleNavigation(r,{replace:true});}}destroy(){this.history=[],this.beforeEachGuards=[],this.afterEachGuards=[],this.onErrorHandlers=[],this.currentRoute.set(null),this.loaderData.set(null),this.error.set(null);}},E=null;function b(i){return E=new m(i),E}var M,g=class{constructor(t){this.lifecycle="booting";this.hooks={};this.extensions=[];this.routeComponents={};this.currentPathSignal=signals.signal(window.location.pathname??"/");this.config=t,this.debug=t.debug??false,this.log("[INIT] Creating ClientManager"),t.lifecycle&&(this.hooks={...t.lifecycle}),this.extensions=t.extensions??[],this.routeComponents=t.routes,this.eventsManager=new browser.EventsManager,this.windowManager=new browser.WindowManager;let e=Object.entries(t.routes).map(([r,o])=>({path:r,component:o}));this.router=b({routes:e,notFoundComponent:t.notFoundComponent,allowedQueryParams:t.allowedQueryParams}),this.router.afterEach(r=>{this.currentPathSignal.set(r.path);}),M=this,this.log("[INIT] ClientManager created");}on(t,e,r,o){return typeof t=="string"&&t.startsWith("on")?(this.hooks[t]=e,this):this.eventsManager.on(t,e,r,o)}async boot(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Already booted or destroyed");return}this.log("\u26A1 Phase: BOOT");try{for(let t of this.extensions)t.onBoot&&(this.log(`\u2192 Extension onBoot: ${t.name}`),await t.onBoot({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onBoot&&(this.log("\u2192 Calling onBoot hook"),await this.hooks.onBoot()),this.log("\u2713 BOOT phase complete");}catch(t){throw console.error("[ClientManager] Boot failed:",t),t}}async ready(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Cannot ready - not in booting phase");return}this.log("\u26A1 Phase: READY");try{let t="body";document.querySelector(t).id="root",this.mount(t),this.log("\u2192 Router mounted");for(let e of this.extensions)e.onReady&&(this.log(`\u2192 Extension onReady: ${e.name}`),await e.onReady({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onReady&&(this.log("\u2192 Calling onReady hook"),await this.hooks.onReady()),this.lifecycle="ready",this.log("\u2713 READY phase complete"),this.log("\u2713 App is ready!");}catch(t){throw console.error("[ClientManager] Ready failed:",t),t}}async destroy(){if(this.lifecycle==="destroyed"){console.warn("[ClientManager] Already destroyed");return}this.lifecycle="destroying",this.log("\u26A1 Phase: DESTROY");try{for(let t=this.extensions.length-1;t>=0;t--){let e=this.extensions[t];e.onDestroy&&(this.log(`\u2192 Extension onDestroy: ${e.name}`),await e.onDestroy({debug:this.debug,config:{},cconfig:this.config}));}this.hooks.onDestroy&&(this.log("\u2192 Calling onDestroy hook"),await this.hooks.onDestroy()),this.eventsManager.destroy(),this.windowManager.destroy(),this.lifecycle="destroyed",this.log("\u2713 DESTROY phase complete");}catch(t){throw console.error("[ClientManager] Destroy failed:",t),t}}navigate(t){this.router.push(t);}mount(t){let e=typeof t=="string"?document.querySelector(t):t;if(!e){console.warn("[ClientManager] Mount target not found:",t);return}let r=e;if(this.config.rootLayout)try{let o=this.config.rootLayout();if(o){jsx.mount(o,e),this.log("\u2192 Root layout mounted");let n=e.querySelector("#main-overlay");n?r=n:console.warn("[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.");}}catch(o){console.error("[ClientManager] Error rendering root layout:",o),e.innerHTML="<p>Error loading root layout</p>";return}signals.effect(()=>{let o=this.currentPathSignal(),n=this.routeComponents[o]||this.config.notFoundComponent||null;if(r.innerHTML="",n)try{let a=n();a&&jsx.mount(a,r);}catch(a){console.error("[ClientManager] Error rendering component:",o,a),r.innerHTML="<p>Error loading component</p>";}else r.innerHTML="<p>No component found for this route</p>";this.log(`\u2192 Route changed to: ${o}`);}),this.log("\u2192 Routing setup complete");}getCurrentPath(){return this.currentPathSignal}createLinkHandler(t){return e=>{e.preventDefault(),this.navigate(t);}}getRouter(){return this.router}off(t,e,r){this.eventsManager.off(t,e,r);}getEventsManager(){return this.eventsManager}getViewport(){return this.windowManager.getViewport()}getWindowManager(){return this.windowManager}getI18n(){return window.__i18n}t(t,e,r){return window.__i18n?window.__i18n.t(t,e)??r??t:(console.warn("[ClientManager] i18n not initialized. Using default value or key."),r??t)}getPhase(){return this.lifecycle}isReady(){return this.lifecycle==="ready"}log(t){this.debug&&console.log(`[ClientManager] ${t}`);}},v=()=>M,u=()=>v()?.getRouter(),W=()=>u()?.back(),$=()=>u()?.forward(),j=i=>u()?.push(i),K=i=>u()?.replace(i),Y=(i,t)=>u()?.visit(i,t),R=()=>v()?.getI18n(),J=()=>R()?.getLanguage(),z=(i,t=true,e=true,r=true)=>R()?.setLanguage(i,t,e,r),X=(i,t,e)=>v()?.t(i,t,e),V=(i,t,e,r)=>R()?.tLang(i,t,e,r)??r??t;async function rt(i){let t=document.querySelector('meta[name="app-i18n"]');if(t){let r=JSON.parse(t.getAttribute("content")||"{}");i.i18n=r;}let e=new g(i);return window.__i18n=await i18n.setupI18n(i.i18n||{defaultLanguage:"en",supportedLanguages:["en"]}),e.boot(),e.ready(),window.addEventListener("beforeunload",async()=>{await e.destroy();}),e}
|
|
2
|
+
exports.CM=v;exports.ClientManager=g;exports.NavigationError=l;exports.back=W;exports.forward=$;exports.getI18n=R;exports.getLang=J;exports.getRouter=u;exports.push=j;exports.replace=K;exports.setLang=z;exports.start=rt;exports.t=X;exports.tLang=V;exports.visit=Y;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/mod/router.ts","../src/mod/manager.ts","../src/index.ts"],"names":["NavigationError","code","message","cause","RouteNode","segment","route","children","paramName","isWildcard","RouteMatcher","parentPath","fullPath","segments","node","isParam","key","child","pathname","params","matchedRoute","paramNode","url","Router","config","signal","error","handler","hash","e","target","options","pathOnly","queryString","pattern","finalQueryString","finalPathname","match","err","meta","descMeta","newMeta","to","from","guard","result","_options","previousRoute","context","data","behavior","scrollBehavior","path","delta","exact","current","index","param","pathWithQuery","globalRouter","createRouter","globalClientManagerInstance","ClientManager","EventsManager","WindowManager","routesArray","component","eventOrTarget","callbackOrEvent","extension","selector","i","container","pageContainer","layoutJsx","mountJSX","pageSlot","effect","currentPath","Component","jsx","event","defaultValue","CM","getRouter","back","forward","push","replace","getI18n","getLang","setLang","lang","t","tLang","start","metaI18n","i18nData","manager","setupI18n"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/types.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n export type {\r\n RouteComponent,\r\n ThemeConfig,\r\n LangConfig,\r\n ClientExtension,\r\n ExtensionContext,\r\n ClientManagerHooks,\r\n ClientManagerConfig\r\n } from '@cruxjs/base';\r\n\r\n \r\n export type RouteParams = Record<string, string>;\r\n\r\n export interface RouteMatch {\r\n path: string\r\n params: RouteParams\r\n query: URLSearchParams\r\n hash: string\r\n route: Route\r\n }\r\n\r\n export interface RouteContext {\r\n params: RouteParams\r\n query: URLSearchParams\r\n request: Request\r\n pathname: string\r\n }\r\n\r\n export class NavigationError extends Error {\r\n constructor(\r\n public code: 'LOADER_ERROR' | 'ACTION_ERROR' | 'GUARD_ERROR' | 'ROUTE_NOT_FOUND',\r\n message: string,\r\n public cause?: Error\r\n ) {\r\n super(message);\r\n this.name = 'NavigationError';\r\n }\r\n }\r\n\r\n export type LoaderFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export type ActionFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export interface Route {\r\n path: string\r\n component: () => any | Promise<any>\r\n loader?: LoaderFunction\r\n action?: ActionFunction\r\n children?: Route[]\r\n meta?: {\r\n title?: string\r\n description?: string\r\n [key: string]: any\r\n }\r\n errorComponent?: () => any\r\n }\r\n\r\n export interface NavigateOptions {\r\n replace?: boolean\r\n state?: any\r\n scroll?: boolean | 'smooth'\r\n }\r\n\r\n export interface RouterConfig {\r\n routes: Route[]\r\n base?: string\r\n mode?: 'history' | 'hash'\r\n scrollBehavior?: 'auto' | 'smooth' | 'instant'\r\n allowedQueryParams?: (string | RegExp)[]\r\n notFoundComponent?: () => any\r\n errorComponent?: () => any\r\n onError?: (error: NavigationError) => void\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/router.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { signal, computed, type Signal } from '@minejs/signals';\r\n import { jsx, Suspense } from '@minejs/jsx';\r\n import * as types from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n class RouteNode {\r\n constructor(\r\n public segment: string,\r\n public route: types.Route | null = null,\r\n public children: Map<string, RouteNode> = new Map(),\r\n public paramName?: string,\r\n public isWildcard = false\r\n ) { }\r\n }\r\n\r\n class RouteMatcher {\r\n private root = new RouteNode('');\r\n private wildcardRoute: types.Route | null = null;\r\n\r\n addRoute(route: types.Route, parentPath = ''): void {\r\n const fullPath = parentPath + route.path;\r\n\r\n // Handle wildcard routes\r\n if (fullPath === '/*' || fullPath === '*') {\r\n this.wildcardRoute = route;\r\n return;\r\n }\r\n\r\n const segments = fullPath.split('/').filter(Boolean);\r\n let node = this.root;\r\n\r\n for (const segment of segments) {\r\n const isParam = segment.startsWith(':');\r\n const key = isParam ? ':param' : segment;\r\n\r\n if (!node.children.has(key)) {\r\n node.children.set(key, new RouteNode(\r\n segment,\r\n null,\r\n new Map(),\r\n isParam ? segment.slice(1) : undefined\r\n ));\r\n }\r\n\r\n node = node.children.get(key)!;\r\n }\r\n\r\n node.route = route;\r\n\r\n // Add child routes recursively\r\n if (route.children) {\r\n route.children.forEach(child => this.addRoute(child, fullPath));\r\n }\r\n }\r\n\r\n match(pathname: string): types.RouteMatch | null {\r\n const segments = pathname.split('/').filter(Boolean);\r\n const params: types.RouteParams = {};\r\n\r\n let node = this.root;\r\n let matchedRoute: types.Route | null = null;\r\n\r\n for (const segment of segments) {\r\n // Try exact match first\r\n if (node.children.has(segment)) {\r\n node = node.children.get(segment)!;\r\n }\r\n // Try param match\r\n else if (node.children.has(':param')) {\r\n const paramNode = node.children.get(':param')!;\r\n params[paramNode.paramName!] = decodeURIComponent(segment);\r\n node = paramNode;\r\n }\r\n // No exact match - try wildcard\r\n else {\r\n matchedRoute = this.wildcardRoute;\r\n break;\r\n }\r\n }\r\n\r\n matchedRoute = matchedRoute || node.route;\r\n\r\n if (!matchedRoute) {\r\n return null;\r\n }\r\n\r\n const url = new URL(window.location.href);\r\n\r\n return {\r\n path: pathname,\r\n params,\r\n query: url.searchParams,\r\n hash: url.hash.slice(1),\r\n route: matchedRoute\r\n };\r\n }\r\n }\r\n\r\n export class Router {\r\n private matcher = new RouteMatcher();\r\n private config : types.RouterConfig;\r\n\r\n // Reactive state\r\n public currentRoute = signal<types.RouteMatch | null>(null);\r\n public isNavigating = signal(false);\r\n public loaderData = signal<any>(null);\r\n public error = signal<types.NavigationError | null>(null);\r\n\r\n // History\r\n private history : types.RouteMatch[] = [];\r\n private historyIndex = 0;\r\n private maxHistory = 50; // Prevent memory leaks\r\n\r\n // Guards\r\n private beforeEachGuards: ((to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>)[] = [];\r\n private afterEachGuards : ((to: types.RouteMatch, from: types.RouteMatch | null) => void)[] = [];\r\n private onErrorHandlers: ((error: types.NavigationError) => void)[] = [];\r\n\r\n constructor(config: types.RouterConfig) {\r\n this.config = {\r\n mode : 'history',\r\n base : '',\r\n scrollBehavior : 'auto',\r\n ...config\r\n };\r\n\r\n // Add error handler\r\n if (config.onError) {\r\n this.onErrorHandlers.push(config.onError);\r\n }\r\n\r\n // Build route tree\r\n config.routes.forEach(route => this.matcher.addRoute(route));\r\n\r\n // Listen to browser navigation\r\n this.setupListeners();\r\n\r\n // Initial route - handle synchronously for basic setup\r\n this.performNavigation(window.location.pathname + window.location.search);\r\n }\r\n\r\n private emitError(error: types.NavigationError): void {\r\n this.error.set(error);\r\n this.onErrorHandlers.forEach(handler => handler(error));\r\n }\r\n\r\n private setupListeners(): void {\r\n if (this.config.mode === 'history') {\r\n window.addEventListener('popstate', () => {\r\n this.handleNavigation(window.location.pathname + window.location.search);\r\n });\r\n } else {\r\n window.addEventListener('hashchange', () => {\r\n const hash = window.location.hash.slice(1);\r\n this.handleNavigation(hash || '/');\r\n });\r\n }\r\n\r\n // Intercept link clicks\r\n document.addEventListener('click', (e) => {\r\n const target = (e.target as HTMLElement).closest('a');\r\n\r\n if (!target || !target.href) return;\r\n\r\n // Check if it's a same-origin link\r\n const url = new URL(target.href);\r\n if (url.origin !== window.location.origin) return;\r\n\r\n // Check if it should be handled by router\r\n if (target.hasAttribute('data-external')) return;\r\n if (target.getAttribute('target') === '_blank') return;\r\n if (e.ctrlKey || e.metaKey || e.shiftKey) return;\r\n\r\n e.preventDefault();\r\n this.push(url.pathname + url.search);\r\n });\r\n }\r\n\r\n private performNavigation(pathname: string, options: types.NavigateOptions = {}): void {\r\n try {\r\n // Extract path and query string\r\n const [pathOnly, queryString] = pathname.split('?');\r\n \r\n // Parse and filter query params\r\n const url = new URL('http://localhost' + pathOnly + (queryString ? '?' + queryString : ''));\r\n \r\n if (this.config.allowedQueryParams && this.config.allowedQueryParams.length > 0) {\r\n const keys = Array.from(url.searchParams.keys());\r\n keys.forEach(key => {\r\n const isAllowed = this.config.allowedQueryParams!.some(pattern => {\r\n if (typeof pattern === 'string') return pattern === key;\r\n return pattern.test(key);\r\n });\r\n \r\n if (!isAllowed) {\r\n url.searchParams.delete(key);\r\n }\r\n });\r\n }\r\n\r\n const finalQueryString = url.searchParams.toString();\r\n const finalPathname = pathOnly + (finalQueryString ? '?' + finalQueryString : '');\r\n\r\n const match = this.matcher.match(pathOnly);\r\n\r\n if (!match) {\r\n const error = new types.NavigationError('ROUTE_NOT_FOUND', `No route matched: ${pathOnly}`);\r\n this.emitError(error);\r\n return;\r\n }\r\n\r\n // Update browser history first (so window.location is correct for subsequent operations)\r\n if (this.config.mode === 'history') {\r\n if (options.replace) {\r\n window.history.replaceState(options.state || {}, '', finalPathname);\r\n } else {\r\n window.history.pushState(options.state || {}, '', finalPathname);\r\n }\r\n } else {\r\n window.location.hash = finalPathname;\r\n }\r\n\r\n match.query = url.searchParams;\r\n match.path = pathOnly;\r\n\r\n // Check guards synchronously (if they're not async)\r\n const canNavigate = this.checkSyncGuards(match, this.currentRoute());\r\n if (canNavigate === false) {\r\n // Revert history if navigation was prevented\r\n window.history.back();\r\n return;\r\n }\r\n\r\n // Clear previous error\r\n this.error.set(null);\r\n\r\n // Update current route immediately (synchronously)\r\n this.currentRoute.set(match);\r\n\r\n // Handle scroll\r\n this.handleScroll(options.scroll);\r\n\r\n // Update document title and meta tags\r\n this.updateMetaTags(match.route.meta);\r\n\r\n // Manage history size to prevent memory leaks\r\n this.pruneHistory();\r\n\r\n // Add to history\r\n this.history.push(match);\r\n this.historyIndex = this.history.length - 1;\r\n\r\n // Run async operations in background\r\n this.runAsyncNavigation(pathname, match, options);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Navigation failed: ' + String(err),\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private updateMetaTags(meta?: Record<string, any>): void {\r\n if (!meta) return;\r\n\r\n if (meta.title) {\r\n document.title = meta.title;\r\n }\r\n if (meta.description) {\r\n const descMeta = document.querySelector('meta[name=\"description\"]') as HTMLMetaElement | null;\r\n if (descMeta) {\r\n descMeta.content = meta.description;\r\n } else {\r\n const newMeta = document.createElement('meta');\r\n newMeta.name = 'description';\r\n newMeta.content = meta.description;\r\n document.head.appendChild(newMeta);\r\n }\r\n }\r\n }\r\n\r\n private pruneHistory(): void {\r\n if (this.history.length > this.maxHistory) {\r\n this.history = this.history.slice(-this.maxHistory);\r\n this.historyIndex = this.history.length - 1;\r\n }\r\n }\r\n\r\n private checkSyncGuards(to: types.RouteMatch, from: types.RouteMatch | null): boolean | undefined {\r\n // If no guards, return undefined (allow)\r\n if (this.beforeEachGuards.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // Check guards - if any are async, we'll check them in runAsyncNavigation\r\n for (const guard of this.beforeEachGuards) {\r\n const result = guard(to, from);\r\n // If we got a Promise, we can't handle it synchronously\r\n if (result instanceof Promise) {\r\n return undefined; // Let async handler deal with it\r\n }\r\n if (result === false) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private async runAsyncNavigation(pathname: string, match: types.RouteMatch, _options: types.NavigateOptions): Promise<void> {\r\n try {\r\n // Run beforeEach guards (including async ones)\r\n const canNavigate = await this.runBeforeEachGuards(match, match);\r\n if (!canNavigate) {\r\n // Revert - remove from current and history\r\n this.currentRoute.set(null);\r\n this.history.pop();\r\n this.historyIndex = Math.max(-1, this.history.length - 1);\r\n // Revert in browser\r\n window.history.back();\r\n return;\r\n }\r\n\r\n const previousRoute = match;\r\n\r\n // Set navigating state\r\n this.isNavigating.set(true);\r\n\r\n try {\r\n // Run loader if exists\r\n if (match.route.loader) {\r\n const context: types.RouteContext = {\r\n params: match.params,\r\n query: match.query,\r\n request: new Request(window.location.href),\r\n pathname\r\n };\r\n\r\n try {\r\n const data = await match.route.loader(context);\r\n this.loaderData.set(data);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'LOADER_ERROR',\r\n `Failed to load data for ${pathname}`,\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n throw error;\r\n }\r\n } else {\r\n this.loaderData.set(null);\r\n }\r\n\r\n // Run afterEach guards\r\n this.runAfterEachGuards(match, previousRoute);\r\n\r\n } finally {\r\n this.isNavigating.set(false);\r\n }\r\n } catch (err) {\r\n if (err instanceof types.NavigationError) {\r\n throw err;\r\n }\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Async navigation failed',\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private async handleNavigation(pathname: string, options: types.NavigateOptions = {}): Promise<void> {\r\n this.performNavigation(pathname, options);\r\n }\r\n\r\n private async runBeforeEachGuards(\r\n to: types.RouteMatch,\r\n from: types.RouteMatch | null\r\n ): Promise<boolean> {\r\n for (const guard of this.beforeEachGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) return false;\r\n }\r\n return true;\r\n }\r\n\r\n private runAfterEachGuards(to: types.RouteMatch, from: types.RouteMatch | null): void {\r\n this.afterEachGuards.forEach(guard => guard(to, from));\r\n }\r\n\r\n private handleScroll(behavior?: boolean | 'smooth'): void {\r\n if (behavior === false) return;\r\n\r\n const scrollBehavior = typeof behavior === 'string'\r\n ? behavior\r\n : this.config.scrollBehavior;\r\n\r\n if (typeof window !== 'undefined' && window.scrollTo) {\r\n window.scrollTo({\r\n top: 0,\r\n left: 0,\r\n behavior: scrollBehavior === 'smooth' ? 'smooth' : 'auto'\r\n });\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // PUBLIC API\r\n // ============================================================================\r\n\r\n /**\r\n * Navigate to a path\r\n */\r\n public push(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: false });\r\n }\r\n\r\n /**\r\n * Replace current route\r\n */\r\n public replace(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: true });\r\n }\r\n\r\n /**\r\n * Go back in history\r\n */\r\n public back(): void {\r\n window.history.back();\r\n }\r\n\r\n /**\r\n * Go forward in history\r\n */\r\n public forward(): void {\r\n window.history.forward();\r\n }\r\n\r\n /**\r\n * Go to specific history entry\r\n */\r\n public go(delta: number): void {\r\n window.history.go(delta);\r\n }\r\n\r\n /**\r\n * Check if path is active\r\n */\r\n public isActive(path: string, exact = false): boolean {\r\n const current = this.currentRoute();\r\n if (!current) return false;\r\n\r\n if (exact) {\r\n return current.path === path;\r\n }\r\n\r\n return current.path.startsWith(path);\r\n }\r\n\r\n /**\r\n * Get current params\r\n */\r\n public getParams(): types.RouteParams {\r\n return this.currentRoute()?.params || {};\r\n }\r\n\r\n /**\r\n * Get current query\r\n */\r\n public getQuery(): URLSearchParams {\r\n return this.currentRoute()?.query || new URLSearchParams();\r\n }\r\n\r\n /**\r\n * Register beforeEach guard\r\n */\r\n public beforeEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>\r\n ): () => void {\r\n this.beforeEachGuards.push(guard);\r\n return () => {\r\n const index = this.beforeEachGuards.indexOf(guard);\r\n if (index > -1) this.beforeEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register afterEach guard\r\n */\r\n public afterEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => void\r\n ): () => void {\r\n this.afterEachGuards.push(guard);\r\n return () => {\r\n const index = this.afterEachGuards.indexOf(guard);\r\n if (index > -1) this.afterEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register error handler\r\n */\r\n public onError(handler: (error: types.NavigationError) => void): () => void {\r\n this.onErrorHandlers.push(handler);\r\n return () => {\r\n const index = this.onErrorHandlers.indexOf(handler);\r\n if (index > -1) this.onErrorHandlers.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Add a query param to the whitelist\r\n */\r\n public addAllowedQueryParam(param: string | RegExp): void {\r\n if (!this.config.allowedQueryParams) {\r\n this.config.allowedQueryParams = [];\r\n }\r\n this.config.allowedQueryParams.push(param);\r\n }\r\n\r\n /**\r\n * Reload current route\r\n */\r\n public async reload(): Promise<void> {\r\n const current = this.currentRoute();\r\n if (current) {\r\n const queryString = current.query.toString();\r\n const pathWithQuery = current.path + (queryString ? '?' + queryString : '');\r\n await this.handleNavigation(pathWithQuery, { replace: true });\r\n }\r\n }\r\n\r\n /**\r\n * Destroy router and cleanup\r\n */\r\n public destroy(): void {\r\n this.history = [];\r\n this.beforeEachGuards = [];\r\n this.afterEachGuards = [];\r\n this.onErrorHandlers = [];\r\n this.currentRoute.set(null);\r\n this.loaderData.set(null);\r\n this.error.set(null);\r\n }\r\n }\r\n\r\n let globalRouter: Router | null = null;\r\n\r\n export function createRouter(config: types.RouterConfig): Router {\r\n globalRouter = new Router(config);\r\n return globalRouter;\r\n }\r\n\r\n export function useRouter(): Router {\r\n if (!globalRouter) {\r\n throw new Error('Router not initialized. Call createRouter() first.');\r\n }\r\n return globalRouter;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HOOK ════════════════════════════════════════╗\r\n\r\n export function useRoute(): Signal<types.RouteMatch | null> {\r\n return useRouter().currentRoute;\r\n }\r\n\r\n export function useParams(): types.RouteParams {\r\n return useRouter().getParams();\r\n }\r\n\r\n export function useQuery(): URLSearchParams {\r\n return useRouter().getQuery();\r\n }\r\n\r\n export function useLoaderData<T = any>(): Signal<T | null> {\r\n return useRouter().loaderData as Signal<T | null>;\r\n }\r\n\r\n export function useNavigate() {\r\n const router = useRouter();\r\n\r\n return {\r\n push: (path: string, options?: types.NavigateOptions) => router.push(path, options),\r\n replace: (path: string, options?: types.NavigateOptions) => router.replace(path, options),\r\n back: () => router.back(),\r\n forward: () => router.forward(),\r\n go: (delta: number) => router.go(delta)\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\r\n\r\n /**\r\n * Link component with active state\r\n */\r\n export function Link(props: {\r\n to : string\r\n children : any\r\n activeClass? : string\r\n exact? : boolean\r\n replace? : boolean\r\n className? : string\r\n [key: string] : any\r\n }) {\r\n const router = useRouter();\r\n const isActive = computed(() => router.isActive(props.to, props.exact));\r\n\r\n const className = computed(() => {\r\n let classes = props.className || '';\r\n if (isActive() && props.activeClass) {\r\n classes += ' ' + props.activeClass;\r\n }\r\n return classes.trim();\r\n });\r\n\r\n const handleClick = (e: Event) => {\r\n e.preventDefault();\r\n\r\n if (props.replace) {\r\n router.replace(props.to);\r\n } else {\r\n router.push(props.to);\r\n }\r\n };\r\n\r\n return jsx('a', {\r\n href : props.to,\r\n className : className(),\r\n onClick : handleClick,\r\n 'data-active' : isActive(),\r\n children : props.children\r\n });\r\n }\r\n\r\n /**\r\n * Router outlet - renders current route component with error boundary\r\n */\r\n export function RouterOutlet() {\r\n const router = useRouter();\r\n const route = router.currentRoute;\r\n const error = router.error;\r\n\r\n return computed(() => {\r\n const currentRoute = route();\r\n const currentError = error();\r\n\r\n // Show error component if error occurred\r\n if (currentError) {\r\n const errorComponent = currentRoute?.route.errorComponent || router.currentRoute()?.route.meta?.errorComponent;\r\n if (errorComponent) {\r\n return errorComponent();\r\n }\r\n // Fallback error display\r\n return jsx('div', {\r\n style: { color: 'red', padding: '20px' },\r\n children: `Navigation Error: ${currentError.message}`\r\n });\r\n }\r\n\r\n if (!currentRoute) {\r\n const notFoundComponent = (router.currentRoute() as any)?.config?.notFoundComponent;\r\n if (notFoundComponent) {\r\n return notFoundComponent();\r\n }\r\n return null;\r\n }\r\n\r\n // Load and render component\r\n const component = currentRoute.route.component();\r\n\r\n if (component instanceof Promise) {\r\n // Async component\r\n return jsx(Suspense, {\r\n fallback: jsx('div', { children: 'Loading...' }),\r\n children: component\r\n });\r\n }\r\n\r\n return component;\r\n });\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ UTIL ════════════════════════════════════════╗\r\n\r\n /**\r\n * Build URL with params\r\n */\r\n export function buildPath(path: string, params: types.RouteParams): string {\r\n let result = path;\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n result = result.replace(`:${key}`, encodeURIComponent(value));\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Parse query string to object\r\n */\r\n export function parseQuery(search: string): Record<string, string> {\r\n const params = new URLSearchParams(search);\r\n const result: Record<string, string> = {};\r\n\r\n params.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Stringify object to query string\r\n */\r\n export function stringifyQuery(obj: Record<string, any>): string {\r\n const params = new URLSearchParams();\r\n\r\n Object.entries(obj).forEach(([key, value]) => {\r\n if (value != null) {\r\n params.append(key, String(value));\r\n }\r\n });\r\n\r\n return params.toString();\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export default {\r\n createRouter,\r\n useRouter,\r\n useRoute,\r\n useParams,\r\n useQuery,\r\n useLoaderData,\r\n useNavigate,\r\n Link,\r\n RouterOutlet,\r\n buildPath,\r\n parseQuery,\r\n stringifyQuery,\r\n Router,\r\n NavigationError: types.NavigationError\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import * as types from '../types';\r\n import { signal, effect } from '@minejs/signals';\r\n import { mount as mountJSX } from '@minejs/jsx';\r\n import { EventsManager, WindowManager } from '@minejs/browser';\r\n import { Router, createRouter } from './router';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n let globalClientManagerInstance: ClientManager | undefined;\r\n\r\n export class ClientManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n private router : Router;\r\n private eventsManager : EventsManager;\r\n private windowManager : WindowManager;\r\n private lifecycle : 'booting' | 'ready' | 'destroying' | 'destroyed' = 'booting';\r\n private config : types.ClientManagerConfig;\r\n private hooks : types.ClientManagerHooks = {};\r\n private extensions : types.ClientExtension[] = [];\r\n private debug : boolean;\r\n private routeComponents : Record<string, types.RouteComponent> = {};\r\n private currentPathSignal = signal<string>(window.location.pathname ?? '/');\r\n\r\n constructor(config: types.ClientManagerConfig) {\r\n this.config = config;\r\n this.debug = config.debug ?? false;\r\n\r\n this.log('[INIT] Creating ClientManager');\r\n\r\n // Merge lifecycle hooks from config\r\n if (config.lifecycle) {\r\n this.hooks = { ...config.lifecycle };\r\n }\r\n\r\n // Store extensions from config\r\n this.extensions = config.extensions ?? [];\r\n\r\n // Store route components provided by user\r\n this.routeComponents = config.routes;\r\n\r\n // Initialize managers from @minejs/browser\r\n this.eventsManager = new EventsManager();\r\n this.windowManager = new WindowManager();\r\n\r\n // Initialize router with user-provided routes\r\n const routesArray = Object.entries(config.routes).map(([path, component]) => ({\r\n path,\r\n component\r\n }));\r\n\r\n this.router = createRouter({\r\n routes: routesArray,\r\n notFoundComponent: config.notFoundComponent,\r\n allowedQueryParams: config.allowedQueryParams\r\n });\r\n\r\n // Connect router changes to signal for automatic re-rendering\r\n this.router.afterEach((to) => {\r\n this.currentPathSignal.set(to.path);\r\n });\r\n\r\n // Store clientManager instance\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n globalClientManagerInstance = this;\r\n\r\n this.log('[INIT] ClientManager created');\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Setup lifecycle hooks OR bind events\r\n * Overloaded: on(event: 'onBoot'|'onReady'|'onDestroy', callback) - lifecycle\r\n * on(target, event, handler) - event binding\r\n */\r\n on(event: keyof types.ClientManagerHooks, callback: any): this;\r\n on<K extends keyof HTMLElementEventMap>(\r\n target: EventTarget,\r\n event: K | string,\r\n handler: EventListener,\r\n options?: AddEventListenerOptions\r\n ): () => void;\r\n on(\r\n eventOrTarget: keyof types.ClientManagerHooks | EventTarget,\r\n callbackOrEvent?: any,\r\n handler?: EventListener,\r\n options?: AddEventListenerOptions\r\n ): this | (() => void) {\r\n // Check if this is a lifecycle hook call\r\n if (typeof eventOrTarget === 'string' && eventOrTarget.startsWith('on')) {\r\n this.hooks[eventOrTarget as keyof types.ClientManagerHooks] = callbackOrEvent;\r\n return this;\r\n }\r\n\r\n // Otherwise it's an event binding\r\n return this.eventsManager.on(\r\n eventOrTarget as EventTarget,\r\n callbackOrEvent as string,\r\n handler as EventListener,\r\n options\r\n );\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Bootstrap the app - Phase 1: BOOT\r\n */\r\n async boot(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Already booted or destroyed');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: BOOT');\r\n\r\n try {\r\n // Call extensions onBoot hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onBoot) {\r\n this.log(`→ Extension onBoot: ${extension.name}`);\r\n await extension.onBoot({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onBoot hook\r\n if (this.hooks.onBoot) {\r\n this.log('→ Calling onBoot hook');\r\n await this.hooks.onBoot();\r\n }\r\n\r\n this.log('✓ BOOT phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Boot failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Ready the app - Phase 2: READY\r\n * Mount to DOM and make everything live\r\n *\r\n * Root selector is always 'body'.\r\n */\r\n async ready(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Cannot ready - not in booting phase');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: READY');\r\n\r\n try {\r\n const selector = 'body';\r\n\r\n // Set body id to 'root' for mounting\r\n (document.querySelector(selector) as HTMLElement).id = 'root';\r\n\r\n // Mount router\r\n this.mount(selector);\r\n\r\n this.log('→ Router mounted');\r\n\r\n // Call extensions onReady hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onReady) {\r\n this.log(`→ Extension onReady: ${extension.name}`);\r\n await extension.onReady({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onReady hook\r\n if (this.hooks.onReady) {\r\n this.log('→ Calling onReady hook');\r\n await this.hooks.onReady();\r\n }\r\n\r\n this.lifecycle = 'ready';\r\n this.log('✓ READY phase complete');\r\n this.log('✓ App is ready!');\r\n } catch (err) {\r\n console.error('[ClientManager] Ready failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown the app - Phase 3: DESTROY\r\n */\r\n async destroy(): Promise<void> {\r\n if (this.lifecycle === 'destroyed') {\r\n console.warn('[ClientManager] Already destroyed');\r\n return;\r\n }\r\n\r\n this.lifecycle = 'destroying';\r\n this.log('⚡ Phase: DESTROY');\r\n\r\n try {\r\n // Call extensions onDestroy hooks (in reverse order)\r\n for (let i = this.extensions.length - 1; i >= 0; i--) {\r\n const extension = this.extensions[i];\r\n if (extension.onDestroy) {\r\n this.log(`→ Extension onDestroy: ${extension.name}`);\r\n await extension.onDestroy({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onDestroy hook\r\n if (this.hooks.onDestroy) {\r\n this.log('→ Calling onDestroy hook');\r\n await this.hooks.onDestroy();\r\n }\r\n\r\n // Cleanup managers\r\n this.eventsManager.destroy();\r\n this.windowManager.destroy();\r\n\r\n this.lifecycle = 'destroyed';\r\n this.log('✓ DESTROY phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Destroy failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Navigate to path\r\n */\r\n navigate(path: string): void {\r\n this.router.push(path);\r\n }\r\n\r\n /**\r\n * Mount router to DOM element and setup reactive routing\r\n * Automatically re-renders when route changes\r\n * If rootLayout is provided, it wraps all pages\r\n */\r\n mount(selector: string | HTMLElement): void {\r\n const container = typeof selector === 'string'\r\n ? (document.querySelector(selector) as HTMLElement)\r\n : selector;\r\n\r\n if (!container) {\r\n console.warn('[ClientManager] Mount target not found:', selector);\r\n return;\r\n }\r\n\r\n let pageContainer = container;\r\n\r\n // If rootLayout is provided, mount it first (only once)\r\n if (this.config.rootLayout) {\r\n try {\r\n const layoutJsx = this.config.rootLayout();\r\n if (layoutJsx) {\r\n mountJSX(layoutJsx, container);\r\n this.log('→ Root layout mounted');\r\n\r\n // Find the page slot for rendering pages\r\n const pageSlot = container.querySelector('#main-overlay');\r\n if (pageSlot) {\r\n pageContainer = pageSlot as HTMLElement;\r\n } else {\r\n console.warn('[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.');\r\n }\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering root layout:', err);\r\n container.innerHTML = '<p>Error loading root layout</p>';\r\n return;\r\n }\r\n }\r\n\r\n // Setup reactive routing effect - re-renders when currentPathSignal changes\r\n effect(() => {\r\n const currentPath = this.currentPathSignal();\r\n const Component = this.routeComponents[currentPath]\r\n || this.config.notFoundComponent\r\n || null;\r\n\r\n // Clear only the page container (not the entire root if layout exists)\r\n pageContainer.innerHTML = '';\r\n\r\n if (Component) {\r\n try {\r\n const jsx = Component();\r\n // Use @minejs/jsx mount function to properly render JSX\r\n if (jsx) {\r\n mountJSX(jsx, pageContainer);\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering component:', currentPath, err);\r\n pageContainer.innerHTML = '<p>Error loading component</p>';\r\n }\r\n } else {\r\n pageContainer.innerHTML = '<p>No component found for this route</p>';\r\n }\r\n\r\n this.log(`→ Route changed to: ${currentPath}`);\r\n });\r\n\r\n // Trigger initial render by pushing the current path\r\n // this.router.push(this.currentPathSignal());\r\n this.log('→ Routing setup complete');\r\n }\r\n\r\n /**\r\n * Get current path signal for reactivity\r\n */\r\n getCurrentPath() {\r\n return this.currentPathSignal;\r\n }\r\n\r\n /**\r\n * Create navigation link handler\r\n */\r\n createLinkHandler(path: string) {\r\n return (e: MouseEvent) => {\r\n e.preventDefault();\r\n this.navigate(path);\r\n };\r\n }\r\n\r\n /**\r\n * Get underlying router for advanced usage\r\n */\r\n getRouter() {\r\n return this.router;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Unbind event\r\n */\r\n off(target: EventTarget, event: string, handler: EventListener): void {\r\n this.eventsManager.off(target, event, handler);\r\n }\r\n\r\n /**\r\n * Get events manager directly\r\n */\r\n getEventsManager(): EventsManager {\r\n return this.eventsManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get viewport info as reactive signal\r\n */\r\n getViewport() {\r\n return this.windowManager.getViewport();\r\n }\r\n\r\n /**\r\n * Get window manager directly\r\n */\r\n getWindowManager(): WindowManager {\r\n return this.windowManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get i18n instance for translations\r\n */\r\n getI18n() {\r\n return (window as any).__i18n;\r\n }\r\n\r\n /**\r\n * Get translation string\r\n */\r\n t(key: string, params?: any, defaultValue?: string) {\r\n if (!(window as any).__i18n) {\r\n console.warn('[ClientManager] i18n not initialized. Using default value or key.');\r\n return defaultValue ?? key;\r\n }\r\n return (window as any).__i18n.t(key, params) ?? defaultValue ?? key;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get lifecycle phase\r\n */\r\n getPhase() {\r\n return this.lifecycle;\r\n }\r\n\r\n /**\r\n * Check if ready\r\n */\r\n isReady(): boolean {\r\n return this.lifecycle === 'ready';\r\n }\r\n\r\n /**\r\n * Internal logging\r\n */\r\n private log(message: string): void {\r\n if (this.debug) {\r\n console.log(`[ClientManager] ${message}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n // Quick access\r\n export const CM = (): ClientManager | undefined => globalClientManagerInstance;\r\n\r\n // Router\r\n export const getRouter = () => CM()?.getRouter();\r\n export const back = () => getRouter()?.back();\r\n export const forward = () => getRouter()?.forward();\r\n export const push = (path: string) => getRouter()?.push(path);\r\n export const replace = (path: string) => getRouter()?.replace(path);\r\n\r\n // i18n\r\n export const getI18n = () => CM()?.getI18n();\r\n export const getLang = () => getI18n()?.getLanguage();\r\n export const setLang = (lang: string) => getI18n()?.setLanguage(lang);\r\n export const t = (key: string, params?: any, defaultValue?: string) => CM()?.t(key, params, defaultValue);\r\n export const tLang = (lang: string, key: string, params?: any, defaultValue?: string) => getI18n()?.tLang(lang, key, params, defaultValue) ?? (defaultValue ?? key);\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientManagerConfig } from './types';\r\n import { ClientManager } from './mod/manager';\r\n import { setupI18n } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n export * from './types';\r\n export * from './mod/manager';\r\n\r\n // Start\r\n export async function start(config: ClientManagerConfig): Promise<ClientManager> {\r\n // Read i18n config from HTML meta tag (injected by server)\r\n const metaI18n = document.querySelector('meta[name=\"app-i18n\"]');\r\n if (metaI18n) {\r\n const i18nData = JSON.parse(metaI18n.getAttribute('content') || '{}');\r\n config.i18n = i18nData;\r\n }\r\n\r\n // Create ClientManager instance\r\n const manager = new ClientManager(config);\r\n\r\n // Phase 0: Setup I18N\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (window as any).__i18n = await setupI18n(config.i18n || {\r\n defaultLanguage: 'en',\r\n supportedLanguages: ['en'],\r\n });\r\n\r\n // Phase 1: BOOT\r\n manager.boot();\r\n\r\n // Phase 2: READY\r\n manager.ready();\r\n\r\n // Handle cleanup on page unload\r\n window.addEventListener('beforeunload', async () => {\r\n await manager.destroy();\r\n });\r\n\r\n return manager;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/mod/router.ts","../src/mod/manager.ts","../src/index.ts"],"names":["NavigationError","code","message","cause","RouteNode","segment","route","children","paramName","isWildcard","RouteMatcher","parentPath","fullPath","segments","node","isParam","key","child","pathname","params","matchedRoute","paramNode","url","Router","config","signal","error","handler","hash","e","target","options","pathOnly","queryString","pattern","finalQueryString","finalPathname","match","err","meta","descMeta","newMeta","to","from","guard","result","_options","previousRoute","context","data","behavior","scrollBehavior","path","delta","exact","current","index","param","blank","pathWithQuery","globalRouter","createRouter","globalClientManagerInstance","ClientManager","EventsManager","WindowManager","routesArray","component","eventOrTarget","callbackOrEvent","extension","selector","i","container","pageContainer","layoutJsx","mountJSX","pageSlot","effect","currentPath","Component","jsx","event","defaultValue","CM","getRouter","back","forward","push","replace","visit","getI18n","getLang","setLang","lang","_setLang","_setDir","_setCookie","t","tLang","start","metaI18n","i18nData","manager","setupI18n"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/types.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n export type {\r\n RouteComponent,\r\n ThemeConfig,\r\n LangConfig,\r\n ClientExtension,\r\n ExtensionContext,\r\n ClientManagerHooks,\r\n ClientManagerConfig\r\n } from '@cruxjs/base';\r\n\r\n \r\n export type RouteParams = Record<string, string>;\r\n\r\n export interface RouteMatch {\r\n path: string\r\n params: RouteParams\r\n query: URLSearchParams\r\n hash: string\r\n route: Route\r\n }\r\n\r\n export interface RouteContext {\r\n params: RouteParams\r\n query: URLSearchParams\r\n request: Request\r\n pathname: string\r\n }\r\n\r\n export class NavigationError extends Error {\r\n constructor(\r\n public code: 'LOADER_ERROR' | 'ACTION_ERROR' | 'GUARD_ERROR' | 'ROUTE_NOT_FOUND',\r\n message: string,\r\n public cause?: Error\r\n ) {\r\n super(message);\r\n this.name = 'NavigationError';\r\n }\r\n }\r\n\r\n export type LoaderFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export type ActionFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export interface Route {\r\n path: string\r\n component: () => any | Promise<any>\r\n loader?: LoaderFunction\r\n action?: ActionFunction\r\n children?: Route[]\r\n meta?: {\r\n title?: string\r\n description?: string\r\n [key: string]: any\r\n }\r\n errorComponent?: () => any\r\n }\r\n\r\n export interface NavigateOptions {\r\n replace?: boolean\r\n state?: any\r\n scroll?: boolean | 'smooth'\r\n }\r\n\r\n export interface RouterConfig {\r\n routes: Route[]\r\n base?: string\r\n mode?: 'history' | 'hash'\r\n scrollBehavior?: 'auto' | 'smooth' | 'instant'\r\n allowedQueryParams?: (string | RegExp)[]\r\n notFoundComponent?: () => any\r\n errorComponent?: () => any\r\n onError?: (error: NavigationError) => void\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/router.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { signal, computed, type Signal } from '@minejs/signals';\r\n import { jsx, Suspense } from '@minejs/jsx';\r\n import * as types from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n class RouteNode {\r\n constructor(\r\n public segment: string,\r\n public route: types.Route | null = null,\r\n public children: Map<string, RouteNode> = new Map(),\r\n public paramName?: string,\r\n public isWildcard = false\r\n ) { }\r\n }\r\n\r\n class RouteMatcher {\r\n private root = new RouteNode('');\r\n private wildcardRoute: types.Route | null = null;\r\n\r\n addRoute(route: types.Route, parentPath = ''): void {\r\n const fullPath = parentPath + route.path;\r\n\r\n // Handle wildcard routes\r\n if (fullPath === '/*' || fullPath === '*') {\r\n this.wildcardRoute = route;\r\n return;\r\n }\r\n\r\n const segments = fullPath.split('/').filter(Boolean);\r\n let node = this.root;\r\n\r\n for (const segment of segments) {\r\n const isParam = segment.startsWith(':');\r\n const key = isParam ? ':param' : segment;\r\n\r\n if (!node.children.has(key)) {\r\n node.children.set(key, new RouteNode(\r\n segment,\r\n null,\r\n new Map(),\r\n isParam ? segment.slice(1) : undefined\r\n ));\r\n }\r\n\r\n node = node.children.get(key)!;\r\n }\r\n\r\n node.route = route;\r\n\r\n // Add child routes recursively\r\n if (route.children) {\r\n route.children.forEach(child => this.addRoute(child, fullPath));\r\n }\r\n }\r\n\r\n match(pathname: string): types.RouteMatch | null {\r\n const segments = pathname.split('/').filter(Boolean);\r\n const params: types.RouteParams = {};\r\n\r\n let node = this.root;\r\n let matchedRoute: types.Route | null = null;\r\n\r\n for (const segment of segments) {\r\n // Try exact match first\r\n if (node.children.has(segment)) {\r\n node = node.children.get(segment)!;\r\n }\r\n // Try param match\r\n else if (node.children.has(':param')) {\r\n const paramNode = node.children.get(':param')!;\r\n params[paramNode.paramName!] = decodeURIComponent(segment);\r\n node = paramNode;\r\n }\r\n // No exact match - try wildcard\r\n else {\r\n matchedRoute = this.wildcardRoute;\r\n break;\r\n }\r\n }\r\n\r\n matchedRoute = matchedRoute || node.route;\r\n\r\n if (!matchedRoute) {\r\n return null;\r\n }\r\n\r\n const url = new URL(window.location.href);\r\n\r\n return {\r\n path: pathname,\r\n params,\r\n query: url.searchParams,\r\n hash: url.hash.slice(1),\r\n route: matchedRoute\r\n };\r\n }\r\n }\r\n\r\n export class Router {\r\n private matcher = new RouteMatcher();\r\n private config : types.RouterConfig;\r\n\r\n // Reactive state\r\n public currentRoute = signal<types.RouteMatch | null>(null);\r\n public isNavigating = signal(false);\r\n public loaderData = signal<any>(null);\r\n public error = signal<types.NavigationError | null>(null);\r\n\r\n // History\r\n private history : types.RouteMatch[] = [];\r\n private historyIndex = 0;\r\n private maxHistory = 50; // Prevent memory leaks\r\n\r\n // Guards\r\n private beforeEachGuards: ((to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>)[] = [];\r\n private afterEachGuards : ((to: types.RouteMatch, from: types.RouteMatch | null) => void)[] = [];\r\n private onErrorHandlers: ((error: types.NavigationError) => void)[] = [];\r\n\r\n constructor(config: types.RouterConfig) {\r\n this.config = {\r\n mode : 'history',\r\n base : '',\r\n scrollBehavior : 'auto',\r\n ...config\r\n };\r\n\r\n // Add error handler\r\n if (config.onError) {\r\n this.onErrorHandlers.push(config.onError);\r\n }\r\n\r\n // Build route tree\r\n config.routes.forEach(route => this.matcher.addRoute(route));\r\n\r\n // Listen to browser navigation\r\n this.setupListeners();\r\n\r\n // Initial route - handle synchronously for basic setup\r\n this.performNavigation(window.location.pathname + window.location.search);\r\n }\r\n\r\n private emitError(error: types.NavigationError): void {\r\n this.error.set(error);\r\n this.onErrorHandlers.forEach(handler => handler(error));\r\n }\r\n\r\n private setupListeners(): void {\r\n if (this.config.mode === 'history') {\r\n window.addEventListener('popstate', () => {\r\n this.handleNavigation(window.location.pathname + window.location.search);\r\n });\r\n } else {\r\n window.addEventListener('hashchange', () => {\r\n const hash = window.location.hash.slice(1);\r\n this.handleNavigation(hash || '/');\r\n });\r\n }\r\n\r\n // Intercept link clicks\r\n document.addEventListener('click', (e) => {\r\n const target = (e.target as HTMLElement).closest('a');\r\n\r\n if (!target || !target.href) return;\r\n\r\n // Check if it's a same-origin link\r\n const url = new URL(target.href);\r\n if (url.origin !== window.location.origin) return;\r\n\r\n // Check if it should be handled by router\r\n if (target.hasAttribute('data-external')) return;\r\n if (target.getAttribute('target') === '_blank') return;\r\n if (e.ctrlKey || e.metaKey || e.shiftKey) return;\r\n\r\n e.preventDefault();\r\n this.push(url.pathname + url.search);\r\n });\r\n }\r\n\r\n private performNavigation(pathname: string, options: types.NavigateOptions = {}): void {\r\n try {\r\n // Extract path and query string\r\n const [pathOnly, queryString] = pathname.split('?');\r\n \r\n // Parse and filter query params\r\n const url = new URL('http://localhost' + pathOnly + (queryString ? '?' + queryString : ''));\r\n \r\n if (this.config.allowedQueryParams && this.config.allowedQueryParams.length > 0) {\r\n const keys = Array.from(url.searchParams.keys());\r\n keys.forEach(key => {\r\n const isAllowed = this.config.allowedQueryParams!.some(pattern => {\r\n if (typeof pattern === 'string') return pattern === key;\r\n return pattern.test(key);\r\n });\r\n \r\n if (!isAllowed) {\r\n url.searchParams.delete(key);\r\n }\r\n });\r\n }\r\n\r\n const finalQueryString = url.searchParams.toString();\r\n const finalPathname = pathOnly + (finalQueryString ? '?' + finalQueryString : '');\r\n\r\n const match = this.matcher.match(pathOnly);\r\n\r\n if (!match) {\r\n const error = new types.NavigationError('ROUTE_NOT_FOUND', `No route matched: ${pathOnly}`);\r\n this.emitError(error);\r\n return;\r\n }\r\n\r\n // Update browser history first (so window.location is correct for subsequent operations)\r\n if (this.config.mode === 'history') {\r\n if (options.replace) {\r\n window.history.replaceState(options.state || {}, '', finalPathname);\r\n } else {\r\n window.history.pushState(options.state || {}, '', finalPathname);\r\n }\r\n } else {\r\n window.location.hash = finalPathname;\r\n }\r\n\r\n match.query = url.searchParams;\r\n match.path = pathOnly;\r\n\r\n // Check guards synchronously (if they're not async)\r\n const canNavigate = this.checkSyncGuards(match, this.currentRoute());\r\n if (canNavigate === false) {\r\n // Revert history if navigation was prevented\r\n window.history.back();\r\n return;\r\n }\r\n\r\n // Clear previous error\r\n this.error.set(null);\r\n\r\n // Update current route immediately (synchronously)\r\n this.currentRoute.set(match);\r\n\r\n // Handle scroll\r\n this.handleScroll(options.scroll);\r\n\r\n // Update document title and meta tags\r\n this.updateMetaTags(match.route.meta);\r\n\r\n // Manage history size to prevent memory leaks\r\n this.pruneHistory();\r\n\r\n // Add to history\r\n this.history.push(match);\r\n this.historyIndex = this.history.length - 1;\r\n\r\n // Run async operations in background\r\n this.runAsyncNavigation(pathname, match, options);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Navigation failed: ' + String(err),\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private updateMetaTags(meta?: Record<string, any>): void {\r\n if (!meta) return;\r\n\r\n if (meta.title) {\r\n document.title = meta.title;\r\n }\r\n if (meta.description) {\r\n const descMeta = document.querySelector('meta[name=\"description\"]') as HTMLMetaElement | null;\r\n if (descMeta) {\r\n descMeta.content = meta.description;\r\n } else {\r\n const newMeta = document.createElement('meta');\r\n newMeta.name = 'description';\r\n newMeta.content = meta.description;\r\n document.head.appendChild(newMeta);\r\n }\r\n }\r\n }\r\n\r\n private pruneHistory(): void {\r\n if (this.history.length > this.maxHistory) {\r\n this.history = this.history.slice(-this.maxHistory);\r\n this.historyIndex = this.history.length - 1;\r\n }\r\n }\r\n\r\n private checkSyncGuards(to: types.RouteMatch, from: types.RouteMatch | null): boolean | undefined {\r\n // If no guards, return undefined (allow)\r\n if (this.beforeEachGuards.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // Check guards - if any are async, we'll check them in runAsyncNavigation\r\n for (const guard of this.beforeEachGuards) {\r\n const result = guard(to, from);\r\n // If we got a Promise, we can't handle it synchronously\r\n if (result instanceof Promise) {\r\n return undefined; // Let async handler deal with it\r\n }\r\n if (result === false) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private async runAsyncNavigation(pathname: string, match: types.RouteMatch, _options: types.NavigateOptions): Promise<void> {\r\n try {\r\n // Run beforeEach guards (including async ones)\r\n const canNavigate = await this.runBeforeEachGuards(match, match);\r\n if (!canNavigate) {\r\n // Revert - remove from current and history\r\n this.currentRoute.set(null);\r\n this.history.pop();\r\n this.historyIndex = Math.max(-1, this.history.length - 1);\r\n // Revert in browser\r\n window.history.back();\r\n return;\r\n }\r\n\r\n const previousRoute = match;\r\n\r\n // Set navigating state\r\n this.isNavigating.set(true);\r\n\r\n try {\r\n // Run loader if exists\r\n if (match.route.loader) {\r\n const context: types.RouteContext = {\r\n params: match.params,\r\n query: match.query,\r\n request: new Request(window.location.href),\r\n pathname\r\n };\r\n\r\n try {\r\n const data = await match.route.loader(context);\r\n this.loaderData.set(data);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'LOADER_ERROR',\r\n `Failed to load data for ${pathname}`,\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n throw error;\r\n }\r\n } else {\r\n this.loaderData.set(null);\r\n }\r\n\r\n // Run afterEach guards\r\n this.runAfterEachGuards(match, previousRoute);\r\n\r\n } finally {\r\n this.isNavigating.set(false);\r\n }\r\n } catch (err) {\r\n if (err instanceof types.NavigationError) {\r\n throw err;\r\n }\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Async navigation failed',\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private async handleNavigation(pathname: string, options: types.NavigateOptions = {}): Promise<void> {\r\n this.performNavigation(pathname, options);\r\n }\r\n\r\n private async runBeforeEachGuards(\r\n to: types.RouteMatch,\r\n from: types.RouteMatch | null\r\n ): Promise<boolean> {\r\n for (const guard of this.beforeEachGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) return false;\r\n }\r\n return true;\r\n }\r\n\r\n private runAfterEachGuards(to: types.RouteMatch, from: types.RouteMatch | null): void {\r\n this.afterEachGuards.forEach(guard => guard(to, from));\r\n }\r\n\r\n private handleScroll(behavior?: boolean | 'smooth'): void {\r\n if (behavior === false) return;\r\n\r\n const scrollBehavior = typeof behavior === 'string'\r\n ? behavior\r\n : this.config.scrollBehavior;\r\n\r\n if (typeof window !== 'undefined' && window.scrollTo) {\r\n window.scrollTo({\r\n top: 0,\r\n left: 0,\r\n behavior: scrollBehavior === 'smooth' ? 'smooth' : 'auto'\r\n });\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // PUBLIC API\r\n // ============================================================================\r\n\r\n /**\r\n * Navigate to a path\r\n */\r\n public push(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: false });\r\n }\r\n\r\n /**\r\n * Replace current route\r\n */\r\n public replace(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: true });\r\n }\r\n\r\n /**\r\n * Go back in history\r\n */\r\n public back(): void {\r\n window.history.back();\r\n }\r\n\r\n /**\r\n * Go forward in history\r\n */\r\n public forward(): void {\r\n window.history.forward();\r\n }\r\n\r\n /**\r\n * Go to specific history entry\r\n */\r\n public go(delta: number): void {\r\n window.history.go(delta);\r\n }\r\n\r\n /**\r\n * Check if path is active\r\n */\r\n public isActive(path: string, exact = false): boolean {\r\n const current = this.currentRoute();\r\n if (!current) return false;\r\n\r\n if (exact) {\r\n return current.path === path;\r\n }\r\n\r\n return current.path.startsWith(path);\r\n }\r\n\r\n /**\r\n * Get current params\r\n */\r\n public getParams(): types.RouteParams {\r\n return this.currentRoute()?.params || {};\r\n }\r\n\r\n /**\r\n * Get current query\r\n */\r\n public getQuery(): URLSearchParams {\r\n return this.currentRoute()?.query || new URLSearchParams();\r\n }\r\n\r\n /**\r\n * Register beforeEach guard\r\n */\r\n public beforeEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>\r\n ): () => void {\r\n this.beforeEachGuards.push(guard);\r\n return () => {\r\n const index = this.beforeEachGuards.indexOf(guard);\r\n if (index > -1) this.beforeEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register afterEach guard\r\n */\r\n public afterEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => void\r\n ): () => void {\r\n this.afterEachGuards.push(guard);\r\n return () => {\r\n const index = this.afterEachGuards.indexOf(guard);\r\n if (index > -1) this.afterEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register error handler\r\n */\r\n public onError(handler: (error: types.NavigationError) => void): () => void {\r\n this.onErrorHandlers.push(handler);\r\n return () => {\r\n const index = this.onErrorHandlers.indexOf(handler);\r\n if (index > -1) this.onErrorHandlers.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Add a query param to the whitelist\r\n */\r\n public addAllowedQueryParam(param: string | RegExp): void {\r\n if (!this.config.allowedQueryParams) {\r\n this.config.allowedQueryParams = [];\r\n }\r\n this.config.allowedQueryParams.push(param);\r\n }\r\n\r\n /**\r\n * Visit an external link\r\n */\r\n public visit(url: string, blank?: boolean): void {\r\n if (blank ?? true) {\r\n window.open(url, '_blank');\r\n } else {\r\n window.location.href = url;\r\n }\r\n }\r\n\r\n /**\r\n * Reload current route\r\n */\r\n public async reload(): Promise<void> {\r\n const current = this.currentRoute();\r\n if (current) {\r\n const queryString = current.query.toString();\r\n const pathWithQuery = current.path + (queryString ? '?' + queryString : '');\r\n await this.handleNavigation(pathWithQuery, { replace: true });\r\n }\r\n }\r\n\r\n /**\r\n * Destroy router and cleanup\r\n */\r\n public destroy(): void {\r\n this.history = [];\r\n this.beforeEachGuards = [];\r\n this.afterEachGuards = [];\r\n this.onErrorHandlers = [];\r\n this.currentRoute.set(null);\r\n this.loaderData.set(null);\r\n this.error.set(null);\r\n }\r\n }\r\n\r\n let globalRouter: Router | null = null;\r\n\r\n export function createRouter(config: types.RouterConfig): Router {\r\n globalRouter = new Router(config);\r\n return globalRouter;\r\n }\r\n\r\n export function useRouter(): Router {\r\n if (!globalRouter) {\r\n throw new Error('Router not initialized. Call createRouter() first.');\r\n }\r\n return globalRouter;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HOOK ════════════════════════════════════════╗\r\n\r\n export function useRoute(): Signal<types.RouteMatch | null> {\r\n return useRouter().currentRoute;\r\n }\r\n\r\n export function useParams(): types.RouteParams {\r\n return useRouter().getParams();\r\n }\r\n\r\n export function useQuery(): URLSearchParams {\r\n return useRouter().getQuery();\r\n }\r\n\r\n export function useLoaderData<T = any>(): Signal<T | null> {\r\n return useRouter().loaderData as Signal<T | null>;\r\n }\r\n\r\n export function useNavigate() {\r\n const router = useRouter();\r\n\r\n return {\r\n push: (path: string, options?: types.NavigateOptions) => router.push(path, options),\r\n replace: (path: string, options?: types.NavigateOptions) => router.replace(path, options),\r\n back: () => router.back(),\r\n forward: () => router.forward(),\r\n go: (delta: number) => router.go(delta),\r\n visit: (url: string, blank?: boolean) => router.visit(url, blank)\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\r\n\r\n /**\r\n * Link component with active state\r\n */\r\n export function Link(props: {\r\n to : string\r\n children : any\r\n activeClass? : string\r\n exact? : boolean\r\n replace? : boolean\r\n className? : string\r\n [key: string] : any\r\n }) {\r\n const router = useRouter();\r\n const isActive = computed(() => router.isActive(props.to, props.exact));\r\n\r\n const className = computed(() => {\r\n let classes = props.className || '';\r\n if (isActive() && props.activeClass) {\r\n classes += ' ' + props.activeClass;\r\n }\r\n return classes.trim();\r\n });\r\n\r\n const handleClick = (e: Event) => {\r\n e.preventDefault();\r\n\r\n if (props.replace) {\r\n router.replace(props.to);\r\n } else {\r\n router.push(props.to);\r\n }\r\n };\r\n\r\n return jsx('a', {\r\n href : props.to,\r\n className : className(),\r\n onClick : handleClick,\r\n 'data-active' : isActive(),\r\n children : props.children\r\n });\r\n }\r\n\r\n /**\r\n * Router outlet - renders current route component with error boundary\r\n */\r\n export function RouterOutlet() {\r\n const router = useRouter();\r\n const route = router.currentRoute;\r\n const error = router.error;\r\n\r\n return computed(() => {\r\n const currentRoute = route();\r\n const currentError = error();\r\n\r\n // Show error component if error occurred\r\n if (currentError) {\r\n const errorComponent = currentRoute?.route.errorComponent || router.currentRoute()?.route.meta?.errorComponent;\r\n if (errorComponent) {\r\n return errorComponent();\r\n }\r\n // Fallback error display\r\n return jsx('div', {\r\n style: { color: 'red', padding: '20px' },\r\n children: `Navigation Error: ${currentError.message}`\r\n });\r\n }\r\n\r\n if (!currentRoute) {\r\n const notFoundComponent = (router.currentRoute() as any)?.config?.notFoundComponent;\r\n if (notFoundComponent) {\r\n return notFoundComponent();\r\n }\r\n return null;\r\n }\r\n\r\n // Load and render component\r\n const component = currentRoute.route.component();\r\n\r\n if (component instanceof Promise) {\r\n // Async component\r\n return jsx(Suspense, {\r\n fallback: jsx('div', { children: 'Loading...' }),\r\n children: component\r\n });\r\n }\r\n\r\n return component;\r\n });\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ UTIL ════════════════════════════════════════╗\r\n\r\n /**\r\n * Build URL with params\r\n */\r\n export function buildPath(path: string, params: types.RouteParams): string {\r\n let result = path;\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n result = result.replace(`:${key}`, encodeURIComponent(value));\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Parse query string to object\r\n */\r\n export function parseQuery(search: string): Record<string, string> {\r\n const params = new URLSearchParams(search);\r\n const result: Record<string, string> = {};\r\n\r\n params.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Stringify object to query string\r\n */\r\n export function stringifyQuery(obj: Record<string, any>): string {\r\n const params = new URLSearchParams();\r\n\r\n Object.entries(obj).forEach(([key, value]) => {\r\n if (value != null) {\r\n params.append(key, String(value));\r\n }\r\n });\r\n\r\n return params.toString();\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export default {\r\n createRouter,\r\n useRouter,\r\n useRoute,\r\n useParams,\r\n useQuery,\r\n useLoaderData,\r\n useNavigate,\r\n Link,\r\n RouterOutlet,\r\n buildPath,\r\n parseQuery,\r\n stringifyQuery,\r\n Router,\r\n NavigationError: types.NavigationError\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import * as types from '../types';\r\n import { signal, effect } from '@minejs/signals';\r\n import { mount as mountJSX } from '@minejs/jsx';\r\n import { EventsManager, WindowManager } from '@minejs/browser';\r\n import { Router, createRouter } from './router';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n let globalClientManagerInstance: ClientManager | undefined;\r\n\r\n export class ClientManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n private router : Router;\r\n private eventsManager : EventsManager;\r\n private windowManager : WindowManager;\r\n private lifecycle : 'booting' | 'ready' | 'destroying' | 'destroyed' = 'booting';\r\n private config : types.ClientManagerConfig;\r\n private hooks : types.ClientManagerHooks = {};\r\n private extensions : types.ClientExtension[] = [];\r\n private debug : boolean;\r\n private routeComponents : Record<string, types.RouteComponent> = {};\r\n private currentPathSignal = signal<string>(window.location.pathname ?? '/');\r\n\r\n constructor(config: types.ClientManagerConfig) {\r\n this.config = config;\r\n this.debug = config.debug ?? false;\r\n\r\n this.log('[INIT] Creating ClientManager');\r\n\r\n // Merge lifecycle hooks from config\r\n if (config.lifecycle) {\r\n this.hooks = { ...config.lifecycle };\r\n }\r\n\r\n // Store extensions from config\r\n this.extensions = config.extensions ?? [];\r\n\r\n // Store route components provided by user\r\n this.routeComponents = config.routes;\r\n\r\n // Initialize managers from @minejs/browser\r\n this.eventsManager = new EventsManager();\r\n this.windowManager = new WindowManager();\r\n\r\n // Initialize router with user-provided routes\r\n const routesArray = Object.entries(config.routes).map(([path, component]) => ({\r\n path,\r\n component\r\n }));\r\n\r\n this.router = createRouter({\r\n routes: routesArray,\r\n notFoundComponent: config.notFoundComponent,\r\n allowedQueryParams: config.allowedQueryParams\r\n });\r\n\r\n // Connect router changes to signal for automatic re-rendering\r\n this.router.afterEach((to) => {\r\n this.currentPathSignal.set(to.path);\r\n });\r\n\r\n // Store clientManager instance\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n globalClientManagerInstance = this;\r\n\r\n this.log('[INIT] ClientManager created');\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Setup lifecycle hooks OR bind events\r\n * Overloaded: on(event: 'onBoot'|'onReady'|'onDestroy', callback) - lifecycle\r\n * on(target, event, handler) - event binding\r\n */\r\n on(event: keyof types.ClientManagerHooks, callback: any): this;\r\n on<K extends keyof HTMLElementEventMap>(\r\n target: EventTarget,\r\n event: K | string,\r\n handler: EventListener,\r\n options?: AddEventListenerOptions\r\n ): () => void;\r\n on(\r\n eventOrTarget: keyof types.ClientManagerHooks | EventTarget,\r\n callbackOrEvent?: any,\r\n handler?: EventListener,\r\n options?: AddEventListenerOptions\r\n ): this | (() => void) {\r\n // Check if this is a lifecycle hook call\r\n if (typeof eventOrTarget === 'string' && eventOrTarget.startsWith('on')) {\r\n this.hooks[eventOrTarget as keyof types.ClientManagerHooks] = callbackOrEvent;\r\n return this;\r\n }\r\n\r\n // Otherwise it's an event binding\r\n return this.eventsManager.on(\r\n eventOrTarget as EventTarget,\r\n callbackOrEvent as string,\r\n handler as EventListener,\r\n options\r\n );\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Bootstrap the app - Phase 1: BOOT\r\n */\r\n async boot(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Already booted or destroyed');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: BOOT');\r\n\r\n try {\r\n // Call extensions onBoot hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onBoot) {\r\n this.log(`→ Extension onBoot: ${extension.name}`);\r\n await extension.onBoot({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onBoot hook\r\n if (this.hooks.onBoot) {\r\n this.log('→ Calling onBoot hook');\r\n await this.hooks.onBoot();\r\n }\r\n\r\n this.log('✓ BOOT phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Boot failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Ready the app - Phase 2: READY\r\n * Mount to DOM and make everything live\r\n *\r\n * Root selector is always 'body'.\r\n */\r\n async ready(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Cannot ready - not in booting phase');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: READY');\r\n\r\n try {\r\n const selector = 'body';\r\n\r\n // Set body id to 'root' for mounting\r\n (document.querySelector(selector) as HTMLElement).id = 'root';\r\n\r\n // Mount router\r\n this.mount(selector);\r\n\r\n this.log('→ Router mounted');\r\n\r\n // Call extensions onReady hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onReady) {\r\n this.log(`→ Extension onReady: ${extension.name}`);\r\n await extension.onReady({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onReady hook\r\n if (this.hooks.onReady) {\r\n this.log('→ Calling onReady hook');\r\n await this.hooks.onReady();\r\n }\r\n\r\n this.lifecycle = 'ready';\r\n this.log('✓ READY phase complete');\r\n this.log('✓ App is ready!');\r\n } catch (err) {\r\n console.error('[ClientManager] Ready failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown the app - Phase 3: DESTROY\r\n */\r\n async destroy(): Promise<void> {\r\n if (this.lifecycle === 'destroyed') {\r\n console.warn('[ClientManager] Already destroyed');\r\n return;\r\n }\r\n\r\n this.lifecycle = 'destroying';\r\n this.log('⚡ Phase: DESTROY');\r\n\r\n try {\r\n // Call extensions onDestroy hooks (in reverse order)\r\n for (let i = this.extensions.length - 1; i >= 0; i--) {\r\n const extension = this.extensions[i];\r\n if (extension.onDestroy) {\r\n this.log(`→ Extension onDestroy: ${extension.name}`);\r\n await extension.onDestroy({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onDestroy hook\r\n if (this.hooks.onDestroy) {\r\n this.log('→ Calling onDestroy hook');\r\n await this.hooks.onDestroy();\r\n }\r\n\r\n // Cleanup managers\r\n this.eventsManager.destroy();\r\n this.windowManager.destroy();\r\n\r\n this.lifecycle = 'destroyed';\r\n this.log('✓ DESTROY phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Destroy failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Navigate to path\r\n */\r\n navigate(path: string): void {\r\n this.router.push(path);\r\n }\r\n\r\n /**\r\n * Mount router to DOM element and setup reactive routing\r\n * Automatically re-renders when route changes\r\n * If rootLayout is provided, it wraps all pages\r\n */\r\n mount(selector: string | HTMLElement): void {\r\n const container = typeof selector === 'string'\r\n ? (document.querySelector(selector) as HTMLElement)\r\n : selector;\r\n\r\n if (!container) {\r\n console.warn('[ClientManager] Mount target not found:', selector);\r\n return;\r\n }\r\n\r\n let pageContainer = container;\r\n\r\n // If rootLayout is provided, mount it first (only once)\r\n if (this.config.rootLayout) {\r\n try {\r\n const layoutJsx = this.config.rootLayout();\r\n if (layoutJsx) {\r\n mountJSX(layoutJsx, container);\r\n this.log('→ Root layout mounted');\r\n\r\n // Find the page slot for rendering pages\r\n const pageSlot = container.querySelector('#main-overlay');\r\n if (pageSlot) {\r\n pageContainer = pageSlot as HTMLElement;\r\n } else {\r\n console.warn('[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.');\r\n }\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering root layout:', err);\r\n container.innerHTML = '<p>Error loading root layout</p>';\r\n return;\r\n }\r\n }\r\n\r\n // Setup reactive routing effect - re-renders when currentPathSignal changes\r\n effect(() => {\r\n const currentPath = this.currentPathSignal();\r\n const Component = this.routeComponents[currentPath]\r\n || this.config.notFoundComponent\r\n || null;\r\n\r\n // Clear only the page container (not the entire root if layout exists)\r\n pageContainer.innerHTML = '';\r\n\r\n if (Component) {\r\n try {\r\n const jsx = Component();\r\n // Use @minejs/jsx mount function to properly render JSX\r\n if (jsx) {\r\n mountJSX(jsx, pageContainer);\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering component:', currentPath, err);\r\n pageContainer.innerHTML = '<p>Error loading component</p>';\r\n }\r\n } else {\r\n pageContainer.innerHTML = '<p>No component found for this route</p>';\r\n }\r\n\r\n this.log(`→ Route changed to: ${currentPath}`);\r\n });\r\n\r\n // Trigger initial render by pushing the current path\r\n // this.router.push(this.currentPathSignal());\r\n this.log('→ Routing setup complete');\r\n }\r\n\r\n /**\r\n * Get current path signal for reactivity\r\n */\r\n getCurrentPath() {\r\n return this.currentPathSignal;\r\n }\r\n\r\n /**\r\n * Create navigation link handler\r\n */\r\n createLinkHandler(path: string) {\r\n return (e: MouseEvent) => {\r\n e.preventDefault();\r\n this.navigate(path);\r\n };\r\n }\r\n\r\n /**\r\n * Get underlying router for advanced usage\r\n */\r\n getRouter() {\r\n return this.router;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Unbind event\r\n */\r\n off(target: EventTarget, event: string, handler: EventListener): void {\r\n this.eventsManager.off(target, event, handler);\r\n }\r\n\r\n /**\r\n * Get events manager directly\r\n */\r\n getEventsManager(): EventsManager {\r\n return this.eventsManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get viewport info as reactive signal\r\n */\r\n getViewport() {\r\n return this.windowManager.getViewport();\r\n }\r\n\r\n /**\r\n * Get window manager directly\r\n */\r\n getWindowManager(): WindowManager {\r\n return this.windowManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get i18n instance for translations\r\n */\r\n getI18n() {\r\n return (window as any).__i18n;\r\n }\r\n\r\n /**\r\n * Get translation string\r\n */\r\n t(key: string, params?: any, defaultValue?: string) {\r\n if (!(window as any).__i18n) {\r\n console.warn('[ClientManager] i18n not initialized. Using default value or key.');\r\n return defaultValue ?? key;\r\n }\r\n return (window as any).__i18n.t(key, params) ?? defaultValue ?? key;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get lifecycle phase\r\n */\r\n getPhase() {\r\n return this.lifecycle;\r\n }\r\n\r\n /**\r\n * Check if ready\r\n */\r\n isReady(): boolean {\r\n return this.lifecycle === 'ready';\r\n }\r\n\r\n /**\r\n * Internal logging\r\n */\r\n private log(message: string): void {\r\n if (this.debug) {\r\n console.log(`[ClientManager] ${message}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n // Quick access\r\n export const CM = (): ClientManager | undefined => globalClientManagerInstance;\r\n\r\n // Router\r\n export const getRouter = () => CM()?.getRouter();\r\n export const back = () => getRouter()?.back();\r\n export const forward = () => getRouter()?.forward();\r\n export const push = (path: string) => getRouter()?.push(path);\r\n export const replace = (path: string) => getRouter()?.replace(path);\r\n export const visit = (url: string, blank?: boolean) => getRouter()?.visit(url, blank);\r\n\r\n // i18n\r\n export const getI18n = () => CM()?.getI18n();\r\n export const getLang = () => getI18n()?.getLanguage();\r\n export const setLang = (lang: string, _setLang=true, _setDir=true, _setCookie=true) => getI18n()?.setLanguage(lang, _setLang, _setDir, _setCookie);\r\n export const t = (key: string, params?: any, defaultValue?: string) => CM()?.t(key, params, defaultValue);\r\n export const tLang = (lang: string, key: string, params?: any, defaultValue?: string) => getI18n()?.tLang(lang, key, params, defaultValue) ?? (defaultValue ?? key);\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientManagerConfig } from './types';\r\n import { ClientManager } from './mod/manager';\r\n import { setupI18n } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n export * from './types';\r\n export * from './mod/manager';\r\n\r\n // Start\r\n export async function start(config: ClientManagerConfig): Promise<ClientManager> {\r\n // Read i18n config from HTML meta tag (injected by server)\r\n const metaI18n = document.querySelector('meta[name=\"app-i18n\"]');\r\n if (metaI18n) {\r\n const i18nData = JSON.parse(metaI18n.getAttribute('content') || '{}');\r\n config.i18n = i18nData;\r\n }\r\n\r\n // Create ClientManager instance\r\n const manager = new ClientManager(config);\r\n\r\n // Phase 0: Setup I18N\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (window as any).__i18n = await setupI18n(config.i18n || {\r\n defaultLanguage: 'en',\r\n supportedLanguages: ['en'],\r\n });\r\n\r\n // Phase 1: BOOT\r\n manager.boot();\r\n\r\n // Phase 2: READY\r\n manager.ready();\r\n\r\n // Handle cleanup on page unload\r\n window.addEventListener('beforeunload', async () => {\r\n await manager.destroy();\r\n });\r\n\r\n return manager;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -128,6 +128,10 @@ declare class Router {
|
|
|
128
128
|
* Add a query param to the whitelist
|
|
129
129
|
*/
|
|
130
130
|
addAllowedQueryParam(param: string | RegExp): void;
|
|
131
|
+
/**
|
|
132
|
+
* Visit an external link
|
|
133
|
+
*/
|
|
134
|
+
visit(url: string, blank?: boolean): void;
|
|
131
135
|
/**
|
|
132
136
|
* Reload current route
|
|
133
137
|
*/
|
|
@@ -237,12 +241,13 @@ declare const back: () => void | undefined;
|
|
|
237
241
|
declare const forward: () => void | undefined;
|
|
238
242
|
declare const push: (path: string) => void | undefined;
|
|
239
243
|
declare const replace: (path: string) => void | undefined;
|
|
244
|
+
declare const visit: (url: string, blank?: boolean) => void | undefined;
|
|
240
245
|
declare const getI18n: () => any;
|
|
241
246
|
declare const getLang: () => any;
|
|
242
|
-
declare const setLang: (lang: string) => any;
|
|
247
|
+
declare const setLang: (lang: string, _setLang?: boolean, _setDir?: boolean, _setCookie?: boolean) => any;
|
|
243
248
|
declare const t: (key: string, params?: any, defaultValue?: string) => any;
|
|
244
249
|
declare const tLang: (lang: string, key: string, params?: any, defaultValue?: string) => any;
|
|
245
250
|
|
|
246
251
|
declare function start(config: ClientManagerConfig): Promise<ClientManager>;
|
|
247
252
|
|
|
248
|
-
export { type ActionFunction, CM, ClientManager, type LoaderFunction, type NavigateOptions, NavigationError, type Route, type RouteContext, type RouteMatch, type RouteParams, type RouterConfig, back, forward, getI18n, getLang, getRouter, push, replace, setLang, start, t, tLang };
|
|
253
|
+
export { type ActionFunction, CM, ClientManager, type LoaderFunction, type NavigateOptions, NavigationError, type Route, type RouteContext, type RouteMatch, type RouteParams, type RouterConfig, back, forward, getI18n, getLang, getRouter, push, replace, setLang, start, t, tLang, visit };
|
package/dist/index.d.ts
CHANGED
|
@@ -128,6 +128,10 @@ declare class Router {
|
|
|
128
128
|
* Add a query param to the whitelist
|
|
129
129
|
*/
|
|
130
130
|
addAllowedQueryParam(param: string | RegExp): void;
|
|
131
|
+
/**
|
|
132
|
+
* Visit an external link
|
|
133
|
+
*/
|
|
134
|
+
visit(url: string, blank?: boolean): void;
|
|
131
135
|
/**
|
|
132
136
|
* Reload current route
|
|
133
137
|
*/
|
|
@@ -237,12 +241,13 @@ declare const back: () => void | undefined;
|
|
|
237
241
|
declare const forward: () => void | undefined;
|
|
238
242
|
declare const push: (path: string) => void | undefined;
|
|
239
243
|
declare const replace: (path: string) => void | undefined;
|
|
244
|
+
declare const visit: (url: string, blank?: boolean) => void | undefined;
|
|
240
245
|
declare const getI18n: () => any;
|
|
241
246
|
declare const getLang: () => any;
|
|
242
|
-
declare const setLang: (lang: string) => any;
|
|
247
|
+
declare const setLang: (lang: string, _setLang?: boolean, _setDir?: boolean, _setCookie?: boolean) => any;
|
|
243
248
|
declare const t: (key: string, params?: any, defaultValue?: string) => any;
|
|
244
249
|
declare const tLang: (lang: string, key: string, params?: any, defaultValue?: string) => any;
|
|
245
250
|
|
|
246
251
|
declare function start(config: ClientManagerConfig): Promise<ClientManager>;
|
|
247
252
|
|
|
248
|
-
export { type ActionFunction, CM, ClientManager, type LoaderFunction, type NavigateOptions, NavigationError, type Route, type RouteContext, type RouteMatch, type RouteParams, type RouterConfig, back, forward, getI18n, getLang, getRouter, push, replace, setLang, start, t, tLang };
|
|
253
|
+
export { type ActionFunction, CM, ClientManager, type LoaderFunction, type NavigateOptions, NavigationError, type Route, type RouteContext, type RouteMatch, type RouteParams, type RouterConfig, back, forward, getI18n, getLang, getRouter, push, replace, setLang, start, t, tLang, visit };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {signal,effect}from'@minejs/signals';import {mount}from'@minejs/jsx';import {EventsManager,WindowManager}from'@minejs/browser';import {setupI18n}from'@minejs/i18n';var l=class extends Error{constructor(e,r,o){super(r);this.code=e;this.cause=o;this.name="NavigationError";}};var h=class{constructor(t,e=null,r=new Map,o,n=false){this.segment=t;this.route=e;this.children=r;this.paramName=o;this.isWildcard=n;}},y=class{constructor(){this.root=new h("");this.wildcardRoute=null;}addRoute(t,e=""){let r=e+t.path;if(r==="/*"||r==="*"){this.wildcardRoute=t;return}let o=r.split("/").filter(Boolean),n=this.root;for(let a of o){let c=a.startsWith(":"),s=c?":param":a;n.children.has(s)||n.children.set(s,new h(a,null,new Map,c?a.slice(1):void 0)),n=n.children.get(s);}n.route=t,t.children&&t.children.forEach(a=>this.addRoute(a,r));}match(t){let e=t.split("/").filter(Boolean),r={},o=this.root,n=null;for(let c of e)if(o.children.has(c))o=o.children.get(c);else if(o.children.has(":param")){let s=o.children.get(":param");r[s.paramName]=decodeURIComponent(c),o=s;}else {n=this.wildcardRoute;break}if(n=n||o.route,!n)return null;let a=new URL(window.location.href);return {path:t,params:r,query:a.searchParams,hash:a.hash.slice(1),route:n}}},m=class{constructor(t){this.matcher=new y;this.currentRoute=signal(null);this.isNavigating=signal(false);this.loaderData=signal(null);this.error=signal(null);this.history=[];this.historyIndex=0;this.maxHistory=50;this.beforeEachGuards=[];this.afterEachGuards=[];this.onErrorHandlers=[];this.config={mode:"history",base:"",scrollBehavior:"auto",...t},t.onError&&this.onErrorHandlers.push(t.onError),t.routes.forEach(e=>this.matcher.addRoute(e)),this.setupListeners(),this.performNavigation(window.location.pathname+window.location.search);}emitError(t){this.error.set(t),this.onErrorHandlers.forEach(e=>e(t));}setupListeners(){this.config.mode==="history"?window.addEventListener("popstate",()=>{this.handleNavigation(window.location.pathname+window.location.search);}):window.addEventListener("hashchange",()=>{let t=window.location.hash.slice(1);this.handleNavigation(t||"/");}),document.addEventListener("click",t=>{let e=t.target.closest("a");if(!e||!e.href)return;let r=new URL(e.href);r.origin===window.location.origin&&(e.hasAttribute("data-external")||e.getAttribute("target")!=="_blank"&&(t.ctrlKey||t.metaKey||t.shiftKey||(t.preventDefault(),this.push(r.pathname+r.search))));});}performNavigation(t,e={}){try{let[r,o]=t.split("?"),n=new URL("http://localhost"+r+(o?"?"+o:""));this.config.allowedQueryParams&&this.config.allowedQueryParams.length>0&&Array.from(n.searchParams.keys()).forEach(p=>{this.config.allowedQueryParams.some(f=>typeof f=="string"?f===p:f.test(p))||n.searchParams.delete(p);});let a=n.searchParams.toString(),c=r+(a?"?"+a:""),s=this.matcher.match(r);if(!s){let w=new l("ROUTE_NOT_FOUND",`No route matched: ${r}`);this.emitError(w);return}if(this.config.mode==="history"?e.replace?window.history.replaceState(e.state||{},"",c):window.history.pushState(e.state||{},"",c):window.location.hash=c,s.query=n.searchParams,s.path=r,this.checkSyncGuards(s,this.currentRoute())===!1){window.history.back();return}this.error.set(null),this.currentRoute.set(s),this.handleScroll(e.scroll),this.updateMetaTags(s.route.meta),this.pruneHistory(),this.history.push(s),this.historyIndex=this.history.length-1,this.runAsyncNavigation(t,s,e);}catch(r){let o=new l("GUARD_ERROR","Navigation failed: "+String(r),r instanceof Error?r:void 0);this.emitError(o);}}updateMetaTags(t){if(t&&(t.title&&(document.title=t.title),t.description)){let e=document.querySelector('meta[name="description"]');if(e)e.content=t.description;else {let r=document.createElement("meta");r.name="description",r.content=t.description,document.head.appendChild(r);}}}pruneHistory(){this.history.length>this.maxHistory&&(this.history=this.history.slice(-this.maxHistory),this.historyIndex=this.history.length-1);}checkSyncGuards(t,e){if(this.beforeEachGuards.length!==0){for(let r of this.beforeEachGuards){let o=r(t,e);if(o instanceof Promise)return;if(o===false)return false}return true}}async runAsyncNavigation(t,e,r){try{if(!await this.runBeforeEachGuards(e,e)){this.currentRoute.set(null),this.history.pop(),this.historyIndex=Math.max(-1,this.history.length-1),window.history.back();return}let n=e;this.isNavigating.set(!0);try{if(e.route.loader){let a={params:e.params,query:e.query,request:new Request(window.location.href),pathname:t};try{let c=await e.route.loader(a);this.loaderData.set(c);}catch(c){let s=new l("LOADER_ERROR",`Failed to load data for ${t}`,c instanceof Error?c:void 0);throw this.emitError(s),s}}else this.loaderData.set(null);this.runAfterEachGuards(e,n);}finally{this.isNavigating.set(!1);}}catch(o){if(o instanceof l)throw o;let n=new l("GUARD_ERROR","Async navigation failed",o instanceof Error?o:void 0);this.emitError(n);}}async handleNavigation(t,e={}){this.performNavigation(t,e);}async runBeforeEachGuards(t,e){for(let r of this.beforeEachGuards)if(await r(t,e)===false)return false;return true}runAfterEachGuards(t,e){this.afterEachGuards.forEach(r=>r(t,e));}handleScroll(t){if(t===false)return;let e=typeof t=="string"?t:this.config.scrollBehavior;typeof window<"u"&&window.scrollTo&&window.scrollTo({top:0,left:0,behavior:e==="smooth"?"smooth":"auto"});}push(t,e={}){this.handleNavigation(t,{...e,replace:false});}replace(t,e={}){this.handleNavigation(t,{...e,replace:true});}back(){window.history.back();}forward(){window.history.forward();}go(t){window.history.go(t);}isActive(t,e=false){let r=this.currentRoute();return r?e?r.path===t:r.path.startsWith(t):false}getParams(){return this.currentRoute()?.params||{}}getQuery(){return this.currentRoute()?.query||new URLSearchParams}beforeEach(t){return this.beforeEachGuards.push(t),()=>{let e=this.beforeEachGuards.indexOf(t);e>-1&&this.beforeEachGuards.splice(e,1);}}afterEach(t){return this.afterEachGuards.push(t),()=>{let e=this.afterEachGuards.indexOf(t);e>-1&&this.afterEachGuards.splice(e,1);}}onError(t){return this.onErrorHandlers.push(t),()=>{let e=this.onErrorHandlers.indexOf(t);e>-1&&this.onErrorHandlers.splice(e,1);}}addAllowedQueryParam(t){this.config.allowedQueryParams||(this.config.allowedQueryParams=[]),this.config.allowedQueryParams.push(t);}async reload(){let t=this.currentRoute();if(t){let e=t.query.toString(),r=t.path+(e?"?"+e:"");await this.handleNavigation(r,{replace:true});}}destroy(){this.history=[],this.beforeEachGuards=[],this.afterEachGuards=[],this.onErrorHandlers=[],this.currentRoute.set(null),this.loaderData.set(null),this.error.set(null);}},E=null;function b(i){return E=new m(i),E}var x,d=class{constructor(t){this.lifecycle="booting";this.hooks={};this.extensions=[];this.routeComponents={};this.currentPathSignal=signal(window.location.pathname??"/");this.config=t,this.debug=t.debug??false,this.log("[INIT] Creating ClientManager"),t.lifecycle&&(this.hooks={...t.lifecycle}),this.extensions=t.extensions??[],this.routeComponents=t.routes,this.eventsManager=new EventsManager,this.windowManager=new WindowManager;let e=Object.entries(t.routes).map(([r,o])=>({path:r,component:o}));this.router=b({routes:e,notFoundComponent:t.notFoundComponent,allowedQueryParams:t.allowedQueryParams}),this.router.afterEach(r=>{this.currentPathSignal.set(r.path);}),x=this,this.log("[INIT] ClientManager created");}on(t,e,r,o){return typeof t=="string"&&t.startsWith("on")?(this.hooks[t]=e,this):this.eventsManager.on(t,e,r,o)}async boot(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Already booted or destroyed");return}this.log("\u26A1 Phase: BOOT");try{for(let t of this.extensions)t.onBoot&&(this.log(`\u2192 Extension onBoot: ${t.name}`),await t.onBoot({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onBoot&&(this.log("\u2192 Calling onBoot hook"),await this.hooks.onBoot()),this.log("\u2713 BOOT phase complete");}catch(t){throw console.error("[ClientManager] Boot failed:",t),t}}async ready(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Cannot ready - not in booting phase");return}this.log("\u26A1 Phase: READY");try{let t="body";document.querySelector(t).id="root",this.mount(t),this.log("\u2192 Router mounted");for(let e of this.extensions)e.onReady&&(this.log(`\u2192 Extension onReady: ${e.name}`),await e.onReady({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onReady&&(this.log("\u2192 Calling onReady hook"),await this.hooks.onReady()),this.lifecycle="ready",this.log("\u2713 READY phase complete"),this.log("\u2713 App is ready!");}catch(t){throw console.error("[ClientManager] Ready failed:",t),t}}async destroy(){if(this.lifecycle==="destroyed"){console.warn("[ClientManager] Already destroyed");return}this.lifecycle="destroying",this.log("\u26A1 Phase: DESTROY");try{for(let t=this.extensions.length-1;t>=0;t--){let e=this.extensions[t];e.onDestroy&&(this.log(`\u2192 Extension onDestroy: ${e.name}`),await e.onDestroy({debug:this.debug,config:{},cconfig:this.config}));}this.hooks.onDestroy&&(this.log("\u2192 Calling onDestroy hook"),await this.hooks.onDestroy()),this.eventsManager.destroy(),this.windowManager.destroy(),this.lifecycle="destroyed",this.log("\u2713 DESTROY phase complete");}catch(t){throw console.error("[ClientManager] Destroy failed:",t),t}}navigate(t){this.router.push(t);}mount(t){let e=typeof t=="string"?document.querySelector(t):t;if(!e){console.warn("[ClientManager] Mount target not found:",t);return}let r=e;if(this.config.rootLayout)try{let o=this.config.rootLayout();if(o){mount(o,e),this.log("\u2192 Root layout mounted");let n=e.querySelector("#main-overlay");n?r=n:console.warn("[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.");}}catch(o){console.error("[ClientManager] Error rendering root layout:",o),e.innerHTML="<p>Error loading root layout</p>";return}effect(()=>{let o=this.currentPathSignal(),n=this.routeComponents[o]||this.config.notFoundComponent||null;if(r.innerHTML="",n)try{let a=n();a&&mount(a,r);}catch(a){console.error("[ClientManager] Error rendering component:",o,a),r.innerHTML="<p>Error loading component</p>";}else r.innerHTML="<p>No component found for this route</p>";this.log(`\u2192 Route changed to: ${o}`);}),this.log("\u2192 Routing setup complete");}getCurrentPath(){return this.currentPathSignal}createLinkHandler(t){return e=>{e.preventDefault(),this.navigate(t);}}getRouter(){return this.router}off(t,e,r){this.eventsManager.off(t,e,r);}getEventsManager(){return this.eventsManager}getViewport(){return this.windowManager.getViewport()}getWindowManager(){return this.windowManager}getI18n(){return window.__i18n}t(t,e,r){return window.__i18n?window.__i18n.t(t,e)??r??t:(console.warn("[ClientManager] i18n not initialized. Using default value or key."),r??t)}getPhase(){return this.lifecycle}isReady(){return this.lifecycle==="ready"}log(t){this.debug&&console.log(`[ClientManager] ${t}`);}},v=()=>x,g=()=>v()?.getRouter(),W=()=>g()?.back(),$=()=>g()?.forward(),j=i=>g()?.push(i),K=i=>g()?.replace(i),R=()=>v()?.getI18n(),Y=()=>R()?.getLanguage(),J=i=>R()?.setLanguage(i),z=(i,t,e)=>v()?.t(i,t,e),X=(i,t,e,r)=>R()?.tLang(i,t,e,r)??r??t;async function et(i){let t=document.querySelector('meta[name="app-i18n"]');if(t){let r=JSON.parse(t.getAttribute("content")||"{}");i.i18n=r;}let e=new d(i);return window.__i18n=await setupI18n(i.i18n||{defaultLanguage:"en",supportedLanguages:["en"]}),e.boot(),e.ready(),window.addEventListener("beforeunload",async()=>{await e.destroy();}),e}
|
|
2
|
-
export{v as CM,
|
|
1
|
+
import {signal,effect}from'@minejs/signals';import {mount}from'@minejs/jsx';import {EventsManager,WindowManager}from'@minejs/browser';import {setupI18n}from'@minejs/i18n';var l=class extends Error{constructor(e,r,o){super(r);this.code=e;this.cause=o;this.name="NavigationError";}};var d=class{constructor(t,e=null,r=new Map,o,n=false){this.segment=t;this.route=e;this.children=r;this.paramName=o;this.isWildcard=n;}},y=class{constructor(){this.root=new d("");this.wildcardRoute=null;}addRoute(t,e=""){let r=e+t.path;if(r==="/*"||r==="*"){this.wildcardRoute=t;return}let o=r.split("/").filter(Boolean),n=this.root;for(let a of o){let c=a.startsWith(":"),s=c?":param":a;n.children.has(s)||n.children.set(s,new d(a,null,new Map,c?a.slice(1):void 0)),n=n.children.get(s);}n.route=t,t.children&&t.children.forEach(a=>this.addRoute(a,r));}match(t){let e=t.split("/").filter(Boolean),r={},o=this.root,n=null;for(let c of e)if(o.children.has(c))o=o.children.get(c);else if(o.children.has(":param")){let s=o.children.get(":param");r[s.paramName]=decodeURIComponent(c),o=s;}else {n=this.wildcardRoute;break}if(n=n||o.route,!n)return null;let a=new URL(window.location.href);return {path:t,params:r,query:a.searchParams,hash:a.hash.slice(1),route:n}}},m=class{constructor(t){this.matcher=new y;this.currentRoute=signal(null);this.isNavigating=signal(false);this.loaderData=signal(null);this.error=signal(null);this.history=[];this.historyIndex=0;this.maxHistory=50;this.beforeEachGuards=[];this.afterEachGuards=[];this.onErrorHandlers=[];this.config={mode:"history",base:"",scrollBehavior:"auto",...t},t.onError&&this.onErrorHandlers.push(t.onError),t.routes.forEach(e=>this.matcher.addRoute(e)),this.setupListeners(),this.performNavigation(window.location.pathname+window.location.search);}emitError(t){this.error.set(t),this.onErrorHandlers.forEach(e=>e(t));}setupListeners(){this.config.mode==="history"?window.addEventListener("popstate",()=>{this.handleNavigation(window.location.pathname+window.location.search);}):window.addEventListener("hashchange",()=>{let t=window.location.hash.slice(1);this.handleNavigation(t||"/");}),document.addEventListener("click",t=>{let e=t.target.closest("a");if(!e||!e.href)return;let r=new URL(e.href);r.origin===window.location.origin&&(e.hasAttribute("data-external")||e.getAttribute("target")!=="_blank"&&(t.ctrlKey||t.metaKey||t.shiftKey||(t.preventDefault(),this.push(r.pathname+r.search))));});}performNavigation(t,e={}){try{let[r,o]=t.split("?"),n=new URL("http://localhost"+r+(o?"?"+o:""));this.config.allowedQueryParams&&this.config.allowedQueryParams.length>0&&Array.from(n.searchParams.keys()).forEach(p=>{this.config.allowedQueryParams.some(f=>typeof f=="string"?f===p:f.test(p))||n.searchParams.delete(p);});let a=n.searchParams.toString(),c=r+(a?"?"+a:""),s=this.matcher.match(r);if(!s){let w=new l("ROUTE_NOT_FOUND",`No route matched: ${r}`);this.emitError(w);return}if(this.config.mode==="history"?e.replace?window.history.replaceState(e.state||{},"",c):window.history.pushState(e.state||{},"",c):window.location.hash=c,s.query=n.searchParams,s.path=r,this.checkSyncGuards(s,this.currentRoute())===!1){window.history.back();return}this.error.set(null),this.currentRoute.set(s),this.handleScroll(e.scroll),this.updateMetaTags(s.route.meta),this.pruneHistory(),this.history.push(s),this.historyIndex=this.history.length-1,this.runAsyncNavigation(t,s,e);}catch(r){let o=new l("GUARD_ERROR","Navigation failed: "+String(r),r instanceof Error?r:void 0);this.emitError(o);}}updateMetaTags(t){if(t&&(t.title&&(document.title=t.title),t.description)){let e=document.querySelector('meta[name="description"]');if(e)e.content=t.description;else {let r=document.createElement("meta");r.name="description",r.content=t.description,document.head.appendChild(r);}}}pruneHistory(){this.history.length>this.maxHistory&&(this.history=this.history.slice(-this.maxHistory),this.historyIndex=this.history.length-1);}checkSyncGuards(t,e){if(this.beforeEachGuards.length!==0){for(let r of this.beforeEachGuards){let o=r(t,e);if(o instanceof Promise)return;if(o===false)return false}return true}}async runAsyncNavigation(t,e,r){try{if(!await this.runBeforeEachGuards(e,e)){this.currentRoute.set(null),this.history.pop(),this.historyIndex=Math.max(-1,this.history.length-1),window.history.back();return}let n=e;this.isNavigating.set(!0);try{if(e.route.loader){let a={params:e.params,query:e.query,request:new Request(window.location.href),pathname:t};try{let c=await e.route.loader(a);this.loaderData.set(c);}catch(c){let s=new l("LOADER_ERROR",`Failed to load data for ${t}`,c instanceof Error?c:void 0);throw this.emitError(s),s}}else this.loaderData.set(null);this.runAfterEachGuards(e,n);}finally{this.isNavigating.set(!1);}}catch(o){if(o instanceof l)throw o;let n=new l("GUARD_ERROR","Async navigation failed",o instanceof Error?o:void 0);this.emitError(n);}}async handleNavigation(t,e={}){this.performNavigation(t,e);}async runBeforeEachGuards(t,e){for(let r of this.beforeEachGuards)if(await r(t,e)===false)return false;return true}runAfterEachGuards(t,e){this.afterEachGuards.forEach(r=>r(t,e));}handleScroll(t){if(t===false)return;let e=typeof t=="string"?t:this.config.scrollBehavior;typeof window<"u"&&window.scrollTo&&window.scrollTo({top:0,left:0,behavior:e==="smooth"?"smooth":"auto"});}push(t,e={}){this.handleNavigation(t,{...e,replace:false});}replace(t,e={}){this.handleNavigation(t,{...e,replace:true});}back(){window.history.back();}forward(){window.history.forward();}go(t){window.history.go(t);}isActive(t,e=false){let r=this.currentRoute();return r?e?r.path===t:r.path.startsWith(t):false}getParams(){return this.currentRoute()?.params||{}}getQuery(){return this.currentRoute()?.query||new URLSearchParams}beforeEach(t){return this.beforeEachGuards.push(t),()=>{let e=this.beforeEachGuards.indexOf(t);e>-1&&this.beforeEachGuards.splice(e,1);}}afterEach(t){return this.afterEachGuards.push(t),()=>{let e=this.afterEachGuards.indexOf(t);e>-1&&this.afterEachGuards.splice(e,1);}}onError(t){return this.onErrorHandlers.push(t),()=>{let e=this.onErrorHandlers.indexOf(t);e>-1&&this.onErrorHandlers.splice(e,1);}}addAllowedQueryParam(t){this.config.allowedQueryParams||(this.config.allowedQueryParams=[]),this.config.allowedQueryParams.push(t);}visit(t,e){e??true?window.open(t,"_blank"):window.location.href=t;}async reload(){let t=this.currentRoute();if(t){let e=t.query.toString(),r=t.path+(e?"?"+e:"");await this.handleNavigation(r,{replace:true});}}destroy(){this.history=[],this.beforeEachGuards=[],this.afterEachGuards=[],this.onErrorHandlers=[],this.currentRoute.set(null),this.loaderData.set(null),this.error.set(null);}},E=null;function b(i){return E=new m(i),E}var M,g=class{constructor(t){this.lifecycle="booting";this.hooks={};this.extensions=[];this.routeComponents={};this.currentPathSignal=signal(window.location.pathname??"/");this.config=t,this.debug=t.debug??false,this.log("[INIT] Creating ClientManager"),t.lifecycle&&(this.hooks={...t.lifecycle}),this.extensions=t.extensions??[],this.routeComponents=t.routes,this.eventsManager=new EventsManager,this.windowManager=new WindowManager;let e=Object.entries(t.routes).map(([r,o])=>({path:r,component:o}));this.router=b({routes:e,notFoundComponent:t.notFoundComponent,allowedQueryParams:t.allowedQueryParams}),this.router.afterEach(r=>{this.currentPathSignal.set(r.path);}),M=this,this.log("[INIT] ClientManager created");}on(t,e,r,o){return typeof t=="string"&&t.startsWith("on")?(this.hooks[t]=e,this):this.eventsManager.on(t,e,r,o)}async boot(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Already booted or destroyed");return}this.log("\u26A1 Phase: BOOT");try{for(let t of this.extensions)t.onBoot&&(this.log(`\u2192 Extension onBoot: ${t.name}`),await t.onBoot({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onBoot&&(this.log("\u2192 Calling onBoot hook"),await this.hooks.onBoot()),this.log("\u2713 BOOT phase complete");}catch(t){throw console.error("[ClientManager] Boot failed:",t),t}}async ready(){if(this.lifecycle!=="booting"){console.warn("[ClientManager] Cannot ready - not in booting phase");return}this.log("\u26A1 Phase: READY");try{let t="body";document.querySelector(t).id="root",this.mount(t),this.log("\u2192 Router mounted");for(let e of this.extensions)e.onReady&&(this.log(`\u2192 Extension onReady: ${e.name}`),await e.onReady({debug:this.debug,config:{},cconfig:this.config}));this.hooks.onReady&&(this.log("\u2192 Calling onReady hook"),await this.hooks.onReady()),this.lifecycle="ready",this.log("\u2713 READY phase complete"),this.log("\u2713 App is ready!");}catch(t){throw console.error("[ClientManager] Ready failed:",t),t}}async destroy(){if(this.lifecycle==="destroyed"){console.warn("[ClientManager] Already destroyed");return}this.lifecycle="destroying",this.log("\u26A1 Phase: DESTROY");try{for(let t=this.extensions.length-1;t>=0;t--){let e=this.extensions[t];e.onDestroy&&(this.log(`\u2192 Extension onDestroy: ${e.name}`),await e.onDestroy({debug:this.debug,config:{},cconfig:this.config}));}this.hooks.onDestroy&&(this.log("\u2192 Calling onDestroy hook"),await this.hooks.onDestroy()),this.eventsManager.destroy(),this.windowManager.destroy(),this.lifecycle="destroyed",this.log("\u2713 DESTROY phase complete");}catch(t){throw console.error("[ClientManager] Destroy failed:",t),t}}navigate(t){this.router.push(t);}mount(t){let e=typeof t=="string"?document.querySelector(t):t;if(!e){console.warn("[ClientManager] Mount target not found:",t);return}let r=e;if(this.config.rootLayout)try{let o=this.config.rootLayout();if(o){mount(o,e),this.log("\u2192 Root layout mounted");let n=e.querySelector("#main-overlay");n?r=n:console.warn("[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.");}}catch(o){console.error("[ClientManager] Error rendering root layout:",o),e.innerHTML="<p>Error loading root layout</p>";return}effect(()=>{let o=this.currentPathSignal(),n=this.routeComponents[o]||this.config.notFoundComponent||null;if(r.innerHTML="",n)try{let a=n();a&&mount(a,r);}catch(a){console.error("[ClientManager] Error rendering component:",o,a),r.innerHTML="<p>Error loading component</p>";}else r.innerHTML="<p>No component found for this route</p>";this.log(`\u2192 Route changed to: ${o}`);}),this.log("\u2192 Routing setup complete");}getCurrentPath(){return this.currentPathSignal}createLinkHandler(t){return e=>{e.preventDefault(),this.navigate(t);}}getRouter(){return this.router}off(t,e,r){this.eventsManager.off(t,e,r);}getEventsManager(){return this.eventsManager}getViewport(){return this.windowManager.getViewport()}getWindowManager(){return this.windowManager}getI18n(){return window.__i18n}t(t,e,r){return window.__i18n?window.__i18n.t(t,e)??r??t:(console.warn("[ClientManager] i18n not initialized. Using default value or key."),r??t)}getPhase(){return this.lifecycle}isReady(){return this.lifecycle==="ready"}log(t){this.debug&&console.log(`[ClientManager] ${t}`);}},v=()=>M,u=()=>v()?.getRouter(),W=()=>u()?.back(),$=()=>u()?.forward(),j=i=>u()?.push(i),K=i=>u()?.replace(i),Y=(i,t)=>u()?.visit(i,t),R=()=>v()?.getI18n(),J=()=>R()?.getLanguage(),z=(i,t=true,e=true,r=true)=>R()?.setLanguage(i,t,e,r),X=(i,t,e)=>v()?.t(i,t,e),V=(i,t,e,r)=>R()?.tLang(i,t,e,r)??r??t;async function rt(i){let t=document.querySelector('meta[name="app-i18n"]');if(t){let r=JSON.parse(t.getAttribute("content")||"{}");i.i18n=r;}let e=new g(i);return window.__i18n=await setupI18n(i.i18n||{defaultLanguage:"en",supportedLanguages:["en"]}),e.boot(),e.ready(),window.addEventListener("beforeunload",async()=>{await e.destroy();}),e}
|
|
2
|
+
export{v as CM,g as ClientManager,l as NavigationError,W as back,$ as forward,R as getI18n,J as getLang,u as getRouter,j as push,K as replace,z as setLang,rt as start,X as t,V as tLang,Y as visit};//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/mod/router.ts","../src/mod/manager.ts","../src/index.ts"],"names":["NavigationError","code","message","cause","RouteNode","segment","route","children","paramName","isWildcard","RouteMatcher","parentPath","fullPath","segments","node","isParam","key","child","pathname","params","matchedRoute","paramNode","url","Router","config","signal","error","handler","hash","e","target","options","pathOnly","queryString","pattern","finalQueryString","finalPathname","match","err","meta","descMeta","newMeta","to","from","guard","result","_options","previousRoute","context","data","behavior","scrollBehavior","path","delta","exact","current","index","param","pathWithQuery","globalRouter","createRouter","globalClientManagerInstance","ClientManager","EventsManager","WindowManager","routesArray","component","eventOrTarget","callbackOrEvent","extension","selector","i","container","pageContainer","layoutJsx","mountJSX","pageSlot","effect","currentPath","Component","jsx","event","defaultValue","CM","getRouter","back","forward","push","replace","getI18n","getLang","setLang","lang","t","tLang","start","metaI18n","i18nData","manager","setupI18n"],"mappings":"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","file":"index.js","sourcesContent":["// src/types.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n export type {\r\n RouteComponent,\r\n ThemeConfig,\r\n LangConfig,\r\n ClientExtension,\r\n ExtensionContext,\r\n ClientManagerHooks,\r\n ClientManagerConfig\r\n } from '@cruxjs/base';\r\n\r\n \r\n export type RouteParams = Record<string, string>;\r\n\r\n export interface RouteMatch {\r\n path: string\r\n params: RouteParams\r\n query: URLSearchParams\r\n hash: string\r\n route: Route\r\n }\r\n\r\n export interface RouteContext {\r\n params: RouteParams\r\n query: URLSearchParams\r\n request: Request\r\n pathname: string\r\n }\r\n\r\n export class NavigationError extends Error {\r\n constructor(\r\n public code: 'LOADER_ERROR' | 'ACTION_ERROR' | 'GUARD_ERROR' | 'ROUTE_NOT_FOUND',\r\n message: string,\r\n public cause?: Error\r\n ) {\r\n super(message);\r\n this.name = 'NavigationError';\r\n }\r\n }\r\n\r\n export type LoaderFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export type ActionFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export interface Route {\r\n path: string\r\n component: () => any | Promise<any>\r\n loader?: LoaderFunction\r\n action?: ActionFunction\r\n children?: Route[]\r\n meta?: {\r\n title?: string\r\n description?: string\r\n [key: string]: any\r\n }\r\n errorComponent?: () => any\r\n }\r\n\r\n export interface NavigateOptions {\r\n replace?: boolean\r\n state?: any\r\n scroll?: boolean | 'smooth'\r\n }\r\n\r\n export interface RouterConfig {\r\n routes: Route[]\r\n base?: string\r\n mode?: 'history' | 'hash'\r\n scrollBehavior?: 'auto' | 'smooth' | 'instant'\r\n allowedQueryParams?: (string | RegExp)[]\r\n notFoundComponent?: () => any\r\n errorComponent?: () => any\r\n onError?: (error: NavigationError) => void\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/router.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { signal, computed, type Signal } from '@minejs/signals';\r\n import { jsx, Suspense } from '@minejs/jsx';\r\n import * as types from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n class RouteNode {\r\n constructor(\r\n public segment: string,\r\n public route: types.Route | null = null,\r\n public children: Map<string, RouteNode> = new Map(),\r\n public paramName?: string,\r\n public isWildcard = false\r\n ) { }\r\n }\r\n\r\n class RouteMatcher {\r\n private root = new RouteNode('');\r\n private wildcardRoute: types.Route | null = null;\r\n\r\n addRoute(route: types.Route, parentPath = ''): void {\r\n const fullPath = parentPath + route.path;\r\n\r\n // Handle wildcard routes\r\n if (fullPath === '/*' || fullPath === '*') {\r\n this.wildcardRoute = route;\r\n return;\r\n }\r\n\r\n const segments = fullPath.split('/').filter(Boolean);\r\n let node = this.root;\r\n\r\n for (const segment of segments) {\r\n const isParam = segment.startsWith(':');\r\n const key = isParam ? ':param' : segment;\r\n\r\n if (!node.children.has(key)) {\r\n node.children.set(key, new RouteNode(\r\n segment,\r\n null,\r\n new Map(),\r\n isParam ? segment.slice(1) : undefined\r\n ));\r\n }\r\n\r\n node = node.children.get(key)!;\r\n }\r\n\r\n node.route = route;\r\n\r\n // Add child routes recursively\r\n if (route.children) {\r\n route.children.forEach(child => this.addRoute(child, fullPath));\r\n }\r\n }\r\n\r\n match(pathname: string): types.RouteMatch | null {\r\n const segments = pathname.split('/').filter(Boolean);\r\n const params: types.RouteParams = {};\r\n\r\n let node = this.root;\r\n let matchedRoute: types.Route | null = null;\r\n\r\n for (const segment of segments) {\r\n // Try exact match first\r\n if (node.children.has(segment)) {\r\n node = node.children.get(segment)!;\r\n }\r\n // Try param match\r\n else if (node.children.has(':param')) {\r\n const paramNode = node.children.get(':param')!;\r\n params[paramNode.paramName!] = decodeURIComponent(segment);\r\n node = paramNode;\r\n }\r\n // No exact match - try wildcard\r\n else {\r\n matchedRoute = this.wildcardRoute;\r\n break;\r\n }\r\n }\r\n\r\n matchedRoute = matchedRoute || node.route;\r\n\r\n if (!matchedRoute) {\r\n return null;\r\n }\r\n\r\n const url = new URL(window.location.href);\r\n\r\n return {\r\n path: pathname,\r\n params,\r\n query: url.searchParams,\r\n hash: url.hash.slice(1),\r\n route: matchedRoute\r\n };\r\n }\r\n }\r\n\r\n export class Router {\r\n private matcher = new RouteMatcher();\r\n private config : types.RouterConfig;\r\n\r\n // Reactive state\r\n public currentRoute = signal<types.RouteMatch | null>(null);\r\n public isNavigating = signal(false);\r\n public loaderData = signal<any>(null);\r\n public error = signal<types.NavigationError | null>(null);\r\n\r\n // History\r\n private history : types.RouteMatch[] = [];\r\n private historyIndex = 0;\r\n private maxHistory = 50; // Prevent memory leaks\r\n\r\n // Guards\r\n private beforeEachGuards: ((to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>)[] = [];\r\n private afterEachGuards : ((to: types.RouteMatch, from: types.RouteMatch | null) => void)[] = [];\r\n private onErrorHandlers: ((error: types.NavigationError) => void)[] = [];\r\n\r\n constructor(config: types.RouterConfig) {\r\n this.config = {\r\n mode : 'history',\r\n base : '',\r\n scrollBehavior : 'auto',\r\n ...config\r\n };\r\n\r\n // Add error handler\r\n if (config.onError) {\r\n this.onErrorHandlers.push(config.onError);\r\n }\r\n\r\n // Build route tree\r\n config.routes.forEach(route => this.matcher.addRoute(route));\r\n\r\n // Listen to browser navigation\r\n this.setupListeners();\r\n\r\n // Initial route - handle synchronously for basic setup\r\n this.performNavigation(window.location.pathname + window.location.search);\r\n }\r\n\r\n private emitError(error: types.NavigationError): void {\r\n this.error.set(error);\r\n this.onErrorHandlers.forEach(handler => handler(error));\r\n }\r\n\r\n private setupListeners(): void {\r\n if (this.config.mode === 'history') {\r\n window.addEventListener('popstate', () => {\r\n this.handleNavigation(window.location.pathname + window.location.search);\r\n });\r\n } else {\r\n window.addEventListener('hashchange', () => {\r\n const hash = window.location.hash.slice(1);\r\n this.handleNavigation(hash || '/');\r\n });\r\n }\r\n\r\n // Intercept link clicks\r\n document.addEventListener('click', (e) => {\r\n const target = (e.target as HTMLElement).closest('a');\r\n\r\n if (!target || !target.href) return;\r\n\r\n // Check if it's a same-origin link\r\n const url = new URL(target.href);\r\n if (url.origin !== window.location.origin) return;\r\n\r\n // Check if it should be handled by router\r\n if (target.hasAttribute('data-external')) return;\r\n if (target.getAttribute('target') === '_blank') return;\r\n if (e.ctrlKey || e.metaKey || e.shiftKey) return;\r\n\r\n e.preventDefault();\r\n this.push(url.pathname + url.search);\r\n });\r\n }\r\n\r\n private performNavigation(pathname: string, options: types.NavigateOptions = {}): void {\r\n try {\r\n // Extract path and query string\r\n const [pathOnly, queryString] = pathname.split('?');\r\n \r\n // Parse and filter query params\r\n const url = new URL('http://localhost' + pathOnly + (queryString ? '?' + queryString : ''));\r\n \r\n if (this.config.allowedQueryParams && this.config.allowedQueryParams.length > 0) {\r\n const keys = Array.from(url.searchParams.keys());\r\n keys.forEach(key => {\r\n const isAllowed = this.config.allowedQueryParams!.some(pattern => {\r\n if (typeof pattern === 'string') return pattern === key;\r\n return pattern.test(key);\r\n });\r\n \r\n if (!isAllowed) {\r\n url.searchParams.delete(key);\r\n }\r\n });\r\n }\r\n\r\n const finalQueryString = url.searchParams.toString();\r\n const finalPathname = pathOnly + (finalQueryString ? '?' + finalQueryString : '');\r\n\r\n const match = this.matcher.match(pathOnly);\r\n\r\n if (!match) {\r\n const error = new types.NavigationError('ROUTE_NOT_FOUND', `No route matched: ${pathOnly}`);\r\n this.emitError(error);\r\n return;\r\n }\r\n\r\n // Update browser history first (so window.location is correct for subsequent operations)\r\n if (this.config.mode === 'history') {\r\n if (options.replace) {\r\n window.history.replaceState(options.state || {}, '', finalPathname);\r\n } else {\r\n window.history.pushState(options.state || {}, '', finalPathname);\r\n }\r\n } else {\r\n window.location.hash = finalPathname;\r\n }\r\n\r\n match.query = url.searchParams;\r\n match.path = pathOnly;\r\n\r\n // Check guards synchronously (if they're not async)\r\n const canNavigate = this.checkSyncGuards(match, this.currentRoute());\r\n if (canNavigate === false) {\r\n // Revert history if navigation was prevented\r\n window.history.back();\r\n return;\r\n }\r\n\r\n // Clear previous error\r\n this.error.set(null);\r\n\r\n // Update current route immediately (synchronously)\r\n this.currentRoute.set(match);\r\n\r\n // Handle scroll\r\n this.handleScroll(options.scroll);\r\n\r\n // Update document title and meta tags\r\n this.updateMetaTags(match.route.meta);\r\n\r\n // Manage history size to prevent memory leaks\r\n this.pruneHistory();\r\n\r\n // Add to history\r\n this.history.push(match);\r\n this.historyIndex = this.history.length - 1;\r\n\r\n // Run async operations in background\r\n this.runAsyncNavigation(pathname, match, options);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Navigation failed: ' + String(err),\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private updateMetaTags(meta?: Record<string, any>): void {\r\n if (!meta) return;\r\n\r\n if (meta.title) {\r\n document.title = meta.title;\r\n }\r\n if (meta.description) {\r\n const descMeta = document.querySelector('meta[name=\"description\"]') as HTMLMetaElement | null;\r\n if (descMeta) {\r\n descMeta.content = meta.description;\r\n } else {\r\n const newMeta = document.createElement('meta');\r\n newMeta.name = 'description';\r\n newMeta.content = meta.description;\r\n document.head.appendChild(newMeta);\r\n }\r\n }\r\n }\r\n\r\n private pruneHistory(): void {\r\n if (this.history.length > this.maxHistory) {\r\n this.history = this.history.slice(-this.maxHistory);\r\n this.historyIndex = this.history.length - 1;\r\n }\r\n }\r\n\r\n private checkSyncGuards(to: types.RouteMatch, from: types.RouteMatch | null): boolean | undefined {\r\n // If no guards, return undefined (allow)\r\n if (this.beforeEachGuards.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // Check guards - if any are async, we'll check them in runAsyncNavigation\r\n for (const guard of this.beforeEachGuards) {\r\n const result = guard(to, from);\r\n // If we got a Promise, we can't handle it synchronously\r\n if (result instanceof Promise) {\r\n return undefined; // Let async handler deal with it\r\n }\r\n if (result === false) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private async runAsyncNavigation(pathname: string, match: types.RouteMatch, _options: types.NavigateOptions): Promise<void> {\r\n try {\r\n // Run beforeEach guards (including async ones)\r\n const canNavigate = await this.runBeforeEachGuards(match, match);\r\n if (!canNavigate) {\r\n // Revert - remove from current and history\r\n this.currentRoute.set(null);\r\n this.history.pop();\r\n this.historyIndex = Math.max(-1, this.history.length - 1);\r\n // Revert in browser\r\n window.history.back();\r\n return;\r\n }\r\n\r\n const previousRoute = match;\r\n\r\n // Set navigating state\r\n this.isNavigating.set(true);\r\n\r\n try {\r\n // Run loader if exists\r\n if (match.route.loader) {\r\n const context: types.RouteContext = {\r\n params: match.params,\r\n query: match.query,\r\n request: new Request(window.location.href),\r\n pathname\r\n };\r\n\r\n try {\r\n const data = await match.route.loader(context);\r\n this.loaderData.set(data);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'LOADER_ERROR',\r\n `Failed to load data for ${pathname}`,\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n throw error;\r\n }\r\n } else {\r\n this.loaderData.set(null);\r\n }\r\n\r\n // Run afterEach guards\r\n this.runAfterEachGuards(match, previousRoute);\r\n\r\n } finally {\r\n this.isNavigating.set(false);\r\n }\r\n } catch (err) {\r\n if (err instanceof types.NavigationError) {\r\n throw err;\r\n }\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Async navigation failed',\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private async handleNavigation(pathname: string, options: types.NavigateOptions = {}): Promise<void> {\r\n this.performNavigation(pathname, options);\r\n }\r\n\r\n private async runBeforeEachGuards(\r\n to: types.RouteMatch,\r\n from: types.RouteMatch | null\r\n ): Promise<boolean> {\r\n for (const guard of this.beforeEachGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) return false;\r\n }\r\n return true;\r\n }\r\n\r\n private runAfterEachGuards(to: types.RouteMatch, from: types.RouteMatch | null): void {\r\n this.afterEachGuards.forEach(guard => guard(to, from));\r\n }\r\n\r\n private handleScroll(behavior?: boolean | 'smooth'): void {\r\n if (behavior === false) return;\r\n\r\n const scrollBehavior = typeof behavior === 'string'\r\n ? behavior\r\n : this.config.scrollBehavior;\r\n\r\n if (typeof window !== 'undefined' && window.scrollTo) {\r\n window.scrollTo({\r\n top: 0,\r\n left: 0,\r\n behavior: scrollBehavior === 'smooth' ? 'smooth' : 'auto'\r\n });\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // PUBLIC API\r\n // ============================================================================\r\n\r\n /**\r\n * Navigate to a path\r\n */\r\n public push(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: false });\r\n }\r\n\r\n /**\r\n * Replace current route\r\n */\r\n public replace(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: true });\r\n }\r\n\r\n /**\r\n * Go back in history\r\n */\r\n public back(): void {\r\n window.history.back();\r\n }\r\n\r\n /**\r\n * Go forward in history\r\n */\r\n public forward(): void {\r\n window.history.forward();\r\n }\r\n\r\n /**\r\n * Go to specific history entry\r\n */\r\n public go(delta: number): void {\r\n window.history.go(delta);\r\n }\r\n\r\n /**\r\n * Check if path is active\r\n */\r\n public isActive(path: string, exact = false): boolean {\r\n const current = this.currentRoute();\r\n if (!current) return false;\r\n\r\n if (exact) {\r\n return current.path === path;\r\n }\r\n\r\n return current.path.startsWith(path);\r\n }\r\n\r\n /**\r\n * Get current params\r\n */\r\n public getParams(): types.RouteParams {\r\n return this.currentRoute()?.params || {};\r\n }\r\n\r\n /**\r\n * Get current query\r\n */\r\n public getQuery(): URLSearchParams {\r\n return this.currentRoute()?.query || new URLSearchParams();\r\n }\r\n\r\n /**\r\n * Register beforeEach guard\r\n */\r\n public beforeEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>\r\n ): () => void {\r\n this.beforeEachGuards.push(guard);\r\n return () => {\r\n const index = this.beforeEachGuards.indexOf(guard);\r\n if (index > -1) this.beforeEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register afterEach guard\r\n */\r\n public afterEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => void\r\n ): () => void {\r\n this.afterEachGuards.push(guard);\r\n return () => {\r\n const index = this.afterEachGuards.indexOf(guard);\r\n if (index > -1) this.afterEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register error handler\r\n */\r\n public onError(handler: (error: types.NavigationError) => void): () => void {\r\n this.onErrorHandlers.push(handler);\r\n return () => {\r\n const index = this.onErrorHandlers.indexOf(handler);\r\n if (index > -1) this.onErrorHandlers.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Add a query param to the whitelist\r\n */\r\n public addAllowedQueryParam(param: string | RegExp): void {\r\n if (!this.config.allowedQueryParams) {\r\n this.config.allowedQueryParams = [];\r\n }\r\n this.config.allowedQueryParams.push(param);\r\n }\r\n\r\n /**\r\n * Reload current route\r\n */\r\n public async reload(): Promise<void> {\r\n const current = this.currentRoute();\r\n if (current) {\r\n const queryString = current.query.toString();\r\n const pathWithQuery = current.path + (queryString ? '?' + queryString : '');\r\n await this.handleNavigation(pathWithQuery, { replace: true });\r\n }\r\n }\r\n\r\n /**\r\n * Destroy router and cleanup\r\n */\r\n public destroy(): void {\r\n this.history = [];\r\n this.beforeEachGuards = [];\r\n this.afterEachGuards = [];\r\n this.onErrorHandlers = [];\r\n this.currentRoute.set(null);\r\n this.loaderData.set(null);\r\n this.error.set(null);\r\n }\r\n }\r\n\r\n let globalRouter: Router | null = null;\r\n\r\n export function createRouter(config: types.RouterConfig): Router {\r\n globalRouter = new Router(config);\r\n return globalRouter;\r\n }\r\n\r\n export function useRouter(): Router {\r\n if (!globalRouter) {\r\n throw new Error('Router not initialized. Call createRouter() first.');\r\n }\r\n return globalRouter;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HOOK ════════════════════════════════════════╗\r\n\r\n export function useRoute(): Signal<types.RouteMatch | null> {\r\n return useRouter().currentRoute;\r\n }\r\n\r\n export function useParams(): types.RouteParams {\r\n return useRouter().getParams();\r\n }\r\n\r\n export function useQuery(): URLSearchParams {\r\n return useRouter().getQuery();\r\n }\r\n\r\n export function useLoaderData<T = any>(): Signal<T | null> {\r\n return useRouter().loaderData as Signal<T | null>;\r\n }\r\n\r\n export function useNavigate() {\r\n const router = useRouter();\r\n\r\n return {\r\n push: (path: string, options?: types.NavigateOptions) => router.push(path, options),\r\n replace: (path: string, options?: types.NavigateOptions) => router.replace(path, options),\r\n back: () => router.back(),\r\n forward: () => router.forward(),\r\n go: (delta: number) => router.go(delta)\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\r\n\r\n /**\r\n * Link component with active state\r\n */\r\n export function Link(props: {\r\n to : string\r\n children : any\r\n activeClass? : string\r\n exact? : boolean\r\n replace? : boolean\r\n className? : string\r\n [key: string] : any\r\n }) {\r\n const router = useRouter();\r\n const isActive = computed(() => router.isActive(props.to, props.exact));\r\n\r\n const className = computed(() => {\r\n let classes = props.className || '';\r\n if (isActive() && props.activeClass) {\r\n classes += ' ' + props.activeClass;\r\n }\r\n return classes.trim();\r\n });\r\n\r\n const handleClick = (e: Event) => {\r\n e.preventDefault();\r\n\r\n if (props.replace) {\r\n router.replace(props.to);\r\n } else {\r\n router.push(props.to);\r\n }\r\n };\r\n\r\n return jsx('a', {\r\n href : props.to,\r\n className : className(),\r\n onClick : handleClick,\r\n 'data-active' : isActive(),\r\n children : props.children\r\n });\r\n }\r\n\r\n /**\r\n * Router outlet - renders current route component with error boundary\r\n */\r\n export function RouterOutlet() {\r\n const router = useRouter();\r\n const route = router.currentRoute;\r\n const error = router.error;\r\n\r\n return computed(() => {\r\n const currentRoute = route();\r\n const currentError = error();\r\n\r\n // Show error component if error occurred\r\n if (currentError) {\r\n const errorComponent = currentRoute?.route.errorComponent || router.currentRoute()?.route.meta?.errorComponent;\r\n if (errorComponent) {\r\n return errorComponent();\r\n }\r\n // Fallback error display\r\n return jsx('div', {\r\n style: { color: 'red', padding: '20px' },\r\n children: `Navigation Error: ${currentError.message}`\r\n });\r\n }\r\n\r\n if (!currentRoute) {\r\n const notFoundComponent = (router.currentRoute() as any)?.config?.notFoundComponent;\r\n if (notFoundComponent) {\r\n return notFoundComponent();\r\n }\r\n return null;\r\n }\r\n\r\n // Load and render component\r\n const component = currentRoute.route.component();\r\n\r\n if (component instanceof Promise) {\r\n // Async component\r\n return jsx(Suspense, {\r\n fallback: jsx('div', { children: 'Loading...' }),\r\n children: component\r\n });\r\n }\r\n\r\n return component;\r\n });\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ UTIL ════════════════════════════════════════╗\r\n\r\n /**\r\n * Build URL with params\r\n */\r\n export function buildPath(path: string, params: types.RouteParams): string {\r\n let result = path;\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n result = result.replace(`:${key}`, encodeURIComponent(value));\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Parse query string to object\r\n */\r\n export function parseQuery(search: string): Record<string, string> {\r\n const params = new URLSearchParams(search);\r\n const result: Record<string, string> = {};\r\n\r\n params.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Stringify object to query string\r\n */\r\n export function stringifyQuery(obj: Record<string, any>): string {\r\n const params = new URLSearchParams();\r\n\r\n Object.entries(obj).forEach(([key, value]) => {\r\n if (value != null) {\r\n params.append(key, String(value));\r\n }\r\n });\r\n\r\n return params.toString();\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export default {\r\n createRouter,\r\n useRouter,\r\n useRoute,\r\n useParams,\r\n useQuery,\r\n useLoaderData,\r\n useNavigate,\r\n Link,\r\n RouterOutlet,\r\n buildPath,\r\n parseQuery,\r\n stringifyQuery,\r\n Router,\r\n NavigationError: types.NavigationError\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import * as types from '../types';\r\n import { signal, effect } from '@minejs/signals';\r\n import { mount as mountJSX } from '@minejs/jsx';\r\n import { EventsManager, WindowManager } from '@minejs/browser';\r\n import { Router, createRouter } from './router';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n let globalClientManagerInstance: ClientManager | undefined;\r\n\r\n export class ClientManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n private router : Router;\r\n private eventsManager : EventsManager;\r\n private windowManager : WindowManager;\r\n private lifecycle : 'booting' | 'ready' | 'destroying' | 'destroyed' = 'booting';\r\n private config : types.ClientManagerConfig;\r\n private hooks : types.ClientManagerHooks = {};\r\n private extensions : types.ClientExtension[] = [];\r\n private debug : boolean;\r\n private routeComponents : Record<string, types.RouteComponent> = {};\r\n private currentPathSignal = signal<string>(window.location.pathname ?? '/');\r\n\r\n constructor(config: types.ClientManagerConfig) {\r\n this.config = config;\r\n this.debug = config.debug ?? false;\r\n\r\n this.log('[INIT] Creating ClientManager');\r\n\r\n // Merge lifecycle hooks from config\r\n if (config.lifecycle) {\r\n this.hooks = { ...config.lifecycle };\r\n }\r\n\r\n // Store extensions from config\r\n this.extensions = config.extensions ?? [];\r\n\r\n // Store route components provided by user\r\n this.routeComponents = config.routes;\r\n\r\n // Initialize managers from @minejs/browser\r\n this.eventsManager = new EventsManager();\r\n this.windowManager = new WindowManager();\r\n\r\n // Initialize router with user-provided routes\r\n const routesArray = Object.entries(config.routes).map(([path, component]) => ({\r\n path,\r\n component\r\n }));\r\n\r\n this.router = createRouter({\r\n routes: routesArray,\r\n notFoundComponent: config.notFoundComponent,\r\n allowedQueryParams: config.allowedQueryParams\r\n });\r\n\r\n // Connect router changes to signal for automatic re-rendering\r\n this.router.afterEach((to) => {\r\n this.currentPathSignal.set(to.path);\r\n });\r\n\r\n // Store clientManager instance\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n globalClientManagerInstance = this;\r\n\r\n this.log('[INIT] ClientManager created');\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Setup lifecycle hooks OR bind events\r\n * Overloaded: on(event: 'onBoot'|'onReady'|'onDestroy', callback) - lifecycle\r\n * on(target, event, handler) - event binding\r\n */\r\n on(event: keyof types.ClientManagerHooks, callback: any): this;\r\n on<K extends keyof HTMLElementEventMap>(\r\n target: EventTarget,\r\n event: K | string,\r\n handler: EventListener,\r\n options?: AddEventListenerOptions\r\n ): () => void;\r\n on(\r\n eventOrTarget: keyof types.ClientManagerHooks | EventTarget,\r\n callbackOrEvent?: any,\r\n handler?: EventListener,\r\n options?: AddEventListenerOptions\r\n ): this | (() => void) {\r\n // Check if this is a lifecycle hook call\r\n if (typeof eventOrTarget === 'string' && eventOrTarget.startsWith('on')) {\r\n this.hooks[eventOrTarget as keyof types.ClientManagerHooks] = callbackOrEvent;\r\n return this;\r\n }\r\n\r\n // Otherwise it's an event binding\r\n return this.eventsManager.on(\r\n eventOrTarget as EventTarget,\r\n callbackOrEvent as string,\r\n handler as EventListener,\r\n options\r\n );\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Bootstrap the app - Phase 1: BOOT\r\n */\r\n async boot(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Already booted or destroyed');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: BOOT');\r\n\r\n try {\r\n // Call extensions onBoot hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onBoot) {\r\n this.log(`→ Extension onBoot: ${extension.name}`);\r\n await extension.onBoot({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onBoot hook\r\n if (this.hooks.onBoot) {\r\n this.log('→ Calling onBoot hook');\r\n await this.hooks.onBoot();\r\n }\r\n\r\n this.log('✓ BOOT phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Boot failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Ready the app - Phase 2: READY\r\n * Mount to DOM and make everything live\r\n *\r\n * Root selector is always 'body'.\r\n */\r\n async ready(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Cannot ready - not in booting phase');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: READY');\r\n\r\n try {\r\n const selector = 'body';\r\n\r\n // Set body id to 'root' for mounting\r\n (document.querySelector(selector) as HTMLElement).id = 'root';\r\n\r\n // Mount router\r\n this.mount(selector);\r\n\r\n this.log('→ Router mounted');\r\n\r\n // Call extensions onReady hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onReady) {\r\n this.log(`→ Extension onReady: ${extension.name}`);\r\n await extension.onReady({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onReady hook\r\n if (this.hooks.onReady) {\r\n this.log('→ Calling onReady hook');\r\n await this.hooks.onReady();\r\n }\r\n\r\n this.lifecycle = 'ready';\r\n this.log('✓ READY phase complete');\r\n this.log('✓ App is ready!');\r\n } catch (err) {\r\n console.error('[ClientManager] Ready failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown the app - Phase 3: DESTROY\r\n */\r\n async destroy(): Promise<void> {\r\n if (this.lifecycle === 'destroyed') {\r\n console.warn('[ClientManager] Already destroyed');\r\n return;\r\n }\r\n\r\n this.lifecycle = 'destroying';\r\n this.log('⚡ Phase: DESTROY');\r\n\r\n try {\r\n // Call extensions onDestroy hooks (in reverse order)\r\n for (let i = this.extensions.length - 1; i >= 0; i--) {\r\n const extension = this.extensions[i];\r\n if (extension.onDestroy) {\r\n this.log(`→ Extension onDestroy: ${extension.name}`);\r\n await extension.onDestroy({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onDestroy hook\r\n if (this.hooks.onDestroy) {\r\n this.log('→ Calling onDestroy hook');\r\n await this.hooks.onDestroy();\r\n }\r\n\r\n // Cleanup managers\r\n this.eventsManager.destroy();\r\n this.windowManager.destroy();\r\n\r\n this.lifecycle = 'destroyed';\r\n this.log('✓ DESTROY phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Destroy failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Navigate to path\r\n */\r\n navigate(path: string): void {\r\n this.router.push(path);\r\n }\r\n\r\n /**\r\n * Mount router to DOM element and setup reactive routing\r\n * Automatically re-renders when route changes\r\n * If rootLayout is provided, it wraps all pages\r\n */\r\n mount(selector: string | HTMLElement): void {\r\n const container = typeof selector === 'string'\r\n ? (document.querySelector(selector) as HTMLElement)\r\n : selector;\r\n\r\n if (!container) {\r\n console.warn('[ClientManager] Mount target not found:', selector);\r\n return;\r\n }\r\n\r\n let pageContainer = container;\r\n\r\n // If rootLayout is provided, mount it first (only once)\r\n if (this.config.rootLayout) {\r\n try {\r\n const layoutJsx = this.config.rootLayout();\r\n if (layoutJsx) {\r\n mountJSX(layoutJsx, container);\r\n this.log('→ Root layout mounted');\r\n\r\n // Find the page slot for rendering pages\r\n const pageSlot = container.querySelector('#main-overlay');\r\n if (pageSlot) {\r\n pageContainer = pageSlot as HTMLElement;\r\n } else {\r\n console.warn('[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.');\r\n }\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering root layout:', err);\r\n container.innerHTML = '<p>Error loading root layout</p>';\r\n return;\r\n }\r\n }\r\n\r\n // Setup reactive routing effect - re-renders when currentPathSignal changes\r\n effect(() => {\r\n const currentPath = this.currentPathSignal();\r\n const Component = this.routeComponents[currentPath]\r\n || this.config.notFoundComponent\r\n || null;\r\n\r\n // Clear only the page container (not the entire root if layout exists)\r\n pageContainer.innerHTML = '';\r\n\r\n if (Component) {\r\n try {\r\n const jsx = Component();\r\n // Use @minejs/jsx mount function to properly render JSX\r\n if (jsx) {\r\n mountJSX(jsx, pageContainer);\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering component:', currentPath, err);\r\n pageContainer.innerHTML = '<p>Error loading component</p>';\r\n }\r\n } else {\r\n pageContainer.innerHTML = '<p>No component found for this route</p>';\r\n }\r\n\r\n this.log(`→ Route changed to: ${currentPath}`);\r\n });\r\n\r\n // Trigger initial render by pushing the current path\r\n // this.router.push(this.currentPathSignal());\r\n this.log('→ Routing setup complete');\r\n }\r\n\r\n /**\r\n * Get current path signal for reactivity\r\n */\r\n getCurrentPath() {\r\n return this.currentPathSignal;\r\n }\r\n\r\n /**\r\n * Create navigation link handler\r\n */\r\n createLinkHandler(path: string) {\r\n return (e: MouseEvent) => {\r\n e.preventDefault();\r\n this.navigate(path);\r\n };\r\n }\r\n\r\n /**\r\n * Get underlying router for advanced usage\r\n */\r\n getRouter() {\r\n return this.router;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Unbind event\r\n */\r\n off(target: EventTarget, event: string, handler: EventListener): void {\r\n this.eventsManager.off(target, event, handler);\r\n }\r\n\r\n /**\r\n * Get events manager directly\r\n */\r\n getEventsManager(): EventsManager {\r\n return this.eventsManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get viewport info as reactive signal\r\n */\r\n getViewport() {\r\n return this.windowManager.getViewport();\r\n }\r\n\r\n /**\r\n * Get window manager directly\r\n */\r\n getWindowManager(): WindowManager {\r\n return this.windowManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get i18n instance for translations\r\n */\r\n getI18n() {\r\n return (window as any).__i18n;\r\n }\r\n\r\n /**\r\n * Get translation string\r\n */\r\n t(key: string, params?: any, defaultValue?: string) {\r\n if (!(window as any).__i18n) {\r\n console.warn('[ClientManager] i18n not initialized. Using default value or key.');\r\n return defaultValue ?? key;\r\n }\r\n return (window as any).__i18n.t(key, params) ?? defaultValue ?? key;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get lifecycle phase\r\n */\r\n getPhase() {\r\n return this.lifecycle;\r\n }\r\n\r\n /**\r\n * Check if ready\r\n */\r\n isReady(): boolean {\r\n return this.lifecycle === 'ready';\r\n }\r\n\r\n /**\r\n * Internal logging\r\n */\r\n private log(message: string): void {\r\n if (this.debug) {\r\n console.log(`[ClientManager] ${message}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n // Quick access\r\n export const CM = (): ClientManager | undefined => globalClientManagerInstance;\r\n\r\n // Router\r\n export const getRouter = () => CM()?.getRouter();\r\n export const back = () => getRouter()?.back();\r\n export const forward = () => getRouter()?.forward();\r\n export const push = (path: string) => getRouter()?.push(path);\r\n export const replace = (path: string) => getRouter()?.replace(path);\r\n\r\n // i18n\r\n export const getI18n = () => CM()?.getI18n();\r\n export const getLang = () => getI18n()?.getLanguage();\r\n export const setLang = (lang: string) => getI18n()?.setLanguage(lang);\r\n export const t = (key: string, params?: any, defaultValue?: string) => CM()?.t(key, params, defaultValue);\r\n export const tLang = (lang: string, key: string, params?: any, defaultValue?: string) => getI18n()?.tLang(lang, key, params, defaultValue) ?? (defaultValue ?? key);\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientManagerConfig } from './types';\r\n import { ClientManager } from './mod/manager';\r\n import { setupI18n } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n export * from './types';\r\n export * from './mod/manager';\r\n\r\n // Start\r\n export async function start(config: ClientManagerConfig): Promise<ClientManager> {\r\n // Read i18n config from HTML meta tag (injected by server)\r\n const metaI18n = document.querySelector('meta[name=\"app-i18n\"]');\r\n if (metaI18n) {\r\n const i18nData = JSON.parse(metaI18n.getAttribute('content') || '{}');\r\n config.i18n = i18nData;\r\n }\r\n\r\n // Create ClientManager instance\r\n const manager = new ClientManager(config);\r\n\r\n // Phase 0: Setup I18N\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (window as any).__i18n = await setupI18n(config.i18n || {\r\n defaultLanguage: 'en',\r\n supportedLanguages: ['en'],\r\n });\r\n\r\n // Phase 1: BOOT\r\n manager.boot();\r\n\r\n // Phase 2: READY\r\n manager.ready();\r\n\r\n // Handle cleanup on page unload\r\n window.addEventListener('beforeunload', async () => {\r\n await manager.destroy();\r\n });\r\n\r\n return manager;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/mod/router.ts","../src/mod/manager.ts","../src/index.ts"],"names":["NavigationError","code","message","cause","RouteNode","segment","route","children","paramName","isWildcard","RouteMatcher","parentPath","fullPath","segments","node","isParam","key","child","pathname","params","matchedRoute","paramNode","url","Router","config","signal","error","handler","hash","e","target","options","pathOnly","queryString","pattern","finalQueryString","finalPathname","match","err","meta","descMeta","newMeta","to","from","guard","result","_options","previousRoute","context","data","behavior","scrollBehavior","path","delta","exact","current","index","param","blank","pathWithQuery","globalRouter","createRouter","globalClientManagerInstance","ClientManager","EventsManager","WindowManager","routesArray","component","eventOrTarget","callbackOrEvent","extension","selector","i","container","pageContainer","layoutJsx","mountJSX","pageSlot","effect","currentPath","Component","jsx","event","defaultValue","CM","getRouter","back","forward","push","replace","visit","getI18n","getLang","setLang","lang","_setLang","_setDir","_setCookie","t","tLang","start","metaI18n","i18nData","manager","setupI18n"],"mappings":"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","file":"index.js","sourcesContent":["// src/types.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n export type {\r\n RouteComponent,\r\n ThemeConfig,\r\n LangConfig,\r\n ClientExtension,\r\n ExtensionContext,\r\n ClientManagerHooks,\r\n ClientManagerConfig\r\n } from '@cruxjs/base';\r\n\r\n \r\n export type RouteParams = Record<string, string>;\r\n\r\n export interface RouteMatch {\r\n path: string\r\n params: RouteParams\r\n query: URLSearchParams\r\n hash: string\r\n route: Route\r\n }\r\n\r\n export interface RouteContext {\r\n params: RouteParams\r\n query: URLSearchParams\r\n request: Request\r\n pathname: string\r\n }\r\n\r\n export class NavigationError extends Error {\r\n constructor(\r\n public code: 'LOADER_ERROR' | 'ACTION_ERROR' | 'GUARD_ERROR' | 'ROUTE_NOT_FOUND',\r\n message: string,\r\n public cause?: Error\r\n ) {\r\n super(message);\r\n this.name = 'NavigationError';\r\n }\r\n }\r\n\r\n export type LoaderFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export type ActionFunction<T = any> = (\r\n context: RouteContext\r\n ) => T | Promise<T>;\r\n\r\n export interface Route {\r\n path: string\r\n component: () => any | Promise<any>\r\n loader?: LoaderFunction\r\n action?: ActionFunction\r\n children?: Route[]\r\n meta?: {\r\n title?: string\r\n description?: string\r\n [key: string]: any\r\n }\r\n errorComponent?: () => any\r\n }\r\n\r\n export interface NavigateOptions {\r\n replace?: boolean\r\n state?: any\r\n scroll?: boolean | 'smooth'\r\n }\r\n\r\n export interface RouterConfig {\r\n routes: Route[]\r\n base?: string\r\n mode?: 'history' | 'hash'\r\n scrollBehavior?: 'auto' | 'smooth' | 'instant'\r\n allowedQueryParams?: (string | RegExp)[]\r\n notFoundComponent?: () => any\r\n errorComponent?: () => any\r\n onError?: (error: NavigationError) => void\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/router.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { signal, computed, type Signal } from '@minejs/signals';\r\n import { jsx, Suspense } from '@minejs/jsx';\r\n import * as types from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n class RouteNode {\r\n constructor(\r\n public segment: string,\r\n public route: types.Route | null = null,\r\n public children: Map<string, RouteNode> = new Map(),\r\n public paramName?: string,\r\n public isWildcard = false\r\n ) { }\r\n }\r\n\r\n class RouteMatcher {\r\n private root = new RouteNode('');\r\n private wildcardRoute: types.Route | null = null;\r\n\r\n addRoute(route: types.Route, parentPath = ''): void {\r\n const fullPath = parentPath + route.path;\r\n\r\n // Handle wildcard routes\r\n if (fullPath === '/*' || fullPath === '*') {\r\n this.wildcardRoute = route;\r\n return;\r\n }\r\n\r\n const segments = fullPath.split('/').filter(Boolean);\r\n let node = this.root;\r\n\r\n for (const segment of segments) {\r\n const isParam = segment.startsWith(':');\r\n const key = isParam ? ':param' : segment;\r\n\r\n if (!node.children.has(key)) {\r\n node.children.set(key, new RouteNode(\r\n segment,\r\n null,\r\n new Map(),\r\n isParam ? segment.slice(1) : undefined\r\n ));\r\n }\r\n\r\n node = node.children.get(key)!;\r\n }\r\n\r\n node.route = route;\r\n\r\n // Add child routes recursively\r\n if (route.children) {\r\n route.children.forEach(child => this.addRoute(child, fullPath));\r\n }\r\n }\r\n\r\n match(pathname: string): types.RouteMatch | null {\r\n const segments = pathname.split('/').filter(Boolean);\r\n const params: types.RouteParams = {};\r\n\r\n let node = this.root;\r\n let matchedRoute: types.Route | null = null;\r\n\r\n for (const segment of segments) {\r\n // Try exact match first\r\n if (node.children.has(segment)) {\r\n node = node.children.get(segment)!;\r\n }\r\n // Try param match\r\n else if (node.children.has(':param')) {\r\n const paramNode = node.children.get(':param')!;\r\n params[paramNode.paramName!] = decodeURIComponent(segment);\r\n node = paramNode;\r\n }\r\n // No exact match - try wildcard\r\n else {\r\n matchedRoute = this.wildcardRoute;\r\n break;\r\n }\r\n }\r\n\r\n matchedRoute = matchedRoute || node.route;\r\n\r\n if (!matchedRoute) {\r\n return null;\r\n }\r\n\r\n const url = new URL(window.location.href);\r\n\r\n return {\r\n path: pathname,\r\n params,\r\n query: url.searchParams,\r\n hash: url.hash.slice(1),\r\n route: matchedRoute\r\n };\r\n }\r\n }\r\n\r\n export class Router {\r\n private matcher = new RouteMatcher();\r\n private config : types.RouterConfig;\r\n\r\n // Reactive state\r\n public currentRoute = signal<types.RouteMatch | null>(null);\r\n public isNavigating = signal(false);\r\n public loaderData = signal<any>(null);\r\n public error = signal<types.NavigationError | null>(null);\r\n\r\n // History\r\n private history : types.RouteMatch[] = [];\r\n private historyIndex = 0;\r\n private maxHistory = 50; // Prevent memory leaks\r\n\r\n // Guards\r\n private beforeEachGuards: ((to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>)[] = [];\r\n private afterEachGuards : ((to: types.RouteMatch, from: types.RouteMatch | null) => void)[] = [];\r\n private onErrorHandlers: ((error: types.NavigationError) => void)[] = [];\r\n\r\n constructor(config: types.RouterConfig) {\r\n this.config = {\r\n mode : 'history',\r\n base : '',\r\n scrollBehavior : 'auto',\r\n ...config\r\n };\r\n\r\n // Add error handler\r\n if (config.onError) {\r\n this.onErrorHandlers.push(config.onError);\r\n }\r\n\r\n // Build route tree\r\n config.routes.forEach(route => this.matcher.addRoute(route));\r\n\r\n // Listen to browser navigation\r\n this.setupListeners();\r\n\r\n // Initial route - handle synchronously for basic setup\r\n this.performNavigation(window.location.pathname + window.location.search);\r\n }\r\n\r\n private emitError(error: types.NavigationError): void {\r\n this.error.set(error);\r\n this.onErrorHandlers.forEach(handler => handler(error));\r\n }\r\n\r\n private setupListeners(): void {\r\n if (this.config.mode === 'history') {\r\n window.addEventListener('popstate', () => {\r\n this.handleNavigation(window.location.pathname + window.location.search);\r\n });\r\n } else {\r\n window.addEventListener('hashchange', () => {\r\n const hash = window.location.hash.slice(1);\r\n this.handleNavigation(hash || '/');\r\n });\r\n }\r\n\r\n // Intercept link clicks\r\n document.addEventListener('click', (e) => {\r\n const target = (e.target as HTMLElement).closest('a');\r\n\r\n if (!target || !target.href) return;\r\n\r\n // Check if it's a same-origin link\r\n const url = new URL(target.href);\r\n if (url.origin !== window.location.origin) return;\r\n\r\n // Check if it should be handled by router\r\n if (target.hasAttribute('data-external')) return;\r\n if (target.getAttribute('target') === '_blank') return;\r\n if (e.ctrlKey || e.metaKey || e.shiftKey) return;\r\n\r\n e.preventDefault();\r\n this.push(url.pathname + url.search);\r\n });\r\n }\r\n\r\n private performNavigation(pathname: string, options: types.NavigateOptions = {}): void {\r\n try {\r\n // Extract path and query string\r\n const [pathOnly, queryString] = pathname.split('?');\r\n \r\n // Parse and filter query params\r\n const url = new URL('http://localhost' + pathOnly + (queryString ? '?' + queryString : ''));\r\n \r\n if (this.config.allowedQueryParams && this.config.allowedQueryParams.length > 0) {\r\n const keys = Array.from(url.searchParams.keys());\r\n keys.forEach(key => {\r\n const isAllowed = this.config.allowedQueryParams!.some(pattern => {\r\n if (typeof pattern === 'string') return pattern === key;\r\n return pattern.test(key);\r\n });\r\n \r\n if (!isAllowed) {\r\n url.searchParams.delete(key);\r\n }\r\n });\r\n }\r\n\r\n const finalQueryString = url.searchParams.toString();\r\n const finalPathname = pathOnly + (finalQueryString ? '?' + finalQueryString : '');\r\n\r\n const match = this.matcher.match(pathOnly);\r\n\r\n if (!match) {\r\n const error = new types.NavigationError('ROUTE_NOT_FOUND', `No route matched: ${pathOnly}`);\r\n this.emitError(error);\r\n return;\r\n }\r\n\r\n // Update browser history first (so window.location is correct for subsequent operations)\r\n if (this.config.mode === 'history') {\r\n if (options.replace) {\r\n window.history.replaceState(options.state || {}, '', finalPathname);\r\n } else {\r\n window.history.pushState(options.state || {}, '', finalPathname);\r\n }\r\n } else {\r\n window.location.hash = finalPathname;\r\n }\r\n\r\n match.query = url.searchParams;\r\n match.path = pathOnly;\r\n\r\n // Check guards synchronously (if they're not async)\r\n const canNavigate = this.checkSyncGuards(match, this.currentRoute());\r\n if (canNavigate === false) {\r\n // Revert history if navigation was prevented\r\n window.history.back();\r\n return;\r\n }\r\n\r\n // Clear previous error\r\n this.error.set(null);\r\n\r\n // Update current route immediately (synchronously)\r\n this.currentRoute.set(match);\r\n\r\n // Handle scroll\r\n this.handleScroll(options.scroll);\r\n\r\n // Update document title and meta tags\r\n this.updateMetaTags(match.route.meta);\r\n\r\n // Manage history size to prevent memory leaks\r\n this.pruneHistory();\r\n\r\n // Add to history\r\n this.history.push(match);\r\n this.historyIndex = this.history.length - 1;\r\n\r\n // Run async operations in background\r\n this.runAsyncNavigation(pathname, match, options);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Navigation failed: ' + String(err),\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private updateMetaTags(meta?: Record<string, any>): void {\r\n if (!meta) return;\r\n\r\n if (meta.title) {\r\n document.title = meta.title;\r\n }\r\n if (meta.description) {\r\n const descMeta = document.querySelector('meta[name=\"description\"]') as HTMLMetaElement | null;\r\n if (descMeta) {\r\n descMeta.content = meta.description;\r\n } else {\r\n const newMeta = document.createElement('meta');\r\n newMeta.name = 'description';\r\n newMeta.content = meta.description;\r\n document.head.appendChild(newMeta);\r\n }\r\n }\r\n }\r\n\r\n private pruneHistory(): void {\r\n if (this.history.length > this.maxHistory) {\r\n this.history = this.history.slice(-this.maxHistory);\r\n this.historyIndex = this.history.length - 1;\r\n }\r\n }\r\n\r\n private checkSyncGuards(to: types.RouteMatch, from: types.RouteMatch | null): boolean | undefined {\r\n // If no guards, return undefined (allow)\r\n if (this.beforeEachGuards.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // Check guards - if any are async, we'll check them in runAsyncNavigation\r\n for (const guard of this.beforeEachGuards) {\r\n const result = guard(to, from);\r\n // If we got a Promise, we can't handle it synchronously\r\n if (result instanceof Promise) {\r\n return undefined; // Let async handler deal with it\r\n }\r\n if (result === false) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private async runAsyncNavigation(pathname: string, match: types.RouteMatch, _options: types.NavigateOptions): Promise<void> {\r\n try {\r\n // Run beforeEach guards (including async ones)\r\n const canNavigate = await this.runBeforeEachGuards(match, match);\r\n if (!canNavigate) {\r\n // Revert - remove from current and history\r\n this.currentRoute.set(null);\r\n this.history.pop();\r\n this.historyIndex = Math.max(-1, this.history.length - 1);\r\n // Revert in browser\r\n window.history.back();\r\n return;\r\n }\r\n\r\n const previousRoute = match;\r\n\r\n // Set navigating state\r\n this.isNavigating.set(true);\r\n\r\n try {\r\n // Run loader if exists\r\n if (match.route.loader) {\r\n const context: types.RouteContext = {\r\n params: match.params,\r\n query: match.query,\r\n request: new Request(window.location.href),\r\n pathname\r\n };\r\n\r\n try {\r\n const data = await match.route.loader(context);\r\n this.loaderData.set(data);\r\n } catch (err) {\r\n const error = new types.NavigationError(\r\n 'LOADER_ERROR',\r\n `Failed to load data for ${pathname}`,\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n throw error;\r\n }\r\n } else {\r\n this.loaderData.set(null);\r\n }\r\n\r\n // Run afterEach guards\r\n this.runAfterEachGuards(match, previousRoute);\r\n\r\n } finally {\r\n this.isNavigating.set(false);\r\n }\r\n } catch (err) {\r\n if (err instanceof types.NavigationError) {\r\n throw err;\r\n }\r\n const error = new types.NavigationError(\r\n 'GUARD_ERROR',\r\n 'Async navigation failed',\r\n err instanceof Error ? err : undefined\r\n );\r\n this.emitError(error);\r\n }\r\n }\r\n\r\n private async handleNavigation(pathname: string, options: types.NavigateOptions = {}): Promise<void> {\r\n this.performNavigation(pathname, options);\r\n }\r\n\r\n private async runBeforeEachGuards(\r\n to: types.RouteMatch,\r\n from: types.RouteMatch | null\r\n ): Promise<boolean> {\r\n for (const guard of this.beforeEachGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) return false;\r\n }\r\n return true;\r\n }\r\n\r\n private runAfterEachGuards(to: types.RouteMatch, from: types.RouteMatch | null): void {\r\n this.afterEachGuards.forEach(guard => guard(to, from));\r\n }\r\n\r\n private handleScroll(behavior?: boolean | 'smooth'): void {\r\n if (behavior === false) return;\r\n\r\n const scrollBehavior = typeof behavior === 'string'\r\n ? behavior\r\n : this.config.scrollBehavior;\r\n\r\n if (typeof window !== 'undefined' && window.scrollTo) {\r\n window.scrollTo({\r\n top: 0,\r\n left: 0,\r\n behavior: scrollBehavior === 'smooth' ? 'smooth' : 'auto'\r\n });\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // PUBLIC API\r\n // ============================================================================\r\n\r\n /**\r\n * Navigate to a path\r\n */\r\n public push(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: false });\r\n }\r\n\r\n /**\r\n * Replace current route\r\n */\r\n public replace(path: string, options: types.NavigateOptions = {}): void {\r\n this.handleNavigation(path, { ...options, replace: true });\r\n }\r\n\r\n /**\r\n * Go back in history\r\n */\r\n public back(): void {\r\n window.history.back();\r\n }\r\n\r\n /**\r\n * Go forward in history\r\n */\r\n public forward(): void {\r\n window.history.forward();\r\n }\r\n\r\n /**\r\n * Go to specific history entry\r\n */\r\n public go(delta: number): void {\r\n window.history.go(delta);\r\n }\r\n\r\n /**\r\n * Check if path is active\r\n */\r\n public isActive(path: string, exact = false): boolean {\r\n const current = this.currentRoute();\r\n if (!current) return false;\r\n\r\n if (exact) {\r\n return current.path === path;\r\n }\r\n\r\n return current.path.startsWith(path);\r\n }\r\n\r\n /**\r\n * Get current params\r\n */\r\n public getParams(): types.RouteParams {\r\n return this.currentRoute()?.params || {};\r\n }\r\n\r\n /**\r\n * Get current query\r\n */\r\n public getQuery(): URLSearchParams {\r\n return this.currentRoute()?.query || new URLSearchParams();\r\n }\r\n\r\n /**\r\n * Register beforeEach guard\r\n */\r\n public beforeEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => boolean | Promise<boolean>\r\n ): () => void {\r\n this.beforeEachGuards.push(guard);\r\n return () => {\r\n const index = this.beforeEachGuards.indexOf(guard);\r\n if (index > -1) this.beforeEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register afterEach guard\r\n */\r\n public afterEach(\r\n guard: (to: types.RouteMatch, from: types.RouteMatch | null) => void\r\n ): () => void {\r\n this.afterEachGuards.push(guard);\r\n return () => {\r\n const index = this.afterEachGuards.indexOf(guard);\r\n if (index > -1) this.afterEachGuards.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Register error handler\r\n */\r\n public onError(handler: (error: types.NavigationError) => void): () => void {\r\n this.onErrorHandlers.push(handler);\r\n return () => {\r\n const index = this.onErrorHandlers.indexOf(handler);\r\n if (index > -1) this.onErrorHandlers.splice(index, 1);\r\n };\r\n }\r\n\r\n /**\r\n * Add a query param to the whitelist\r\n */\r\n public addAllowedQueryParam(param: string | RegExp): void {\r\n if (!this.config.allowedQueryParams) {\r\n this.config.allowedQueryParams = [];\r\n }\r\n this.config.allowedQueryParams.push(param);\r\n }\r\n\r\n /**\r\n * Visit an external link\r\n */\r\n public visit(url: string, blank?: boolean): void {\r\n if (blank ?? true) {\r\n window.open(url, '_blank');\r\n } else {\r\n window.location.href = url;\r\n }\r\n }\r\n\r\n /**\r\n * Reload current route\r\n */\r\n public async reload(): Promise<void> {\r\n const current = this.currentRoute();\r\n if (current) {\r\n const queryString = current.query.toString();\r\n const pathWithQuery = current.path + (queryString ? '?' + queryString : '');\r\n await this.handleNavigation(pathWithQuery, { replace: true });\r\n }\r\n }\r\n\r\n /**\r\n * Destroy router and cleanup\r\n */\r\n public destroy(): void {\r\n this.history = [];\r\n this.beforeEachGuards = [];\r\n this.afterEachGuards = [];\r\n this.onErrorHandlers = [];\r\n this.currentRoute.set(null);\r\n this.loaderData.set(null);\r\n this.error.set(null);\r\n }\r\n }\r\n\r\n let globalRouter: Router | null = null;\r\n\r\n export function createRouter(config: types.RouterConfig): Router {\r\n globalRouter = new Router(config);\r\n return globalRouter;\r\n }\r\n\r\n export function useRouter(): Router {\r\n if (!globalRouter) {\r\n throw new Error('Router not initialized. Call createRouter() first.');\r\n }\r\n return globalRouter;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HOOK ════════════════════════════════════════╗\r\n\r\n export function useRoute(): Signal<types.RouteMatch | null> {\r\n return useRouter().currentRoute;\r\n }\r\n\r\n export function useParams(): types.RouteParams {\r\n return useRouter().getParams();\r\n }\r\n\r\n export function useQuery(): URLSearchParams {\r\n return useRouter().getQuery();\r\n }\r\n\r\n export function useLoaderData<T = any>(): Signal<T | null> {\r\n return useRouter().loaderData as Signal<T | null>;\r\n }\r\n\r\n export function useNavigate() {\r\n const router = useRouter();\r\n\r\n return {\r\n push: (path: string, options?: types.NavigateOptions) => router.push(path, options),\r\n replace: (path: string, options?: types.NavigateOptions) => router.replace(path, options),\r\n back: () => router.back(),\r\n forward: () => router.forward(),\r\n go: (delta: number) => router.go(delta),\r\n visit: (url: string, blank?: boolean) => router.visit(url, blank)\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\r\n\r\n /**\r\n * Link component with active state\r\n */\r\n export function Link(props: {\r\n to : string\r\n children : any\r\n activeClass? : string\r\n exact? : boolean\r\n replace? : boolean\r\n className? : string\r\n [key: string] : any\r\n }) {\r\n const router = useRouter();\r\n const isActive = computed(() => router.isActive(props.to, props.exact));\r\n\r\n const className = computed(() => {\r\n let classes = props.className || '';\r\n if (isActive() && props.activeClass) {\r\n classes += ' ' + props.activeClass;\r\n }\r\n return classes.trim();\r\n });\r\n\r\n const handleClick = (e: Event) => {\r\n e.preventDefault();\r\n\r\n if (props.replace) {\r\n router.replace(props.to);\r\n } else {\r\n router.push(props.to);\r\n }\r\n };\r\n\r\n return jsx('a', {\r\n href : props.to,\r\n className : className(),\r\n onClick : handleClick,\r\n 'data-active' : isActive(),\r\n children : props.children\r\n });\r\n }\r\n\r\n /**\r\n * Router outlet - renders current route component with error boundary\r\n */\r\n export function RouterOutlet() {\r\n const router = useRouter();\r\n const route = router.currentRoute;\r\n const error = router.error;\r\n\r\n return computed(() => {\r\n const currentRoute = route();\r\n const currentError = error();\r\n\r\n // Show error component if error occurred\r\n if (currentError) {\r\n const errorComponent = currentRoute?.route.errorComponent || router.currentRoute()?.route.meta?.errorComponent;\r\n if (errorComponent) {\r\n return errorComponent();\r\n }\r\n // Fallback error display\r\n return jsx('div', {\r\n style: { color: 'red', padding: '20px' },\r\n children: `Navigation Error: ${currentError.message}`\r\n });\r\n }\r\n\r\n if (!currentRoute) {\r\n const notFoundComponent = (router.currentRoute() as any)?.config?.notFoundComponent;\r\n if (notFoundComponent) {\r\n return notFoundComponent();\r\n }\r\n return null;\r\n }\r\n\r\n // Load and render component\r\n const component = currentRoute.route.component();\r\n\r\n if (component instanceof Promise) {\r\n // Async component\r\n return jsx(Suspense, {\r\n fallback: jsx('div', { children: 'Loading...' }),\r\n children: component\r\n });\r\n }\r\n\r\n return component;\r\n });\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ UTIL ════════════════════════════════════════╗\r\n\r\n /**\r\n * Build URL with params\r\n */\r\n export function buildPath(path: string, params: types.RouteParams): string {\r\n let result = path;\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n result = result.replace(`:${key}`, encodeURIComponent(value));\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Parse query string to object\r\n */\r\n export function parseQuery(search: string): Record<string, string> {\r\n const params = new URLSearchParams(search);\r\n const result: Record<string, string> = {};\r\n\r\n params.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Stringify object to query string\r\n */\r\n export function stringifyQuery(obj: Record<string, any>): string {\r\n const params = new URLSearchParams();\r\n\r\n Object.entries(obj).forEach(([key, value]) => {\r\n if (value != null) {\r\n params.append(key, String(value));\r\n }\r\n });\r\n\r\n return params.toString();\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export default {\r\n createRouter,\r\n useRouter,\r\n useRoute,\r\n useParams,\r\n useQuery,\r\n useLoaderData,\r\n useNavigate,\r\n Link,\r\n RouterOutlet,\r\n buildPath,\r\n parseQuery,\r\n stringifyQuery,\r\n Router,\r\n NavigationError: types.NavigationError\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/mod/manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import * as types from '../types';\r\n import { signal, effect } from '@minejs/signals';\r\n import { mount as mountJSX } from '@minejs/jsx';\r\n import { EventsManager, WindowManager } from '@minejs/browser';\r\n import { Router, createRouter } from './router';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n let globalClientManagerInstance: ClientManager | undefined;\r\n\r\n export class ClientManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n private router : Router;\r\n private eventsManager : EventsManager;\r\n private windowManager : WindowManager;\r\n private lifecycle : 'booting' | 'ready' | 'destroying' | 'destroyed' = 'booting';\r\n private config : types.ClientManagerConfig;\r\n private hooks : types.ClientManagerHooks = {};\r\n private extensions : types.ClientExtension[] = [];\r\n private debug : boolean;\r\n private routeComponents : Record<string, types.RouteComponent> = {};\r\n private currentPathSignal = signal<string>(window.location.pathname ?? '/');\r\n\r\n constructor(config: types.ClientManagerConfig) {\r\n this.config = config;\r\n this.debug = config.debug ?? false;\r\n\r\n this.log('[INIT] Creating ClientManager');\r\n\r\n // Merge lifecycle hooks from config\r\n if (config.lifecycle) {\r\n this.hooks = { ...config.lifecycle };\r\n }\r\n\r\n // Store extensions from config\r\n this.extensions = config.extensions ?? [];\r\n\r\n // Store route components provided by user\r\n this.routeComponents = config.routes;\r\n\r\n // Initialize managers from @minejs/browser\r\n this.eventsManager = new EventsManager();\r\n this.windowManager = new WindowManager();\r\n\r\n // Initialize router with user-provided routes\r\n const routesArray = Object.entries(config.routes).map(([path, component]) => ({\r\n path,\r\n component\r\n }));\r\n\r\n this.router = createRouter({\r\n routes: routesArray,\r\n notFoundComponent: config.notFoundComponent,\r\n allowedQueryParams: config.allowedQueryParams\r\n });\r\n\r\n // Connect router changes to signal for automatic re-rendering\r\n this.router.afterEach((to) => {\r\n this.currentPathSignal.set(to.path);\r\n });\r\n\r\n // Store clientManager instance\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n globalClientManagerInstance = this;\r\n\r\n this.log('[INIT] ClientManager created');\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Setup lifecycle hooks OR bind events\r\n * Overloaded: on(event: 'onBoot'|'onReady'|'onDestroy', callback) - lifecycle\r\n * on(target, event, handler) - event binding\r\n */\r\n on(event: keyof types.ClientManagerHooks, callback: any): this;\r\n on<K extends keyof HTMLElementEventMap>(\r\n target: EventTarget,\r\n event: K | string,\r\n handler: EventListener,\r\n options?: AddEventListenerOptions\r\n ): () => void;\r\n on(\r\n eventOrTarget: keyof types.ClientManagerHooks | EventTarget,\r\n callbackOrEvent?: any,\r\n handler?: EventListener,\r\n options?: AddEventListenerOptions\r\n ): this | (() => void) {\r\n // Check if this is a lifecycle hook call\r\n if (typeof eventOrTarget === 'string' && eventOrTarget.startsWith('on')) {\r\n this.hooks[eventOrTarget as keyof types.ClientManagerHooks] = callbackOrEvent;\r\n return this;\r\n }\r\n\r\n // Otherwise it's an event binding\r\n return this.eventsManager.on(\r\n eventOrTarget as EventTarget,\r\n callbackOrEvent as string,\r\n handler as EventListener,\r\n options\r\n );\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Bootstrap the app - Phase 1: BOOT\r\n */\r\n async boot(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Already booted or destroyed');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: BOOT');\r\n\r\n try {\r\n // Call extensions onBoot hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onBoot) {\r\n this.log(`→ Extension onBoot: ${extension.name}`);\r\n await extension.onBoot({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onBoot hook\r\n if (this.hooks.onBoot) {\r\n this.log('→ Calling onBoot hook');\r\n await this.hooks.onBoot();\r\n }\r\n\r\n this.log('✓ BOOT phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Boot failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Ready the app - Phase 2: READY\r\n * Mount to DOM and make everything live\r\n *\r\n * Root selector is always 'body'.\r\n */\r\n async ready(): Promise<void> {\r\n if (this.lifecycle !== 'booting') {\r\n console.warn('[ClientManager] Cannot ready - not in booting phase');\r\n return;\r\n }\r\n\r\n this.log('⚡ Phase: READY');\r\n\r\n try {\r\n const selector = 'body';\r\n\r\n // Set body id to 'root' for mounting\r\n (document.querySelector(selector) as HTMLElement).id = 'root';\r\n\r\n // Mount router\r\n this.mount(selector);\r\n\r\n this.log('→ Router mounted');\r\n\r\n // Call extensions onReady hooks\r\n for (const extension of this.extensions) {\r\n if (extension.onReady) {\r\n this.log(`→ Extension onReady: ${extension.name}`);\r\n await extension.onReady({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onReady hook\r\n if (this.hooks.onReady) {\r\n this.log('→ Calling onReady hook');\r\n await this.hooks.onReady();\r\n }\r\n\r\n this.lifecycle = 'ready';\r\n this.log('✓ READY phase complete');\r\n this.log('✓ App is ready!');\r\n } catch (err) {\r\n console.error('[ClientManager] Ready failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown the app - Phase 3: DESTROY\r\n */\r\n async destroy(): Promise<void> {\r\n if (this.lifecycle === 'destroyed') {\r\n console.warn('[ClientManager] Already destroyed');\r\n return;\r\n }\r\n\r\n this.lifecycle = 'destroying';\r\n this.log('⚡ Phase: DESTROY');\r\n\r\n try {\r\n // Call extensions onDestroy hooks (in reverse order)\r\n for (let i = this.extensions.length - 1; i >= 0; i--) {\r\n const extension = this.extensions[i];\r\n if (extension.onDestroy) {\r\n this.log(`→ Extension onDestroy: ${extension.name}`);\r\n await extension.onDestroy({\r\n debug: this.debug,\r\n config: {},\r\n cconfig: this.config\r\n });\r\n }\r\n }\r\n\r\n // Call user onDestroy hook\r\n if (this.hooks.onDestroy) {\r\n this.log('→ Calling onDestroy hook');\r\n await this.hooks.onDestroy();\r\n }\r\n\r\n // Cleanup managers\r\n this.eventsManager.destroy();\r\n this.windowManager.destroy();\r\n\r\n this.lifecycle = 'destroyed';\r\n this.log('✓ DESTROY phase complete');\r\n } catch (err) {\r\n console.error('[ClientManager] Destroy failed:', err);\r\n throw err;\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Navigate to path\r\n */\r\n navigate(path: string): void {\r\n this.router.push(path);\r\n }\r\n\r\n /**\r\n * Mount router to DOM element and setup reactive routing\r\n * Automatically re-renders when route changes\r\n * If rootLayout is provided, it wraps all pages\r\n */\r\n mount(selector: string | HTMLElement): void {\r\n const container = typeof selector === 'string'\r\n ? (document.querySelector(selector) as HTMLElement)\r\n : selector;\r\n\r\n if (!container) {\r\n console.warn('[ClientManager] Mount target not found:', selector);\r\n return;\r\n }\r\n\r\n let pageContainer = container;\r\n\r\n // If rootLayout is provided, mount it first (only once)\r\n if (this.config.rootLayout) {\r\n try {\r\n const layoutJsx = this.config.rootLayout();\r\n if (layoutJsx) {\r\n mountJSX(layoutJsx, container);\r\n this.log('→ Root layout mounted');\r\n\r\n // Find the page slot for rendering pages\r\n const pageSlot = container.querySelector('#main-overlay');\r\n if (pageSlot) {\r\n pageContainer = pageSlot as HTMLElement;\r\n } else {\r\n console.warn('[ClientManager] Page slot #main-overlay not found in root layout. Pages will render to the root container.');\r\n }\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering root layout:', err);\r\n container.innerHTML = '<p>Error loading root layout</p>';\r\n return;\r\n }\r\n }\r\n\r\n // Setup reactive routing effect - re-renders when currentPathSignal changes\r\n effect(() => {\r\n const currentPath = this.currentPathSignal();\r\n const Component = this.routeComponents[currentPath]\r\n || this.config.notFoundComponent\r\n || null;\r\n\r\n // Clear only the page container (not the entire root if layout exists)\r\n pageContainer.innerHTML = '';\r\n\r\n if (Component) {\r\n try {\r\n const jsx = Component();\r\n // Use @minejs/jsx mount function to properly render JSX\r\n if (jsx) {\r\n mountJSX(jsx, pageContainer);\r\n }\r\n } catch (err) {\r\n console.error('[ClientManager] Error rendering component:', currentPath, err);\r\n pageContainer.innerHTML = '<p>Error loading component</p>';\r\n }\r\n } else {\r\n pageContainer.innerHTML = '<p>No component found for this route</p>';\r\n }\r\n\r\n this.log(`→ Route changed to: ${currentPath}`);\r\n });\r\n\r\n // Trigger initial render by pushing the current path\r\n // this.router.push(this.currentPathSignal());\r\n this.log('→ Routing setup complete');\r\n }\r\n\r\n /**\r\n * Get current path signal for reactivity\r\n */\r\n getCurrentPath() {\r\n return this.currentPathSignal;\r\n }\r\n\r\n /**\r\n * Create navigation link handler\r\n */\r\n createLinkHandler(path: string) {\r\n return (e: MouseEvent) => {\r\n e.preventDefault();\r\n this.navigate(path);\r\n };\r\n }\r\n\r\n /**\r\n * Get underlying router for advanced usage\r\n */\r\n getRouter() {\r\n return this.router;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Unbind event\r\n */\r\n off(target: EventTarget, event: string, handler: EventListener): void {\r\n this.eventsManager.off(target, event, handler);\r\n }\r\n\r\n /**\r\n * Get events manager directly\r\n */\r\n getEventsManager(): EventsManager {\r\n return this.eventsManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get viewport info as reactive signal\r\n */\r\n getViewport() {\r\n return this.windowManager.getViewport();\r\n }\r\n\r\n /**\r\n * Get window manager directly\r\n */\r\n getWindowManager(): WindowManager {\r\n return this.windowManager;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get i18n instance for translations\r\n */\r\n getI18n() {\r\n return (window as any).__i18n;\r\n }\r\n\r\n /**\r\n * Get translation string\r\n */\r\n t(key: string, params?: any, defaultValue?: string) {\r\n if (!(window as any).__i18n) {\r\n console.warn('[ClientManager] i18n not initialized. Using default value or key.');\r\n return defaultValue ?? key;\r\n }\r\n return (window as any).__i18n.t(key, params) ?? defaultValue ?? key;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── ──── ──────────────────────────────┐\r\n\r\n /**\r\n * Get lifecycle phase\r\n */\r\n getPhase() {\r\n return this.lifecycle;\r\n }\r\n\r\n /**\r\n * Check if ready\r\n */\r\n isReady(): boolean {\r\n return this.lifecycle === 'ready';\r\n }\r\n\r\n /**\r\n * Internal logging\r\n */\r\n private log(message: string): void {\r\n if (this.debug) {\r\n console.log(`[ClientManager] ${message}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n // Quick access\r\n export const CM = (): ClientManager | undefined => globalClientManagerInstance;\r\n\r\n // Router\r\n export const getRouter = () => CM()?.getRouter();\r\n export const back = () => getRouter()?.back();\r\n export const forward = () => getRouter()?.forward();\r\n export const push = (path: string) => getRouter()?.push(path);\r\n export const replace = (path: string) => getRouter()?.replace(path);\r\n export const visit = (url: string, blank?: boolean) => getRouter()?.visit(url, blank);\r\n\r\n // i18n\r\n export const getI18n = () => CM()?.getI18n();\r\n export const getLang = () => getI18n()?.getLanguage();\r\n export const setLang = (lang: string, _setLang=true, _setDir=true, _setCookie=true) => getI18n()?.setLanguage(lang, _setLang, _setDir, _setCookie);\r\n export const t = (key: string, params?: any, defaultValue?: string) => CM()?.t(key, params, defaultValue);\r\n export const tLang = (lang: string, key: string, params?: any, defaultValue?: string) => getI18n()?.tLang(lang, key, params, defaultValue) ?? (defaultValue ?? key);\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientManagerConfig } from './types';\r\n import { ClientManager } from './mod/manager';\r\n import { setupI18n } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n export * from './types';\r\n export * from './mod/manager';\r\n\r\n // Start\r\n export async function start(config: ClientManagerConfig): Promise<ClientManager> {\r\n // Read i18n config from HTML meta tag (injected by server)\r\n const metaI18n = document.querySelector('meta[name=\"app-i18n\"]');\r\n if (metaI18n) {\r\n const i18nData = JSON.parse(metaI18n.getAttribute('content') || '{}');\r\n config.i18n = i18nData;\r\n }\r\n\r\n // Create ClientManager instance\r\n const manager = new ClientManager(config);\r\n\r\n // Phase 0: Setup I18N\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (window as any).__i18n = await setupI18n(config.i18n || {\r\n defaultLanguage: 'en',\r\n supportedLanguages: ['en'],\r\n });\r\n\r\n // Phase 1: BOOT\r\n manager.boot();\r\n\r\n // Phase 2: READY\r\n manager.ready();\r\n\r\n // Handle cleanup on page unload\r\n window.addEventListener('beforeunload', async () => {\r\n await manager.destroy();\r\n });\r\n\r\n return manager;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cruxjs/client",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Client application manager with routing, lifecycle hooks, and plugin-based extensibility.",
|
|
5
5
|
"keywords": ["cruxjs", "client"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@cruxjs/base": "^0.2.0",
|
|
44
44
|
"@cruxkit/core": "^0.0.2",
|
|
45
45
|
"@minejs/browser": "^0.0.5",
|
|
46
|
-
"@minejs/i18n": "^0.1.
|
|
46
|
+
"@minejs/i18n": "^0.1.8",
|
|
47
47
|
"@minejs/jsx": "^0.1.5",
|
|
48
48
|
"@minejs/signals": "^0.0.6",
|
|
49
49
|
"@minejs/store": "^0.0.3"
|