@deijose/nix-js 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/nix/router.d.ts +54 -78
- package/dist/lib/router.cjs +4 -4
- package/dist/lib/router.js +3 -3
- package/package.json +1 -1
package/dist/lib/nix/router.d.ts
CHANGED
|
@@ -24,9 +24,7 @@ export interface RouteRecord {
|
|
|
24
24
|
/** Route-level guard. Runs only when entering this specific route. */
|
|
25
25
|
beforeEnter?: NavigationGuard;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Callback for `afterEach` hooks — receives the committed `to` and `from` paths.
|
|
29
|
-
*/
|
|
27
|
+
/** Callback for `afterEach` hooks — receives the committed `to` and `from` paths. */
|
|
30
28
|
export type AfterEachHook = (to: string, from: string) => void;
|
|
31
29
|
/** Named route target for programmatic navigation. */
|
|
32
30
|
export interface NamedRouteLocation {
|
|
@@ -50,118 +48,96 @@ export interface ScrollPosition {
|
|
|
50
48
|
export type ScrollBehavior = (to: string, from: string, savedPosition: ScrollPosition | null) => ScrollPosition | false | void;
|
|
51
49
|
/** Router URL mode strategy. */
|
|
52
50
|
export type RouterMode = "history" | "hash";
|
|
53
|
-
/**
|
|
54
|
-
* Result of `router.resolve(path)` — inspect what would match without navigating.
|
|
55
|
-
*/
|
|
51
|
+
/** Result of `router.resolve(path)`. */
|
|
56
52
|
export interface ResolvedRoute {
|
|
57
|
-
/** Whether the path matched any registered route. */
|
|
58
53
|
matched: boolean;
|
|
59
|
-
/** Extracted route params (empty object if no match). */
|
|
60
54
|
params: Record<string, string>;
|
|
61
|
-
/** The matched route record, or `undefined` if no match. */
|
|
62
55
|
route: RouteRecord | undefined;
|
|
63
56
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
export type NavigationAction = "push" | "replace" | "pop" | "initial";
|
|
58
|
+
export type NavigationDirection = "forward" | "back" | "root" | "none";
|
|
59
|
+
export interface NavigationIntent {
|
|
60
|
+
/** Which router method produced the navigation. */
|
|
61
|
+
action: NavigationAction;
|
|
62
|
+
/** Logical direction — used by Ionic, custom animation builders, etc. */
|
|
63
|
+
direction: NavigationDirection;
|
|
64
|
+
/** Opaque animation builder passed through to the outlet. */
|
|
65
|
+
animation?: unknown;
|
|
66
|
+
}
|
|
67
|
+
/** Options accepted by `navigate` / `replace`. */
|
|
68
|
+
export interface NavigateOptions {
|
|
69
|
+
query?: Record<string, string | number | boolean | null | undefined>;
|
|
70
|
+
/** Override the inferred direction (e.g. tab change should be `"none"`). */
|
|
71
|
+
direction?: NavigationDirection;
|
|
72
|
+
/** Animation builder passed to outlets that animate. Ionic AnimationBuilder, etc. */
|
|
73
|
+
animation?: unknown;
|
|
74
|
+
}
|
|
67
75
|
export interface RouterOptions {
|
|
68
76
|
/**
|
|
69
|
-
* Base path for the application.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* If omitted, the router auto-detects the base from the `<base href>` tag
|
|
73
|
-
* that tools like Vite inject when you set `base` in your config.
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* // vite.config.ts sets base: "/my-app/"
|
|
77
|
-
* // No need to pass base — auto-detected from <base href>
|
|
78
|
-
* createRouter(routes);
|
|
79
|
-
*
|
|
80
|
-
* // Or pass it explicitly:
|
|
81
|
-
* createRouter(routes, { base: "/my-app/" });
|
|
77
|
+
* Base path for the application (sub-path deployments).
|
|
78
|
+
* If omitted, auto-detected from `<base href>`.
|
|
82
79
|
*/
|
|
83
80
|
base?: string;
|
|
84
81
|
/** URL handling mode. `history` by default. */
|
|
85
82
|
mode?: RouterMode;
|
|
86
|
-
/**
|
|
87
|
-
* Optional custom scroll behavior for navigation.
|
|
88
|
-
* If omitted, router scrolls to top on push/replace and restores saved
|
|
89
|
-
* positions on back/forward when available.
|
|
90
|
-
*/
|
|
83
|
+
/** Optional custom scroll behavior. */
|
|
91
84
|
scrollBehavior?: ScrollBehavior;
|
|
92
85
|
}
|
|
93
86
|
export interface Router {
|
|
94
|
-
/** Signal with the current active pathname (without the base prefix). */
|
|
95
87
|
readonly current: Signal<string>;
|
|
96
|
-
/** Signal with the extracted dynamic route params. */
|
|
97
88
|
readonly params: Signal<Record<string, string>>;
|
|
98
|
-
/** Signal with the URL query params. */
|
|
99
89
|
readonly query: Signal<Record<string, string>>;
|
|
100
|
-
/** The resolved base path used by the router. */
|
|
101
90
|
readonly base: string;
|
|
102
|
-
/**
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Last navigation intent. Updated SYNCHRONOUSLY before `current` whenever
|
|
93
|
+
* navigation commits, so an effect that reads `current` will also see the
|
|
94
|
+
* matching `intent`.
|
|
95
|
+
*/
|
|
96
|
+
readonly intent: Signal<NavigationIntent>;
|
|
97
|
+
/**
|
|
98
|
+
* Whether there is a previous entry in this router's logical stack.
|
|
99
|
+
* Differs from `history.length` — only counts entries this router pushed.
|
|
100
|
+
*/
|
|
101
|
+
readonly canGoBack: Signal<boolean>;
|
|
102
|
+
navigate(location: RouteLocation, options?: NavigateOptions): void;
|
|
103
|
+
replace(location: RouteLocation, options?: NavigateOptions): void;
|
|
104
|
+
back(animation?: unknown): void;
|
|
105
|
+
forward(animation?: unknown): void;
|
|
111
106
|
go(delta: number): void;
|
|
112
|
-
/** Check if `path` is currently active. `exact=false` enables prefix matching. */
|
|
113
107
|
isActive(path: string, exact?: boolean): boolean;
|
|
114
|
-
/** Inspect what route would match `path` without navigating. */
|
|
115
108
|
resolve(path: string): ResolvedRoute;
|
|
116
|
-
/** Original route tree passed to `createRouter`. */
|
|
117
109
|
readonly routes: RouteRecord[];
|
|
118
|
-
/** Register a global navigation guard. Returns a removal function. */
|
|
119
110
|
beforeEach(guard: NavigationGuard): () => void;
|
|
120
|
-
/** Register a hook that runs after every successful navigation. Returns a removal function. */
|
|
121
111
|
afterEach(hook: AfterEachHook): () => void;
|
|
122
112
|
}
|
|
123
|
-
/** DI key for router instances.
|
|
113
|
+
/** DI key for router instances. */
|
|
124
114
|
export declare const RouterKey: import("./context").InjectionKey<Router>;
|
|
125
|
-
export interface _RouterDebugInternal {
|
|
126
|
-
mode: RouterMode;
|
|
127
|
-
base: string;
|
|
128
|
-
currentPath: string;
|
|
129
|
-
params: Record<string, string>;
|
|
130
|
-
query: Record<string, string>;
|
|
131
|
-
matchedPath: string | null;
|
|
132
|
-
activeGuards: {
|
|
133
|
-
globalCount: number;
|
|
134
|
-
hasRouteGuard: boolean;
|
|
135
|
-
names: string[];
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Creates the History API router and sets it as the active singleton.
|
|
140
|
-
* In production the server must serve `index.html` for all non-file routes.
|
|
141
|
-
*
|
|
142
|
-
* @param routes The route tree.
|
|
143
|
-
* @param options Optional configuration — use `base` for sub-path deployments.
|
|
144
|
-
*/
|
|
145
115
|
export declare function createRouter(routes: RouteRecord[], options?: RouterOptions): Router;
|
|
146
|
-
/** Returns the active router singleton. */
|
|
147
116
|
export declare function nixRouter(): Router;
|
|
148
|
-
/**
|
|
149
|
-
* @internal — Resets the router singleton. Used by tests to avoid
|
|
150
|
-
* "A router already exists" warnings between test cases.
|
|
151
|
-
*/
|
|
117
|
+
/** @internal */
|
|
152
118
|
export declare function _resetRouter(): void;
|
|
153
|
-
/** @internal — lightweight router state accessor for optional devtools modules. */
|
|
154
|
-
export declare function _debugGetRouterInternal(): _RouterDebugInternal | null;
|
|
155
|
-
/** Renders the matched route component at the given nesting `depth`. */
|
|
156
119
|
export declare class RouterView extends NixComponent {
|
|
157
120
|
private _depth;
|
|
158
121
|
constructor(depth?: number);
|
|
159
122
|
render(): NixTemplate;
|
|
160
123
|
}
|
|
161
|
-
/** Reactive navigation link styled as active/inactive based on the current route. */
|
|
162
124
|
export declare class Link extends NixComponent {
|
|
163
125
|
private _to;
|
|
164
126
|
private _label;
|
|
165
127
|
constructor(to: string, label: string);
|
|
166
128
|
render(): NixTemplate;
|
|
167
129
|
}
|
|
130
|
+
export interface _RouterDebugInternal {
|
|
131
|
+
mode: RouterMode;
|
|
132
|
+
base: string;
|
|
133
|
+
currentPath: string;
|
|
134
|
+
params: Record<string, string>;
|
|
135
|
+
query: Record<string, string>;
|
|
136
|
+
matchedPath: string | null;
|
|
137
|
+
activeGuards: {
|
|
138
|
+
globalCount: number;
|
|
139
|
+
hasRouteGuard: boolean;
|
|
140
|
+
names: string[];
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export declare function _debugGetRouterInternal(): _RouterDebugInternal | null;
|
package/dist/lib/router.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./signals.cjs"),t=require("./template2.cjs"),n=require("./lifecycle.cjs"),r=require("./context.cjs");var i=r.createInjectionKey("nix:router"),a=null,o=null,s="__nix_scroll";function
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./signals.cjs"),t=require("./template2.cjs"),n=require("./lifecycle.cjs"),r=require("./context.cjs");var i=r.createInjectionKey("nix:router"),a=null,o=null,s="__nix_scroll",c="__nix_pos";function l(){if(!a)throw Error("[Nix] No active router. Call createRouter() first.");return a}function u(){return{left:window.scrollX??window.pageXOffset??0,top:window.scrollY??window.pageYOffset??0}}function d(e){if(!e||"object"!=typeof e)return null;let t=e[s];if(!t||"object"!=typeof t)return null;let r=t.left,n=t.top;return"number"!=typeof r||"number"!=typeof n?null:{left:r,top:n}}function f(e){if(!e||"object"!=typeof e)return null;let t=e[c];return"number"==typeof t?t:null}function p(e,t,r){let n=e&&"object"==typeof e?{...e}:{};return n[s]={left:t.left,top:t.top},n[c]=r,n}function m(e){let t={};return new URLSearchParams(e).forEach((e,r)=>{t[r]=e}),t}function h(e){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))null!=n&&!1!==n&&t.set(r,String(n));let r=t.toString();return r?"?"+r:""}function g(e){return"*"===e?[{kind:"wildcard"}]:e.split("/").filter(Boolean).map(e=>"*"===e?{kind:"wildcard"}:e.startsWith(":")?{kind:"param",name:e.slice(1)}:{kind:"literal",value:e})}function _(e,t){return"*"===t?""===e?"*":e+"/*":(e+(t.startsWith("/")?t:"/"+t)).replace(/\/+/g,"/")||"/"}function v(e,t="",r=[]){let n=[];for(let o of e){let e=_(t,o.path),a=[...r,o.component],i=g(e);n.push({fullPath:e,segments:i,chain:a,name:o.name,meta:o.meta,beforeEnter:o.beforeEnter,record:o}),o.children?.length&&n.push(...v(o.children,e,a))}return n}function y(e,t){let r=e.split("/").filter(Boolean),n=t.segments;if(1===n.length&&"wildcard"===n[0].kind)return{};let o=n.length>0&&"wildcard"===n[n.length-1].kind,a=o?n.slice(0,-1):n;if(o){if(r.length<a.length)return null}else if(r.length!==a.length)return null;let i={};for(let e=0;e<a.length;e++){let t=a[e];if("literal"===t.kind){if(r[e]!==t.value)return null}else if("param"===t.kind)try{i[t.name]=decodeURIComponent(r[e]??"")}catch{i[t.name]=r[e]??""}}return i}function b(e){return e.segments.reduce((e,t)=>"literal"===t.kind?e+2:"param"===t.kind?e+1:e,0)}function x(e,t){let r,n={},o=-1;for(let a of t){let t=y(e,a);if(null===t)continue;let i=b(a);i>o&&(r=a,n=t,o=i)}return r?{route:r,params:n}:void 0}function S(e){let t=e.trim();return t&&"/"!==t?(t.startsWith("/")||(t="/"+t),t.endsWith("/")&&(t=t.slice(0,-1)),t):""}function ee(){if(typeof document>"u")return"";let e=document.querySelector("base");if(!e)return"";let t=e.getAttribute("href")||"";try{return S(new URL(t,window.location.origin).pathname)}catch{return S(t)}}function C(t,r){let n=null==r?.base?ee():S(r.base),i=r?.mode??"history",l="hash"===i,s=r?.scrollBehavior,c=new Map,g=!1;function w(e){return e?e.startsWith("/")?e:"/"+e:"/"}function y(e){let t=w(e||"/");if(n&&t.startsWith(n)){let e=t.slice(n.length);return""===e?"/":w(e)}return t}function b(){return l?function(){let e=window.location.hash||"";if(e.startsWith("#")&&(e=e.slice(1)),!e)return{pathname:"/",search:""};e.startsWith("/")||(e="/"+e);let t=e.indexOf("?"),r=-1===t?e:e.slice(0,t),n=-1===t?"":e.slice(t);return{pathname:y(r),search:n}}():{pathname:y(window.location.pathname||"/"),search:window.location.search||""}}function _(e,t){let r=function(e){let t=w(e);return n?(n+t).replace(/\/+/g,"/")||"/":t}(e)+h(t);return l?"#"+r:r}function k(e,t){return w(e)+h(t)}let E=b(),R=E.pathname,j=m(E.search),q=v(t),O=new Map;for(let e of q)e.name&&(O.has(e.name)&&console.warn(`[Nix Router] Duplicate route name: "${e.name}"`),O.set(e.name,e));let W=x(R,q),$=e.signal(R),N=e.signal(W?.params??{}),C=e.signal(j),L=f(history.state)??0,P=e.signal({action:"initial",direction:"none"}),M=e.signal(L>0);function B(e){window.scrollTo(e.left,e.top)}function T(e,t,r){if(s){let n=s(e,t,r);if(!n)return;return void B(n)}B(r??{left:0,top:0})}l?c.set(k(R,j),u()):history.replaceState(p(history.state,u(),L),"");let U=[],D=[],G=0;function I(e,t,r,n,o){let a=[...U];r&&a.push(r);let i=++G;if(0===a.length)return void n();let l=0;!function r(u){if(i!==G)return;if(!1===u)return void o?.();if("string"==typeof u)return void(u===e?n():z(u));if(l>=a.length)return void n();let s=a[l++](e,t);s instanceof Promise?s.then(r):r(s)}(void 0)}let A=!1;function Q(e,t){let r=e.indexOf("?"),n=w((-1===r?e:e.slice(0,r))||"/"),o=-1===r?{}:m(e.slice(r)),a=t?{...o,...t}:o,i={};for(let[e,t]of Object.entries(a))null!=t&&!1!==t&&(i[e]=String(t));return{pathname:n,stringQuery:i}}function K(e,t){return"string"==typeof e?Q(e,t?.query):Q(function(e){let t=O.get(e.name);if(!t)throw Error(`[Nix Router] No route with name "${e.name}"`);return"/"+t.segments.map(t=>{if("literal"===t.kind)return t.value;if("wildcard"===t.kind)return"";let r=e.params?.[t.name];if(null==r)throw Error(`[Nix Router] Missing param "${t.name}" for route "${e.name}"`);return encodeURIComponent(String(r))}).filter(Boolean).join("/")}(e),{...e.query??{},...t?.query??{}})}o&&=(o(),null);let X,Y=(e,t,r,n,o)=>{let a=$.value,i={...C.value},l=x(e,q),u="none";null!=n&&(n<L?u="back":n>L&&(u="forward")),I(e,a,l?.route.beforeEnter,()=>{null!=n&&(L=n);let o=X;X=void 0,P.value={action:"pop",direction:u,animation:o},N.value=l?.params??{},C.value=t,$.value=e,M.value=L>0,T(e,a,r);for(let t of D)try{t(e,a)}catch{}},()=>o(a,i))};if(l){let e=()=>{if(g)return void(g=!1);let e=b(),t=m(e.search),r=c.get(k(e.pathname,t))??null;Y(e.pathname,t,r,null,(e,t)=>{g=!0,window.location.hash=_(e,t).slice(1),queueMicrotask(()=>{g=!1})})};window.addEventListener("hashchange",e),o=()=>window.removeEventListener("hashchange",e)}else{let e=e=>{let t=b(),r=m(t.search),n=d(e.state??history.state),o=f(e.state??history.state);Y(t.pathname,r,n,o,(e,t)=>{history.pushState(p({},u(),L),"",_(e,t))})};window.addEventListener("popstate",e),o=()=>window.removeEventListener("popstate",e)}function V(e,t,r,n,o,a,i){i||(function(e,t){let r=u();l?c.set(k(e,t),r):history.replaceState(p(history.state,r,L),"")}(r,n),L+=1),P.value=a,N.value=o?.params??{},C.value=t,$.value=e,M.value=L>0;let s=_(e,t);if(l)c.set(k(e,t),{left:0,top:0}),i?history.replaceState(history.state,"",s):(g=!0,window.location.hash=s.slice(1),queueMicrotask(()=>{g=!1}));else{let e=p({},{left:0,top:0},L);i?history.replaceState(e,"",s):history.pushState(e,"",s)}T(e,r,null);for(let t of D)try{t(e,r)}catch{}}function z(e,t){A=!0;let{pathname:r,stringQuery:n}=K(e,t),o=$.value,a={...C.value},i=x(r,q),l={action:"push",direction:t?.direction??"forward",animation:t?.animation};I(r,o,i?.route.beforeEnter,()=>V(r,n,o,a,i,l,!1))}let F={current:$,params:N,query:C,intent:P,canGoBack:M,base:n||"/",navigate:z,replace:function(e,t){A=!0;let{pathname:r,stringQuery:n}=K(e,t),o=$.value,a={...C.value},i=x(r,q),l={action:"replace",direction:t?.direction??"root",animation:t?.animation};I(r,o,i?.route.beforeEnter,()=>V(r,n,o,a,i,l,!0))},back:function(e){void 0!==e&&(X=e),history.back()},forward:function(e){void 0!==e&&(X=e),history.forward()},go:function(e){history.go(e)},isActive:function(e,t=!0){let r=$.value;return t?r===e:r===e||r.startsWith(e.endsWith("/")?e:e+"/")},resolve:function(e){let t=x(e,q);return t?{matched:!0,params:t.params,route:t.route.record}:{matched:!1,params:{},route:void 0}},beforeEach:function(e){return U.push(e),()=>{let t=U.indexOf(e);-1!==t&&U.splice(t,1)}},afterEach:function(e){return D.push(e),()=>{let t=D.indexOf(e);-1!==t&&D.splice(t,1)}},routes:t,_flat:q,_guards:U,_base:n,_mode:i};return a&&console.warn("[Nix] A router already exists. The previous router is being replaced. Only one router instance should be active at a time."),a=F,queueMicrotask(()=>{A||I(R,"",x(R,q)?.route.beforeEnter,()=>{},()=>{let e=_("/",{});l?(c.set(k("/",{}),{left:0,top:0}),history.replaceState(history.state,"",e)):history.replaceState(p({},{left:0,top:0},L),"",e);let t=x("/",q);P.value={action:"replace",direction:"root"},$.value="/",N.value=t?.params??{},C.value={},M.value=L>0,T("/",R,null)})}),F}function w(){return r.inject(i)||l()}function T(){o&&=(o(),null),a=null}var E=class extends n.NixComponent{_depth;constructor(e=0){super(),this._depth=e}render(){let e=this._depth;return t.l`<div class="router-view">${()=>{let r=w(),n=x(r.current.value,r._flat);return n?e>=n.route.chain.length?t.l`<span></span>`:n.route.chain[e]():t.l`<div style="color:#f87171;padding:16px 0">
|
|
2
2
|
404 — Route not found: <strong>${r.current.value}</strong>
|
|
3
|
-
</div>`}}</div>`}},D=class extends n.NixComponent{_to;_label;constructor(e,t){super(),this._to=e,this._label=t}render(){let e=this._to,r=this._label,n=
|
|
4
|
-
href=${"hash"===n._mode?"#"+
|
|
3
|
+
</div>`}}</div>`}},D=class extends n.NixComponent{_to;_label;constructor(e,t){super(),this._to=e,this._label=t}render(){let e=this._to,r=this._label,n=w(),o=e.startsWith("/")?e:"/"+e,a=(n._base?n._base+o:o).replace(/\/+/g,"/");return t.l`<a
|
|
4
|
+
href=${"hash"===n._mode?"#"+a:a}
|
|
5
5
|
style=${()=>n.current.value===e?"color:#38bdf8;font-weight:700;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px;background:#0c2a3a":"color:#a3a3a3;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px"}
|
|
6
6
|
@click=${t=>{t.preventDefault(),n.navigate(e)}}
|
|
7
|
-
>${r}</a>`}};exports.Link=D,exports.RouterKey=i,exports.RouterView=E,exports._debugGetRouterInternal=
|
|
7
|
+
>${r}</a>`}};function O(){if(!a)return null;let e=a.current.value,t=x(e,a._flat),r=t?.route.beforeEnter,n=a._guards.map((e,t)=>e.name||`beforeEach#${t+1}`);return r&&n.push(r.name||"beforeEnter"),{mode:a._mode,base:a._base||"/",currentPath:e,params:{...a.params.value},query:{...a.query.value},matchedPath:t?.route.fullPath??null,activeGuards:{globalCount:a._guards.length,hasRouteGuard:!!r,names:n}}}exports.Link=D,exports.RouterKey=i,exports.RouterView=E,exports._debugGetRouterInternal=O,exports._resetRouter=T,exports.createRouter=C,exports.nixRouter=w;
|
package/dist/lib/router.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{signal as e}from"./signals.js";import{l as t}from"./template2.js";import{NixComponent as n}from"./lifecycle.js";import{createInjectionKey as r,inject as i}from"./context.js";var a=r("nix:router"),o=null,s=null,c="__nix_scroll";function
|
|
1
|
+
import{signal as e}from"./signals.js";import{l as t}from"./template2.js";import{NixComponent as n}from"./lifecycle.js";import{createInjectionKey as r,inject as i}from"./context.js";var a=r("nix:router"),o=null,s=null,c="__nix_scroll",l="__nix_pos";function u(){if(!o)throw Error("[Nix] No active router. Call createRouter() first.");return o}function d(){return{left:window.scrollX??window.pageXOffset??0,top:window.scrollY??window.pageYOffset??0}}function ee(e){if(!e||"object"!=typeof e)return null;let t=e[c];if(!t||"object"!=typeof t)return null;let r=t.left,n=t.top;return"number"!=typeof r||"number"!=typeof n?null:{left:r,top:n}}function f(e){if(!e||"object"!=typeof e)return null;let t=e[l];return"number"==typeof t?t:null}function p(e,t,r){let n=e&&"object"==typeof e?{...e}:{};return n[c]={left:t.left,top:t.top},n[l]=r,n}function m(e){let t={};return new URLSearchParams(e).forEach((e,r)=>{t[r]=e}),t}function h(e){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))null!=n&&!1!==n&&t.set(r,String(n));let r=t.toString();return r?"?"+r:""}function g(e){return"*"===e?[{kind:"wildcard"}]:e.split("/").filter(Boolean).map(e=>"*"===e?{kind:"wildcard"}:e.startsWith(":")?{kind:"param",name:e.slice(1)}:{kind:"literal",value:e})}function _(e,t){return"*"===t?""===e?"*":e+"/*":(e+(t.startsWith("/")?t:"/"+t)).replace(/\/+/g,"/")||"/"}function v(e,t="",r=[]){let n=[];for(let o of e){let e=_(t,o.path),a=[...r,o.component],i=g(e);n.push({fullPath:e,segments:i,chain:a,name:o.name,meta:o.meta,beforeEnter:o.beforeEnter,record:o}),o.children?.length&&n.push(...v(o.children,e,a))}return n}function y(e,t){let r=e.split("/").filter(Boolean),n=t.segments;if(1===n.length&&"wildcard"===n[0].kind)return{};let o=n.length>0&&"wildcard"===n[n.length-1].kind,a=o?n.slice(0,-1):n;if(o){if(r.length<a.length)return null}else if(r.length!==a.length)return null;let i={};for(let e=0;e<a.length;e++){let t=a[e];if("literal"===t.kind){if(r[e]!==t.value)return null}else if("param"===t.kind)try{i[t.name]=decodeURIComponent(r[e]??"")}catch{i[t.name]=r[e]??""}}return i}function b(e){return e.segments.reduce((e,t)=>"literal"===t.kind?e+2:"param"===t.kind?e+1:e,0)}function x(e,t){let r,n={},o=-1;for(let a of t){let t=y(e,a);if(null===t)continue;let i=b(a);i>o&&(r=a,n=t,o=i)}return r?{route:r,params:n}:void 0}function S(e){let t=e.trim();return t&&"/"!==t?(t.startsWith("/")||(t="/"+t),t.endsWith("/")&&(t=t.slice(0,-1)),t):""}function te(){if(typeof document>"u")return"";let e=document.querySelector("base");if(!e)return"";let t=e.getAttribute("href")||"";try{return S(new URL(t,window.location.origin).pathname)}catch{return S(t)}}function C(t,r){let n=null==r?.base?te():S(r.base),a=r?.mode??"history",i="hash"===a,l=r?.scrollBehavior,u=new Map,c=!1;function g(e){return e?e.startsWith("/")?e:"/"+e:"/"}function w(e){let t=g(e||"/");if(n&&t.startsWith(n)){let e=t.slice(n.length);return""===e?"/":g(e)}return t}function y(){return i?function(){let e=window.location.hash||"";if(e.startsWith("#")&&(e=e.slice(1)),!e)return{pathname:"/",search:""};e.startsWith("/")||(e="/"+e);let t=e.indexOf("?"),r=-1===t?e:e.slice(0,t),n=-1===t?"":e.slice(t);return{pathname:w(r),search:n}}():{pathname:w(window.location.pathname||"/"),search:window.location.search||""}}function b(e,t){let r=function(e){let t=g(e);return n?(n+t).replace(/\/+/g,"/")||"/":t}(e)+h(t);return i?"#"+r:r}function _(e,t){return g(e)+h(t)}let k=y(),E=k.pathname,R=m(k.search),j=v(t),O=new Map;for(let e of j)e.name&&(O.has(e.name)&&console.warn(`[Nix Router] Duplicate route name: "${e.name}"`),O.set(e.name,e));let W=x(E,j),$=e(E),q=e(W?.params??{}),L=e(R),N=f(history.state)??0,C=e({action:"initial",direction:"none"}),P=e(N>0);function M(e){window.scrollTo(e.left,e.top)}function B(e,t,r){if(l){let n=l(e,t,r);if(!n)return;return void M(n)}M(r??{left:0,top:0})}i?u.set(_(E,R),d()):history.replaceState(p(history.state,d(),N),"");let U=[],D=[],G=0;function I(e,t,r,n,o){let a=[...U];r&&a.push(r);let i=++G;if(0===a.length)return void n();let l=0;!function r(u){if(i!==G)return;if(!1===u)return void o?.();if("string"==typeof u)return void(u===e?n():V(u));if(l>=a.length)return void n();let s=a[l++](e,t);s instanceof Promise?s.then(r):r(s)}(void 0)}let T=!1;function A(e,t){let r=e.indexOf("?"),n=g((-1===r?e:e.slice(0,r))||"/"),o=-1===r?{}:m(e.slice(r)),a=t?{...o,...t}:o,i={};for(let[e,t]of Object.entries(a))null!=t&&!1!==t&&(i[e]=String(t));return{pathname:n,stringQuery:i}}function Q(e,t){return"string"==typeof e?A(e,t?.query):A(function(e){let t=O.get(e.name);if(!t)throw Error(`[Nix Router] No route with name "${e.name}"`);return"/"+t.segments.map(t=>{if("literal"===t.kind)return t.value;if("wildcard"===t.kind)return"";let r=e.params?.[t.name];if(null==r)throw Error(`[Nix Router] Missing param "${t.name}" for route "${e.name}"`);return encodeURIComponent(String(r))}).filter(Boolean).join("/")}(e),{...e.query??{},...t?.query??{}})}s&&=(s(),null);let K,X=(e,t,r,n,o)=>{let a=$.value,i={...L.value},l=x(e,j),u="none";null!=n&&(n<N?u="back":n>N&&(u="forward")),I(e,a,l?.route.beforeEnter,()=>{null!=n&&(N=n);let o=K;K=void 0,C.value={action:"pop",direction:u,animation:o},q.value=l?.params??{},L.value=t,$.value=e,P.value=N>0,B(e,a,r);for(let t of D)try{t(e,a)}catch{}},()=>o(a,i))};if(i){let e=()=>{if(c)return void(c=!1);let e=y(),t=m(e.search),r=u.get(_(e.pathname,t))??null;X(e.pathname,t,r,null,(e,t)=>{c=!0,window.location.hash=b(e,t).slice(1),queueMicrotask(()=>{c=!1})})};window.addEventListener("hashchange",e),s=()=>window.removeEventListener("hashchange",e)}else{let e=e=>{let t=y(),r=m(t.search),n=ee(e.state??history.state),o=f(e.state??history.state);X(t.pathname,r,n,o,(e,t)=>{history.pushState(p({},d(),N),"",b(e,t))})};window.addEventListener("popstate",e),s=()=>window.removeEventListener("popstate",e)}function Y(e,t,r,n,o,a,l){l||(function(e,t){let r=d();i?u.set(_(e,t),r):history.replaceState(p(history.state,r,N),"")}(r,n),N+=1),C.value=a,q.value=o?.params??{},L.value=t,$.value=e,P.value=N>0;let s=b(e,t);if(i)u.set(_(e,t),{left:0,top:0}),l?history.replaceState(history.state,"",s):(c=!0,window.location.hash=s.slice(1),queueMicrotask(()=>{c=!1}));else{let e=p({},{left:0,top:0},N);l?history.replaceState(e,"",s):history.pushState(e,"",s)}B(e,r,null);for(let t of D)try{t(e,r)}catch{}}function V(e,t){T=!0;let{pathname:r,stringQuery:n}=Q(e,t),o=$.value,a={...L.value},i=x(r,j),l={action:"push",direction:t?.direction??"forward",animation:t?.animation};I(r,o,i?.route.beforeEnter,()=>Y(r,n,o,a,i,l,!1))}let z={current:$,params:q,query:L,intent:C,canGoBack:P,base:n||"/",navigate:V,replace:function(e,t){T=!0;let{pathname:r,stringQuery:n}=Q(e,t),o=$.value,a={...L.value},i=x(r,j),l={action:"replace",direction:t?.direction??"root",animation:t?.animation};I(r,o,i?.route.beforeEnter,()=>Y(r,n,o,a,i,l,!0))},back:function(e){void 0!==e&&(K=e),history.back()},forward:function(e){void 0!==e&&(K=e),history.forward()},go:function(e){history.go(e)},isActive:function(e,t=!0){let r=$.value;return t?r===e:r===e||r.startsWith(e.endsWith("/")?e:e+"/")},resolve:function(e){let t=x(e,j);return t?{matched:!0,params:t.params,route:t.route.record}:{matched:!1,params:{},route:void 0}},beforeEach:function(e){return U.push(e),()=>{let t=U.indexOf(e);-1!==t&&U.splice(t,1)}},afterEach:function(e){return D.push(e),()=>{let t=D.indexOf(e);-1!==t&&D.splice(t,1)}},routes:t,_flat:j,_guards:U,_base:n,_mode:a};return o&&console.warn("[Nix] A router already exists. The previous router is being replaced. Only one router instance should be active at a time."),o=z,queueMicrotask(()=>{T||I(E,"",x(E,j)?.route.beforeEnter,()=>{},()=>{let e=b("/",{});i?(u.set(_("/",{}),{left:0,top:0}),history.replaceState(history.state,"",e)):history.replaceState(p({},{left:0,top:0},N),"",e);let t=x("/",j);C.value={action:"replace",direction:"root"},$.value="/",q.value=t?.params??{},L.value={},P.value=N>0,B("/",E,null)})}),z}function w(){return i(a)||u()}function T(){s&&=(s(),null),o=null}var E=class extends n{_depth;constructor(e=0){super(),this._depth=e}render(){let e=this._depth;return t`<div class="router-view">${()=>{let r=w(),n=x(r.current.value,r._flat);return n?e>=n.route.chain.length?t`<span></span>`:n.route.chain[e]():t`<div style="color:#f87171;padding:16px 0">
|
|
2
2
|
404 — Route not found: <strong>${r.current.value}</strong>
|
|
3
|
-
</div>`}}</div>`}},
|
|
3
|
+
</div>`}}</div>`}},D=class extends n{_to;_label;constructor(e,t){super(),this._to=e,this._label=t}render(){let e=this._to,r=this._label,n=w(),o=e.startsWith("/")?e:"/"+e,a=(n._base?n._base+o:o).replace(/\/+/g,"/");return t`<a
|
|
4
4
|
href=${"hash"===n._mode?"#"+a:a}
|
|
5
5
|
style=${()=>n.current.value===e?"color:#38bdf8;font-weight:700;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px;background:#0c2a3a":"color:#a3a3a3;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px"}
|
|
6
6
|
@click=${t=>{t.preventDefault(),n.navigate(e)}}
|
|
7
|
-
>${r}</a>`}};export{
|
|
7
|
+
>${r}</a>`}};function O(){if(!o)return null;let e=o.current.value,t=x(e,o._flat),r=t?.route.beforeEnter,n=o._guards.map((e,t)=>e.name||`beforeEach#${t+1}`);return r&&n.push(r.name||"beforeEnter"),{mode:o._mode,base:o._base||"/",currentPath:e,params:{...o.params.value},query:{...o.query.value},matchedPath:t?.route.fullPath??null,activeGuards:{globalCount:o._guards.length,hasRouteGuard:!!r,names:n}}}export{D as Link,a as RouterKey,E as RouterView,O as _debugGetRouterInternal,T as _resetRouter,C as createRouter,w as nixRouter};
|
package/package.json
CHANGED