@deijose/nix-js 2.4.2 → 2.4.3
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 +23 -35
- package/dist/lib/router.cjs +11 -7
- package/dist/lib/router.js +11 -7
- package/package.json +1 -1
package/dist/lib/nix/router.d.ts
CHANGED
|
@@ -3,11 +3,18 @@ import { NixComponent } from "./lifecycle";
|
|
|
3
3
|
import type { NixTemplate } from "./template";
|
|
4
4
|
/**
|
|
5
5
|
* Value returned (or resolved) by a navigation guard.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* - `true` / `void` / `undefined` — allow.
|
|
8
|
+
* - `false` — cancel (no redirect).
|
|
7
9
|
* - `string` — redirect to that path.
|
|
8
|
-
* - `
|
|
10
|
+
* - `{ redirect: string }` — redirect, object form.
|
|
11
|
+
*
|
|
12
|
+
* The object form exists so guards written for the outlet API can be reused
|
|
13
|
+
* verbatim by the core. See `nix-ionic`'s `GuardResult`.
|
|
9
14
|
*/
|
|
10
|
-
export type NavigationGuardResult = void | undefined |
|
|
15
|
+
export type NavigationGuardResult = void | undefined | boolean | string | {
|
|
16
|
+
redirect: string;
|
|
17
|
+
};
|
|
11
18
|
/** Guard function invoked before navigation commits. */
|
|
12
19
|
export type NavigationGuard = (to: string, from: string) => NavigationGuardResult | Promise<NavigationGuardResult>;
|
|
13
20
|
export interface RouteRecord {
|
|
@@ -15,8 +22,14 @@ export interface RouteRecord {
|
|
|
15
22
|
name?: string;
|
|
16
23
|
/** Route path segment. Supports literals, params (`:id`), and wildcards (`*`). */
|
|
17
24
|
path: string;
|
|
18
|
-
/**
|
|
19
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Factory returning the view for this route level.
|
|
27
|
+
*
|
|
28
|
+
* OPTIONAL — when the core router is auto-bootstrapped by an outlet
|
|
29
|
+
* (Ionic's IonRouterOutlet, future others), the outlet owns component
|
|
30
|
+
* mounting and the core never invokes this. In that case, omit it.
|
|
31
|
+
*/
|
|
32
|
+
component?: () => NixTemplate | NixComponent;
|
|
20
33
|
/** Optional arbitrary metadata for guards, layouts, and auth checks. */
|
|
21
34
|
meta?: Record<string, unknown>;
|
|
22
35
|
/** Child routes. Paths are joined with the parent. */
|
|
@@ -39,16 +52,8 @@ export interface ScrollPosition {
|
|
|
39
52
|
left: number;
|
|
40
53
|
top: number;
|
|
41
54
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Scroll behavior callback.
|
|
44
|
-
* - `savedPosition` is non-null on popstate (back/forward) when a saved position exists.
|
|
45
|
-
* - Return `{ left, top }` to scroll there.
|
|
46
|
-
* - Return `false` or `undefined` to skip router scrolling.
|
|
47
|
-
*/
|
|
48
55
|
export type ScrollBehavior = (to: string, from: string, savedPosition: ScrollPosition | null) => ScrollPosition | false | void;
|
|
49
|
-
/** Router URL mode strategy. */
|
|
50
56
|
export type RouterMode = "history" | "hash";
|
|
51
|
-
/** Result of `router.resolve(path)`. */
|
|
52
57
|
export interface ResolvedRoute {
|
|
53
58
|
matched: boolean;
|
|
54
59
|
params: Record<string, string>;
|
|
@@ -57,30 +62,18 @@ export interface ResolvedRoute {
|
|
|
57
62
|
export type NavigationAction = "push" | "replace" | "pop" | "initial";
|
|
58
63
|
export type NavigationDirection = "forward" | "back" | "root" | "none";
|
|
59
64
|
export interface NavigationIntent {
|
|
60
|
-
/** Which router method produced the navigation. */
|
|
61
65
|
action: NavigationAction;
|
|
62
|
-
/** Logical direction — used by Ionic, custom animation builders, etc. */
|
|
63
66
|
direction: NavigationDirection;
|
|
64
|
-
/** Opaque animation builder passed through to the outlet. */
|
|
65
67
|
animation?: unknown;
|
|
66
68
|
}
|
|
67
|
-
/** Options accepted by `navigate` / `replace`. */
|
|
68
69
|
export interface NavigateOptions {
|
|
69
70
|
query?: Record<string, string | number | boolean | null | undefined>;
|
|
70
|
-
/** Override the inferred direction (e.g. tab change should be `"none"`). */
|
|
71
71
|
direction?: NavigationDirection;
|
|
72
|
-
/** Animation builder passed to outlets that animate. Ionic AnimationBuilder, etc. */
|
|
73
72
|
animation?: unknown;
|
|
74
73
|
}
|
|
75
74
|
export interface RouterOptions {
|
|
76
|
-
/**
|
|
77
|
-
* Base path for the application (sub-path deployments).
|
|
78
|
-
* If omitted, auto-detected from `<base href>`.
|
|
79
|
-
*/
|
|
80
75
|
base?: string;
|
|
81
|
-
/** URL handling mode. `history` by default. */
|
|
82
76
|
mode?: RouterMode;
|
|
83
|
-
/** Optional custom scroll behavior. */
|
|
84
77
|
scrollBehavior?: ScrollBehavior;
|
|
85
78
|
}
|
|
86
79
|
export interface Router {
|
|
@@ -88,16 +81,7 @@ export interface Router {
|
|
|
88
81
|
readonly params: Signal<Record<string, string>>;
|
|
89
82
|
readonly query: Signal<Record<string, string>>;
|
|
90
83
|
readonly base: string;
|
|
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
84
|
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
85
|
readonly canGoBack: Signal<boolean>;
|
|
102
86
|
navigate(location: RouteLocation, options?: NavigateOptions): void;
|
|
103
87
|
replace(location: RouteLocation, options?: NavigateOptions): void;
|
|
@@ -110,8 +94,12 @@ export interface Router {
|
|
|
110
94
|
beforeEach(guard: NavigationGuard): () => void;
|
|
111
95
|
afterEach(hook: AfterEachHook): () => void;
|
|
112
96
|
}
|
|
113
|
-
/** DI key for router instances. */
|
|
114
97
|
export declare const RouterKey: import("./context").InjectionKey<Router>;
|
|
98
|
+
/**
|
|
99
|
+
* @internal Whether a router is currently active. Used by outlets that
|
|
100
|
+
* want to auto-bootstrap if the user didn't call `createRouter()` themselves.
|
|
101
|
+
*/
|
|
102
|
+
export declare function _hasActiveRouter(): boolean;
|
|
115
103
|
export declare function createRouter(routes: RouteRecord[], options?: RouterOptions): Router;
|
|
116
104
|
export declare function nixRouter(): Router;
|
|
117
105
|
/** @internal */
|
package/dist/lib/router.cjs
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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",c="__nix_pos";function l(){if(!a)throw Error("[Nix] No active router. Call createRouter() first, or instantiate an outlet that auto-bootstraps one (e.g. IonRouterOutlet).");return a}function u(){return null!==a}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[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 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(e){return!1===e?{allow:!1}:!0===e||null==e?{allow:!0}:"string"==typeof e?{allow:!1,redirect:e}:"object"==typeof e&&"redirect"in e&&"string"==typeof e.redirect?{allow:!1,redirect:e.redirect}:{allow:!0}}function w(t,r){let n=null==r?.base?te():S(r.base),i=r?.mode??"history",l="hash"===i,u=r?.scrollBehavior,s=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 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: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 l?"#"+r:r}function _(e,t){return g(e)+h(t)}let k=y(),E=k.pathname,R=m(k.search),j=v(t),q=new Map;for(let e of j)e.name&&(q.has(e.name)&&console.warn(`[Nix Router] Duplicate route name: "${e.name}"`),q.set(e.name,e));let O=x(E,j),W=e.signal(E),$=e.signal(O?.params??{}),N=e.signal(R),L=f(history.state)??0,P=e.signal({action:"initial",direction:"none"}),M=e.signal(L>0);function T(e){window.scrollTo(e.left,e.top)}function B(e,t,r){if(u){let n=u(e,t,r);if(!n)return;return void T(n)}T(r??{left:0,top:0})}l?s.set(_(E,R),d()):history.replaceState(p(history.state,d(),L),"");let I=[],U=[],A=0;function D(e,t,r,n,o){let a=[...I];r&&a.push(r);let i=++A;if(0===a.length)return void n();let l=0;!function r(u){if(i!==A)return;let s=C(u);if(!s.allow)return s.redirect&&s.redirect!==e?void z(s.redirect):s.redirect===e?void n():void o?.();if(l>=a.length)return void n();let c=a[l++](e,t);c instanceof Promise?c.then(r):r(c)}(void 0)}let G=!1;function Q(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 K(e,t){return"string"==typeof e?Q(e,t?.query):Q(function(e){let t=q.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=W.value,i={...N.value},l=x(e,j),u="none";null!=n&&(n<L?u="back":n>L&&(u="forward")),D(e,a,l?.route.beforeEnter,()=>{null!=n&&(L=n);let o=X;X=void 0,P.value={action:"pop",direction:u,animation:o},$.value=l?.params??{},N.value=t,W.value=e,M.value=L>0,B(e,a,r);for(let t of U)try{t(e,a)}catch{}},()=>o(a,i))};if(l){let e=()=>{if(c)return void(c=!1);let e=y(),t=m(e.search),r=s.get(_(e.pathname,t))??null;Y(e.pathname,t,r,null,(e,t)=>{c=!0,window.location.hash=b(e,t).slice(1),queueMicrotask(()=>{c=!1})})};window.addEventListener("hashchange",e),o=()=>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);Y(t.pathname,r,n,o,(e,t)=>{history.pushState(p({},d(),L),"",b(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=d();l?s.set(_(e,t),r):history.replaceState(p(history.state,r,L),"")}(r,n),L+=1),P.value=a,$.value=o?.params??{},N.value=t,W.value=e,M.value=L>0;let u=b(e,t);if(l)s.set(_(e,t),{left:0,top:0}),i?history.replaceState(history.state,"",u):(c=!0,window.location.hash=u.slice(1),queueMicrotask(()=>{c=!1}));else{let e=p({},{left:0,top:0},L);i?history.replaceState(e,"",u):history.pushState(e,"",u)}B(e,r,null);for(let t of U)try{t(e,r)}catch{}}function z(e,t){G=!0;let{pathname:r,stringQuery:n}=K(e,t),o=W.value,a={...N.value},i=x(r,j),l={action:"push",direction:t?.direction??"forward",animation:t?.animation};D(r,o,i?.route.beforeEnter,()=>V(r,n,o,a,i,l,!1))}let F={current:W,params:$,query:N,intent:P,canGoBack:M,base:n||"/",navigate:z,replace:function(e,t){G=!0;let{pathname:r,stringQuery:n}=K(e,t),o=W.value,a={...N.value},i=x(r,j),l={action:"replace",direction:t?.direction??"root",animation:t?.animation};D(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=W.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 I.push(e),()=>{let t=I.indexOf(e);-1!==t&&I.splice(t,1)}},afterEach:function(e){return U.push(e),()=>{let t=U.indexOf(e);-1!==t&&U.splice(t,1)}},routes:t,_flat:j,_guards:I,_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(()=>{G||D(E,"",x(E,j)?.route.beforeEnter,()=>{},()=>{let e=b("/",{});l?(s.set(_("/",{}),{left:0,top:0}),history.replaceState(history.state,"",e)):history.replaceState(p({},{left:0,top:0},L),"",e);let t=x("/",j);P.value={action:"replace",direction:"root"},W.value="/",$.value=t?.params??{},N.value={},M.value=L>0,B("/",E,null)})}),F}function T(){return r.inject(i)||l()}function E(){o&&=(o(),null),a=null}var D=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=T(),n=x(r.current.value,r._flat);if(!n)return t.l`
|
|
2
|
+
<div style="color:#f87171;padding:16px 0">
|
|
3
|
+
404 — Route not found: <strong>${r.current.value}</strong>
|
|
4
|
+
</div>
|
|
5
|
+
`;if(e>=n.route.chain.length)return t.l`
|
|
6
|
+
<span></span>
|
|
7
|
+
`;let o=n.route.chain[e];return o?o():t.l`
|
|
8
|
+
<span></span>
|
|
9
|
+
`}}</div>`}},O=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=T(),o=e.startsWith("/")?e:"/"+e,a=(n._base?n._base+o:o).replace(/\/+/g,"/");return t.l`
|
|
10
|
+
<a href=${"hash"===n._mode?"#"+a:a} 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"} @click=${t=>{t.preventDefault(),n.navigate(e)}}>${r}</a>
|
|
11
|
+
`}};function k(){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=O,exports.RouterKey=i,exports.RouterView=D,exports._debugGetRouterInternal=k,exports._hasActiveRouter=u,exports._resetRouter=E,exports.createRouter=w,exports.nixRouter=T;
|
package/dist/lib/router.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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",l="__nix_pos";function u(){if(!o)throw Error("[Nix] No active router. Call createRouter() first, or instantiate an outlet that auto-bootstraps one (e.g. IonRouterOutlet).");return o}function d(){return null!==o}function f(){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 p(e){if(!e||"object"!=typeof e)return null;let t=e[l];return"number"==typeof t?t:null}function m(e,t,r){let n=e&&"object"==typeof e?{...e}:{};return n[c]={left:t.left,top:t.top},n[l]=r,n}function h(e){let t={};return new URLSearchParams(e).forEach((e,r)=>{t[r]=e}),t}function g(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 _(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 v(e,t){return"*"===t?""===e?"*":e+"/*":(e+(t.startsWith("/")?t:"/"+t)).replace(/\/+/g,"/")||"/"}function y(e,t="",r=[]){let n=[];for(let o of e){let e=v(t,o.path),a=[...r,o.component],i=_(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(...y(o.children,e,a))}return n}function b(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 x(e){return e.segments.reduce((e,t)=>"literal"===t.kind?e+2:"param"===t.kind?e+1:e,0)}function S(e,t){let r,n={},o=-1;for(let a of t){let t=b(e,a);if(null===t)continue;let i=x(a);i>o&&(r=a,n=t,o=i)}return r?{route:r,params:n}:void 0}function C(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 C(new URL(t,window.location.origin).pathname)}catch{return C(t)}}function ne(e){return!1===e?{allow:!1}:!0===e||null==e?{allow:!0}:"string"==typeof e?{allow:!1,redirect:e}:"object"==typeof e&&"redirect"in e&&"string"==typeof e.redirect?{allow:!1,redirect:e.redirect}:{allow:!0}}function w(t,r){let n=null==r?.base?te():C(r.base),a=r?.mode??"history",i="hash"===a,l=r?.scrollBehavior,u=new Map,c=!1;function d(e){return e?e.startsWith("/")?e:"/"+e:"/"}function v(e){let t=d(e||"/");if(n&&t.startsWith(n)){let e=t.slice(n.length);return""===e?"/":d(e)}return t}function w(){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:v(r),search:n}}():{pathname:v(window.location.pathname||"/"),search:window.location.search||""}}function b(e,t){let r=function(e){let t=d(e);return n?(n+t).replace(/\/+/g,"/")||"/":t}(e)+g(t);return i?"#"+r:r}function _(e,t){return d(e)+g(t)}let x=w(),k=x.pathname,E=h(x.search),R=y(t),j=new Map;for(let e of R)e.name&&(j.has(e.name)&&console.warn(`[Nix Router] Duplicate route name: "${e.name}"`),j.set(e.name,e));let O=S(k,R),W=e(k),$=e(O?.params??{}),q=e(E),L=p(history.state)??0,N=e({action:"initial",direction:"none"}),P=e(L>0);function M(e){window.scrollTo(e.left,e.top)}function T(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(_(k,E),f()):history.replaceState(m(history.state,f(),L),"");let B=[],I=[],U=0;function A(e,t,r,n,o){let a=[...B];r&&a.push(r);let i=++U;if(0===a.length)return void n();let l=0;!function r(u){if(i!==U)return;let s=ne(u);if(!s.allow)return s.redirect&&s.redirect!==e?void V(s.redirect):s.redirect===e?void n():void o?.();if(l>=a.length)return void n();let c=a[l++](e,t);c instanceof Promise?c.then(r):r(c)}(void 0)}let D=!1;function G(e,t){let r=e.indexOf("?"),n=d((-1===r?e:e.slice(0,r))||"/"),o=-1===r?{}:h(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?G(e,t?.query):G(function(e){let t=j.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=W.value,i={...q.value},l=S(e,R),u="none";null!=n&&(n<L?u="back":n>L&&(u="forward")),A(e,a,l?.route.beforeEnter,()=>{null!=n&&(L=n);let o=K;K=void 0,N.value={action:"pop",direction:u,animation:o},$.value=l?.params??{},q.value=t,W.value=e,P.value=L>0,T(e,a,r);for(let t of I)try{t(e,a)}catch{}},()=>o(a,i))};if(i){let e=()=>{if(c)return void(c=!1);let e=w(),t=h(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=w(),r=h(t.search),n=ee(e.state??history.state),o=p(e.state??history.state);X(t.pathname,r,n,o,(e,t)=>{history.pushState(m({},f(),L),"",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=f();i?u.set(_(e,t),r):history.replaceState(m(history.state,r,L),"")}(r,n),L+=1),N.value=a,$.value=o?.params??{},q.value=t,W.value=e,P.value=L>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=m({},{left:0,top:0},L);l?history.replaceState(e,"",s):history.pushState(e,"",s)}T(e,r,null);for(let t of I)try{t(e,r)}catch{}}function V(e,t){D=!0;let{pathname:r,stringQuery:n}=Q(e,t),o=W.value,a={...q.value},i=S(r,R),l={action:"push",direction:t?.direction??"forward",animation:t?.animation};A(r,o,i?.route.beforeEnter,()=>Y(r,n,o,a,i,l,!1))}let z={current:W,params:$,query:q,intent:N,canGoBack:P,base:n||"/",navigate:V,replace:function(e,t){D=!0;let{pathname:r,stringQuery:n}=Q(e,t),o=W.value,a={...q.value},i=S(r,R),l={action:"replace",direction:t?.direction??"root",animation:t?.animation};A(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=W.value;return t?r===e:r===e||r.startsWith(e.endsWith("/")?e:e+"/")},resolve:function(e){let t=S(e,R);return t?{matched:!0,params:t.params,route:t.route.record}:{matched:!1,params:{},route:void 0}},beforeEach:function(e){return B.push(e),()=>{let t=B.indexOf(e);-1!==t&&B.splice(t,1)}},afterEach:function(e){return I.push(e),()=>{let t=I.indexOf(e);-1!==t&&I.splice(t,1)}},routes:t,_flat:R,_guards:B,_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(()=>{D||A(k,"",S(k,R)?.route.beforeEnter,()=>{},()=>{let e=b("/",{});i?(u.set(_("/",{}),{left:0,top:0}),history.replaceState(history.state,"",e)):history.replaceState(m({},{left:0,top:0},L),"",e);let t=S("/",R);N.value={action:"replace",direction:"root"},W.value="/",$.value=t?.params??{},q.value={},P.value=L>0,T("/",k,null)})}),z}function T(){return i(a)||u()}function E(){s&&=(s(),null),o=null}var D=class extends n{_depth;constructor(e=0){super(),this._depth=e}render(){let e=this._depth;return t`<div class="router-view">${()=>{let r=T(),n=S(r.current.value,r._flat);if(!n)return t`
|
|
2
|
+
<div style="color:#f87171;padding:16px 0">
|
|
3
|
+
404 — Route not found: <strong>${r.current.value}</strong>
|
|
4
|
+
</div>
|
|
5
|
+
`;if(e>=n.route.chain.length)return t`
|
|
6
|
+
<span></span>
|
|
7
|
+
`;let o=n.route.chain[e];return o?o():t`
|
|
8
|
+
<span></span>
|
|
9
|
+
`}}</div>`}},O=class extends n{_to;_label;constructor(e,t){super(),this._to=e,this._label=t}render(){let e=this._to,r=this._label,n=T(),o=e.startsWith("/")?e:"/"+e,a=(n._base?n._base+o:o).replace(/\/+/g,"/");return t`
|
|
10
|
+
<a href=${"hash"===n._mode?"#"+a:a} 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"} @click=${t=>{t.preventDefault(),n.navigate(e)}}>${r}</a>
|
|
11
|
+
`}};function k(){if(!o)return null;let e=o.current.value,t=S(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{O as Link,a as RouterKey,D as RouterView,k as _debugGetRouterInternal,d as _hasActiveRouter,E as _resetRouter,w as createRouter,T as nixRouter};
|
package/package.json
CHANGED