routexiz 0.2.0 → 0.2.1-z2
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 +33 -26
- package/build/index.esm.js +1 -1
- package/build/index.js +1 -1
- package/build/router/core.d.ts +3 -2
- package/build/router/navigation.d.ts +9 -9
- package/build/router/types.d.ts +19 -7
- package/build/router/utils.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
A lightweight, powerful, and modern router for React.
|
|
8
8
|
|
|
9
|
-
> Tree-based routing — modeled like a TreeView, where each route is a node and navigation resolves a single path from root to leaf.
|
|
9
|
+
> Tree-based routing — modeled like a TreeView, where each route is a node and navigation resolves a single path from root to leaf.
|
|
10
|
+
> Nested layouts via `children`.
|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -45,7 +46,7 @@ npm install routexiz
|
|
|
45
46
|
|
|
46
47
|
---
|
|
47
48
|
|
|
48
|
-
#
|
|
49
|
+
# Basic
|
|
49
50
|
|
|
50
51
|
```tsx
|
|
51
52
|
import { route, RouterProvider } from "routexiz"
|
|
@@ -61,36 +62,30 @@ export default function App() {
|
|
|
61
62
|
|
|
62
63
|
# Routing API
|
|
63
64
|
|
|
64
|
-
<b>route
|
|
65
|
+
<b>route</b>
|
|
65
66
|
|
|
66
67
|
```ts
|
|
67
68
|
route(path, component, config?)
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
<b>builder
|
|
71
|
+
<b>builder</b>
|
|
71
72
|
|
|
72
73
|
```ts
|
|
73
|
-
// home
|
|
74
|
-
// /dashboard
|
|
74
|
+
// /home
|
|
75
75
|
route("/", Layout, root => {
|
|
76
|
+
// /dashboard
|
|
76
77
|
root.route("/dashboard", Dashboard, dash => {
|
|
77
78
|
dash.guard(fn)
|
|
78
79
|
dash.middleware(fn)
|
|
79
80
|
dash.meta({ title: "Dashboard" })
|
|
80
81
|
})
|
|
81
|
-
|
|
82
82
|
// more
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
// /admin
|
|
86
|
-
// admin/dashboard
|
|
87
86
|
route("/admin", Admin, root => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
dash.middleware(fn)
|
|
91
|
-
dash.meta({ title: "Dashboard" })
|
|
92
|
-
})
|
|
93
|
-
|
|
87
|
+
// /admin/dashboard
|
|
88
|
+
root.route("/dashboard", AdminDashboard)
|
|
94
89
|
// more
|
|
95
90
|
})
|
|
96
91
|
|
|
@@ -98,6 +93,13 @@ route("/admin", Admin, root => {
|
|
|
98
93
|
|
|
99
94
|
```
|
|
100
95
|
|
|
96
|
+
<b>flatten</b>
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
route("/admin", Admin)
|
|
100
|
+
route("/admin/dashboard", AdminDashboard)
|
|
101
|
+
```
|
|
102
|
+
|
|
101
103
|
> Supports multiple route trees and deeply nested routing via a flexible builder API.
|
|
102
104
|
|
|
103
105
|
---
|
|
@@ -120,6 +122,17 @@ navigate("/users/:id", {
|
|
|
120
122
|
|
|
121
123
|
---
|
|
122
124
|
|
|
125
|
+
## redirect
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
redirect("/users/:id", {
|
|
129
|
+
params: { id: 1 },
|
|
130
|
+
query: { tab: "profile" }
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
123
136
|
## Link
|
|
124
137
|
|
|
125
138
|
```tsx
|
|
@@ -166,8 +179,8 @@ A guard determines whether navigation is allowed.
|
|
|
166
179
|
- Runs before entering a route
|
|
167
180
|
- Can block navigation
|
|
168
181
|
- Returns:
|
|
169
|
-
- true → allow
|
|
170
|
-
- false → block
|
|
182
|
+
- `true` → allow
|
|
183
|
+
- `false` → block
|
|
171
184
|
|
|
172
185
|
```ts
|
|
173
186
|
dash.guard(({ params }) => {
|
|
@@ -867,7 +880,7 @@ It’s lightweight and flexible, designed for client-side SPAs.
|
|
|
867
880
|
# Architecture
|
|
868
881
|
|
|
869
882
|
```text
|
|
870
|
-
Link / navigate
|
|
883
|
+
Link / navigate / redirect
|
|
871
884
|
↓
|
|
872
885
|
matchRouteChain
|
|
873
886
|
↓
|
|
@@ -877,7 +890,7 @@ loader (cached)
|
|
|
877
890
|
↓
|
|
878
891
|
Suspense
|
|
879
892
|
↓
|
|
880
|
-
render
|
|
893
|
+
render
|
|
881
894
|
```
|
|
882
895
|
|
|
883
896
|
---
|
|
@@ -890,17 +903,11 @@ Each route must resolve to a unique full path in the route tree.
|
|
|
890
903
|
|
|
891
904
|
## Why?
|
|
892
905
|
|
|
893
|
-
Because routing is tree-based:
|
|
894
|
-
|
|
895
906
|
- Navigation resolves a single path from root to leaf
|
|
896
907
|
- Duplicate paths create ambiguous matches
|
|
897
908
|
- This leads to unpredictable behavior
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
⚠️ Duplicate routes are NOT validated automatically.
|
|
902
|
-
|
|
903
|
-
The router will NOT throw an error or warning.
|
|
909
|
+
- Duplicate routes are NOT validated automatically.
|
|
910
|
+
- The router will NOT throw an error or warning.
|
|
904
911
|
|
|
905
912
|
## Requirement
|
|
906
913
|
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import n,{createContext as t,useContext as e,useState as r,useRef as o,useEffect as a,Suspense as i,forwardRef as s}from"react";import{jsx as c,Fragment as u,jsxs as l}from"react/jsx-runtime";import h from"joinclass";const d=new Map;function p(n=1/0){const t=Date.now();let e=0;for(const[r,o]of d.entries())if(o.expiry<=t&&(d.delete(r),e++,e>=n))break}function f(n,t,e,r){const o=Date.now(),a=d.get(n);if(a&&!r&&(!e||a.expiry>o))return a.resource;const i=m(t());return d.set(n,{resource:i,expiry:o+(e??0)}),i}function m(n,t){let e=t?"success":"pending",r=t??null;const o=n.then(n=>{e="success",r=n},n=>{e="error",r=n});return{read(){if("pending"===e)throw o;if("error"===e)throw r;return r},update(n){r=n,e="success"},get:()=>r}}function y(n){return n.startsWith("/")||(n="/"+n),"/"!==n&&n.endsWith("/")&&(n=n.slice(0,-1)),n}function g(n){return y(n).split("/").filter(Boolean)}function w(n){const[t,e]=n.split("#"),[r,o]=t.split("?"),a={};return o&&o.split("&").forEach(n=>{const[t,e]=n.split("=");if(!t)return;const r=decodeURIComponent(t),o=decodeURIComponent(e??"");void 0!==a[r]?Array.isArray(a[r])?a[r].push(o):a[r]=[a[r],o]:a[r]=o}),{path:y(r),query:a,hash:e??""}}function v(n,t){const e=n[t];return Array.isArray(e)?e[0]:e}function P(n){const t={};if(!n)return t;if("string"==typeof n){const e=new URLSearchParams(n);e.forEach((n,r)=>{const o=e.getAll(r);t[r]=o.length>1?o:o[0]})}else for(const e in n){const r=n[e];Array.isArray(r)?t[e]=r.map(n=>String(n)):null!=r&&(t[e]=String(r))}return t}function b(n){const t=g(n);let e=10*t.length;for(const n of t)"*"===n?e+=0:n.startsWith(":")?e+=1:e+=5;return e}function q(n){return[...n].sort((n,t)=>b(t.path)-b(n.path))}function E(n,t){const{path:e,query:r,hash:o}=w(t),a=g(e),i=q(n).map(n=>({node:n,segIndex:0,params:{},chain:[]}));for(;i.length;){const{node:n,segIndex:t,params:e,chain:s}=i.pop(),c=g(n.path),u={...e};let l=0;for(;l<c.length;l++){const n=c[l],e=a[t+l];if(!e)break;if("*"===n){u["*"]=a.slice(t+l).join("/"),l=c.length;break}if(n.startsWith(":"))u[n.slice(1)]=decodeURIComponent(e);else if(n!==e)break}if(l!==c.length)continue;const h=t+l,d=[...s,{node:n,params:u,query:r,hash:o}];if(h===a.length)return d;const p=q(n.children||[]);for(let n=p.length-1;n>=0;n--){const t=g(p[n].path).some(n=>n.startsWith(":"));i.push({node:p[n],segIndex:t?0:h,params:u,chain:d})}}return null}function k(n,t,e,r,o){const{path:a,query:i,hash:s}=w(n);let c=y(a);if(t)for(const n in t)c=c.replace(`:${n}`,encodeURIComponent(t[n]));const u=o?.replaceQuery?{...e??{}}:{...i,...e??{}},l=new URLSearchParams;for(const n in u){const t=u[n];Array.isArray(t)?t.forEach(t=>l.append(n,String(t))):l.append(n,String(t))}const h=l.toString();return h&&(c+=`?${h}`),r?c+=`#${r}`:s&&(c+=`#${s}`),c}function x(n){return JSON.stringify(Object.keys(n||{}).sort().reduce((t,e)=>(t[e]=n[e],t),{}))}function N(n,t){return`${n.path}|${x(t.params)}|${x(t.query)}|${t.hash}`}let S=[];function A(){S=[]}function R(){return S}function K(n){const t={guard:e=>(n.guardFns||(n.guardFns=[]),n.guardFns.push(e),t),middleware:e=>(n.middlewares||(n.middlewares=[]),n.middlewares.push(e),t),meta:e=>(n.meta={...n.meta||{},...e},t),route(t,e,r){const o={path:y(t),component:e,children:[],options:{},guardFns:[],middlewares:[],parent:n};return"function"==typeof r?K(o)(r):r&&(o.options=r),n.children.push(o),K(o).api}};return Object.assign(n=>n(t),{api:t})}function C(n,t,e){const r={path:y(n),component:t,children:[],options:{},parent:void 0};return"function"==typeof e?K(r)(e):e&&(r.options=e),S.push(r),K(r).api}const $=t(null),I=t(null),M=t(null),j=t({loading:!1,path:"",pendingPath:""}),F=t({name:"none",stage:"idle"});function L(){const n=e($);try{return n?.read()}catch{return}}function O(){const n=e(I);if(!n)throw new Error("RouteContext not found");return n}function B(){return e(M)??{}}function D(){try{const n=O();if(n?.query)return n.query}catch{}const{query:n}=w(window.location.pathname+window.location.search+window.location.hash);return n}function Q(){return e(j)}function U(){return e(F)}function W(){try{return L()}catch{return}}function T(){const{meta:n,params:t,path:e,query:r}=O();return{data:W(),params:t??{},query:r??{},path:e,meta:n}}const G=200;function J({name:n="fade",stage:t,duration:e=200,children:i}){const[s,d]=r(i),[p,f]=r(null),m=o();return a(()=>{m.current&&clearTimeout(m.current),"exiting"===t&&f(s),"entering"===t&&(d(i),m.current=window.setTimeout(()=>{f(null)},e))},[i,t,e]),"idle"===t?c(u,{children:i}):l("div",{className:h("rtx",`rtx-${n}`),children:[p&&c("div",{className:"rtx-exit",children:p}),c("div",{className:h("rtx-enter",`rtx-${t}`),children:s})]})}let z=!1,H=!1,V=c("div",{children:"Loading..."});const X=({error:n})=>l("div",{children:["Global Error: ",String(n)]});let Y=null;function Z(n,t){z=n,t&&(V=t)}function _(n,t){H=n,Y=t??null}function nn(){return z}function tn(){return H}function en(){return V}function rn(){return Y?({error:n})=>Y(n):X}class on extends n.Component{constructor(n){super(n),this.reset=()=>{this.setState(n=>({hasError:!1,error:null,resetKey:n.resetKey+1}))},this.state={hasError:!1,error:null,resetKey:0}}static getDerivedStateFromError(n){return{hasError:!0,error:n}}render(){if(this.state.hasError){const n=this.props.errorBoundary??(tn()?rn():void 0);return n?c(n,{error:this.state.error,params:this.props.params}):this.props.fallback??l("div",{children:["Error: ",String(this.state.error)]})}return c(n.Fragment,{children:this.props.children},this.state.resetKey)}}function an({resource:t,errorBoundary:e,children:r,resetKey:o}){const[a,i]=n.useState(null);n.useEffect(()=>{i(null)},[o]);try{return t?.read(),a&&i(null),c(u,{children:r})}catch(n){if(n instanceof Promise)throw n;const t=e??(tn()?rn():void 0);if(t)return c(t,{error:n});throw n}}function sn({chain:n,data:t}){return c(u,{children:function e(r=0){const o=n[r];if(!o)return null;const a=o.node.component;if(!a)return e(r+1);const s={params:o.params,path:o.node.path,query:o.query,hash:o.hash},u=function(n,t){let e=n;for(;e;){const n=e.options?.fallback;if(n)return"function"==typeof n?n(t):n;e=e.parent}return nn()?en():null}(o.node,s),l=Object.assign({},...n.slice(0,r+1).map(n=>n.node.meta)),h=t[N(o.node,s)];return c(on,{fallback:u,errorBoundary:o.node.options?.errorBoundary,params:o.params,children:c(i,{fallback:u,children:c(I.Provider,{value:{path:o.node.path,params:o.params,query:P(o.query),hash:o.hash??"",meta:l},children:c($.Provider,{value:h,children:c(M.Provider,{value:o.params,children:c(an,{resource:h,errorBoundary:o.node.options?.errorBoundary,resetKey:o.params.id||o.params,children:c(a,{children:e(r+1)})})})})})})})}()})}let cn=null;function un(){return cn}function ln(n,t){const e=R(),[r,o]=n.split("?"),a={...P(o),...t?.query??{}},i=E(e,k(r,t?.params,a,t?.hash));i&&hn(i,{forceReload:!1})}function hn(n,t){const e={};return n.forEach(n=>{const r=n.node.options?.loader;if(!r)return;const o={params:n.params,path:n.node.path,query:n.query,hash:n.hash},a=N(n.node,o),i=n.node.options?.ttl,s=t?.forceReload??n.node.options?.shouldReload?.({prev:void 0,next:o})??!0;e[a]=f(a,()=>Promise.resolve(r(o)),i,s)}),e}function dn({transition:n,duration:t,wrapper:e}){const[i,s]=r({chain:[],data:{},loading:!1,path:"",pendingPath:"",transition:{name:"none",stage:"idle"},duration:t??G}),u=o(0);async function l(e,r){const o=++u.current,a=R(),i=E(a,e)??E(a,"*")??[];for(const n of i)for(const t of n.node.guardFns||[]){if(!await t({params:n.params,path:n.node.path,query:n.query,hash:n.hash}))return console.warn("Navigation blocked",e),!1}for(const n of i)for(const t of n.node.middlewares||[])await t({params:n.params,path:n.node.path,query:n.query,hash:n.hash}).catch(console.error);const c=function(n,t,e){if(t?.transition)return t.transition;for(let t=n.length-1;t>=0;t--){const e=n[t].node;if(e.options?.transition)return e.options.transition;if(e.meta?.transition)return e.meta.transition}return e??"none"}(i,r,n),l=function(n,t,e){if(null!=t?.duration)return t.duration;for(let t=n.length-1;t>=0;t--){const e=n[t].node;if(null!=e.options?.duration)return e.options.duration}return null!=e?e:G}(i,r,t);s(n=>({...n,loading:!0,pendingPath:e,transition:{name:c,stage:"exiting"},duration:l})),await new Promise(n=>setTimeout(n,l));const h=hn(i,r);return o===u.current&&(s(n=>({...n,chain:i,data:{...n.data,...h},loading:!1,path:e,pendingPath:"",transition:{name:c,stage:"entering"},duration:l})),window.scrollTo(0,0),!0)}a(()=>{cn=l;const n=()=>window.location.pathname+window.location.search+window.location.hash;l(n());const t=()=>l(n());window.addEventListener("popstate",t);const e=()=>{const t=E(R(),n());if(!t)return;const e={};t.forEach(n=>{n.node.options?.revalidateOnFocus&&Object.assign(e,hn([n],{forceReload:!0}))}),Object.keys(e).length&&s(n=>({...n,data:{...n.data,...e}}))};return window.addEventListener("focus",e),()=>{window.removeEventListener("popstate",t),window.removeEventListener("focus",e)}},[]);const h=c(sn,{chain:i.chain,data:i.data},i.path);let d=h;if("none"!==i.transition.name&&(d=c(J,{name:i.transition.name,stage:i.transition.stage,duration:i.duration,children:h})),e){d=c(e,{children:d})}return c(j.Provider,{value:{loading:i.loading,path:i.path,pendingPath:i.pendingPath},children:c(F.Provider,{value:i.transition,children:d})})}const pn=[],fn=[];function mn(n){pn.push(n)}function yn(n){fn.push(n)}async function gn(n,t,e=!1){const r={...t,forceReload:t?.forceReload??!0},o=k(n,r.params,r.query,r.hash);if(window.location.pathname+window.location.search+window.location.hash===o)return!0;if(!await async function(n){return(await Promise.all(pn.map(t=>t(n)))).every(n=>!1!==n)}(o))return console.warn("Navigation blocked by beforeNavigation hook",o),!1;const a=un();if(!r.shallow&&a){if(!await a(o,r))return console.warn("Navigation blocked by route guard",o),!1}return e?window.history.replaceState({},"",o):window.history.pushState({},"",o),async function(n){for(const t of fn)await t(n)}(o),!0}function wn(n,t){return gn(n,t,!1)}function vn(n,t){return wn(n,t)}function Pn(){const n=(n,t)=>gn(n,t);return n.replace=(n,t)=>gn(n,t,!0),n}function bn(n){return Q().path===n}function qn(n,t){return()=>ln(n,t)}function En({to:n,transition:t,replace:e,params:r,query:i,hash:s,partialMatch:c,disablePrefetch:u,replaceQuery:l}){const h=Pn(),d=Q(),p=o(null),f=k(n,r,i,s,{replaceQuery:l}),m=c?d.path?.startsWith(f):d.path===f;return a(()=>{if(u)return;const n=p.current;if(!n)return;const t=new IntersectionObserver(n=>{n.some(n=>n.isIntersecting)&&(ln(f),t.disconnect())},{rootMargin:"200px"});return t.observe(n),()=>t.disconnect()},[f,u]),{ref:p,fullPath:f,isActive:m,go:async()=>e?h.replace(n,{transition:t,params:r,query:i,hash:s}):h(n,{transition:t,params:r,query:i,hash:s})}}wn.replace=(n,t)=>gn(n,t,!0);const kn=s(({fullPath:n,onNavigate:t,onPrefetch:e,onClick:r,onMouseEnter:o,onKeyDown:a,disablePrefetch:i,...s},u)=>c("a",{ref:u,href:n,...s,onClick:async e=>{if(r&&r(e),e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;e.preventDefault();await t()||console.warn("Navigation blocked:",n)},onMouseEnter:n=>{o&&o(n),i||e?.()},onKeyDown:async e=>{if("Enter"===e.key){e.preventDefault();await t()||console.warn("Navigation blocked:",n)}a&&a(e)}}));function xn(n){const{to:t,transition:e,replace:r,activeClassName:o="active",onNavigate:a,partialMatch:i,params:s,query:u,hash:l,className:d,disablePrefetch:p,replaceQuery:f,...m}=n,{ref:y,fullPath:g,isActive:w,go:v}=En({to:t,transition:e,replace:r,params:s,query:u,hash:l,partialMatch:i,disablePrefetch:p,replaceQuery:f});return c(kn,{ref:y,fullPath:g,onNavigate:async()=>{const n=await v();return a?.(g),n},onPrefetch:()=>ln(g),className:h(d,w&&o),disablePrefetch:p,...m})}function Nn(n){const{to:t,transition:e,replace:r,params:o,query:a,hash:i,partialMatch:s,className:u,style:l,disablePrefetch:d,replaceQuery:p,...f}=n,{ref:m,fullPath:y,isActive:g,go:w}=En({to:t,transition:e,replace:r,params:o,query:a,hash:i,partialMatch:s,disablePrefetch:d,replaceQuery:p}),v="function"==typeof u?u({isActive:g}):u,P="function"==typeof l?l({isActive:g}):l;return c(kn,{ref:m,fullPath:y,onNavigate:async()=>(await w(),!0),onPrefetch:()=>ln(y),className:h(v),style:P,disablePrefetch:d,...f})}kn.displayName="LinkCore";export{G as DEFAULT_DURATION,xn as Link,$ as LoaderDataContext,Nn as NavLink,M as ParamsContext,I as RouteContext,dn as RouterProvider,j as RouterStateContext,J as Transition,F as TransitionContext,yn as addAfterNavigationHook,mn as addBeforeNavigationHook,N as buildCacheKey,k as buildPath,p as cleanupCache,A as clearRoutes,m as createResource,rn as getGlobalError,en as getGlobalFallback,un as getGlobalResolve,v as getQueryFirst,f as getResource,R as getRoutes,tn as getUseGlobalError,nn as getUseGlobalFallback,E as matchRouteChain,wn as navigate,y as normalize,P as normalizeQuery,w as parseQueryHash,ln as prefetch,vn as redirect,C as route,_ as setGlobalError,Z as setGlobalFallback,g as split,En as useLinkCore,L as useLoaderData,Pn as useNavigate,Q as useNavigation,B as useParams,qn as usePrefetch,D as useQuery,O as useRouteContext,bn as useRouteMatch,T as useRouterData,W as useSafeLoaderData,U as useTransition};
|
|
1
|
+
import n,{createContext as t,useContext as e,useState as r,useRef as o,useEffect as a,Suspense as i,forwardRef as s}from"react";import{jsx as c,Fragment as u,jsxs as l}from"react/jsx-runtime";import h from"joinclass";const d=new Map;function f(n=1/0){const t=Date.now();let e=0;for(const[r,o]of d.entries())if(o.expiry<=t&&(d.delete(r),e++,e>=n))break}function p(n,t,e,r){const o=Date.now(),a=d.get(n);if(a&&!r&&(!e||a.expiry>o))return a.resource;const i=m(t());return d.set(n,{resource:i,expiry:o+(e??0)}),i}function m(n,t){let e=t?"success":"pending",r=t??null;const o=n.then(n=>{e="success",r=n},n=>{e="error",r=n});return{read(){if("pending"===e)throw o;if("error"===e)throw r;return r},update(n){r=n,e="success"},get:()=>r}}function y(n){return n.startsWith("/")||(n="/"+n),"/"!==n&&n.endsWith("/")&&(n=n.slice(0,-1)),n}function g(n){return y(n).split("/").filter(Boolean)}function w(n){const[t,e]=n.split("#"),[r,o]=t.split("?"),a={};return o&&o.split("&").forEach(n=>{const[t,e]=n.split("=");if(!t)return;const r=decodeURIComponent(t),o=decodeURIComponent(e??"");void 0!==a[r]?Array.isArray(a[r])?a[r].push(o):a[r]=[a[r],o]:a[r]=o}),{path:y(r),query:a,hash:e??""}}function v(n,t){const e=n[t];return Array.isArray(e)?e[0]:e}function P(n){const t={};if(!n)return t;if("string"==typeof n){const e=new URLSearchParams(n);e.forEach((n,r)=>{const o=e.getAll(r);t[r]=o.length>1?o:o[0]})}else for(const e in n){const r=n[e];Array.isArray(r)?t[e]=r.map(n=>String(n)):null!=r&&(t[e]=String(r))}return t}function b(n){const t=g(n);let e=10*t.length;for(const n of t)"*"===n?e+=0:n.startsWith(":")?e+=1:e+=5;return e}function q(n){return[...n].sort((n,t)=>b(t.path)-b(n.path))}function x(n,t){const{path:e,query:r,hash:o}=w(t),a=g(e),i=q(n).map(n=>({node:n,segIndex:0,params:{},chain:[]}));for(;i.length;){const{node:n,segIndex:t,params:e,chain:s}=i.pop(),c=g(n.path),u={...e};let l=0;for(;l<c.length;l++){const n=c[l],e=a[t+l];if(!e)break;if("*"===n){u["*"]=a.slice(t+l).join("/"),l=c.length;break}if(n.startsWith(":"))u[n.slice(1)]=decodeURIComponent(e);else if(n!==e)break}if(l!==c.length)continue;const h=t+l,d=[...s,{node:n,params:u,query:r,hash:o}];if(h===a.length)return d;const f=q(n.children||[]);for(let n=f.length-1;n>=0;n--){const t=g(f[n].path).some(n=>n.startsWith(":"));i.push({node:f[n],segIndex:t?0:h,params:u,chain:d})}}return null}function k(n,t,e,r,o){const{path:a,query:i,hash:s}=w(n);let c=y(a);if(t)for(const n in t)c=c.replace(`:${n}`,encodeURIComponent(t[n]));const u=o?.replaceQuery?{...e??{}}:{...i,...e??{}},l=new URLSearchParams;for(const n in u){const t=u[n];Array.isArray(t)?t.forEach(t=>l.append(n,String(t))):l.append(n,String(t))}const h=l.toString();return h&&(c+=`?${h}`),r?c+=`#${r}`:s&&(c+=`#${s}`),c}function E(n){return JSON.stringify(Object.keys(n||{}).sort().reduce((t,e)=>(t[e]=n[e],t),{}))}function N(n,t){return`${n.path}|${E(t.params)}|${E(t.query)}|${t.hash}`}let S=[];function A(){S=[]}function R(){return S}function K(n){const t={guard:e=>(n.guardFns||(n.guardFns=[]),n.guardFns.push(e),t),middleware:e=>(n.middlewares||(n.middlewares=[]),n.middlewares.push(e),t),meta:e=>(n.meta={...n.meta||{},...e},t),route(t,e,r){const o={path:y(t),component:e,children:[],options:{},guardFns:[],middlewares:[],parent:n};return"function"==typeof r?K(o)(r):r&&(o.options=r),n.children.push(o),K(o).api}};return Object.assign(n=>n(t),{api:t})}function C(n,t,e){const r={path:y(n),component:t,children:[],options:{},parent:void 0};return"function"==typeof e?K(r)(e):e&&(r.options=e),S.push(r),K(r).api}const $=t(null),j=t(null),I=t(null),M=t({loading:!1,path:"",pendingPath:""}),F=t({name:"none",stage:"idle"});function L(){const n=e($);try{return n?.read()}catch{return}}function O(){const n=e(j);if(!n)throw new Error("RouteContext not found");return n}function B(){return e(I)??{}}function D(){try{const n=O();if(n?.query)return n.query}catch{}const{query:n}=w(window.location.pathname+window.location.search+window.location.hash);return n}function Q(){return e(M)}function U(){return e(F)}function W(){try{return L()}catch{return}}function T(){const{meta:n,params:t,path:e,query:r}=O();return{data:W(),params:t??{},query:r??{},path:e,meta:n}}const G=200;function J({name:n="fade",stage:t,duration:e=200,children:i}){const[s,d]=r(i),[f,p]=r(null),m=o();return a(()=>{m.current&&clearTimeout(m.current),"exiting"===t&&p(s),"entering"===t&&(d(i),m.current=window.setTimeout(()=>{p(null)},e))},[i,t,e]),"idle"===t?c(u,{children:i}):l("div",{className:h("rtx",`rtx-${n}`),children:[f&&c("div",{className:"rtx-exit",children:f}),c("div",{className:h("rtx-enter",`rtx-${t}`),children:s})]})}let z=!1,H=!1,V=c("div",{children:"Loading..."});const X=({error:n})=>l("div",{children:["Global Error: ",String(n)]});let Y=null;function Z(n,t){z=n,t&&(V=t)}function _(n,t){H=n,Y=t??null}function nn(){return z}function tn(){return H}function en(){return V}function rn(){return Y?({error:n})=>Y(n):X}class on extends n.Component{constructor(n){super(n),this.reset=()=>{this.setState(n=>({hasError:!1,error:null,resetKey:n.resetKey+1}))},this.state={hasError:!1,error:null,resetKey:0}}static getDerivedStateFromError(n){return{hasError:!0,error:n}}render(){if(this.state.hasError){const n=this.props.errorBoundary??(tn()?rn():void 0);return n?c(n,{error:this.state.error,params:this.props.params}):this.props.fallback??l("div",{children:["Error: ",String(this.state.error)]})}return c(n.Fragment,{children:this.props.children},this.state.resetKey)}}function an({resource:t,errorBoundary:e,children:r,resetKey:o}){const[a,i]=n.useState(null);n.useEffect(()=>{i(null)},[o]);try{return t?.read(),a&&i(null),c(u,{children:r})}catch(n){if(n instanceof Promise)throw n;const t=e??(tn()?rn():void 0);if(t)return c(t,{error:n});throw n}}function sn({chain:n,data:t}){return c(u,{children:function e(r=0){const o=n[r];if(!o)return null;const a=o.node.component;if(!a)return e(r+1);const s={params:o.params,path:o.node.path,query:o.query,hash:o.hash},u=function(n,t){let e=n;for(;e;){const n=e.options?.fallback;if(n)return"function"==typeof n?n(t):n;e=e.parent}return nn()?en():null}(o.node,s),l=Object.assign({},...n.slice(0,r+1).map(n=>n.node.meta)),h=t[N(o.node,s)];return c(on,{fallback:u,errorBoundary:o.node.options?.errorBoundary,params:o.params,children:c(i,{fallback:u,children:c(j.Provider,{value:{path:o.node.path,params:o.params,query:P(o.query),hash:o.hash??"",meta:l},children:c($.Provider,{value:h,children:c(I.Provider,{value:o.params,children:c(an,{resource:h,errorBoundary:o.node.options?.errorBoundary,resetKey:o.params.id||o.params,children:c(a,{children:e(r+1)})})})})})})})}()})}function cn(n,t){const e={};for(const r of n){const n=r.node.options?.loader;if(!n)continue;const o={params:r.params,path:r.node.path,query:r.query,hash:r.hash},a=N(r.node,o),i=r.node.options?.ttl,s=t?.forceReload??r.node.options?.shouldReload?.({prev:void 0,next:o})??!0;e[a]=p(a,()=>Promise.resolve(n(o)),i,s)}return e}let un=null;function ln(){return un}function hn(n,t){const e=R(),[r,o]=n.split("?"),a={...P(o),...t?.query??{}},i=x(e,k(r,t?.params,a,t?.hash));i&&cn(i,{forceReload:!1})}function dn({transition:n,duration:t,wrapper:e}){const[i,s]=r({chain:[],data:{},loading:!1,path:"",pendingPath:"",transition:{name:"none",stage:"idle"},duration:t??G}),u=o(0),l=async(e,r)=>{const o=++u.current,a=function(n){const t=R();return x(t,n)??x(t,"*")??[]}(e),i=await async function(n,t){for(const e of n)for(const n of e.node.guardFns||[]){const r=await n({params:e.params,path:e.node.path,query:e.query,hash:e.hash});if(!1===r)return!1;if("object"==typeof r&&"redirect"in r)return await t(r.redirect),!1}return!0}(a,l);if(!i)return!1;await async function(n){for(const t of n)for(const n of t.node.middlewares||[])await Promise.resolve(n({params:t.params,path:t.node.path,query:t.query,hash:t.hash})).catch(console.error)}(a);const c=function(n,t,e){if(t?.transition)return t.transition;for(let t=n.length-1;t>=0;t--){const e=n[t].node;if(e.options?.transition)return e.options.transition;if(e.meta?.transition)return e.meta.transition}return e??"none"}(a,r,n),h=function(n,t,e){if(null!=t?.duration)return t.duration;for(let t=n.length-1;t>=0;t--){const e=n[t].node;if(null!=e.options?.duration)return e.options.duration}return null!=e?e:G}(a,r,t);!function(n,t,e,r){n(n=>({...n,loading:!0,pendingPath:t,transition:{name:e,stage:"exiting"},duration:r}))}(s,e,c,h),await new Promise(n=>setTimeout(n,h));const d=r?.shallow?{}:cn(a,r);return o===u.current&&(function(n,t,e,r,o,a){n(n=>({...n,chain:t,data:{...n.data,...e},loading:!1,path:r,pendingPath:"",transition:{name:o,stage:"entering"},duration:a}))}(s,a,d??{},e,c,h),r?.shallow||window.scrollTo(0,0),!0)};a(()=>{un=l;const n=()=>window.location.pathname+window.location.search+window.location.hash;l(n());const t=()=>l(n());window.addEventListener("popstate",t);const e=()=>{const t=x(R(),n());if(!t)return;const e={};for(const n of t)n.node.options?.revalidateOnFocus&&Object.assign(e,cn([n],{forceReload:!0}));Object.keys(e).length&&s(n=>({...n,data:{...n.data,...e}}))};return window.addEventListener("focus",e),()=>{window.removeEventListener("popstate",t),window.removeEventListener("focus",e),un=null}},[]);const h=c(sn,{chain:i.chain,data:i.data},i.path);let d=h;if("none"!==i.transition.name&&(d=c(J,{name:i.transition.name,stage:i.transition.stage,duration:i.duration,children:h})),e){d=c(e,{children:d})}return c(M.Provider,{value:{loading:i.loading,path:i.path,pendingPath:i.pendingPath},children:c(F.Provider,{value:i.transition,children:d})})}const fn=[],pn=[];function mn(n){fn.push(n)}function yn(n){pn.push(n)}async function gn(n,t,e=!1){const r={...t,forceReload:t?.forceReload??!0},o=k(n,r.params,r.query,r.hash);if(window.location.pathname+window.location.search+window.location.hash===o)return!0;if(!await async function(n){return(await Promise.all(fn.map(t=>t(n)))).every(n=>!1!==n)}(o))return console.warn("Navigation blocked by beforeNavigation hook",o),!1;const a=ln();if(!r.shallow&&a){if(!await a(o,r))return console.warn("Navigation blocked by route guard",o),!1}return e?window.history.replaceState({},"",o):window.history.pushState({},"",o),async function(n){for(const t of pn)await t(n)}(o),!0}function wn(n,t){return gn(n,t,!1)}function vn(n,t){return wn(n,t)}function Pn(){const n=(n,t)=>gn(n,t);return n.replace=(n,t)=>gn(n,t,!0),n}function bn(n){return Q().path===n}function qn(n,t){return()=>hn(n,t)}function xn({to:n,transition:t,replace:e,params:r,query:i,hash:s,partialMatch:c,disablePrefetch:u,replaceQuery:l}){const h=Pn(),d=Q(),f=o(null),p=k(n,r,i,s,{replaceQuery:l}),m=c?d.path?.startsWith(p):d.path===p;return a(()=>{if(u)return;const n=f.current;if(!n)return;const t=new IntersectionObserver(n=>{n.some(n=>n.isIntersecting)&&(hn(p),t.disconnect())},{rootMargin:"200px"});return t.observe(n),()=>t.disconnect()},[p,u]),{ref:f,fullPath:p,isActive:m,go:async()=>e?h.replace(n,{transition:t,params:r,query:i,hash:s}):h(n,{transition:t,params:r,query:i,hash:s})}}wn.replace=function(n,t){return gn(n,t,!0)};const kn=s(({fullPath:n,onNavigate:t,onPrefetch:e,onClick:r,onMouseEnter:o,onKeyDown:a,disablePrefetch:i,...s},u)=>c("a",{ref:u,href:n,...s,onClick:async e=>{if(r&&r(e),e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;e.preventDefault();await t()||console.warn("Navigation blocked:",n)},onMouseEnter:n=>{o&&o(n),i||e?.()},onKeyDown:async e=>{if("Enter"===e.key){e.preventDefault();await t()||console.warn("Navigation blocked:",n)}a&&a(e)}}));function En(n){const{to:t,transition:e,replace:r,activeClassName:o="active",onNavigate:a,partialMatch:i,params:s,query:u,hash:l,className:d,disablePrefetch:f,replaceQuery:p,...m}=n,{ref:y,fullPath:g,isActive:w,go:v}=xn({to:t,transition:e,replace:r,params:s,query:u,hash:l,partialMatch:i,disablePrefetch:f,replaceQuery:p});return c(kn,{ref:y,fullPath:g,onNavigate:async()=>{const n=await v();return a?.(g),n},onPrefetch:()=>hn(g),className:h(d,w&&o),disablePrefetch:f,...m})}function Nn(n){const{to:t,transition:e,replace:r,params:o,query:a,hash:i,partialMatch:s,className:u,style:l,disablePrefetch:d,replaceQuery:f,...p}=n,{ref:m,fullPath:y,isActive:g,go:w}=xn({to:t,transition:e,replace:r,params:o,query:a,hash:i,partialMatch:s,disablePrefetch:d,replaceQuery:f}),v="function"==typeof u?u({isActive:g}):u,P="function"==typeof l?l({isActive:g}):l;return c(kn,{ref:m,fullPath:y,onNavigate:async()=>(await w(),!0),onPrefetch:()=>hn(y),className:h(v),style:P,disablePrefetch:d,...p})}kn.displayName="LinkCore";export{G as DEFAULT_DURATION,En as Link,$ as LoaderDataContext,Nn as NavLink,I as ParamsContext,j as RouteContext,dn as RouterProvider,M as RouterStateContext,J as Transition,F as TransitionContext,yn as addAfterNavigationHook,mn as addBeforeNavigationHook,N as buildCacheKey,k as buildPath,f as cleanupCache,A as clearRoutes,m as createResource,rn as getGlobalError,en as getGlobalFallback,ln as getGlobalResolve,v as getQueryFirst,p as getResource,R as getRoutes,tn as getUseGlobalError,nn as getUseGlobalFallback,x as matchRouteChain,wn as navigate,y as normalize,P as normalizeQuery,w as parseQueryHash,hn as prefetch,vn as redirect,C as route,_ as setGlobalError,Z as setGlobalFallback,g as split,xn as useLinkCore,L as useLoaderData,Pn as useNavigate,Q as useNavigation,B as useParams,qn as usePrefetch,D as useQuery,O as useRouteContext,bn as useRouteMatch,T as useRouterData,W as useSafeLoaderData,U as useTransition};
|
package/build/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("react"),t=require("react/jsx-runtime"),r=require("joinclass");const n=new Map;function o(e,t,r,o){const s=Date.now(),i=n.get(e);if(i&&!o&&(!r||i.expiry>s))return i.resource;const c=a(t());return n.set(e,{resource:c,expiry:s+(r??0)}),c}function a(e,t){let r=t?"success":"pending",n=t??null;const o=e.then(e=>{r="success",n=e},e=>{r="error",n=e});return{read(){if("pending"===r)throw o;if("error"===r)throw n;return n},update(e){n=e,r="success"},get:()=>n}}function s(e){return e.startsWith("/")||(e="/"+e),"/"!==e&&e.endsWith("/")&&(e=e.slice(0,-1)),e}function i(e){return s(e).split("/").filter(Boolean)}function c(e){const[t,r]=e.split("#"),[n,o]=t.split("?"),a={};return o&&o.split("&").forEach(e=>{const[t,r]=e.split("=");if(!t)return;const n=decodeURIComponent(t),o=decodeURIComponent(r??"");void 0!==a[n]?Array.isArray(a[n])?a[n].push(o):a[n]=[a[n],o]:a[n]=o}),{path:s(n),query:a,hash:r??""}}function u(e){const t={};if(!e)return t;if("string"==typeof e){const r=new URLSearchParams(e);r.forEach((e,n)=>{const o=r.getAll(n);t[n]=o.length>1?o:o[0]})}else for(const r in e){const n=e[r];Array.isArray(n)?t[r]=n.map(e=>String(e)):null!=n&&(t[r]=String(n))}return t}function l(e){const t=i(e);let r=10*t.length;for(const e of t)"*"===e?r+=0:e.startsWith(":")?r+=1:r+=5;return r}function p(e){return[...e].sort((e,t)=>l(t.path)-l(e.path))}function h(e,t){const{path:r,query:n,hash:o}=c(t),a=i(r),s=p(e).map(e=>({node:e,segIndex:0,params:{},chain:[]}));for(;s.length;){const{node:e,segIndex:t,params:r,chain:c}=s.pop(),u=i(e.path),l={...r};let h=0;for(;h<u.length;h++){const e=u[h],r=a[t+h];if(!r)break;if("*"===e){l["*"]=a.slice(t+h).join("/"),h=u.length;break}if(e.startsWith(":"))l[e.slice(1)]=decodeURIComponent(r);else if(e!==r)break}if(h!==u.length)continue;const d=t+h,f=[...c,{node:e,params:l,query:n,hash:o}];if(d===a.length)return f;const x=p(e.children||[]);for(let e=x.length-1;e>=0;e--){const t=i(x[e].path).some(e=>e.startsWith(":"));s.push({node:x[e],segIndex:t?0:d,params:l,chain:f})}}return null}function d(e,t,r,n,o){const{path:a,query:i,hash:u}=c(e);let l=s(a);if(t)for(const e in t)l=l.replace(`:${e}`,encodeURIComponent(t[e]));const p=o?.replaceQuery?{...r??{}}:{...i,...r??{}},h=new URLSearchParams;for(const e in p){const t=p[e];Array.isArray(t)?t.forEach(t=>h.append(e,String(t))):h.append(e,String(t))}const d=h.toString();return d&&(l+=`?${d}`),n?l+=`#${n}`:u&&(l+=`#${u}`),l}function f(e){return JSON.stringify(Object.keys(e||{}).sort().reduce((t,r)=>(t[r]=e[r],t),{}))}function x(e,t){return`${e.path}|${f(t.params)}|${f(t.query)}|${t.hash}`}let m=[];function y(){return m}function g(e){const t={guard:r=>(e.guardFns||(e.guardFns=[]),e.guardFns.push(r),t),middleware:r=>(e.middlewares||(e.middlewares=[]),e.middlewares.push(r),t),meta:r=>(e.meta={...e.meta||{},...r},t),route(t,r,n){const o={path:s(t),component:r,children:[],options:{},guardFns:[],middlewares:[],parent:e};return"function"==typeof n?g(o)(n):n&&(o.options=n),e.children.push(o),g(o).api}};return Object.assign(e=>e(t),{api:t})}const w=e.createContext(null),v=e.createContext(null),b=e.createContext(null),P=e.createContext({loading:!1,path:"",pendingPath:""}),j=e.createContext({name:"none",stage:"idle"});function q(){const t=e.useContext(w);try{return t?.read()}catch{return}}function C(){const t=e.useContext(v);if(!t)throw new Error("RouteContext not found");return t}function R(){return e.useContext(P)}function k(){try{return q()}catch{return}}const E=200;function N({name:n="fade",stage:o,duration:a=200,children:s}){const[i,c]=e.useState(s),[u,l]=e.useState(null),p=e.useRef();return e.useEffect(()=>{p.current&&clearTimeout(p.current),"exiting"===o&&l(i),"entering"===o&&(c(s),p.current=window.setTimeout(()=>{l(null)},a))},[s,o,a]),"idle"===o?t.jsx(t.Fragment,{children:s}):t.jsxs("div",{className:r("rtx",`rtx-${n}`),children:[u&&t.jsx("div",{className:"rtx-exit",children:u}),t.jsx("div",{className:r("rtx-enter",`rtx-${o}`),children:i})]})}let S=!1,A=!1,F=t.jsx("div",{children:"Loading..."});const L=({error:e})=>t.jsxs("div",{children:["Global Error: ",String(e)]});let D=null;function K(){return S}function Q(){return A}function I(){return F}function M(){return D?({error:e})=>D(e):L}class U extends e.Component{constructor(e){super(e),this.reset=()=>{this.setState(e=>({hasError:!1,error:null,resetKey:e.resetKey+1}))},this.state={hasError:!1,error:null,resetKey:0}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}render(){if(this.state.hasError){const e=this.props.errorBoundary??(Q()?M():void 0);return e?t.jsx(e,{error:this.state.error,params:this.props.params}):this.props.fallback??t.jsxs("div",{children:["Error: ",String(this.state.error)]})}return t.jsx(e.Fragment,{children:this.props.children},this.state.resetKey)}}function $({resource:r,errorBoundary:n,children:o,resetKey:a}){const[s,i]=e.useState(null);e.useEffect(()=>{i(null)},[a]);try{return r?.read(),s&&i(null),t.jsx(t.Fragment,{children:o})}catch(e){if(e instanceof Promise)throw e;const r=n??(Q()?M():void 0);if(r)return t.jsx(r,{error:e});throw e}}function O({chain:r,data:n}){return t.jsx(t.Fragment,{children:function o(a=0){const s=r[a];if(!s)return null;const i=s.node.component;if(!i)return o(a+1);const c={params:s.params,path:s.node.path,query:s.query,hash:s.hash},l=function(e,t){let r=e;for(;r;){const e=r.options?.fallback;if(e)return"function"==typeof e?e(t):e;r=r.parent}return K()?I():null}(s.node,c),p=Object.assign({},...r.slice(0,a+1).map(e=>e.node.meta)),h=n[x(s.node,c)];return t.jsx(U,{fallback:l,errorBoundary:s.node.options?.errorBoundary,params:s.params,children:t.jsx(e.Suspense,{fallback:l,children:t.jsx(v.Provider,{value:{path:s.node.path,params:s.params,query:u(s.query),hash:s.hash??"",meta:p},children:t.jsx(w.Provider,{value:h,children:t.jsx(b.Provider,{value:s.params,children:t.jsx($,{resource:h,errorBoundary:s.node.options?.errorBoundary,resetKey:s.params.id||s.params,children:t.jsx(i,{children:o(a+1)})})})})})})})}()})}let T=null;function B(){return T}function G(e,t){const r=y(),[n,o]=e.split("?"),a={...u(o),...t?.query??{}},s=h(r,d(n,t?.params,a,t?.hash));s&&W(s,{forceReload:!1})}function W(e,t){const r={};return e.forEach(e=>{const n=e.node.options?.loader;if(!n)return;const a={params:e.params,path:e.node.path,query:e.query,hash:e.hash},s=x(e.node,a),i=e.node.options?.ttl,c=t?.forceReload??e.node.options?.shouldReload?.({prev:void 0,next:a})??!0;r[s]=o(s,()=>Promise.resolve(n(a)),i,c)}),r}const H=[],z=[];async function J(e,t,r=!1){const n={...t,forceReload:t?.forceReload??!0},o=d(e,n.params,n.query,n.hash);if(window.location.pathname+window.location.search+window.location.hash===o)return!0;if(!await async function(e){return(await Promise.all(H.map(t=>t(e)))).every(e=>!1!==e)}(o))return console.warn("Navigation blocked by beforeNavigation hook",o),!1;const a=B();if(!n.shallow&&a){if(!await a(o,n))return console.warn("Navigation blocked by route guard",o),!1}return r?window.history.replaceState({},"",o):window.history.pushState({},"",o),async function(e){for(const t of z)await t(e)}(o),!0}function _(e,t){return J(e,t,!1)}function V(){const e=(e,t)=>J(e,t);return e.replace=(e,t)=>J(e,t,!0),e}function X({to:t,transition:r,replace:n,params:o,query:a,hash:s,partialMatch:i,disablePrefetch:c,replaceQuery:u}){const l=V(),p=R(),h=e.useRef(null),f=d(t,o,a,s,{replaceQuery:u}),x=i?p.path?.startsWith(f):p.path===f;return e.useEffect(()=>{if(c)return;const e=h.current;if(!e)return;const t=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(G(f),t.disconnect())},{rootMargin:"200px"});return t.observe(e),()=>t.disconnect()},[f,c]),{ref:h,fullPath:f,isActive:x,go:async()=>n?l.replace(t,{transition:r,params:o,query:a,hash:s}):l(t,{transition:r,params:o,query:a,hash:s})}}_.replace=(e,t)=>J(e,t,!0);const Y=e.forwardRef(({fullPath:e,onNavigate:r,onPrefetch:n,onClick:o,onMouseEnter:a,onKeyDown:s,disablePrefetch:i,...c},u)=>t.jsx("a",{ref:u,href:e,...c,onClick:async t=>{if(o&&o(t),t.metaKey||t.ctrlKey||t.shiftKey||t.altKey)return;t.preventDefault();await r()||console.warn("Navigation blocked:",e)},onMouseEnter:e=>{a&&a(e),i||n?.()},onKeyDown:async t=>{if("Enter"===t.key){t.preventDefault();await r()||console.warn("Navigation blocked:",e)}s&&s(t)}}));Y.displayName="LinkCore",exports.DEFAULT_DURATION=E,exports.Link=function(e){const{to:n,transition:o,replace:a,activeClassName:s="active",onNavigate:i,partialMatch:c,params:u,query:l,hash:p,className:h,disablePrefetch:d,replaceQuery:f,...x}=e,{ref:m,fullPath:y,isActive:g,go:w}=X({to:n,transition:o,replace:a,params:u,query:l,hash:p,partialMatch:c,disablePrefetch:d,replaceQuery:f});return t.jsx(Y,{ref:m,fullPath:y,onNavigate:async()=>{const e=await w();return i?.(y),e},onPrefetch:()=>G(y),className:r(h,g&&s),disablePrefetch:d,...x})},exports.LoaderDataContext=w,exports.NavLink=function(e){const{to:n,transition:o,replace:a,params:s,query:i,hash:c,partialMatch:u,className:l,style:p,disablePrefetch:h,replaceQuery:d,...f}=e,{ref:x,fullPath:m,isActive:y,go:g}=X({to:n,transition:o,replace:a,params:s,query:i,hash:c,partialMatch:u,disablePrefetch:h,replaceQuery:d}),w="function"==typeof l?l({isActive:y}):l,v="function"==typeof p?p({isActive:y}):p;return t.jsx(Y,{ref:x,fullPath:m,onNavigate:async()=>(await g(),!0),onPrefetch:()=>G(m),className:r(w),style:v,disablePrefetch:h,...f})},exports.ParamsContext=b,exports.RouteContext=v,exports.RouterProvider=function({transition:r,duration:n,wrapper:o}){const[a,s]=e.useState({chain:[],data:{},loading:!1,path:"",pendingPath:"",transition:{name:"none",stage:"idle"},duration:n??E}),i=e.useRef(0);async function c(e,t){const o=++i.current,a=y(),c=h(a,e)??h(a,"*")??[];for(const t of c)for(const r of t.node.guardFns||[]){if(!await r({params:t.params,path:t.node.path,query:t.query,hash:t.hash}))return console.warn("Navigation blocked",e),!1}for(const e of c)for(const t of e.node.middlewares||[])await t({params:e.params,path:e.node.path,query:e.query,hash:e.hash}).catch(console.error);const u=function(e,t,r){if(t?.transition)return t.transition;for(let t=e.length-1;t>=0;t--){const r=e[t].node;if(r.options?.transition)return r.options.transition;if(r.meta?.transition)return r.meta.transition}return r??"none"}(c,t,r),l=function(e,t,r){if(null!=t?.duration)return t.duration;for(let t=e.length-1;t>=0;t--){const r=e[t].node;if(null!=r.options?.duration)return r.options.duration}return null!=r?r:E}(c,t,n);s(t=>({...t,loading:!0,pendingPath:e,transition:{name:u,stage:"exiting"},duration:l})),await new Promise(e=>setTimeout(e,l));const p=W(c,t);return o===i.current&&(s(t=>({...t,chain:c,data:{...t.data,...p},loading:!1,path:e,pendingPath:"",transition:{name:u,stage:"entering"},duration:l})),window.scrollTo(0,0),!0)}e.useEffect(()=>{T=c;const e=()=>window.location.pathname+window.location.search+window.location.hash;c(e());const t=()=>c(e());window.addEventListener("popstate",t);const r=()=>{const t=h(y(),e());if(!t)return;const r={};t.forEach(e=>{e.node.options?.revalidateOnFocus&&Object.assign(r,W([e],{forceReload:!0}))}),Object.keys(r).length&&s(e=>({...e,data:{...e.data,...r}}))};return window.addEventListener("focus",r),()=>{window.removeEventListener("popstate",t),window.removeEventListener("focus",r)}},[]);const u=t.jsx(O,{chain:a.chain,data:a.data},a.path);let l=u;if("none"!==a.transition.name&&(l=t.jsx(N,{name:a.transition.name,stage:a.transition.stage,duration:a.duration,children:u})),o){const e=o;l=t.jsx(e,{children:l})}return t.jsx(P.Provider,{value:{loading:a.loading,path:a.path,pendingPath:a.pendingPath},children:t.jsx(j.Provider,{value:a.transition,children:l})})},exports.RouterStateContext=P,exports.Transition=N,exports.TransitionContext=j,exports.addAfterNavigationHook=function(e){z.push(e)},exports.addBeforeNavigationHook=function(e){H.push(e)},exports.buildCacheKey=x,exports.buildPath=d,exports.cleanupCache=function(e=1/0){const t=Date.now();let r=0;for(const[o,a]of n.entries())if(a.expiry<=t&&(n.delete(o),r++,r>=e))break},exports.clearRoutes=function(){m=[]},exports.createResource=a,exports.getGlobalError=M,exports.getGlobalFallback=I,exports.getGlobalResolve=B,exports.getQueryFirst=function(e,t){const r=e[t];return Array.isArray(r)?r[0]:r},exports.getResource=o,exports.getRoutes=y,exports.getUseGlobalError=Q,exports.getUseGlobalFallback=K,exports.matchRouteChain=h,exports.navigate=_,exports.normalize=s,exports.normalizeQuery=u,exports.parseQueryHash=c,exports.prefetch=G,exports.redirect=function(e,t){return _(e,t)},exports.route=function(e,t,r){const n={path:s(e),component:t,children:[],options:{},parent:void 0};return"function"==typeof r?g(n)(r):r&&(n.options=r),m.push(n),g(n).api},exports.setGlobalError=function(e,t){A=e,D=t??null},exports.setGlobalFallback=function(e,t){S=e,t&&(F=t)},exports.split=i,exports.useLinkCore=X,exports.useLoaderData=q,exports.useNavigate=V,exports.useNavigation=R,exports.useParams=function(){return e.useContext(b)??{}},exports.usePrefetch=function(e,t){return()=>G(e,t)},exports.useQuery=function(){try{const e=C();if(e?.query)return e.query}catch{}const{query:e}=c(window.location.pathname+window.location.search+window.location.hash);return e},exports.useRouteContext=C,exports.useRouteMatch=function(e){return R().path===e},exports.useRouterData=function(){const{meta:e,params:t,path:r,query:n}=C();return{data:k(),params:t??{},query:n??{},path:r,meta:e}},exports.useSafeLoaderData=k,exports.useTransition=function(){return e.useContext(j)};
|
|
1
|
+
"use strict";var e=require("react"),t=require("react/jsx-runtime"),r=require("joinclass");const n=new Map;function o(e,t,r,o){const s=Date.now(),i=n.get(e);if(i&&!o&&(!r||i.expiry>s))return i.resource;const c=a(t());return n.set(e,{resource:c,expiry:s+(r??0)}),c}function a(e,t){let r=t?"success":"pending",n=t??null;const o=e.then(e=>{r="success",n=e},e=>{r="error",n=e});return{read(){if("pending"===r)throw o;if("error"===r)throw n;return n},update(e){n=e,r="success"},get:()=>n}}function s(e){return e.startsWith("/")||(e="/"+e),"/"!==e&&e.endsWith("/")&&(e=e.slice(0,-1)),e}function i(e){return s(e).split("/").filter(Boolean)}function c(e){const[t,r]=e.split("#"),[n,o]=t.split("?"),a={};return o&&o.split("&").forEach(e=>{const[t,r]=e.split("=");if(!t)return;const n=decodeURIComponent(t),o=decodeURIComponent(r??"");void 0!==a[n]?Array.isArray(a[n])?a[n].push(o):a[n]=[a[n],o]:a[n]=o}),{path:s(n),query:a,hash:r??""}}function u(e){const t={};if(!e)return t;if("string"==typeof e){const r=new URLSearchParams(e);r.forEach((e,n)=>{const o=r.getAll(n);t[n]=o.length>1?o:o[0]})}else for(const r in e){const n=e[r];Array.isArray(n)?t[r]=n.map(e=>String(e)):null!=n&&(t[r]=String(n))}return t}function l(e){const t=i(e);let r=10*t.length;for(const e of t)"*"===e?r+=0:e.startsWith(":")?r+=1:r+=5;return r}function p(e){return[...e].sort((e,t)=>l(t.path)-l(e.path))}function h(e,t){const{path:r,query:n,hash:o}=c(t),a=i(r),s=p(e).map(e=>({node:e,segIndex:0,params:{},chain:[]}));for(;s.length;){const{node:e,segIndex:t,params:r,chain:c}=s.pop(),u=i(e.path),l={...r};let h=0;for(;h<u.length;h++){const e=u[h],r=a[t+h];if(!r)break;if("*"===e){l["*"]=a.slice(t+h).join("/"),h=u.length;break}if(e.startsWith(":"))l[e.slice(1)]=decodeURIComponent(r);else if(e!==r)break}if(h!==u.length)continue;const d=t+h,f=[...c,{node:e,params:l,query:n,hash:o}];if(d===a.length)return f;const x=p(e.children||[]);for(let e=x.length-1;e>=0;e--){const t=i(x[e].path).some(e=>e.startsWith(":"));s.push({node:x[e],segIndex:t?0:d,params:l,chain:f})}}return null}function d(e,t,r,n,o){const{path:a,query:i,hash:u}=c(e);let l=s(a);if(t)for(const e in t)l=l.replace(`:${e}`,encodeURIComponent(t[e]));const p=o?.replaceQuery?{...r??{}}:{...i,...r??{}},h=new URLSearchParams;for(const e in p){const t=p[e];Array.isArray(t)?t.forEach(t=>h.append(e,String(t))):h.append(e,String(t))}const d=h.toString();return d&&(l+=`?${d}`),n?l+=`#${n}`:u&&(l+=`#${u}`),l}function f(e){return JSON.stringify(Object.keys(e||{}).sort().reduce((t,r)=>(t[r]=e[r],t),{}))}function x(e,t){return`${e.path}|${f(t.params)}|${f(t.query)}|${t.hash}`}let m=[];function y(){return m}function g(e){const t={guard:r=>(e.guardFns||(e.guardFns=[]),e.guardFns.push(r),t),middleware:r=>(e.middlewares||(e.middlewares=[]),e.middlewares.push(r),t),meta:r=>(e.meta={...e.meta||{},...r},t),route(t,r,n){const o={path:s(t),component:r,children:[],options:{},guardFns:[],middlewares:[],parent:e};return"function"==typeof n?g(o)(n):n&&(o.options=n),e.children.push(o),g(o).api}};return Object.assign(e=>e(t),{api:t})}const w=e.createContext(null),v=e.createContext(null),b=e.createContext(null),P=e.createContext({loading:!1,path:"",pendingPath:""}),j=e.createContext({name:"none",stage:"idle"});function q(){const t=e.useContext(w);try{return t?.read()}catch{return}}function C(){const t=e.useContext(v);if(!t)throw new Error("RouteContext not found");return t}function R(){return e.useContext(P)}function k(){try{return q()}catch{return}}const E=200;function N({name:n="fade",stage:o,duration:a=200,children:s}){const[i,c]=e.useState(s),[u,l]=e.useState(null),p=e.useRef();return e.useEffect(()=>{p.current&&clearTimeout(p.current),"exiting"===o&&l(i),"entering"===o&&(c(s),p.current=window.setTimeout(()=>{l(null)},a))},[s,o,a]),"idle"===o?t.jsx(t.Fragment,{children:s}):t.jsxs("div",{className:r("rtx",`rtx-${n}`),children:[u&&t.jsx("div",{className:"rtx-exit",children:u}),t.jsx("div",{className:r("rtx-enter",`rtx-${o}`),children:i})]})}let S=!1,A=!1,F=t.jsx("div",{children:"Loading..."});const L=({error:e})=>t.jsxs("div",{children:["Global Error: ",String(e)]});let D=null;function K(){return S}function Q(){return A}function I(){return F}function M(){return D?({error:e})=>D(e):L}class U extends e.Component{constructor(e){super(e),this.reset=()=>{this.setState(e=>({hasError:!1,error:null,resetKey:e.resetKey+1}))},this.state={hasError:!1,error:null,resetKey:0}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}render(){if(this.state.hasError){const e=this.props.errorBoundary??(Q()?M():void 0);return e?t.jsx(e,{error:this.state.error,params:this.props.params}):this.props.fallback??t.jsxs("div",{children:["Error: ",String(this.state.error)]})}return t.jsx(e.Fragment,{children:this.props.children},this.state.resetKey)}}function $({resource:r,errorBoundary:n,children:o,resetKey:a}){const[s,i]=e.useState(null);e.useEffect(()=>{i(null)},[a]);try{return r?.read(),s&&i(null),t.jsx(t.Fragment,{children:o})}catch(e){if(e instanceof Promise)throw e;const r=n??(Q()?M():void 0);if(r)return t.jsx(r,{error:e});throw e}}function O({chain:r,data:n}){return t.jsx(t.Fragment,{children:function o(a=0){const s=r[a];if(!s)return null;const i=s.node.component;if(!i)return o(a+1);const c={params:s.params,path:s.node.path,query:s.query,hash:s.hash},l=function(e,t){let r=e;for(;r;){const e=r.options?.fallback;if(e)return"function"==typeof e?e(t):e;r=r.parent}return K()?I():null}(s.node,c),p=Object.assign({},...r.slice(0,a+1).map(e=>e.node.meta)),h=n[x(s.node,c)];return t.jsx(U,{fallback:l,errorBoundary:s.node.options?.errorBoundary,params:s.params,children:t.jsx(e.Suspense,{fallback:l,children:t.jsx(v.Provider,{value:{path:s.node.path,params:s.params,query:u(s.query),hash:s.hash??"",meta:p},children:t.jsx(w.Provider,{value:h,children:t.jsx(b.Provider,{value:s.params,children:t.jsx($,{resource:h,errorBoundary:s.node.options?.errorBoundary,resetKey:s.params.id||s.params,children:t.jsx(i,{children:o(a+1)})})})})})})})}()})}function T(e,t){const r={};for(const n of e){const e=n.node.options?.loader;if(!e)continue;const a={params:n.params,path:n.node.path,query:n.query,hash:n.hash},s=x(n.node,a),i=n.node.options?.ttl,c=t?.forceReload??n.node.options?.shouldReload?.({prev:void 0,next:a})??!0;r[s]=o(s,()=>Promise.resolve(e(a)),i,c)}return r}let B=null;function G(){return B}function W(e,t){const r=y(),[n,o]=e.split("?"),a={...u(o),...t?.query??{}},s=h(r,d(n,t?.params,a,t?.hash));s&&T(s,{forceReload:!1})}const H=[],z=[];async function J(e,t,r=!1){const n={...t,forceReload:t?.forceReload??!0},o=d(e,n.params,n.query,n.hash);if(window.location.pathname+window.location.search+window.location.hash===o)return!0;if(!await async function(e){return(await Promise.all(H.map(t=>t(e)))).every(e=>!1!==e)}(o))return console.warn("Navigation blocked by beforeNavigation hook",o),!1;const a=G();if(!n.shallow&&a){if(!await a(o,n))return console.warn("Navigation blocked by route guard",o),!1}return r?window.history.replaceState({},"",o):window.history.pushState({},"",o),async function(e){for(const t of z)await t(e)}(o),!0}function _(e,t){return J(e,t,!1)}function V(){const e=(e,t)=>J(e,t);return e.replace=(e,t)=>J(e,t,!0),e}function X({to:t,transition:r,replace:n,params:o,query:a,hash:s,partialMatch:i,disablePrefetch:c,replaceQuery:u}){const l=V(),p=R(),h=e.useRef(null),f=d(t,o,a,s,{replaceQuery:u}),x=i?p.path?.startsWith(f):p.path===f;return e.useEffect(()=>{if(c)return;const e=h.current;if(!e)return;const t=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(W(f),t.disconnect())},{rootMargin:"200px"});return t.observe(e),()=>t.disconnect()},[f,c]),{ref:h,fullPath:f,isActive:x,go:async()=>n?l.replace(t,{transition:r,params:o,query:a,hash:s}):l(t,{transition:r,params:o,query:a,hash:s})}}_.replace=function(e,t){return J(e,t,!0)};const Y=e.forwardRef(({fullPath:e,onNavigate:r,onPrefetch:n,onClick:o,onMouseEnter:a,onKeyDown:s,disablePrefetch:i,...c},u)=>t.jsx("a",{ref:u,href:e,...c,onClick:async t=>{if(o&&o(t),t.metaKey||t.ctrlKey||t.shiftKey||t.altKey)return;t.preventDefault();await r()||console.warn("Navigation blocked:",e)},onMouseEnter:e=>{a&&a(e),i||n?.()},onKeyDown:async t=>{if("Enter"===t.key){t.preventDefault();await r()||console.warn("Navigation blocked:",e)}s&&s(t)}}));Y.displayName="LinkCore",exports.DEFAULT_DURATION=E,exports.Link=function(e){const{to:n,transition:o,replace:a,activeClassName:s="active",onNavigate:i,partialMatch:c,params:u,query:l,hash:p,className:h,disablePrefetch:d,replaceQuery:f,...x}=e,{ref:m,fullPath:y,isActive:g,go:w}=X({to:n,transition:o,replace:a,params:u,query:l,hash:p,partialMatch:c,disablePrefetch:d,replaceQuery:f});return t.jsx(Y,{ref:m,fullPath:y,onNavigate:async()=>{const e=await w();return i?.(y),e},onPrefetch:()=>W(y),className:r(h,g&&s),disablePrefetch:d,...x})},exports.LoaderDataContext=w,exports.NavLink=function(e){const{to:n,transition:o,replace:a,params:s,query:i,hash:c,partialMatch:u,className:l,style:p,disablePrefetch:h,replaceQuery:d,...f}=e,{ref:x,fullPath:m,isActive:y,go:g}=X({to:n,transition:o,replace:a,params:s,query:i,hash:c,partialMatch:u,disablePrefetch:h,replaceQuery:d}),w="function"==typeof l?l({isActive:y}):l,v="function"==typeof p?p({isActive:y}):p;return t.jsx(Y,{ref:x,fullPath:m,onNavigate:async()=>(await g(),!0),onPrefetch:()=>W(m),className:r(w),style:v,disablePrefetch:h,...f})},exports.ParamsContext=b,exports.RouteContext=v,exports.RouterProvider=function({transition:r,duration:n,wrapper:o}){const[a,s]=e.useState({chain:[],data:{},loading:!1,path:"",pendingPath:"",transition:{name:"none",stage:"idle"},duration:n??E}),i=e.useRef(0),c=async(e,t)=>{const o=++i.current,a=function(e){const t=y();return h(t,e)??h(t,"*")??[]}(e),u=await async function(e,t){for(const r of e)for(const e of r.node.guardFns||[]){const n=await e({params:r.params,path:r.node.path,query:r.query,hash:r.hash});if(!1===n)return!1;if("object"==typeof n&&"redirect"in n)return await t(n.redirect),!1}return!0}(a,c);if(!u)return!1;await async function(e){for(const t of e)for(const e of t.node.middlewares||[])await Promise.resolve(e({params:t.params,path:t.node.path,query:t.query,hash:t.hash})).catch(console.error)}(a);const l=function(e,t,r){if(t?.transition)return t.transition;for(let t=e.length-1;t>=0;t--){const r=e[t].node;if(r.options?.transition)return r.options.transition;if(r.meta?.transition)return r.meta.transition}return r??"none"}(a,t,r),p=function(e,t,r){if(null!=t?.duration)return t.duration;for(let t=e.length-1;t>=0;t--){const r=e[t].node;if(null!=r.options?.duration)return r.options.duration}return null!=r?r:E}(a,t,n);!function(e,t,r,n){e(e=>({...e,loading:!0,pendingPath:t,transition:{name:r,stage:"exiting"},duration:n}))}(s,e,l,p),await new Promise(e=>setTimeout(e,p));const d=t?.shallow?{}:T(a,t);return o===i.current&&(function(e,t,r,n,o,a){e(e=>({...e,chain:t,data:{...e.data,...r},loading:!1,path:n,pendingPath:"",transition:{name:o,stage:"entering"},duration:a}))}(s,a,d??{},e,l,p),t?.shallow||window.scrollTo(0,0),!0)};e.useEffect(()=>{B=c;const e=()=>window.location.pathname+window.location.search+window.location.hash;c(e());const t=()=>c(e());window.addEventListener("popstate",t);const r=()=>{const t=h(y(),e());if(!t)return;const r={};for(const e of t)e.node.options?.revalidateOnFocus&&Object.assign(r,T([e],{forceReload:!0}));Object.keys(r).length&&s(e=>({...e,data:{...e.data,...r}}))};return window.addEventListener("focus",r),()=>{window.removeEventListener("popstate",t),window.removeEventListener("focus",r),B=null}},[]);const u=t.jsx(O,{chain:a.chain,data:a.data},a.path);let l=u;if("none"!==a.transition.name&&(l=t.jsx(N,{name:a.transition.name,stage:a.transition.stage,duration:a.duration,children:u})),o){const e=o;l=t.jsx(e,{children:l})}return t.jsx(P.Provider,{value:{loading:a.loading,path:a.path,pendingPath:a.pendingPath},children:t.jsx(j.Provider,{value:a.transition,children:l})})},exports.RouterStateContext=P,exports.Transition=N,exports.TransitionContext=j,exports.addAfterNavigationHook=function(e){z.push(e)},exports.addBeforeNavigationHook=function(e){H.push(e)},exports.buildCacheKey=x,exports.buildPath=d,exports.cleanupCache=function(e=1/0){const t=Date.now();let r=0;for(const[o,a]of n.entries())if(a.expiry<=t&&(n.delete(o),r++,r>=e))break},exports.clearRoutes=function(){m=[]},exports.createResource=a,exports.getGlobalError=M,exports.getGlobalFallback=I,exports.getGlobalResolve=G,exports.getQueryFirst=function(e,t){const r=e[t];return Array.isArray(r)?r[0]:r},exports.getResource=o,exports.getRoutes=y,exports.getUseGlobalError=Q,exports.getUseGlobalFallback=K,exports.matchRouteChain=h,exports.navigate=_,exports.normalize=s,exports.normalizeQuery=u,exports.parseQueryHash=c,exports.prefetch=W,exports.redirect=function(e,t){return _(e,t)},exports.route=function(e,t,r){const n={path:s(e),component:t,children:[],options:{},parent:void 0};return"function"==typeof r?g(n)(r):r&&(n.options=r),m.push(n),g(n).api},exports.setGlobalError=function(e,t){A=e,D=t??null},exports.setGlobalFallback=function(e,t){S=e,t&&(F=t)},exports.split=i,exports.useLinkCore=X,exports.useLoaderData=q,exports.useNavigate=V,exports.useNavigation=R,exports.useParams=function(){return e.useContext(b)??{}},exports.usePrefetch=function(e,t){return()=>W(e,t)},exports.useQuery=function(){try{const e=C();if(e?.query)return e.query}catch{}const{query:e}=c(window.location.pathname+window.location.search+window.location.hash);return e},exports.useRouteContext=C,exports.useRouteMatch=function(e){return R().path===e},exports.useRouterData=function(){const{meta:e,params:t,path:r,query:n}=C();return{data:k(),params:t??{},query:n??{},path:r,meta:e}},exports.useSafeLoaderData=k,exports.useTransition=function(){return e.useContext(j)};
|
package/build/router/core.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ type RouterProviderProps = {
|
|
|
8
8
|
children: React.ReactNode;
|
|
9
9
|
}>;
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
export declare function
|
|
11
|
+
type ResolveFn = (path: string, opts?: NavigateOpts<any>) => Promise<boolean>;
|
|
12
|
+
export declare function getGlobalResolve(): ResolveFn | null;
|
|
13
|
+
export declare function prefetch<P extends string>(path: P, options?: NavigateOpts<P>): void;
|
|
13
14
|
export declare function RouterProvider({ transition: defaultTransition, duration: providerDuration, wrapper, }: RouterProviderProps): JSX.Element;
|
|
14
15
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { TransitionName } from './types';
|
|
2
|
-
export type NavigateOpts = {
|
|
1
|
+
import type { ExtractParams, TransitionName } from './types';
|
|
2
|
+
export type NavigateOpts<P extends string> = {
|
|
3
3
|
transition?: TransitionName;
|
|
4
4
|
forceReload?: boolean;
|
|
5
|
-
params?:
|
|
5
|
+
params?: ExtractParams<P>;
|
|
6
6
|
query?: Record<string, string | number>;
|
|
7
7
|
hash?: string;
|
|
8
8
|
shallow?: boolean;
|
|
@@ -10,14 +10,14 @@ export type NavigateOpts = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare function addBeforeNavigationHook(fn: (path: string) => boolean | Promise<boolean>): void;
|
|
12
12
|
export declare function addAfterNavigationHook(fn: (path: string) => void | Promise<void>): void;
|
|
13
|
-
export declare function navigate(path:
|
|
13
|
+
export declare function navigate<P extends string>(path: P, opts?: NavigateOpts<P>): Promise<boolean>;
|
|
14
14
|
export declare namespace navigate {
|
|
15
|
-
var replace: (path:
|
|
15
|
+
var replace: <P extends string>(path: P, opts?: NavigateOpts<P>) => Promise<boolean>;
|
|
16
16
|
}
|
|
17
|
-
export declare function redirect(path:
|
|
17
|
+
export declare function redirect<P extends string>(path: P, opts?: NavigateOpts<P>): Promise<boolean>;
|
|
18
18
|
export declare function useNavigate(): {
|
|
19
|
-
(path:
|
|
20
|
-
replace(path:
|
|
19
|
+
<P extends string>(path: P, opts?: NavigateOpts<P>): Promise<boolean>;
|
|
20
|
+
replace<P extends string>(path: P, opts?: NavigateOpts<P>): Promise<boolean>;
|
|
21
21
|
};
|
|
22
22
|
export declare function useRouteMatch(pathPattern: string): boolean;
|
|
23
|
-
export declare function usePrefetch(path:
|
|
23
|
+
export declare function usePrefetch<P extends string>(path: P, opts?: NavigateOpts<P>): () => void;
|
package/build/router/types.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
export type TransitionName = 'fade' | 'slide' | 'scale' | 'none';
|
|
3
3
|
export type TransitionStage = 'idle' | 'entering' | 'exiting';
|
|
4
|
-
type
|
|
4
|
+
export type QueryValue = string | number | string[] | number[];
|
|
5
|
+
export type Query = Record<string, QueryValue>;
|
|
6
|
+
export type LoaderContext<P = any> = {
|
|
5
7
|
params: P;
|
|
6
8
|
path: string;
|
|
7
|
-
query?:
|
|
9
|
+
query?: Query;
|
|
8
10
|
hash?: string;
|
|
9
11
|
};
|
|
12
|
+
export type LoaderFn<P, R> = (context: LoaderContext<P>) => Promise<R> | R;
|
|
10
13
|
export type RouteOptions<P = any, R = any> = {
|
|
11
|
-
loader?:
|
|
14
|
+
loader?: LoaderFn<P, R>;
|
|
12
15
|
ttl?: number;
|
|
13
16
|
shouldReload?: (context: {
|
|
14
17
|
prev?: LoaderContext<P>;
|
|
@@ -27,10 +30,11 @@ export type RouteOptions<P = any, R = any> = {
|
|
|
27
30
|
transition?: TransitionName;
|
|
28
31
|
duration?: number;
|
|
29
32
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export type
|
|
33
|
+
type GuardResult = boolean | {
|
|
34
|
+
redirect: string;
|
|
35
|
+
};
|
|
36
|
+
export type GuardFn<P = any> = (ctx: LoaderContext<P>) => GuardResult | Promise<GuardResult>;
|
|
37
|
+
export type MiddlewareFn<P = any> = (context: LoaderContext<P>) => void | Promise<void>;
|
|
34
38
|
export type RouteComponent = React.ComponentType<{
|
|
35
39
|
children?: ReactNode;
|
|
36
40
|
}> | (() => Promise<{
|
|
@@ -48,6 +52,12 @@ export type RouteNode<P = any, R = any> = {
|
|
|
48
52
|
meta?: Record<string, any>;
|
|
49
53
|
parent?: RouteNode;
|
|
50
54
|
};
|
|
55
|
+
export type InternalRouteMatch<P = any> = {
|
|
56
|
+
node: RouteNode<P>;
|
|
57
|
+
params: P;
|
|
58
|
+
query?: Query;
|
|
59
|
+
hash?: string;
|
|
60
|
+
};
|
|
51
61
|
export type ExtractParams<Path extends string> = Path extends `${string}:${infer Param}/${infer Rest}` ? {
|
|
52
62
|
[K in Param | keyof ExtractParams<`/${Rest}`>]: string;
|
|
53
63
|
} : Path extends `${string}:${infer Param}` ? {
|
|
@@ -59,4 +69,6 @@ export type BuilderRouteAPI<Params = any> = {
|
|
|
59
69
|
meta: (obj: Record<string, any>) => BuilderRouteAPI<Params>;
|
|
60
70
|
route: <Path extends string, R = any>(path: Path, component?: RouteComponent, options?: ((api: BuilderRouteAPI<Params & ExtractParams<Path>>) => void) | RouteOptions<Params & ExtractParams<Path>, R>) => BuilderRouteAPI<Params & ExtractParams<Path>>;
|
|
61
71
|
};
|
|
72
|
+
export type InferParams<T> = T extends InternalRouteMatch<infer P> ? P : never;
|
|
73
|
+
export type InferLoaderData<T> = T extends RouteNode<any, infer R> ? R : never;
|
|
62
74
|
export {};
|
package/build/router/utils.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare function parseQueryHash(pathname: string): {
|
|
|
6
6
|
query: Query;
|
|
7
7
|
hash: string;
|
|
8
8
|
};
|
|
9
|
-
export declare function getQueryFirst(q: Query, key: string): string;
|
|
9
|
+
export declare function getQueryFirst(q: Query, key: string): string | number;
|
|
10
10
|
export declare function normalizeQuery(input?: string | Record<string, any>): Record<string, string | string[]>;
|
|
11
11
|
export declare function matchRouteChain(routes: RouteNode[], pathname: string): any[] | null;
|
|
12
12
|
export declare function buildPath(path: string, params?: Record<string, any>, query?: Record<string, any>, hash?: string, options?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "routexiz",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-z2",
|
|
4
4
|
"description": "A modern tree-based router for React with intent-driven navigation, Suspense-first data loading, and built-in guards, middleware, and caching.",
|
|
5
5
|
"author": "Delpi.Kye",
|
|
6
6
|
"license": "MIT",
|