@native-router/react 1.2.1 → 1.3.1
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 +9 -4
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -1
- package/dist/ssr-Cow2_ikA.cjs +2 -0
- package/dist/ssr-Cow2_ikA.cjs.map +1 -0
- package/dist/ssr-j5c5cH-B.js +8 -0
- package/dist/ssr-j5c5cH-B.js.map +1 -0
- package/dist/types/context.d.ts +10 -1
- package/dist/types/types.d.ts +27 -0
- package/package.json +4 -4
- package/dist/ssr-DLMUHksm.js +0 -8
- package/dist/ssr-DLMUHksm.js.map +0 -1
- package/dist/ssr-HDpHA-cn.cjs +0 -2
- package/dist/ssr-HDpHA-cn.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ function Preview({visible}: {visible: boolean}) {
|
|
|
70
70
|
|
|
71
71
|
- Three history modes out of the box: `HistoryRouter`, `HashRouter`, `MemoryRouter` (tests, widgets); `Router` renders with an externally created instance, `createRouter` builds one for a custom history
|
|
72
72
|
- Route guards: static `redirect` and async `beforeLoad` on every route level, run shallow → deep; more than 10 chained redirects reject with `RedirectLoopError`
|
|
73
|
-
- Cancelable async navigation: starting a new navigation supersedes the in-flight one; `cancel(router)` aborts it; a history POP cancels it too
|
|
73
|
+
- Cancelable async navigation: starting a new navigation supersedes the in-flight one; `cancel(router)` aborts it; a history POP cancels it too — and the chain's `AbortSignal` reaches every `data` loader as `ctx.signal` (`fetch(url, {signal: ctx.signal})`), so superseded navigations stop their requests instead of only having results dropped
|
|
74
74
|
- `NavLink` with `isActive`/`isExactActive`, `end`, `caseSensitive` and `aria-current` (defaults to `"page"`); `className`/`style`/`children` accept `({isActive, isExactActive})` callbacks; `to="/"` is active for every path
|
|
75
75
|
- `useSearchParams` reads and writes the query string; writes push by default or replace with `{replace: true}`
|
|
76
76
|
- Typed search: an optional Standard Schema validator (zod/valibot/arktype, no hard dependency) on any route `search` field, parsed at resolve time — loaders receive a typed `ctx.search` and an invalid search fails the level through the existing error layers; `useSearch(schema?)` reads it in components, degrading to the raw object without a schema
|
|
@@ -78,6 +78,7 @@ function Preview({visible}: {visible: boolean}) {
|
|
|
78
78
|
- Router-level `preload(router, to)` shares resolved views across links with in-flight dedup and a 30s TTL; `PrefetchLink` prefetch through it
|
|
79
79
|
- Hooks: `useRouter`, `useView`, `useData<T>(name?)` (typed data of the current level, or named data of ancestor routes), `useMatched` (matched levels, params, location), `useLoading`, `usePrefetch`, `useSearch(schema?)`
|
|
80
80
|
- Two error layers: global `errorHandler` prop on the Router, per-route `errorComponent` receiving `{error, ctx}`
|
|
81
|
+
- Route-level `pendingComponent` skeleton, shown only when no previous view can be retained (cold start, refresh, re-navigation after an error); the nearest matched ancestor's wins, and in-app navigation keeps the previous view instead
|
|
81
82
|
- SSR: `resolveServerView` (from `@native-router/react/server`) renders the view plus an inline data payload; `hydrate` reuses that payload on the client with zero refetch
|
|
82
83
|
- Tree-shakable: `sideEffects: false` — unused components and hooks drop out of the bundle
|
|
83
84
|
|
|
@@ -128,7 +129,9 @@ const routes = {
|
|
|
128
129
|
{
|
|
129
130
|
path: '/users',
|
|
130
131
|
component: () => import('./UserList'),
|
|
131
|
-
data: userService.fetchList
|
|
132
|
+
data: userService.fetchList,
|
|
133
|
+
// cold-start/refresh skeleton; in-app navigation keeps the old view
|
|
134
|
+
pendingComponent: () => <UserListSkeleton />
|
|
132
135
|
},
|
|
133
136
|
{
|
|
134
137
|
path: '/users/:id',
|
|
@@ -137,8 +140,10 @@ const routes = {
|
|
|
137
140
|
async beforeLoad({params}) {
|
|
138
141
|
if (!await canView(+params.id)) return '/login';
|
|
139
142
|
},
|
|
140
|
-
// data receives {matched, index, router, location, params}
|
|
141
|
-
|
|
143
|
+
// data receives {matched, index, router, location, params, search, signal};
|
|
144
|
+
// ctx.signal aborts when this navigation is superseded/cancelled
|
|
145
|
+
data: ({params, signal}) =>
|
|
146
|
+
userService.fetchById(+params.id, {signal}),
|
|
142
147
|
errorComponent: ({error}) => <p>{error.message}</p>
|
|
143
148
|
},
|
|
144
149
|
{
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ssr-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ssr-Cow2_ikA.cjs");let t=require("react"),r=require("history"),o=require("react/jsx-runtime"),n=require("@native-router/core"),s=require("use-sync-external-store/shim");function u(e,t,r){return!(e.defaultPrevented||0!==e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||"_blank"===t||"_parent"===t||"_top"===t||(r??"").split(/\s+/).includes("external"))}function c({to:r,...s}){const c=e.useRouter(),a=(0,t.useRef)(!1);return(0,o.jsx)("a",{...s,href:(0,n.createHref)(c,r),onClick:function(e){u(e,s.target,s.rel)&&(e.preventDefault(),a.current||(a.current=!0,(0,n.navigate)(c,r).catch(()=>{}).finally(()=>{a.current=!1})))}})}var a=(0,t.createContext)({loading:!1});exports.HashRouter=e.HashRouter,exports.HistoryRouter=e.HistoryRouter,exports.Link=c,exports.MemoryRouter=e.MemoryRouter,exports.NavLink=function({to:r,end:u=!1,caseSensitive:a=!1,className:i,style:l,ariaCurrent:f,children:h,...d}){const p=e.useRouter(),y=(0,t.useCallback)(e=>p.history.listen(()=>e()),[p]),x=(0,t.useCallback)(()=>p.history.location.pathname,[p]),R=(0,s.useSyncExternalStore)(y,x,x),v=(0,n.toLocation)(p,r).pathname,[w,m]=a?[R,v]:[R.toLowerCase(),v.toLowerCase()],S=w===m,k=u||S?S:w.startsWith(m.endsWith("/")?m:`${m}/`),b={isActive:k,isExactActive:S};return(0,o.jsx)(c,{to:r,...d,className:"function"==typeof i?i(b):i,style:"function"==typeof l?l(b):l,"aria-current":k?f??"page":void 0,children:"function"==typeof h?h(b):h})},exports.PrefetchLink=function({to:r,prefetch:s="intent",children:c,...i}){const l=e.useRouter(),f=(0,t.useRef)(null),h=(0,t.useRef)(void 0),d=(0,t.useRef)(!1),[p,y]=(0,t.useState)(!1),[x,R]=(0,t.useState)(),[v,w]=(0,t.useState)();function m(){y(!0),R(void 0),d.current=!1;const e=(0,n.preload)(l,r);return h.current=e,e.then(e=>e.task).then(e=>w(e),e=>{R(e),d.current=!0}).finally(()=>y(!1)),e}function S(){h.current||m()}(0,t.useEffect)(()=>{h.current=void 0,d.current=!1,y(!1),R(void 0),w(void 0)},[r,l]),(0,t.useEffect)(()=>{if("render"===s)return void S();if("viewport"!==s)return;const e=f.current;if(!e||"undefined"==typeof IntersectionObserver)return;const t=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(t.disconnect(),S())});return t.observe(e),()=>t.disconnect()},[s,r,l]);const k=(0,t.useMemo)(()=>({loading:p,error:x,view:v}),[p,x,v]),b="intent"===s?{onMouseEnter:S,onFocus:S}:void 0;return(0,o.jsx)(a.Provider,{value:k,children:(0,o.jsx)("a",{...i,...b,ref:f,href:(0,n.createHref)(l,r),onClick:function(e){if(!u(e,i.target,i.rel))return;e.preventDefault();const t=h.current;(!t||d.current?m():t).then(e=>(0,n.commit)(l,e.task,e.location)).catch(()=>{}).finally(()=>{h.current=void 0,d.current=!1})},children:c})})},exports.Router=e.Router,exports.ScrollRestoration=function({resetOnPush:o=!0}){const n=e.useRouter(),s=(0,t.useRef)(new Map),u=(0,t.useRef)(-1),c=(0,t.useRef)("");return(0,t.useEffect)(()=>{if("undefined"==typeof window)return;window.history.scrollRestoration&&(window.history.scrollRestoration="manual");const e=s.current,t=e=>e?.index||0;u.current=t(n.history.location.state),c.current=(0,r.createPath)(n.history.location);let a=!1,i=!1,l=!0;const f=n.history.listen(({action:s})=>{i||="POP"===s,a||(a=!0,queueMicrotask(()=>{if(a=!1,!l)return;const s=i;i=!1;const{location:f}=n.history,h=t(f.state),d=(0,r.createPath)(f),p=u.current;if(h!==p&&e.set(p,{x:window.scrollX,y:window.scrollY}),s){const t=e.get(h)??{x:0,y:0};window.scrollTo(t.x,t.y),e.set(h,t)}else!o||h===p&&d===c.current||(window.scrollTo(0,0),e.set(h,{x:0,y:0}));u.current=h,c.current=d}))});return()=>{l=!1,f()}},[n,o]),null},exports.View=e.View,exports.createRouter=e.createRouter,exports.defaultResolveView=e.resolveView,exports.hydrate=e.hydrate,exports.useData=e.useData,exports.useLoading=e.useLoading,exports.useMatched=e.useMatched,exports.useNamedData=e.useNamedData,exports.usePrefetch=function(){return(0,t.useContext)(a)},exports.useRouter=e.useRouter,exports.useSearch=function(r){const o=e.useRouter(),u=(0,t.useCallback)(e=>o.history.listen(()=>e()),[o]),c=(0,t.useCallback)(()=>o.history.location.search,[o]),a=(0,t.useCallback)(()=>"",[]),i=(0,s.useSyncExternalStore)(u,c,a);return r?(0,n.parseSearchSync)(r,i):(0,n.parseSearchInput)(i)},exports.useSearchParams=function(){const r=e.useRouter(),o=(0,t.useCallback)(e=>r.history.listen(()=>e()),[r]),u=(0,t.useCallback)(()=>r.history.location.search,[r]),c=(0,t.useCallback)(()=>"",[]);return[new URLSearchParams((0,s.useSyncExternalStore)(o,u,c)),(0,t.useCallback)((e,t)=>{const{history:o}=r,s=("function"==typeof e?e(new URLSearchParams(o.location.search)):e).toString(),{pathname:u,hash:c}=o.location,a=u+(s?`?${s}`:"")+c;return t?.replace?(0,n.resolveEntry)(r,(0,n.toLocation)(r,a)).then(e=>(0,n.commitReplace)(r,e.task,e.location)):(0,n.navigate)(r,a)},[r])]},exports.useView=e.useView;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as t,c as n,d as r,f as e,h as o,i,l as s,m as c,o as a,p as u,r as l,s as f,t as h,u as d}from"./ssr-
|
|
1
|
+
import{a as t,c as n,d as r,f as e,h as o,i,l as s,m as c,o as a,p as u,r as l,s as f,t as h,u as d}from"./ssr-j5c5cH-B.js";import{createContext as y,useCallback as p,useContext as m,useEffect as v,useMemo as w,useRef as x,useState as g}from"react";import{createPath as k}from"history";import{jsx as P}from"react/jsx-runtime";import{commit as b,commitReplace as C,createHref as R,navigate as K,parseSearchInput as L,parseSearchSync as O,preload as S,resolveEntry as I,toLocation as M}from"@native-router/core";import{useSyncExternalStore as _}from"use-sync-external-store/shim";function j(t,n,r){return!(t.defaultPrevented||0!==t.button||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||"_blank"===n||"_parent"===n||"_top"===n||(r??"").split(/\s+/).includes("external"))}function A({to:t,...r}){const e=n(),o=x(!1);/* @__PURE__ */
|
|
2
2
|
return P("a",{...r,href:R(e,t),onClick:function(n){j(n,r.target,r.rel)&&(n.preventDefault(),o.current||(o.current=!0,K(e,t).catch(()=>{}).finally(()=>{o.current=!1})))}})}function D({to:t,end:r=!1,caseSensitive:e=!1,className:o,style:i,ariaCurrent:s,children:c,...a}){const u=n(),l=p(t=>u.history.listen(()=>t()),[u]),f=p(()=>u.history.location.pathname,[u]),h=_(l,f,f),d=M(u,t).pathname,[y,m]=e?[h,d]:[h.toLowerCase(),d.toLowerCase()],v=y===m,w=r||v?v:y.startsWith(m.endsWith("/")?m:`${m}/`),x={isActive:w,isExactActive:v};/* @__PURE__ */
|
|
3
3
|
return P(A,{to:t,...a,className:"function"==typeof o?o(x):o,style:"function"==typeof i?i(x):i,"aria-current":w?s??"page":void 0,children:"function"==typeof c?c(x):c})}var E=y({loading:!1});function N(){return m(E)}function T({to:t,prefetch:r="intent",children:e,...o}){const i=n(),s=x(null),c=x(void 0),a=x(!1),[u,l]=g(!1),[f,h]=g(),[d,y]=g();function p(){l(!0),h(void 0),a.current=!1;const n=S(i,t);return c.current=n,n.then(t=>t.task).then(t=>y(t),t=>{h(t),a.current=!0}).finally(()=>l(!1)),n}function m(){c.current||p()}v(()=>{c.current=void 0,a.current=!1,l(!1),h(void 0),y(void 0)},[t,i]),v(()=>{if("render"===r)return void m();if("viewport"!==r)return;const t=s.current;if(!t||"undefined"==typeof IntersectionObserver)return;const n=new IntersectionObserver(t=>{t.some(t=>t.isIntersecting)&&(n.disconnect(),m())});return n.observe(t),()=>n.disconnect()},[r,t,i]);const k=w(()=>({loading:u,error:f,view:d}),[u,f,d]),C="intent"===r?{onMouseEnter:m,onFocus:m}:void 0;/* @__PURE__ */
|
|
4
4
|
return P(E.Provider,{value:k,children:/* @__PURE__ */P("a",{...o,...C,ref:s,href:R(i,t),onClick:function(t){if(!j(t,o.target,o.rel))return;t.preventDefault();const n=c.current;(!n||a.current?p():n).then(t=>b(i,t.task,t.location)).catch(()=>{}).finally(()=>{c.current=void 0,a.current=!1})},children:e})})}function U({resetOnPush:t=!0}){const r=n(),e=x(/* @__PURE__ */new Map),o=x(-1),i=x("");return v(()=>{if("undefined"==typeof window)return;window.history.scrollRestoration&&(window.history.scrollRestoration="manual");const n=e.current,s=t=>t?.index||0;o.current=s(r.history.location.state),i.current=k(r.history.location);let c=!1,a=!1,u=!0;const l=r.history.listen(({action:e})=>{a||="POP"===e,c||(c=!0,queueMicrotask(()=>{if(c=!1,!u)return;const e=a;a=!1;const{location:l}=r.history,f=s(l.state),h=k(l),d=o.current;if(f!==d&&n.set(d,{x:window.scrollX,y:window.scrollY}),e){const t=n.get(f)??{x:0,y:0};window.scrollTo(t.x,t.y),n.set(f,t)}else!t||f===d&&h===i.current||(window.scrollTo(0,0),n.set(f,{x:0,y:0}));o.current=f,i.current=h}))});return()=>{u=!1,l()}},[r,t]),null}function W(){const t=n(),r=p(n=>t.history.listen(()=>n()),[t]),e=p(()=>t.history.location.search,[t]),o=p(()=>"",[]);return[new URLSearchParams(_(r,e,o)),p((n,r)=>{const{history:e}=t,o=("function"==typeof n?n(new URLSearchParams(e.location.search)):n).toString(),{pathname:i,hash:s}=e.location,c=i+(o?`?${o}`:"")+s;return r?.replace?I(t,M(t,c)).then(n=>C(t,n.task,n.location)):K(t,c)},[t])]}function $(t){const r=n(),e=p(t=>r.history.listen(()=>t()),[r]),o=p(()=>r.history.location.search,[r]),i=p(()=>"",[]),s=_(e,o,i);return t?O(t,s):L(s)}export{l as HashRouter,i as HistoryRouter,A as Link,t as MemoryRouter,D as NavLink,T as PrefetchLink,a as Router,U as ScrollRestoration,d as View,f as createRouter,s as defaultResolveView,h as hydrate,r as useData,e as useLoading,u as useMatched,c as useNamedData,N as usePrefetch,n as useRouter,$ as useSearch,W as useSearchParams,o as useView};
|
package/dist/server.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ssr-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ssr-Cow2_ikA.cjs");exports.resolveServerView=e.resolveServerView;
|
package/dist/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as r}from"./ssr-
|
|
1
|
+
import{n as r}from"./ssr-j5c5cH-B.js";export{r as resolveServerView};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
let e=require("react"),r=require("history"),t=require("react/jsx-runtime"),n=require("@native-router/core"),o=require("@native-router/core/util"),u=require("use-sync-external-store/shim");var i=(0,e.createContext)(null);function a(e){return(0,t.jsx)(i.Provider,{...e})}function c(){return(0,e.useContext)(i)}var s=(0,e.createContext)(null);function l(){const r=c(),t=(0,e.useContext)(s);return r??t}var d=(0,e.createContext)([void 0,{}]);function f(){return(0,e.useContext)(d)}function x(){return f()[1]}function p({children:r,name:n,data:o}){const u=x(),i=(0,e.useMemo)(()=>[o,n?{...u,[n]:o}:u],[o,n,u]);return(0,t.jsx)(d.Provider,{value:i,children:r})}var h=(0,e.createContext)(void 0);function m(){return(0,e.useContext)(h)}function v(e){const[r,t]=f();return e?t[e]:r}var y=(0,e.createContext)(void 0);function b(){return(0,e.useContext)(y)}function g(e,r){return C(e,r,(e,r)=>e?.(r))}var j=new WeakMap;function P(e,r){const t=new Array(e.length);return C(e,r,(e,r)=>Promise.resolve(e?.(r)).then(e=>t[r.index]=e)).then(e=>(j.set(e,t),e))}function C(e,{router:r,location:o,signal:u},i){return Promise.all(e.map(({route:a},c)=>{const s={matched:e,params:(0,n.mergeMatchedParams)(e,c),index:c,router:r,location:o,search:(0,n.parseSearchInput)(o.search),signal:u??(new AbortController).signal};return Promise.all([a.search?(0,n.parseSearch)(a.search,o.search).then(e=>(s.search=e,i(a.data,s))):i(a.data,s),function(){if(!a.component)return l;const e=a.component(s);return Promise.resolve(e).then(e=>"default"in e?e.default:e)}()]).then(([e,r])=>(0,t.jsx)(p,{data:e,name:a.name,children:(0,t.jsx)(h.Provider,{value:s,children:(0,t.jsx)(r,{})})}),e=>{if(!a.errorComponent)throw e;return(0,t.jsx)(p,{data:void 0,name:a.name,children:(0,t.jsx)(h.Provider,{value:s,children:(0,t.jsx)(a.errorComponent,{error:e,ctx:s})})})})})).then(e=>e.reverse().reduce((e,r)=>(0,t.jsx)(a,{value:e,children:r})))}var w=(0,e.createContext)(null);function O({router:r,children:o}){const i=(0,e.useRef)((0,n.getCurrentView)(r)),c=(0,e.useCallback)(e=>(0,n.listen)(r,r=>{i.current=r,e()}),[r]),l=(0,e.useCallback)(()=>i.current,[]),d=(0,e.useCallback)(()=>(0,n.getCurrentView)(r),[r]),f=(0,u.useSyncExternalStore)(c,l,d),x=(0,e.useContext)(y),p=null==f&&"pending"===x?.status?function(e,r){const{resolving:o}=e,u=o?(0,n.match)(e,o.pathname):void 0;if(!u)return null;for(let n=u.length-1;n>=0;n--){const e=u[n].route.pendingComponent;if(e)return(0,t.jsx)(e,{},r)}return null}(r,x.key):null;return(0,t.jsx)(w.Provider,{value:r,children:void 0===o?f??p:(0,t.jsx)(a,{value:f,children:(0,t.jsx)(s.Provider,{value:p,children:o})})})}function R(e,r,{resolveView:t=g,...o}={}){return(0,n.create)(e,r,t,o)}function M({routes:r,children:u,...i},a){const[c,s]=(0,o.splitProps)(i,["baseUrl","currentView"]),{baseUrl:l,currentView:d}=c,[f,x]=(0,e.useState)(),p=(0,e.useMemo)(()=>R(r,a(),{...i,onLoadingChange(e){x(e&&{key:(0,o.uniqId)(),status:e})}}),[r,a,l,d]);(0,e.useEffect)(()=>{(0,n.setOptions)(p,{...s,onLoadingChange(e){x(e&&{key:(0,o.uniqId)(),status:e})}})},[p,s]);const h=(0,e.useMemo)(()=>(0,t.jsx)(O,{router:p,children:u}),[p,u]);return(0,t.jsx)(y.Provider,{value:f,children:h})}function S(e){return M(e,r.createBrowserHistory)}function H(e){return M(e,r.createHashHistory)}function V({initialEntries:t,initialIndex:n,...o}){return M(o,(0,e.useMemo)(()=>()=>(0,r.createMemoryHistory)({initialEntries:t,initialIndex:n}),[t,n]))}function q(){const r=(0,e.useContext)(w);if(!r)throw new Error("useRouter() must be used within a <Router> component");return r}var k="_nativeRouterReactSSRData";function E(e,r,o){return(0,n.resolve)(e,r).then(n=>{const u=function(e){return j.get(e)}(n),i=e.history.location.state?.index||0;return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(O,{router:e,children:n}),(0,t.jsx)("script",{...o?.scriptAttributes,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`window.${o?.hydrateKey||k} = ${a={data:u,location:r,index:i},JSON.stringify(a).replace(/</g,"\\u003c").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")};`}})]});var a})}function I(e,t,{scriptAttributes:u,hydrateKey:i,...a}={}){const c=(0,n.create)(e,(0,r.createMemoryHistory)({initialEntries:[t]}),P,a);return E(c,(0,o.isString)(t)?(0,n.toLocation)(c,t):t,{scriptAttributes:u,hydrateKey:i})}function A(e,t){const{data:o,location:u,index:i=0}=window[t?.hydrateKey||k],a=(0,r.createBrowserHistory)();a.replace((0,r.createPath)(a.location),{index:i});const c=(0,n.create)(e,a,function(e){return(r,t)=>C(r,t,(r,t)=>e[t.index])}(o),t);return(0,n.resolve)(c,u).then(e=>({view:e,router:c}))}Object.defineProperty(exports,"HashRouter",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"HistoryRouter",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"MemoryRouter",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"Router",{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,"View",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"createRouter",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"hydrate",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"resolveServerView",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"resolveView",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"useData",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"useLoading",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"useMatched",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"useNamedData",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"useRouter",{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,"useView",{enumerable:!0,get:function(){return c}});
|
|
2
|
+
//# sourceMappingURL=ssr-Cow2_ikA.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-Cow2_ikA.cjs","names":[],"sources":["../src/context.tsx","../src/resolve-view.tsx","../src/components/Router.tsx","../src/ssr.tsx"],"sourcesContent":["import {createContext, ReactNode, useContext, useMemo} from 'react';\nimport type {Context, LoadStatus, Route} from './types';\n\nconst ViewContext = createContext<ReactNode>(null);\n\nexport function ViewProvider(props: {children: ReactNode; value: ReactNode}) {\n return <ViewContext.Provider {...props} />;\n}\n\n/**\n * @group Hooks\n * @see {@link View View Component}\n */\nexport function useView() {\n return useContext(ViewContext);\n}\n\n/**\n * Route-level pending skeleton(`pendingComponent` of the nearest matched\n * ancestor), set by the Router only while a navigation is pending with no\n * previous view to retain(cold start, refresh, re-navigation after an\n * error); `null` otherwise, so in-app navigation keeps the previous view.\n * @see {@link Route.pendingComponent}\n */\nexport const PendingContext = createContext<ReactNode>(null);\n\n/**\n * Used for route component to render child route component.\n * It just render the return of {@link useView}, falling back to the\n * route-level pending skeleton when the view slot is empty.\n * @group Components\n */\nexport function View() {\n const view = useView();\n const pending = useContext(PendingContext);\n return view ?? pending;\n}\n\nconst DataContext = createContext<[any, Record<string, any>]>([undefined, {}]);\n\nfunction useDataContext() {\n return useContext(DataContext);\n}\n\n/**\n * Get the named data map of the resolved route levels: an object keyed by\n * each ancestor's `name`, holding its resolved `data`. The current level\n * is included only when it declares a `name`.\n *\n * Give the generic the expected map shape to read values type-safely:\n * `useNamedData<{user: User}>()`.\n * @group Hooks\n */\nexport function useNamedData<T = Record<string, unknown>>() {\n return useDataContext()[1] as T;\n}\n\nexport function DataProvider({\n children,\n name,\n data\n}: {\n children: ReactNode;\n data: any;\n name?: string;\n}) {\n const namedData = useNamedData();\n const value = useMemo(\n () => [data, name ? {...namedData, [name]: data} : namedData] as [any, any],\n [data, name, namedData]\n );\n return <DataContext.Provider value={value}>{children}</DataContext.Provider>;\n}\n\nexport const MatchedContext = createContext<Context<Route> | undefined>(\n undefined\n);\n\n/**\n * @group Hooks\n */\nexport function useMatched() {\n return useContext(MatchedContext)!;\n}\n\n/**\n * Get the resolved `data` of the current route level, or the named data\n * of an ancestor level when `name` is given.\n *\n * Give the generic the expected data type to read it type-safely without\n * a cast: `useData<Article>()` → `Article | undefined`.\n * @group Hooks\n */\nexport function useData<T = unknown>(name?: string): T | undefined {\n const [data, namedData] = useDataContext();\n return (name ? namedData[name] : data) as T | undefined;\n}\n\nexport const LoadingContext = createContext<LoadStatus | undefined>(undefined);\n\n/**\n * @group Hooks\n */\nexport function useLoading() {\n return useContext(LoadingContext);\n}\n","import type {ComponentType, ReactElement} from 'react';\nimport type {Context, ResolveViewContext, Route} from '@@/types';\nimport {\n mergeMatchedParams,\n parseSearch,\n parseSearchInput\n} from '@native-router/core';\nimport type {Matched} from '@native-router/core';\nimport {DataProvider, MatchedContext, View, ViewProvider} from './context';\n\n/**\n * The default implementation of resolve view\n * @param matched the matched result\n * @param viewContext resolved view context\n * @returns the resolve view\n * @see {@link create router->create}\n */\nexport default function resolveView(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n return resolveViewBase(matched, ctx, (data, dataCtx) => data?.(dataCtx));\n}\n\nconst viewDataMap = new WeakMap<ReactElement, any[]>();\n\nexport function resolveViewServer(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n const dataResults = new Array(matched.length);\n return resolveViewBase(matched, ctx, (data, dataCtx) =>\n Promise.resolve(data?.(dataCtx)).then(\n (result) => (dataResults[dataCtx.index] = result)\n )\n ).then((view) => {\n viewDataMap.set(view, dataResults);\n return view;\n });\n}\n\nexport function createHydrateResolveView(data: any[]) {\n return (matched: Matched<Route>[], ctx: ResolveViewContext<Route>) =>\n resolveViewBase(matched, ctx, (_, dataCtx) => data[dataCtx.index]);\n}\n\nexport function getViewData(view: ReactElement) {\n return viewDataMap.get(view);\n}\n\nfunction resolveViewBase(\n matched: Matched<Route>[],\n {router, location, signal}: ResolveViewContext<Route>,\n resolveData: (\n dataFetcher: ((ctx: Context<Route>) => any) | undefined,\n ctx: Context<Route>\n ) => any\n) {\n return Promise.all(\n matched.map(({route}, index) => {\n // `search` starts as the degraded input and is upgraded to the\n // schema output before the data fetcher runs below; schema outputs\n // are user-typed(`Route<P, S>`), so the property stays `any` here.\n const ctx: Context<Route, Record<string, string>, any> = {\n matched: matched!,\n params: mergeMatchedParams(matched, index),\n index,\n router,\n location,\n search: parseSearchInput(location.search),\n // The chain's abort signal(navigation-superseded/cancelled) is\n // forwarded to every level's loader; a hand-rolled resolveView\n // context without one still yields a never-aborting signal.\n signal: signal ?? new AbortController().signal\n };\n function resolveComponent(): ComponentType | Promise<ComponentType> {\n if (!route.component) return View;\n const r = route.component(ctx);\n return Promise.resolve(r).then((m) => ('default' in m ? m.default : m));\n }\n\n // The level's search schema runs before its data fetcher: the parsed\n // output replaces the degraded input in `ctx.search`, and a rejected\n // validation fails the level exactly like a data error.\n const resolveDataWithSearch = () =>\n route.search\n ? parseSearch(route.search, location.search).then((search) => {\n ctx.search = search;\n return resolveData(route.data, ctx);\n })\n : resolveData(route.data, ctx);\n\n // A level that fails to resolve (search, data or component) is\n // replaced by its route-level errorComponent when configured;\n // otherwise the error bubbles up to the global errorHandler as before.\n return Promise.all([resolveDataWithSearch(), resolveComponent()]).then(\n ([data, C]) => (\n <DataProvider data={data} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <C />\n </MatchedContext.Provider>\n </DataProvider>\n ),\n (error: Error) => {\n if (!route.errorComponent) throw error;\n return (\n <DataProvider data={undefined} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <route.errorComponent error={error} ctx={ctx} />\n </MatchedContext.Provider>\n </DataProvider>\n );\n }\n );\n })\n ).then((views) =>\n views\n .reverse()\n .reduce((acc, view) => <ViewProvider value={acc}>{view}</ViewProvider>)\n );\n}\n","import {\n ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react';\nimport {\n History,\n createBrowserHistory,\n createHashHistory,\n createMemoryHistory,\n MemoryHistoryOptions\n} from 'history';\nimport type {LoadStatus, Route} from '@@/types';\nimport {LoadingContext, PendingContext, ViewProvider} from '@@/context';\nimport {\n create,\n getCurrentView,\n listen,\n match,\n setOptions\n} from '@native-router/core';\nimport type {Options, ResolveView, RouterInstance} from '@native-router/core';\nimport {splitProps, uniqId} from '@native-router/core/util';\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\nimport defaultResolve from '@@/resolve-view';\n\nconst RouterContext = createContext<RouterInstance<Route, ReactNode> | null>(\n null\n);\n\ntype Props = {\n children?: ReactNode;\n routes: Route[] | Route;\n resolveView?: typeof defaultResolve;\n} & Omit<Options<ReactNode>, 'onLoadingChange'>;\n\n/**\n * Base Router Component.\n * @group Components\n */\nexport function Router({\n router,\n children\n}: {\n children?: ReactNode;\n router: RouterInstance<Route, ReactNode>;\n}) {\n const viewRef = useRef<ReactNode>(getCurrentView(router));\n const subscribe = useCallback(\n (onStoreChange: () => void) =>\n listen(router, (view) => {\n viewRef.current = view;\n onStoreChange();\n }),\n [router]\n );\n const getSnapshot = useCallback(() => viewRef.current, []);\n // `getServerSnapshot` is required by the native implementation when the\n // Router is rendered inside server-rendered content(e.g. resolveServerView).\n const getServerSnapshot = useCallback(() => getCurrentView(router), [router]);\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n // Route-level pending skeleton, only when no previous view is retained\n // (cold start, refresh, re-navigation after an error); in-app navigation\n // keeps the old view by design, the global loading signal already\n // covers that phase. Reading LoadingContext here also re-renders the\n // Router on every loading transition.\n const loading = useContext(LoadingContext);\n const pending =\n view == null && loading?.status === 'pending'\n ? resolvePendingView(router, loading.key)\n : null;\n\n return (\n <RouterContext.Provider value={router}>\n {children === undefined ? (\n (view ?? pending)\n ) : (\n <ViewProvider value={view}>\n <PendingContext.Provider value={pending}>\n {children}\n </PendingContext.Provider>\n </ViewProvider>\n )}\n </RouterContext.Provider>\n );\n}\n\n/**\n * Render the `pendingComponent` of the nearest matched ancestor of the\n * resolving location, walked deepest first(the resolving route's own\n * included). Keyed by the loading episode so a new pending phase remounts\n * the skeleton(stateful shimmer animations restart). Guards may still\n * redirect the resolution away; until then the initially matched chain\n * is the best — and only — answer available.\n */\nfunction resolvePendingView(\n router: RouterInstance<Route, ReactNode>,\n key: number\n) {\n const {resolving} = router;\n const matched = resolving ? match(router, resolving.pathname) : undefined;\n if (!matched) return null;\n for (let i = matched.length - 1; i >= 0; i--) {\n const Pending = matched[i].route.pendingComponent;\n if (Pending) return <Pending key={key} />;\n }\n return null;\n}\n\nexport function createRouter(\n routes: Route | Route[],\n history: History,\n {\n resolveView = defaultResolve,\n ...options\n }: Options<ReactNode> & {resolveView?: ResolveView<Route, ReactNode>} = {}\n): RouterInstance<Route, ReactNode> {\n return create(routes, history, resolveView, options);\n}\n\nfunction useNewRouter(\n {routes, children, ...options}: Props,\n createHistory: () => History\n) {\n const [tracked, rest] = splitProps(options, ['baseUrl', 'currentView']);\n const {baseUrl, currentView} = tracked;\n const [loading, setLoading] = useState<LoadStatus>();\n // Initial options are baked in at creation: the cold-start resolve fires\n // from the subscribe effect(children effects run first) before the\n // setOptions effect below runs, and the default errorHandler would let\n // listen's refresh().catch(noop) swallow a first failure, leaving the\n // view blank forever.\n const router = useMemo(\n () =>\n createRouter(routes, createHistory(), {\n ...options,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n }),\n // Only the tracked options belong to the deps: option updates flow\n // through the setOptions effect below instead of recreating the router.\n [routes, createHistory, baseUrl, currentView]\n );\n\n // Options are refreshed on every commit, so `onLoadingChange` and the\n // callback options always see the latest closure.\n useEffect(() => {\n setOptions(router, {\n ...rest,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n });\n }, [router, rest]);\n\n const r = useMemo(\n () => <Router router={router}>{children}</Router>,\n [router, children]\n );\n\n return <LoadingContext.Provider value={loading}>{r}</LoadingContext.Provider>;\n}\n\n/**\n * History mode Router Component.\n * @group Components\n */\nexport function HistoryRouter(props: Props) {\n return useNewRouter(props, createBrowserHistory);\n}\n\n/**\n * Hash mode Router Component.\n * @group Components\n */\nexport function HashRouter(props: Props) {\n return useNewRouter(props, createHashHistory);\n}\n\n/**\n * Memory mode Router Component.\n * @group Components\n */\nexport function MemoryRouter({\n initialEntries,\n initialIndex,\n ...props\n}: Props & MemoryHistoryOptions) {\n const createHistory = useMemo(\n () => () => createMemoryHistory({initialEntries, initialIndex}),\n [initialEntries, initialIndex]\n );\n return useNewRouter(props, createHistory);\n}\n\n/**\n * Get Router instance.\n * @group Hooks\n * @returns Router Instance\n */\nexport function useRouter() {\n const router = useContext(RouterContext);\n if (!router) {\n throw new Error('useRouter() must be used within a <Router> component');\n }\n return router;\n}\n","import {createBrowserHistory, createMemoryHistory, createPath} from 'history';\nimport {ReactElement, ReactNode} from 'react';\nimport {create, resolve, toLocation} from '@native-router/core';\nimport type {\n HistoryState,\n Location,\n Options,\n RouterInstance\n} from '@native-router/core';\nimport {isString} from '@native-router/core/util';\nimport {Router} from './components/Router';\nimport {\n createHydrateResolveView,\n getViewData,\n resolveViewServer\n} from './resolve-view';\nimport type {Route} from './types';\n\nconst defaultHydrateKey = '_nativeRouterReactSSRData';\n\n/**\n * Serialize the SSR payload for embedding in a script element.\n * `JSON.stringify` does not escape `<`, U+2028 and U+2029,\n * so route data like `</script>` would break out of the script element.\n * @param payload the payload to serialize\n * @returns the escaped JSON string\n */\nfunction serializePayload(payload: {\n data?: any[];\n location: Location;\n index: number;\n}) {\n return JSON.stringify(payload)\n .replace(/</g, '\\\\u003c')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport function resolveServerViewBase(\n router: RouterInstance<Route, ReactNode>,\n location: Location,\n options?: {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n }\n) {\n return resolve<Route, ReactNode>(router, location).then((view) => {\n const data = getViewData(view as ReactElement);\n const index =\n (router.history.location.state as HistoryState | undefined)?.index || 0;\n return (\n <>\n <Router router={router}>{view}</Router>\n <script\n {...options?.scriptAttributes}\n suppressHydrationWarning\n // eslint-disable-next-line @eslint-react/dom-no-dangerously-set-innerhtml -- serialized state for hydration\n dangerouslySetInnerHTML={{\n __html: `window.${\n options?.hydrateKey || defaultHydrateKey\n } = ${serializePayload({data, location, index})};`\n }}\n />\n </>\n );\n });\n}\n\nexport function resolveServerView(\n routes: Route | Route[],\n location: Location | string,\n {\n scriptAttributes,\n hydrateKey,\n ...options\n }: Options<ReactElement> & {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n } = {}\n) {\n const router = create(\n routes,\n createMemoryHistory({initialEntries: [location]}),\n resolveViewServer,\n options\n );\n\n return resolveServerViewBase(\n router,\n isString(location) ? toLocation(router, location) : location,\n {\n scriptAttributes,\n hydrateKey\n }\n );\n}\n\n/**\n * Hydrate the SSR result of {@link resolveServerView} on the client.\n * The router is bound to the browser history(aligned with the index\n * in the SSR payload), so navigation after hydration updates the address bar.\n * @param routes routes config, must match the server side\n * @param options options, `hydrateKey` must match the server side\n * @returns the resolved view and the router instance, for example:\n * `const {view, router} = await hydrate(routes);`\n * `hydrateRoot(root, <Router router={router}>{view}</Router>)`\n * @group Methods\n */\nexport function hydrate(\n routes: Route | Route[],\n options?: Options<ReactElement> & {\n hydrateKey?: string;\n }\n): Promise<{view: ReactNode; router: RouterInstance<Route, ReactNode>}> {\n const {\n data,\n location,\n index = 0\n } = (window as any)[options?.hydrateKey || defaultHydrateKey] as {\n data: any[];\n location: Location;\n index?: number;\n };\n const history = createBrowserHistory();\n history.replace(createPath(history.location), {index});\n const router = create(\n routes,\n history,\n createHydrateResolveView(data),\n options\n );\n return resolve<Route, ReactNode>(router, location).then((view) => ({\n view,\n router\n }));\n}\n"],"mappings":"4LAGA,IAAM,GAAA,EAAc,EAAA,eAAyB,MAE7C,SAAgB,EAAa,GAC3B,OAAO,EAAA,EAAA,KAAC,EAAY,SAAb,IAA0B,GACnC,CAMA,SAAgB,IACd,OAAA,EAAO,EAAA,YAAW,EACpB,CASA,IAAa,GAAA,EAAiB,EAAA,eAAyB,MAQvD,SAAgB,IACd,MAAM,EAAO,IACP,GAAA,EAAU,EAAA,YAAW,GAC3B,OAAO,GAAQ,CACjB,CAEA,IAAM,GAAA,EAAc,EAAA,eAA0C,MAAC,EAAW,CAAC,IAE3E,SAAS,IACP,OAAA,EAAO,EAAA,YAAW,EACpB,CAWA,SAAgB,IACd,OAAO,IAAiB,EAC1B,CAEA,SAAgB,GAAa,SAC3B,EAAA,KACA,EAAA,KACA,IAMA,MAAM,EAAY,IACZ,GAAA,EAAQ,EAAA,SAAA,IACN,CAAC,EAAM,EAAO,IAAI,EAAY,CAAA,GAAO,GAAQ,GACnD,CAAC,EAAM,EAAM,IAEf,OAAO,EAAA,EAAA,KAAC,EAAY,SAAb,CAA6B,QAAQ,YAC9C,CAEA,IAAa,GAAA,EAAiB,EAAA,oBAC5B,GAMF,SAAgB,IACd,OAAA,EAAO,EAAA,YAAW,EACpB,CAUA,SAAgB,EAAqB,GACnC,MAAO,EAAM,GAAa,IAC1B,OAAQ,EAAO,EAAU,GAAQ,CACnC,CAEA,IAAa,GAAA,EAAiB,EAAA,oBAAsC,GAKpE,SAAgB,IACd,OAAA,EAAO,EAAA,YAAW,EACpB,CCxFA,SAAwB,EACtB,EACA,GAEA,OAAO,EAAgB,EAAS,EAAA,CAAM,EAAM,IAAY,IAAO,GACjE,CAEA,IAAM,EAAc,IAAI,QAExB,SAAgB,EACd,EACA,GAEA,MAAM,EAAc,IAAI,MAAM,EAAQ,QACtC,OAAO,EAAgB,EAAS,EAAA,CAAM,EAAM,IAC1C,QAAQ,QAAQ,IAAO,IAAU,KAC9B,GAAY,EAAY,EAAQ,OAAS,IAE5C,KAAM,IACN,EAAY,IAAI,EAAM,GACf,GAEX,CAWA,SAAS,EACP,GACA,OAAC,EAAA,SAAQ,EAAA,OAAU,GACnB,GAKA,OAAO,QAAQ,IACb,EAAQ,IAAA,EAAM,SAAQ,KAIpB,MAAM,EAAmD,CAC9C,UACT,QAAA,EAAQ,EAAA,oBAAmB,EAAS,GACpC,QACA,SACA,WACA,QAAA,EAAQ,EAAA,kBAAiB,EAAS,QAIlC,OAAQ,IAAU,IAAI,iBAAkB,QAsB1C,OAAO,QAAQ,IAAI,CAVjB,EAAM,QAAA,EACF,EAAA,aAAY,EAAM,OAAQ,EAAS,QAAQ,KAAM,IAC/C,EAAI,OAAS,EACN,EAAY,EAAM,KAAM,KAEjC,EAAY,EAAM,KAAM,GAf9B,WACE,IAAK,EAAM,UAAW,OAAO,EAC7B,MAAM,EAAI,EAAM,UAAU,GAC1B,OAAO,QAAQ,QAAQ,GAAG,KAAM,GAAO,YAAa,EAAI,EAAE,QAAU,EACtE,CAgB6C,KAAqB,KAAA,EAC9D,EAAM,MACN,EAAA,EAAA,KAAC,EAAD,CAAoB,OAAM,KAAM,EAAM,KACpC,UAAA,EAAA,EAAA,KAAC,EAAe,SAAhB,CAAyB,MAAO,EAC9B,UAAA,EAAA,EAAA,KAAC,EAAD,CAAI,OAIT,IACC,IAAK,EAAM,eAAgB,MAAM,EACjC,OACE,EAAA,EAAA,KAAC,EAAD,CAAc,UAAM,EAAW,KAAM,EAAM,KACzC,UAAA,EAAA,EAAA,KAAC,EAAe,SAAhB,CAAyB,MAAO,EAC9B,UAAA,EAAA,EAAA,KAAC,EAAM,eAAP,CAA6B,QAAY,iBAOrD,KAAM,GACN,EACG,UACA,OAAA,CAAQ,EAAK,KAAS,EAAA,EAAA,KAAC,EAAD,CAAc,MAAO,EAAM,SAAA,KAExD,CCzFA,IAAM,GAAA,EAAgB,EAAA,eACpB,MAaF,SAAgB,GAAO,OACrB,EAAA,SACA,IAKA,MAAM,GAAA,EAAU,EAAA,SAAA,EAAkB,EAAA,gBAAe,IAC3C,GAAA,EAAY,EAAA,aACf,IAAA,EACC,EAAA,QAAO,EAAS,IACd,EAAQ,QAAU,EAClB,MAEJ,CAAC,IAEG,GAAA,EAAc,EAAA,aAAA,IAAkB,EAAQ,QAAS,IAGjD,GAAA,EAAoB,EAAA,aAAA,KAAA,EAAkB,EAAA,gBAAe,GAAS,CAAC,IAC/D,GAAA,EAAO,EAAA,sBAAqB,EAAW,EAAa,GAMpD,GAAA,EAAU,EAAA,YAAW,GACrB,EACI,MAAR,GAAoC,YAApB,GAAS,OA2B7B,SACE,EACA,GAEA,MAAM,UAAC,GAAa,EACd,EAAU,GAAA,EAAY,EAAA,OAAM,EAAQ,EAAU,eAAY,EAChE,IAAK,EAAS,OAAO,KACrB,IAAK,IAAI,EAAI,EAAQ,OAAS,EAAG,GAAK,EAAG,IAAK,CAC5C,MAAM,EAAU,EAAQ,GAAG,MAAM,iBACjC,GAAI,EAAS,OAAO,EAAA,EAAA,KAAC,EAAD,CAAoB,EAAN,EACpC,CACA,OAAO,IACT,CAtCQ,CAAmB,EAAQ,EAAQ,KACnC,KAEN,OACE,EAAA,EAAA,KAAC,EAAc,SAAf,CAAwB,MAAO,EAC5B,cAAa,IAAb,EACE,GAAQ,GAET,EAAA,EAAA,KAAC,EAAD,CAAc,MAAO,EACnB,UAAA,EAAA,EAAA,KAAC,EAAe,SAAhB,CAAyB,MAAO,EAC7B,gBAMb,CAwBA,SAAgB,EACd,EACA,GAEE,YAAA,EAAc,KACX,GACmE,CAAC,GAEzE,OAAA,EAAO,EAAA,QAAO,EAAQ,EAAS,EAAa,EAC9C,CAEA,SAAS,GACP,OAAC,EAAA,SAAQ,KAAa,GACtB,GAEA,MAAO,EAAS,IAAA,EAAQ,EAAA,YAAW,EAAS,CAAC,UAAW,iBAClD,QAAC,EAAA,YAAS,GAAe,GACxB,EAAS,IAAA,EAAc,EAAA,YAMxB,GAAA,EAAS,EAAA,SAAA,IAEX,EAAa,EAAQ,IAAiB,IACjC,EACH,eAAA,CAAgB,GACd,EAAW,GAAU,CAAC,KAAA,EAAK,EAAA,UAAU,UACvC,IAIJ,CAAC,EAAQ,EAAe,EAAS,KAKnC,EAAA,EAAA,WAAA,MACE,EAAA,EAAA,YAAW,EAAQ,IACd,EACH,eAAA,CAAgB,GACd,EAAW,GAAU,CAAC,KAAA,EAAK,EAAA,UAAU,UACvC,KAED,CAAC,EAAQ,IAEZ,MAAM,GAAA,EAAI,EAAA,SAAA,KACF,EAAA,EAAA,KAAC,EAAD,CAAgB,SAAS,aAC/B,CAAC,EAAQ,IAGX,OAAO,EAAA,EAAA,KAAC,EAAe,SAAhB,CAAyB,MAAO,EAAU,SAAA,GACnD,CAMA,SAAgB,EAAc,GAC5B,OAAO,EAAa,EAAO,EAAA,qBAC7B,CAMA,SAAgB,EAAW,GACzB,OAAO,EAAa,EAAO,EAAA,kBAC7B,CAMA,SAAgB,GAAa,eAC3B,EAAA,aACA,KACG,IAMH,OAAO,EAAa,GAAA,EAJE,EAAA,SAAA,IAAA,KAAA,EACR,EAAA,qBAAoB,CAAC,iBAAgB,iBACjD,CAAC,EAAgB,IAGrB,CAOA,SAAgB,IACd,MAAM,GAAA,EAAS,EAAA,YAAW,GAC1B,IAAK,EACH,MAAM,IAAI,MAAM,wDAElB,OAAO,CACT,CClMA,IAAM,EAAoB,4BAoB1B,SAAgB,EACd,EACA,EACA,GAKA,OAAA,EAAO,EAAA,SAA0B,EAAQ,GAAU,KAAM,IACvD,MAAM,EFDV,SAA4B,GAC1B,OAAO,EAAY,IAAI,EACzB,CEDiB,CAAY,GACnB,EACH,EAAO,QAAQ,SAAS,OAAoC,OAAS,EACxE,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAgB,SAAS,SAAA,KACzB,EAAA,EAAA,KAAC,SAAD,IACM,GAAS,iBACb,0BAAA,EAEA,wBAAyB,CACvB,OAAQ,UACN,GAAS,YAAc,OAhCX,EAiCS,CAAC,OAAM,WAAU,SA5B3C,KAAK,UAAU,GACnB,QAAQ,KAAM,WACd,QAAQ,UAAW,WACnB,QAAQ,UAAW,oBARxB,IAA0B,GAuC1B,CAEA,SAAgB,EACd,EACA,GACA,iBACE,EAAA,WACA,KACG,GAID,CAAC,GAEL,MAAM,GAAA,EAAS,EAAA,QACb,GAAA,EACA,EAAA,qBAAoB,CAAC,eAAgB,CAAC,KACtC,EACA,GAGF,OAAO,EACL,GAAA,EACA,EAAA,UAAS,IAAQ,EAAI,EAAA,YAAW,EAAQ,GAAY,EACpD,CACE,mBACA,cAGN,CAaA,SAAgB,EACd,EACA,GAIA,MAAM,KACJ,EAAA,SACA,EAAA,MACA,EAAQ,GACL,OAAe,GAAS,YAAc,GAKrC,GAAA,EAAU,EAAA,wBAChB,EAAQ,SAAA,EAAQ,EAAA,YAAW,EAAQ,UAAW,CAAC,UAC/C,MAAM,GAAA,EAAS,EAAA,QACb,EACA,EFtFJ,SAAyC,GACvC,MAAA,CAAQ,EAA2B,IACjC,EAAgB,EAAS,EAAA,CAAM,EAAG,IAAY,EAAK,EAAQ,OAC/D,CEoFI,CAAyB,GACzB,GAEF,OAAA,EAAO,EAAA,SAA0B,EAAQ,GAAU,KAAM,IAAA,CACvD,OACA,WAEJ"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{createContext as r,useCallback as n,useContext as e,useEffect as t,useMemo as i,useRef as o,useState as a}from"react";import{createBrowserHistory as u,createHashHistory as c,createMemoryHistory as s,createPath as l}from"history";import{Fragment as d,jsx as h,jsxs as f}from"react/jsx-runtime";import{create as v,getCurrentView as m,listen as p,match as g,mergeMatchedParams as y,parseSearch as w,parseSearchInput as x,resolve as P,setOptions as b,toLocation as C}from"@native-router/core";import{isString as A,splitProps as R,uniqId as k}from"@native-router/core/util";import{useSyncExternalStore as E}from"use-sync-external-store/shim";var K=r(null);function S(r){/* @__PURE__ */
|
|
2
|
+
return h(K.Provider,{...r})}function I(){return e(K)}var L=r(null);function V(){const r=I(),n=e(L);return r??n}var _=r([void 0,{}]);function H(){return e(_)}function M(){return H()[1]}function U({children:r,name:n,data:e}){const t=M(),o=i(()=>[e,n?{...t,[n]:e}:t],[e,n,t]);/* @__PURE__ */
|
|
3
|
+
return h(_.Provider,{value:o,children:r})}var W=r(void 0);function $(){return e(W)}function j(r){const[n,e]=H();return r?e[r]:n}var D=r(void 0);function J(){return e(D)}function N(r,n){return q(r,n,(r,n)=>r?.(n))}var O=/* @__PURE__ */new WeakMap;function T(r,n){const e=new Array(r.length);return q(r,n,(r,n)=>Promise.resolve(r?.(n)).then(r=>e[n.index]=r)).then(r=>(O.set(r,e),r))}function q(r,{router:n,location:e,signal:t},i){return Promise.all(r.map(({route:o},a)=>{const u={matched:r,params:y(r,a),index:a,router:n,location:e,search:x(e.search),signal:t??(new AbortController).signal};return Promise.all([o.search?w(o.search,e.search).then(r=>(u.search=r,i(o.data,u))):i(o.data,u),function(){if(!o.component)return V;const r=o.component(u);return Promise.resolve(r).then(r=>"default"in r?r.default:r)}()]).then(([r,n])=>/* @__PURE__ */h(U,{data:r,name:o.name,children:/* @__PURE__ */h(W.Provider,{value:u,children:/* @__PURE__ */h(n,{})})}),r=>{if(!o.errorComponent)throw r;/* @__PURE__ */
|
|
4
|
+
return h(U,{data:void 0,name:o.name,children:/* @__PURE__ */h(W.Provider,{value:u,children:/* @__PURE__ */h(o.errorComponent,{error:r,ctx:u})})})})})).then(r=>r.reverse().reduce((r,n)=>/* @__PURE__ */h(S,{value:r,children:n})))}var z=r(null);function B({router:r,children:t}){const i=o(m(r)),a=n(n=>p(r,r=>{i.current=r,n()}),[r]),u=n(()=>i.current,[]),c=n(()=>m(r),[r]),s=E(a,u,c),l=e(D),d=null==s&&"pending"===l?.status?function(r,n){const{resolving:e}=r,t=e?g(r,e.pathname):void 0;if(!t)return null;for(let i=t.length-1;i>=0;i--){const r=t[i].route.pendingComponent;if(r)/* @__PURE__ */return h(r,{},n)}return null}(r,l.key):null;/* @__PURE__ */
|
|
5
|
+
return h(z.Provider,{value:r,children:void 0===t?s??d:/* @__PURE__ */h(S,{value:s,children:/* @__PURE__ */h(L.Provider,{value:d,children:t})})})}function F(r,n,{resolveView:e=N,...t}={}){return v(r,n,e,t)}function G({routes:r,children:n,...e},o){const[u,c]=R(e,["baseUrl","currentView"]),{baseUrl:s,currentView:l}=u,[d,f]=a(),v=i(()=>F(r,o(),{...e,onLoadingChange(r){f(r&&{key:k(),status:r})}}),[r,o,s,l]);t(()=>{b(v,{...c,onLoadingChange(r){f(r&&{key:k(),status:r})}})},[v,c]);const m=i(()=>/* @__PURE__ */h(B,{router:v,children:n}),[v,n]);/* @__PURE__ */
|
|
6
|
+
return h(D.Provider,{value:d,children:m})}function Q(r){return G(r,u)}function X(r){return G(r,c)}function Y({initialEntries:r,initialIndex:n,...e}){return G(e,i(()=>()=>s({initialEntries:r,initialIndex:n}),[r,n]))}function Z(){const r=e(z);if(!r)throw new Error("useRouter() must be used within a <Router> component");return r}var rr="_nativeRouterReactSSRData";function nr(r,n,e){return P(r,n).then(t=>{const i=function(r){return O.get(r)}(t),o=r.history.location.state?.index||0;/* @__PURE__ */
|
|
7
|
+
return f(d,{children:[/* @__PURE__ */h(B,{router:r,children:t}),/* @__PURE__ */h("script",{...e?.scriptAttributes,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`window.${e?.hydrateKey||rr} = ${a={data:i,location:n,index:o},JSON.stringify(a).replace(/</g,"\\u003c").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")};`}})]});var a})}function er(r,n,{scriptAttributes:e,hydrateKey:t,...i}={}){const o=v(r,s({initialEntries:[n]}),T,i);return nr(o,A(n)?C(o,n):n,{scriptAttributes:e,hydrateKey:t})}function tr(r,n){const{data:e,location:t,index:i=0}=window[n?.hydrateKey||rr],o=u();o.replace(l(o.location),{index:i});const a=v(r,o,function(r){return(n,e)=>q(n,e,(n,e)=>r[e.index])}(e),n);return P(a,t).then(r=>({view:r,router:a}))}export{Y as a,Z as c,j as d,J as f,I as h,Q as i,N as l,M as m,er as n,B as o,$ as p,X as r,F as s,tr as t,V as u};
|
|
8
|
+
//# sourceMappingURL=ssr-j5c5cH-B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-j5c5cH-B.js","names":[],"sources":["../src/context.tsx","../src/resolve-view.tsx","../src/components/Router.tsx","../src/ssr.tsx"],"sourcesContent":["import {createContext, ReactNode, useContext, useMemo} from 'react';\nimport type {Context, LoadStatus, Route} from './types';\n\nconst ViewContext = createContext<ReactNode>(null);\n\nexport function ViewProvider(props: {children: ReactNode; value: ReactNode}) {\n return <ViewContext.Provider {...props} />;\n}\n\n/**\n * @group Hooks\n * @see {@link View View Component}\n */\nexport function useView() {\n return useContext(ViewContext);\n}\n\n/**\n * Route-level pending skeleton(`pendingComponent` of the nearest matched\n * ancestor), set by the Router only while a navigation is pending with no\n * previous view to retain(cold start, refresh, re-navigation after an\n * error); `null` otherwise, so in-app navigation keeps the previous view.\n * @see {@link Route.pendingComponent}\n */\nexport const PendingContext = createContext<ReactNode>(null);\n\n/**\n * Used for route component to render child route component.\n * It just render the return of {@link useView}, falling back to the\n * route-level pending skeleton when the view slot is empty.\n * @group Components\n */\nexport function View() {\n const view = useView();\n const pending = useContext(PendingContext);\n return view ?? pending;\n}\n\nconst DataContext = createContext<[any, Record<string, any>]>([undefined, {}]);\n\nfunction useDataContext() {\n return useContext(DataContext);\n}\n\n/**\n * Get the named data map of the resolved route levels: an object keyed by\n * each ancestor's `name`, holding its resolved `data`. The current level\n * is included only when it declares a `name`.\n *\n * Give the generic the expected map shape to read values type-safely:\n * `useNamedData<{user: User}>()`.\n * @group Hooks\n */\nexport function useNamedData<T = Record<string, unknown>>() {\n return useDataContext()[1] as T;\n}\n\nexport function DataProvider({\n children,\n name,\n data\n}: {\n children: ReactNode;\n data: any;\n name?: string;\n}) {\n const namedData = useNamedData();\n const value = useMemo(\n () => [data, name ? {...namedData, [name]: data} : namedData] as [any, any],\n [data, name, namedData]\n );\n return <DataContext.Provider value={value}>{children}</DataContext.Provider>;\n}\n\nexport const MatchedContext = createContext<Context<Route> | undefined>(\n undefined\n);\n\n/**\n * @group Hooks\n */\nexport function useMatched() {\n return useContext(MatchedContext)!;\n}\n\n/**\n * Get the resolved `data` of the current route level, or the named data\n * of an ancestor level when `name` is given.\n *\n * Give the generic the expected data type to read it type-safely without\n * a cast: `useData<Article>()` → `Article | undefined`.\n * @group Hooks\n */\nexport function useData<T = unknown>(name?: string): T | undefined {\n const [data, namedData] = useDataContext();\n return (name ? namedData[name] : data) as T | undefined;\n}\n\nexport const LoadingContext = createContext<LoadStatus | undefined>(undefined);\n\n/**\n * @group Hooks\n */\nexport function useLoading() {\n return useContext(LoadingContext);\n}\n","import type {ComponentType, ReactElement} from 'react';\nimport type {Context, ResolveViewContext, Route} from '@@/types';\nimport {\n mergeMatchedParams,\n parseSearch,\n parseSearchInput\n} from '@native-router/core';\nimport type {Matched} from '@native-router/core';\nimport {DataProvider, MatchedContext, View, ViewProvider} from './context';\n\n/**\n * The default implementation of resolve view\n * @param matched the matched result\n * @param viewContext resolved view context\n * @returns the resolve view\n * @see {@link create router->create}\n */\nexport default function resolveView(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n return resolveViewBase(matched, ctx, (data, dataCtx) => data?.(dataCtx));\n}\n\nconst viewDataMap = new WeakMap<ReactElement, any[]>();\n\nexport function resolveViewServer(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n const dataResults = new Array(matched.length);\n return resolveViewBase(matched, ctx, (data, dataCtx) =>\n Promise.resolve(data?.(dataCtx)).then(\n (result) => (dataResults[dataCtx.index] = result)\n )\n ).then((view) => {\n viewDataMap.set(view, dataResults);\n return view;\n });\n}\n\nexport function createHydrateResolveView(data: any[]) {\n return (matched: Matched<Route>[], ctx: ResolveViewContext<Route>) =>\n resolveViewBase(matched, ctx, (_, dataCtx) => data[dataCtx.index]);\n}\n\nexport function getViewData(view: ReactElement) {\n return viewDataMap.get(view);\n}\n\nfunction resolveViewBase(\n matched: Matched<Route>[],\n {router, location, signal}: ResolveViewContext<Route>,\n resolveData: (\n dataFetcher: ((ctx: Context<Route>) => any) | undefined,\n ctx: Context<Route>\n ) => any\n) {\n return Promise.all(\n matched.map(({route}, index) => {\n // `search` starts as the degraded input and is upgraded to the\n // schema output before the data fetcher runs below; schema outputs\n // are user-typed(`Route<P, S>`), so the property stays `any` here.\n const ctx: Context<Route, Record<string, string>, any> = {\n matched: matched!,\n params: mergeMatchedParams(matched, index),\n index,\n router,\n location,\n search: parseSearchInput(location.search),\n // The chain's abort signal(navigation-superseded/cancelled) is\n // forwarded to every level's loader; a hand-rolled resolveView\n // context without one still yields a never-aborting signal.\n signal: signal ?? new AbortController().signal\n };\n function resolveComponent(): ComponentType | Promise<ComponentType> {\n if (!route.component) return View;\n const r = route.component(ctx);\n return Promise.resolve(r).then((m) => ('default' in m ? m.default : m));\n }\n\n // The level's search schema runs before its data fetcher: the parsed\n // output replaces the degraded input in `ctx.search`, and a rejected\n // validation fails the level exactly like a data error.\n const resolveDataWithSearch = () =>\n route.search\n ? parseSearch(route.search, location.search).then((search) => {\n ctx.search = search;\n return resolveData(route.data, ctx);\n })\n : resolveData(route.data, ctx);\n\n // A level that fails to resolve (search, data or component) is\n // replaced by its route-level errorComponent when configured;\n // otherwise the error bubbles up to the global errorHandler as before.\n return Promise.all([resolveDataWithSearch(), resolveComponent()]).then(\n ([data, C]) => (\n <DataProvider data={data} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <C />\n </MatchedContext.Provider>\n </DataProvider>\n ),\n (error: Error) => {\n if (!route.errorComponent) throw error;\n return (\n <DataProvider data={undefined} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <route.errorComponent error={error} ctx={ctx} />\n </MatchedContext.Provider>\n </DataProvider>\n );\n }\n );\n })\n ).then((views) =>\n views\n .reverse()\n .reduce((acc, view) => <ViewProvider value={acc}>{view}</ViewProvider>)\n );\n}\n","import {\n ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react';\nimport {\n History,\n createBrowserHistory,\n createHashHistory,\n createMemoryHistory,\n MemoryHistoryOptions\n} from 'history';\nimport type {LoadStatus, Route} from '@@/types';\nimport {LoadingContext, PendingContext, ViewProvider} from '@@/context';\nimport {\n create,\n getCurrentView,\n listen,\n match,\n setOptions\n} from '@native-router/core';\nimport type {Options, ResolveView, RouterInstance} from '@native-router/core';\nimport {splitProps, uniqId} from '@native-router/core/util';\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\nimport defaultResolve from '@@/resolve-view';\n\nconst RouterContext = createContext<RouterInstance<Route, ReactNode> | null>(\n null\n);\n\ntype Props = {\n children?: ReactNode;\n routes: Route[] | Route;\n resolveView?: typeof defaultResolve;\n} & Omit<Options<ReactNode>, 'onLoadingChange'>;\n\n/**\n * Base Router Component.\n * @group Components\n */\nexport function Router({\n router,\n children\n}: {\n children?: ReactNode;\n router: RouterInstance<Route, ReactNode>;\n}) {\n const viewRef = useRef<ReactNode>(getCurrentView(router));\n const subscribe = useCallback(\n (onStoreChange: () => void) =>\n listen(router, (view) => {\n viewRef.current = view;\n onStoreChange();\n }),\n [router]\n );\n const getSnapshot = useCallback(() => viewRef.current, []);\n // `getServerSnapshot` is required by the native implementation when the\n // Router is rendered inside server-rendered content(e.g. resolveServerView).\n const getServerSnapshot = useCallback(() => getCurrentView(router), [router]);\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n // Route-level pending skeleton, only when no previous view is retained\n // (cold start, refresh, re-navigation after an error); in-app navigation\n // keeps the old view by design, the global loading signal already\n // covers that phase. Reading LoadingContext here also re-renders the\n // Router on every loading transition.\n const loading = useContext(LoadingContext);\n const pending =\n view == null && loading?.status === 'pending'\n ? resolvePendingView(router, loading.key)\n : null;\n\n return (\n <RouterContext.Provider value={router}>\n {children === undefined ? (\n (view ?? pending)\n ) : (\n <ViewProvider value={view}>\n <PendingContext.Provider value={pending}>\n {children}\n </PendingContext.Provider>\n </ViewProvider>\n )}\n </RouterContext.Provider>\n );\n}\n\n/**\n * Render the `pendingComponent` of the nearest matched ancestor of the\n * resolving location, walked deepest first(the resolving route's own\n * included). Keyed by the loading episode so a new pending phase remounts\n * the skeleton(stateful shimmer animations restart). Guards may still\n * redirect the resolution away; until then the initially matched chain\n * is the best — and only — answer available.\n */\nfunction resolvePendingView(\n router: RouterInstance<Route, ReactNode>,\n key: number\n) {\n const {resolving} = router;\n const matched = resolving ? match(router, resolving.pathname) : undefined;\n if (!matched) return null;\n for (let i = matched.length - 1; i >= 0; i--) {\n const Pending = matched[i].route.pendingComponent;\n if (Pending) return <Pending key={key} />;\n }\n return null;\n}\n\nexport function createRouter(\n routes: Route | Route[],\n history: History,\n {\n resolveView = defaultResolve,\n ...options\n }: Options<ReactNode> & {resolveView?: ResolveView<Route, ReactNode>} = {}\n): RouterInstance<Route, ReactNode> {\n return create(routes, history, resolveView, options);\n}\n\nfunction useNewRouter(\n {routes, children, ...options}: Props,\n createHistory: () => History\n) {\n const [tracked, rest] = splitProps(options, ['baseUrl', 'currentView']);\n const {baseUrl, currentView} = tracked;\n const [loading, setLoading] = useState<LoadStatus>();\n // Initial options are baked in at creation: the cold-start resolve fires\n // from the subscribe effect(children effects run first) before the\n // setOptions effect below runs, and the default errorHandler would let\n // listen's refresh().catch(noop) swallow a first failure, leaving the\n // view blank forever.\n const router = useMemo(\n () =>\n createRouter(routes, createHistory(), {\n ...options,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n }),\n // Only the tracked options belong to the deps: option updates flow\n // through the setOptions effect below instead of recreating the router.\n [routes, createHistory, baseUrl, currentView]\n );\n\n // Options are refreshed on every commit, so `onLoadingChange` and the\n // callback options always see the latest closure.\n useEffect(() => {\n setOptions(router, {\n ...rest,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n });\n }, [router, rest]);\n\n const r = useMemo(\n () => <Router router={router}>{children}</Router>,\n [router, children]\n );\n\n return <LoadingContext.Provider value={loading}>{r}</LoadingContext.Provider>;\n}\n\n/**\n * History mode Router Component.\n * @group Components\n */\nexport function HistoryRouter(props: Props) {\n return useNewRouter(props, createBrowserHistory);\n}\n\n/**\n * Hash mode Router Component.\n * @group Components\n */\nexport function HashRouter(props: Props) {\n return useNewRouter(props, createHashHistory);\n}\n\n/**\n * Memory mode Router Component.\n * @group Components\n */\nexport function MemoryRouter({\n initialEntries,\n initialIndex,\n ...props\n}: Props & MemoryHistoryOptions) {\n const createHistory = useMemo(\n () => () => createMemoryHistory({initialEntries, initialIndex}),\n [initialEntries, initialIndex]\n );\n return useNewRouter(props, createHistory);\n}\n\n/**\n * Get Router instance.\n * @group Hooks\n * @returns Router Instance\n */\nexport function useRouter() {\n const router = useContext(RouterContext);\n if (!router) {\n throw new Error('useRouter() must be used within a <Router> component');\n }\n return router;\n}\n","import {createBrowserHistory, createMemoryHistory, createPath} from 'history';\nimport {ReactElement, ReactNode} from 'react';\nimport {create, resolve, toLocation} from '@native-router/core';\nimport type {\n HistoryState,\n Location,\n Options,\n RouterInstance\n} from '@native-router/core';\nimport {isString} from '@native-router/core/util';\nimport {Router} from './components/Router';\nimport {\n createHydrateResolveView,\n getViewData,\n resolveViewServer\n} from './resolve-view';\nimport type {Route} from './types';\n\nconst defaultHydrateKey = '_nativeRouterReactSSRData';\n\n/**\n * Serialize the SSR payload for embedding in a script element.\n * `JSON.stringify` does not escape `<`, U+2028 and U+2029,\n * so route data like `</script>` would break out of the script element.\n * @param payload the payload to serialize\n * @returns the escaped JSON string\n */\nfunction serializePayload(payload: {\n data?: any[];\n location: Location;\n index: number;\n}) {\n return JSON.stringify(payload)\n .replace(/</g, '\\\\u003c')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport function resolveServerViewBase(\n router: RouterInstance<Route, ReactNode>,\n location: Location,\n options?: {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n }\n) {\n return resolve<Route, ReactNode>(router, location).then((view) => {\n const data = getViewData(view as ReactElement);\n const index =\n (router.history.location.state as HistoryState | undefined)?.index || 0;\n return (\n <>\n <Router router={router}>{view}</Router>\n <script\n {...options?.scriptAttributes}\n suppressHydrationWarning\n // eslint-disable-next-line @eslint-react/dom-no-dangerously-set-innerhtml -- serialized state for hydration\n dangerouslySetInnerHTML={{\n __html: `window.${\n options?.hydrateKey || defaultHydrateKey\n } = ${serializePayload({data, location, index})};`\n }}\n />\n </>\n );\n });\n}\n\nexport function resolveServerView(\n routes: Route | Route[],\n location: Location | string,\n {\n scriptAttributes,\n hydrateKey,\n ...options\n }: Options<ReactElement> & {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n } = {}\n) {\n const router = create(\n routes,\n createMemoryHistory({initialEntries: [location]}),\n resolveViewServer,\n options\n );\n\n return resolveServerViewBase(\n router,\n isString(location) ? toLocation(router, location) : location,\n {\n scriptAttributes,\n hydrateKey\n }\n );\n}\n\n/**\n * Hydrate the SSR result of {@link resolveServerView} on the client.\n * The router is bound to the browser history(aligned with the index\n * in the SSR payload), so navigation after hydration updates the address bar.\n * @param routes routes config, must match the server side\n * @param options options, `hydrateKey` must match the server side\n * @returns the resolved view and the router instance, for example:\n * `const {view, router} = await hydrate(routes);`\n * `hydrateRoot(root, <Router router={router}>{view}</Router>)`\n * @group Methods\n */\nexport function hydrate(\n routes: Route | Route[],\n options?: Options<ReactElement> & {\n hydrateKey?: string;\n }\n): Promise<{view: ReactNode; router: RouterInstance<Route, ReactNode>}> {\n const {\n data,\n location,\n index = 0\n } = (window as any)[options?.hydrateKey || defaultHydrateKey] as {\n data: any[];\n location: Location;\n index?: number;\n };\n const history = createBrowserHistory();\n history.replace(createPath(history.location), {index});\n const router = create(\n routes,\n history,\n createHydrateResolveView(data),\n options\n );\n return resolve<Route, ReactNode>(router, location).then((view) => ({\n view,\n router\n }));\n}\n"],"mappings":"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"}
|
package/dist/types/context.d.ts
CHANGED
|
@@ -9,9 +9,18 @@ export declare function ViewProvider(props: {
|
|
|
9
9
|
* @see {@link View View Component}
|
|
10
10
|
*/
|
|
11
11
|
export declare function useView(): ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Route-level pending skeleton(`pendingComponent` of the nearest matched
|
|
14
|
+
* ancestor), set by the Router only while a navigation is pending with no
|
|
15
|
+
* previous view to retain(cold start, refresh, re-navigation after an
|
|
16
|
+
* error); `null` otherwise, so in-app navigation keeps the previous view.
|
|
17
|
+
* @see {@link Route.pendingComponent}
|
|
18
|
+
*/
|
|
19
|
+
export declare const PendingContext: import("react").Context<ReactNode>;
|
|
12
20
|
/**
|
|
13
21
|
* Used for route component to render child route component.
|
|
14
|
-
* It just render the return of {@link useView}
|
|
22
|
+
* It just render the return of {@link useView}, falling back to the
|
|
23
|
+
* route-level pending skeleton when the view slot is empty.
|
|
15
24
|
* @group Components
|
|
16
25
|
*/
|
|
17
26
|
export declare function View(): ReactNode;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -3,6 +3,13 @@ import type { BaseRoute, ExtractPathParams, Matched, Location, RouterInstance, S
|
|
|
3
3
|
export type ResolveViewContext<R extends BaseRoute> = {
|
|
4
4
|
router: RouterInstance<R>;
|
|
5
5
|
location: Location;
|
|
6
|
+
/**
|
|
7
|
+
* The navigation chain's abort signal, aborted when this navigation is
|
|
8
|
+
* superseded or cancelled. Optional for custom `resolveView`
|
|
9
|
+
* implementations: core always passes it, but hand-rolled contexts
|
|
10
|
+
* (tests, SSR shims) keep compiling without it.
|
|
11
|
+
*/
|
|
12
|
+
signal?: AbortSignal;
|
|
6
13
|
};
|
|
7
14
|
export type Context<T extends BaseRoute, P = Record<string, string>, S = SearchInput> = {
|
|
8
15
|
matched: Matched<T>[];
|
|
@@ -17,6 +24,14 @@ export type Context<T extends BaseRoute, P = Record<string, string>, S = SearchI
|
|
|
17
24
|
* keys).
|
|
18
25
|
*/
|
|
19
26
|
search: S;
|
|
27
|
+
/**
|
|
28
|
+
* Aborted when this navigation is superseded by a newer one or
|
|
29
|
+
* cancelled(see {@link RouterInstance.cancelAll cancel}). Forward it to
|
|
30
|
+
* the loader's requests — `fetch(url, {signal})` or
|
|
31
|
+
* `useRun({signal: true})` loaders — so a discarded navigation stops
|
|
32
|
+
* consuming the network instead of only having its result dropped.
|
|
33
|
+
*/
|
|
34
|
+
signal: AbortSignal;
|
|
20
35
|
};
|
|
21
36
|
/**
|
|
22
37
|
* Params shape of a route path. Literal patterns get a precise shape via
|
|
@@ -61,6 +76,18 @@ export type Route<P extends string = string, S = any> = Omit<BaseRoute<{
|
|
|
61
76
|
error: Error;
|
|
62
77
|
ctx: Context<Route>;
|
|
63
78
|
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Skeleton rendered while a navigation is pending AND there is no
|
|
81
|
+
* previous view to retain — cold start, refresh, or re-navigation
|
|
82
|
+
* after an error left the view slot blank. The nearest one up the
|
|
83
|
+
* matched chain(deepest first, the route's own included) wins.
|
|
84
|
+
*
|
|
85
|
+
* In-app navigation never renders it: the previous view stays on
|
|
86
|
+
* screen until the new one resolves(the view stack design), the
|
|
87
|
+
* global loading signal(`useLoading`) already covers that phase.
|
|
88
|
+
* Receives no props.
|
|
89
|
+
*/
|
|
90
|
+
pendingComponent?: ComponentType;
|
|
64
91
|
}>, 'path' | 'children'> & {
|
|
65
92
|
/** Path pattern; params of the contexts above are inferred from it. */
|
|
66
93
|
path?: P;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@native-router/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@native-router/core": "^1.
|
|
65
|
+
"@native-router/core": "^1.5.0",
|
|
66
66
|
"history": "^5.3.0",
|
|
67
67
|
"use-sync-external-store": "^1.6.0"
|
|
68
68
|
},
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
"eslint-import-resolver-typescript": "^4.4.5",
|
|
96
96
|
"eslint-plugin-compat": "^7.0.2",
|
|
97
97
|
"eslint-plugin-import-x": "^4.17.1",
|
|
98
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
98
99
|
"eslint-plugin-prettier": "^5.5.6",
|
|
99
100
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
100
101
|
"gh-pages": "^6.3.0",
|
|
@@ -116,7 +117,6 @@
|
|
|
116
117
|
"typescript": "^6.0.3",
|
|
117
118
|
"typescript-eslint": "^8.67.0",
|
|
118
119
|
"vite": "^8.2.2",
|
|
119
|
-
"vitest": "^4.1.11"
|
|
120
|
-
"eslint-plugin-jsx-a11y": "^6.10.2"
|
|
120
|
+
"vitest": "^4.1.11"
|
|
121
121
|
}
|
|
122
122
|
}
|
package/dist/ssr-DLMUHksm.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{createContext as r,useCallback as e,useContext as n,useEffect as t,useMemo as i,useRef as o,useState as a}from"react";import{createBrowserHistory as u,createHashHistory as c,createMemoryHistory as s,createPath as d}from"history";import{Fragment as l,jsx as h,jsxs as f}from"react/jsx-runtime";import{create as m,getCurrentView as v,listen as p,mergeMatchedParams as y,parseSearch as w,parseSearchInput as x,resolve as g,setOptions as P,toLocation as b}from"@native-router/core";import{isString as R,splitProps as A,uniqId as C}from"@native-router/core/util";import{useSyncExternalStore as E}from"use-sync-external-store/shim";var K=r(null);function S(r){/* @__PURE__ */
|
|
2
|
-
return h(K.Provider,{...r})}function k(){return n(K)}function I(){return k()}var L=r([void 0,{}]);function V(){return n(L)}function _(){return V()[1]}function H({children:r,name:e,data:n}){const t=_(),o=i(()=>[n,e?{...t,[e]:n}:t],[n,e,t]);/* @__PURE__ */
|
|
3
|
-
return h(L.Provider,{value:o,children:r})}var M=r(void 0);function U(){return n(M)}function W(r){const[e,n]=V();return r?n[r]:e}var $=r(void 0);function j(){return n($)}function D(r,e){return O(r,e,(r,e)=>r?.(e))}var J=/* @__PURE__ */new WeakMap;function N(r,e){const n=new Array(r.length);return O(r,e,(r,e)=>Promise.resolve(r?.(e)).then(r=>n[e.index]=r)).then(r=>(J.set(r,n),r))}function O(r,{router:e,location:n},t){return Promise.all(r.map(({route:i},o)=>{const a={matched:r,params:y(r,o),index:o,router:e,location:n,search:x(n.search)};return Promise.all([i.search?w(i.search,n.search).then(r=>(a.search=r,t(i.data,a))):t(i.data,a),function(){if(!i.component)return I;const r=i.component(a);return Promise.resolve(r).then(r=>"default"in r?r.default:r)}()]).then(([r,e])=>/* @__PURE__ */h(H,{data:r,name:i.name,children:/* @__PURE__ */h(M.Provider,{value:a,children:/* @__PURE__ */h(e,{})})}),r=>{if(!i.errorComponent)throw r;/* @__PURE__ */
|
|
4
|
-
return h(H,{data:void 0,name:i.name,children:/* @__PURE__ */h(M.Provider,{value:a,children:/* @__PURE__ */h(i.errorComponent,{error:r,ctx:a})})})})})).then(r=>r.reverse().reduce((r,e)=>/* @__PURE__ */h(S,{value:r,children:e})))}var T=r(null);function q({router:r,children:n}){const t=o(v(r)),i=e(e=>p(r,r=>{t.current=r,e()}),[r]),a=e(()=>t.current,[]),u=e(()=>v(r),[r]),c=E(i,a,u);/* @__PURE__ */
|
|
5
|
-
return h(T.Provider,{value:r,children:void 0===n?c:/* @__PURE__ */h(S,{value:c,children:n})})}function z(r,e,{resolveView:n=D,...t}={}){return m(r,e,n,t)}function B({routes:r,children:e,...n},o){const[u,c]=A(n,["baseUrl","currentView"]),{baseUrl:s,currentView:d}=u,[l,f]=a(),m=i(()=>z(r,o(),{...n,onLoadingChange(r){f(r&&{key:C(),status:r})}}),[r,o,s,d]);t(()=>{P(m,{...c,onLoadingChange(r){f(r&&{key:C(),status:r})}})},[m,c]);const v=i(()=>/* @__PURE__ */h(q,{router:m,children:e}),[m,e]);/* @__PURE__ */
|
|
6
|
-
return h($.Provider,{value:l,children:v})}function F(r){return B(r,u)}function G(r){return B(r,c)}function Q({initialEntries:r,initialIndex:e,...n}){return B(n,i(()=>()=>s({initialEntries:r,initialIndex:e}),[r,e]))}function X(){const r=n(T);if(!r)throw new Error("useRouter() must be used within a <Router> component");return r}var Y="_nativeRouterReactSSRData";function Z(r,e,n){return g(r,e).then(t=>{const i=function(r){return J.get(r)}(t),o=r.history.location.state?.index||0;/* @__PURE__ */
|
|
7
|
-
return f(l,{children:[/* @__PURE__ */h(q,{router:r,children:t}),/* @__PURE__ */h("script",{...n?.scriptAttributes,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`window.${n?.hydrateKey||Y} = ${a={data:i,location:e,index:o},JSON.stringify(a).replace(/</g,"\\u003c").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")};`}})]});var a})}function rr(r,e,{scriptAttributes:n,hydrateKey:t,...i}={}){const o=m(r,s({initialEntries:[e]}),N,i);return Z(o,R(e)?b(o,e):e,{scriptAttributes:n,hydrateKey:t})}function er(r,e){const{data:n,location:t,index:i=0}=window[e?.hydrateKey||Y],o=u();o.replace(d(o.location),{index:i});const a=m(r,o,function(r){return(e,n)=>O(e,n,(e,n)=>r[n.index])}(n),e);return g(a,t).then(r=>({view:r,router:a}))}export{Q as a,X as c,W as d,j as f,k as h,F as i,D as l,_ as m,rr as n,q as o,U as p,G as r,z as s,er as t,I as u};
|
|
8
|
-
//# sourceMappingURL=ssr-DLMUHksm.js.map
|
package/dist/ssr-DLMUHksm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-DLMUHksm.js","names":[],"sources":["../src/context.tsx","../src/resolve-view.tsx","../src/components/Router.tsx","../src/ssr.tsx"],"sourcesContent":["import {createContext, ReactNode, useContext, useMemo} from 'react';\nimport type {Context, LoadStatus, Route} from './types';\n\nconst ViewContext = createContext<ReactNode>(null);\n\nexport function ViewProvider(props: {children: ReactNode; value: ReactNode}) {\n return <ViewContext.Provider {...props} />;\n}\n\n/**\n * @group Hooks\n * @see {@link View View Component}\n */\nexport function useView() {\n return useContext(ViewContext);\n}\n\n/**\n * Used for route component to render child route component.\n * It just render the return of {@link useView}\n * @group Components\n */\nexport function View() {\n return useView();\n}\n\nconst DataContext = createContext<[any, Record<string, any>]>([undefined, {}]);\n\nfunction useDataContext() {\n return useContext(DataContext);\n}\n\n/**\n * Get the named data map of the resolved route levels: an object keyed by\n * each ancestor's `name`, holding its resolved `data`. The current level\n * is included only when it declares a `name`.\n *\n * Give the generic the expected map shape to read values type-safely:\n * `useNamedData<{user: User}>()`.\n * @group Hooks\n */\nexport function useNamedData<T = Record<string, unknown>>() {\n return useDataContext()[1] as T;\n}\n\nexport function DataProvider({\n children,\n name,\n data\n}: {\n children: ReactNode;\n data: any;\n name?: string;\n}) {\n const namedData = useNamedData();\n const value = useMemo(\n () => [data, name ? {...namedData, [name]: data} : namedData] as [any, any],\n [data, name, namedData]\n );\n return <DataContext.Provider value={value}>{children}</DataContext.Provider>;\n}\n\nexport const MatchedContext = createContext<Context<Route> | undefined>(\n undefined\n);\n\n/**\n * @group Hooks\n */\nexport function useMatched() {\n return useContext(MatchedContext)!;\n}\n\n/**\n * Get the resolved `data` of the current route level, or the named data\n * of an ancestor level when `name` is given.\n *\n * Give the generic the expected data type to read it type-safely without\n * a cast: `useData<Article>()` → `Article | undefined`.\n * @group Hooks\n */\nexport function useData<T = unknown>(name?: string): T | undefined {\n const [data, namedData] = useDataContext();\n return (name ? namedData[name] : data) as T | undefined;\n}\n\nexport const LoadingContext = createContext<LoadStatus | undefined>(undefined);\n\n/**\n * @group Hooks\n */\nexport function useLoading() {\n return useContext(LoadingContext);\n}\n","import type {ComponentType, ReactElement} from 'react';\nimport type {Context, ResolveViewContext, Route} from '@@/types';\nimport {\n mergeMatchedParams,\n parseSearch,\n parseSearchInput\n} from '@native-router/core';\nimport type {Matched} from '@native-router/core';\nimport {DataProvider, MatchedContext, View, ViewProvider} from './context';\n\n/**\n * The default implementation of resolve view\n * @param matched the matched result\n * @param viewContext resolved view context\n * @returns the resolve view\n * @see {@link create router->create}\n */\nexport default function resolveView(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n return resolveViewBase(matched, ctx, (data, dataCtx) => data?.(dataCtx));\n}\n\nconst viewDataMap = new WeakMap<ReactElement, any[]>();\n\nexport function resolveViewServer(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n const dataResults = new Array(matched.length);\n return resolveViewBase(matched, ctx, (data, dataCtx) =>\n Promise.resolve(data?.(dataCtx)).then(\n (result) => (dataResults[dataCtx.index] = result)\n )\n ).then((view) => {\n viewDataMap.set(view, dataResults);\n return view;\n });\n}\n\nexport function createHydrateResolveView(data: any[]) {\n return (matched: Matched<Route>[], ctx: ResolveViewContext<Route>) =>\n resolveViewBase(matched, ctx, (_, dataCtx) => data[dataCtx.index]);\n}\n\nexport function getViewData(view: ReactElement) {\n return viewDataMap.get(view);\n}\n\nfunction resolveViewBase(\n matched: Matched<Route>[],\n {router, location}: ResolveViewContext<Route>,\n resolveData: (\n dataFetcher: ((ctx: Context<Route>) => any) | undefined,\n ctx: Context<Route>\n ) => any\n) {\n return Promise.all(\n matched.map(({route}, index) => {\n // `search` starts as the degraded input and is upgraded to the\n // schema output before the data fetcher runs below; schema outputs\n // are user-typed(`Route<P, S>`), so the property stays `any` here.\n const ctx: Context<Route, Record<string, string>, any> = {\n matched: matched!,\n params: mergeMatchedParams(matched, index),\n index,\n router,\n location,\n search: parseSearchInput(location.search)\n };\n function resolveComponent(): ComponentType | Promise<ComponentType> {\n if (!route.component) return View;\n const r = route.component(ctx);\n return Promise.resolve(r).then((m) => ('default' in m ? m.default : m));\n }\n\n // The level's search schema runs before its data fetcher: the parsed\n // output replaces the degraded input in `ctx.search`, and a rejected\n // validation fails the level exactly like a data error.\n const resolveDataWithSearch = () =>\n route.search\n ? parseSearch(route.search, location.search).then((search) => {\n ctx.search = search;\n return resolveData(route.data, ctx);\n })\n : resolveData(route.data, ctx);\n\n // A level that fails to resolve (search, data or component) is\n // replaced by its route-level errorComponent when configured;\n // otherwise the error bubbles up to the global errorHandler as before.\n return Promise.all([resolveDataWithSearch(), resolveComponent()]).then(\n ([data, C]) => (\n <DataProvider data={data} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <C />\n </MatchedContext.Provider>\n </DataProvider>\n ),\n (error: Error) => {\n if (!route.errorComponent) throw error;\n return (\n <DataProvider data={undefined} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <route.errorComponent error={error} ctx={ctx} />\n </MatchedContext.Provider>\n </DataProvider>\n );\n }\n );\n })\n ).then((views) =>\n views\n .reverse()\n .reduce((acc, view) => <ViewProvider value={acc}>{view}</ViewProvider>)\n );\n}\n","import {\n ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react';\nimport {\n History,\n createBrowserHistory,\n createHashHistory,\n createMemoryHistory,\n MemoryHistoryOptions\n} from 'history';\nimport type {LoadStatus, Route} from '@@/types';\nimport {LoadingContext, ViewProvider} from '@@/context';\nimport {create, getCurrentView, listen, setOptions} from '@native-router/core';\nimport type {Options, ResolveView, RouterInstance} from '@native-router/core';\nimport {splitProps, uniqId} from '@native-router/core/util';\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\nimport defaultResolve from '@@/resolve-view';\n\nconst RouterContext = createContext<RouterInstance<Route, ReactNode> | null>(\n null\n);\n\ntype Props = {\n children?: ReactNode;\n routes: Route[] | Route;\n resolveView?: typeof defaultResolve;\n} & Omit<Options<ReactNode>, 'onLoadingChange'>;\n\n/**\n * Base Router Component.\n * @group Components\n */\nexport function Router({\n router,\n children\n}: {\n children?: ReactNode;\n router: RouterInstance<Route, ReactNode>;\n}) {\n const viewRef = useRef<ReactNode>(getCurrentView(router));\n const subscribe = useCallback(\n (onStoreChange: () => void) =>\n listen(router, (view) => {\n viewRef.current = view;\n onStoreChange();\n }),\n [router]\n );\n const getSnapshot = useCallback(() => viewRef.current, []);\n // `getServerSnapshot` is required by the native implementation when the\n // Router is rendered inside server-rendered content(e.g. resolveServerView).\n const getServerSnapshot = useCallback(() => getCurrentView(router), [router]);\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n return (\n <RouterContext.Provider value={router}>\n {children === undefined ? (\n view\n ) : (\n <ViewProvider value={view}>{children}</ViewProvider>\n )}\n </RouterContext.Provider>\n );\n}\n\nexport function createRouter(\n routes: Route | Route[],\n history: History,\n {\n resolveView = defaultResolve,\n ...options\n }: Options<ReactNode> & {resolveView?: ResolveView<Route, ReactNode>} = {}\n): RouterInstance<Route, ReactNode> {\n return create(routes, history, resolveView, options);\n}\n\nfunction useNewRouter(\n {routes, children, ...options}: Props,\n createHistory: () => History\n) {\n const [tracked, rest] = splitProps(options, ['baseUrl', 'currentView']);\n const {baseUrl, currentView} = tracked;\n const [loading, setLoading] = useState<LoadStatus>();\n // Initial options are baked in at creation: the cold-start resolve fires\n // from the subscribe effect(children effects run first) before the\n // setOptions effect below runs, and the default errorHandler would let\n // listen's refresh().catch(noop) swallow a first failure, leaving the\n // view blank forever.\n const router = useMemo(\n () =>\n createRouter(routes, createHistory(), {\n ...options,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n }),\n // Only the tracked options belong to the deps: option updates flow\n // through the setOptions effect below instead of recreating the router.\n [routes, createHistory, baseUrl, currentView]\n );\n\n // Options are refreshed on every commit, so `onLoadingChange` and the\n // callback options always see the latest closure.\n useEffect(() => {\n setOptions(router, {\n ...rest,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n });\n }, [router, rest]);\n\n const r = useMemo(\n () => <Router router={router}>{children}</Router>,\n [router, children]\n );\n\n return <LoadingContext.Provider value={loading}>{r}</LoadingContext.Provider>;\n}\n\n/**\n * History mode Router Component.\n * @group Components\n */\nexport function HistoryRouter(props: Props) {\n return useNewRouter(props, createBrowserHistory);\n}\n\n/**\n * Hash mode Router Component.\n * @group Components\n */\nexport function HashRouter(props: Props) {\n return useNewRouter(props, createHashHistory);\n}\n\n/**\n * Memory mode Router Component.\n * @group Components\n */\nexport function MemoryRouter({\n initialEntries,\n initialIndex,\n ...props\n}: Props & MemoryHistoryOptions) {\n const createHistory = useMemo(\n () => () => createMemoryHistory({initialEntries, initialIndex}),\n [initialEntries, initialIndex]\n );\n return useNewRouter(props, createHistory);\n}\n\n/**\n * Get Router instance.\n * @group Hooks\n * @returns Router Instance\n */\nexport function useRouter() {\n const router = useContext(RouterContext);\n if (!router) {\n throw new Error('useRouter() must be used within a <Router> component');\n }\n return router;\n}\n","import {createBrowserHistory, createMemoryHistory, createPath} from 'history';\nimport {ReactElement, ReactNode} from 'react';\nimport {create, resolve, toLocation} from '@native-router/core';\nimport type {\n HistoryState,\n Location,\n Options,\n RouterInstance\n} from '@native-router/core';\nimport {isString} from '@native-router/core/util';\nimport {Router} from './components/Router';\nimport {\n createHydrateResolveView,\n getViewData,\n resolveViewServer\n} from './resolve-view';\nimport type {Route} from './types';\n\nconst defaultHydrateKey = '_nativeRouterReactSSRData';\n\n/**\n * Serialize the SSR payload for embedding in a script element.\n * `JSON.stringify` does not escape `<`, U+2028 and U+2029,\n * so route data like `</script>` would break out of the script element.\n * @param payload the payload to serialize\n * @returns the escaped JSON string\n */\nfunction serializePayload(payload: {\n data?: any[];\n location: Location;\n index: number;\n}) {\n return JSON.stringify(payload)\n .replace(/</g, '\\\\u003c')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport function resolveServerViewBase(\n router: RouterInstance<Route, ReactNode>,\n location: Location,\n options?: {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n }\n) {\n return resolve<Route, ReactNode>(router, location).then((view) => {\n const data = getViewData(view as ReactElement);\n const index =\n (router.history.location.state as HistoryState | undefined)?.index || 0;\n return (\n <>\n <Router router={router}>{view}</Router>\n <script\n {...options?.scriptAttributes}\n suppressHydrationWarning\n // eslint-disable-next-line @eslint-react/dom-no-dangerously-set-innerhtml -- serialized state for hydration\n dangerouslySetInnerHTML={{\n __html: `window.${\n options?.hydrateKey || defaultHydrateKey\n } = ${serializePayload({data, location, index})};`\n }}\n />\n </>\n );\n });\n}\n\nexport function resolveServerView(\n routes: Route | Route[],\n location: Location | string,\n {\n scriptAttributes,\n hydrateKey,\n ...options\n }: Options<ReactElement> & {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n } = {}\n) {\n const router = create(\n routes,\n createMemoryHistory({initialEntries: [location]}),\n resolveViewServer,\n options\n );\n\n return resolveServerViewBase(\n router,\n isString(location) ? toLocation(router, location) : location,\n {\n scriptAttributes,\n hydrateKey\n }\n );\n}\n\n/**\n * Hydrate the SSR result of {@link resolveServerView} on the client.\n * The router is bound to the browser history(aligned with the index\n * in the SSR payload), so navigation after hydration updates the address bar.\n * @param routes routes config, must match the server side\n * @param options options, `hydrateKey` must match the server side\n * @returns the resolved view and the router instance, for example:\n * `const {view, router} = await hydrate(routes);`\n * `hydrateRoot(root, <Router router={router}>{view}</Router>)`\n * @group Methods\n */\nexport function hydrate(\n routes: Route | Route[],\n options?: Options<ReactElement> & {\n hydrateKey?: string;\n }\n): Promise<{view: ReactNode; router: RouterInstance<Route, ReactNode>}> {\n const {\n data,\n location,\n index = 0\n } = (window as any)[options?.hydrateKey || defaultHydrateKey] as {\n data: any[];\n location: Location;\n index?: number;\n };\n const history = createBrowserHistory();\n history.replace(createPath(history.location), {index});\n const router = create(\n routes,\n history,\n createHydrateResolveView(data),\n options\n );\n return resolve<Route, ReactNode>(router, location).then((view) => ({\n view,\n router\n }));\n}\n"],"mappings":"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"}
|
package/dist/ssr-HDpHA-cn.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
let e=require("react"),r=require("history"),t=require("react/jsx-runtime"),n=require("@native-router/core"),o=require("@native-router/core/util"),u=require("use-sync-external-store/shim");var i=(0,e.createContext)(null);function a(e){return(0,t.jsx)(i.Provider,{...e})}function c(){return(0,e.useContext)(i)}function s(){return c()}var l=(0,e.createContext)([void 0,{}]);function d(){return(0,e.useContext)(l)}function f(){return d()[1]}function p({children:r,name:n,data:o}){const u=f(),i=(0,e.useMemo)(()=>[o,n?{...u,[n]:o}:u],[o,n,u]);return(0,t.jsx)(l.Provider,{value:i,children:r})}var x=(0,e.createContext)(void 0);function h(){return(0,e.useContext)(x)}function m(e){const[r,t]=d();return e?t[e]:r}var y=(0,e.createContext)(void 0);function b(){return(0,e.useContext)(y)}function v(e,r){return P(e,r,(e,r)=>e?.(r))}var g=new WeakMap;function j(e,r){const t=new Array(e.length);return P(e,r,(e,r)=>Promise.resolve(e?.(r)).then(e=>t[r.index]=e)).then(e=>(g.set(e,t),e))}function P(e,{router:r,location:o},u){return Promise.all(e.map(({route:i},a)=>{const c={matched:e,params:(0,n.mergeMatchedParams)(e,a),index:a,router:r,location:o,search:(0,n.parseSearchInput)(o.search)};return Promise.all([i.search?(0,n.parseSearch)(i.search,o.search).then(e=>(c.search=e,u(i.data,c))):u(i.data,c),function(){if(!i.component)return s;const e=i.component(c);return Promise.resolve(e).then(e=>"default"in e?e.default:e)}()]).then(([e,r])=>(0,t.jsx)(p,{data:e,name:i.name,children:(0,t.jsx)(x.Provider,{value:c,children:(0,t.jsx)(r,{})})}),e=>{if(!i.errorComponent)throw e;return(0,t.jsx)(p,{data:void 0,name:i.name,children:(0,t.jsx)(x.Provider,{value:c,children:(0,t.jsx)(i.errorComponent,{error:e,ctx:c})})})})})).then(e=>e.reverse().reduce((e,r)=>(0,t.jsx)(a,{value:e,children:r})))}var w=(0,e.createContext)(null);function C({router:r,children:o}){const i=(0,e.useRef)((0,n.getCurrentView)(r)),c=(0,e.useCallback)(e=>(0,n.listen)(r,r=>{i.current=r,e()}),[r]),s=(0,e.useCallback)(()=>i.current,[]),l=(0,e.useCallback)(()=>(0,n.getCurrentView)(r),[r]),d=(0,u.useSyncExternalStore)(c,s,l);return(0,t.jsx)(w.Provider,{value:r,children:void 0===o?d:(0,t.jsx)(a,{value:d,children:o})})}function O(e,r,{resolveView:t=v,...o}={}){return(0,n.create)(e,r,t,o)}function R({routes:r,children:u,...i},a){const[c,s]=(0,o.splitProps)(i,["baseUrl","currentView"]),{baseUrl:l,currentView:d}=c,[f,p]=(0,e.useState)(),x=(0,e.useMemo)(()=>O(r,a(),{...i,onLoadingChange(e){p(e&&{key:(0,o.uniqId)(),status:e})}}),[r,a,l,d]);(0,e.useEffect)(()=>{(0,n.setOptions)(x,{...s,onLoadingChange(e){p(e&&{key:(0,o.uniqId)(),status:e})}})},[x,s]);const h=(0,e.useMemo)(()=>(0,t.jsx)(C,{router:x,children:u}),[x,u]);return(0,t.jsx)(y.Provider,{value:f,children:h})}function M(e){return R(e,r.createBrowserHistory)}function S(e){return R(e,r.createHashHistory)}function H({initialEntries:t,initialIndex:n,...o}){return R(o,(0,e.useMemo)(()=>()=>(0,r.createMemoryHistory)({initialEntries:t,initialIndex:n}),[t,n]))}function V(){const r=(0,e.useContext)(w);if(!r)throw new Error("useRouter() must be used within a <Router> component");return r}var q="_nativeRouterReactSSRData";function k(e,r,o){return(0,n.resolve)(e,r).then(n=>{const u=function(e){return g.get(e)}(n),i=e.history.location.state?.index||0;return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(C,{router:e,children:n}),(0,t.jsx)("script",{...o?.scriptAttributes,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`window.${o?.hydrateKey||q} = ${a={data:u,location:r,index:i},JSON.stringify(a).replace(/</g,"\\u003c").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")};`}})]});var a})}function E(e,t,{scriptAttributes:u,hydrateKey:i,...a}={}){const c=(0,n.create)(e,(0,r.createMemoryHistory)({initialEntries:[t]}),j,a);return k(c,(0,o.isString)(t)?(0,n.toLocation)(c,t):t,{scriptAttributes:u,hydrateKey:i})}function I(e,t){const{data:o,location:u,index:i=0}=window[t?.hydrateKey||q],a=(0,r.createBrowserHistory)();a.replace((0,r.createPath)(a.location),{index:i});const c=(0,n.create)(e,a,function(e){return(r,t)=>P(r,t,(r,t)=>e[t.index])}(o),t);return(0,n.resolve)(c,u).then(e=>({view:e,router:c}))}Object.defineProperty(exports,"HashRouter",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"HistoryRouter",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"MemoryRouter",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"Router",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"View",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"createRouter",{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,"hydrate",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"resolveServerView",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"resolveView",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"useData",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"useLoading",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"useMatched",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"useNamedData",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"useRouter",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"useView",{enumerable:!0,get:function(){return c}});
|
|
2
|
-
//# sourceMappingURL=ssr-HDpHA-cn.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-HDpHA-cn.cjs","names":[],"sources":["../src/context.tsx","../src/resolve-view.tsx","../src/components/Router.tsx","../src/ssr.tsx"],"sourcesContent":["import {createContext, ReactNode, useContext, useMemo} from 'react';\nimport type {Context, LoadStatus, Route} from './types';\n\nconst ViewContext = createContext<ReactNode>(null);\n\nexport function ViewProvider(props: {children: ReactNode; value: ReactNode}) {\n return <ViewContext.Provider {...props} />;\n}\n\n/**\n * @group Hooks\n * @see {@link View View Component}\n */\nexport function useView() {\n return useContext(ViewContext);\n}\n\n/**\n * Used for route component to render child route component.\n * It just render the return of {@link useView}\n * @group Components\n */\nexport function View() {\n return useView();\n}\n\nconst DataContext = createContext<[any, Record<string, any>]>([undefined, {}]);\n\nfunction useDataContext() {\n return useContext(DataContext);\n}\n\n/**\n * Get the named data map of the resolved route levels: an object keyed by\n * each ancestor's `name`, holding its resolved `data`. The current level\n * is included only when it declares a `name`.\n *\n * Give the generic the expected map shape to read values type-safely:\n * `useNamedData<{user: User}>()`.\n * @group Hooks\n */\nexport function useNamedData<T = Record<string, unknown>>() {\n return useDataContext()[1] as T;\n}\n\nexport function DataProvider({\n children,\n name,\n data\n}: {\n children: ReactNode;\n data: any;\n name?: string;\n}) {\n const namedData = useNamedData();\n const value = useMemo(\n () => [data, name ? {...namedData, [name]: data} : namedData] as [any, any],\n [data, name, namedData]\n );\n return <DataContext.Provider value={value}>{children}</DataContext.Provider>;\n}\n\nexport const MatchedContext = createContext<Context<Route> | undefined>(\n undefined\n);\n\n/**\n * @group Hooks\n */\nexport function useMatched() {\n return useContext(MatchedContext)!;\n}\n\n/**\n * Get the resolved `data` of the current route level, or the named data\n * of an ancestor level when `name` is given.\n *\n * Give the generic the expected data type to read it type-safely without\n * a cast: `useData<Article>()` → `Article | undefined`.\n * @group Hooks\n */\nexport function useData<T = unknown>(name?: string): T | undefined {\n const [data, namedData] = useDataContext();\n return (name ? namedData[name] : data) as T | undefined;\n}\n\nexport const LoadingContext = createContext<LoadStatus | undefined>(undefined);\n\n/**\n * @group Hooks\n */\nexport function useLoading() {\n return useContext(LoadingContext);\n}\n","import type {ComponentType, ReactElement} from 'react';\nimport type {Context, ResolveViewContext, Route} from '@@/types';\nimport {\n mergeMatchedParams,\n parseSearch,\n parseSearchInput\n} from '@native-router/core';\nimport type {Matched} from '@native-router/core';\nimport {DataProvider, MatchedContext, View, ViewProvider} from './context';\n\n/**\n * The default implementation of resolve view\n * @param matched the matched result\n * @param viewContext resolved view context\n * @returns the resolve view\n * @see {@link create router->create}\n */\nexport default function resolveView(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n return resolveViewBase(matched, ctx, (data, dataCtx) => data?.(dataCtx));\n}\n\nconst viewDataMap = new WeakMap<ReactElement, any[]>();\n\nexport function resolveViewServer(\n matched: Matched<Route>[],\n ctx: ResolveViewContext<Route>\n) {\n const dataResults = new Array(matched.length);\n return resolveViewBase(matched, ctx, (data, dataCtx) =>\n Promise.resolve(data?.(dataCtx)).then(\n (result) => (dataResults[dataCtx.index] = result)\n )\n ).then((view) => {\n viewDataMap.set(view, dataResults);\n return view;\n });\n}\n\nexport function createHydrateResolveView(data: any[]) {\n return (matched: Matched<Route>[], ctx: ResolveViewContext<Route>) =>\n resolveViewBase(matched, ctx, (_, dataCtx) => data[dataCtx.index]);\n}\n\nexport function getViewData(view: ReactElement) {\n return viewDataMap.get(view);\n}\n\nfunction resolveViewBase(\n matched: Matched<Route>[],\n {router, location}: ResolveViewContext<Route>,\n resolveData: (\n dataFetcher: ((ctx: Context<Route>) => any) | undefined,\n ctx: Context<Route>\n ) => any\n) {\n return Promise.all(\n matched.map(({route}, index) => {\n // `search` starts as the degraded input and is upgraded to the\n // schema output before the data fetcher runs below; schema outputs\n // are user-typed(`Route<P, S>`), so the property stays `any` here.\n const ctx: Context<Route, Record<string, string>, any> = {\n matched: matched!,\n params: mergeMatchedParams(matched, index),\n index,\n router,\n location,\n search: parseSearchInput(location.search)\n };\n function resolveComponent(): ComponentType | Promise<ComponentType> {\n if (!route.component) return View;\n const r = route.component(ctx);\n return Promise.resolve(r).then((m) => ('default' in m ? m.default : m));\n }\n\n // The level's search schema runs before its data fetcher: the parsed\n // output replaces the degraded input in `ctx.search`, and a rejected\n // validation fails the level exactly like a data error.\n const resolveDataWithSearch = () =>\n route.search\n ? parseSearch(route.search, location.search).then((search) => {\n ctx.search = search;\n return resolveData(route.data, ctx);\n })\n : resolveData(route.data, ctx);\n\n // A level that fails to resolve (search, data or component) is\n // replaced by its route-level errorComponent when configured;\n // otherwise the error bubbles up to the global errorHandler as before.\n return Promise.all([resolveDataWithSearch(), resolveComponent()]).then(\n ([data, C]) => (\n <DataProvider data={data} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <C />\n </MatchedContext.Provider>\n </DataProvider>\n ),\n (error: Error) => {\n if (!route.errorComponent) throw error;\n return (\n <DataProvider data={undefined} name={route.name}>\n <MatchedContext.Provider value={ctx}>\n <route.errorComponent error={error} ctx={ctx} />\n </MatchedContext.Provider>\n </DataProvider>\n );\n }\n );\n })\n ).then((views) =>\n views\n .reverse()\n .reduce((acc, view) => <ViewProvider value={acc}>{view}</ViewProvider>)\n );\n}\n","import {\n ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react';\nimport {\n History,\n createBrowserHistory,\n createHashHistory,\n createMemoryHistory,\n MemoryHistoryOptions\n} from 'history';\nimport type {LoadStatus, Route} from '@@/types';\nimport {LoadingContext, ViewProvider} from '@@/context';\nimport {create, getCurrentView, listen, setOptions} from '@native-router/core';\nimport type {Options, ResolveView, RouterInstance} from '@native-router/core';\nimport {splitProps, uniqId} from '@native-router/core/util';\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\nimport defaultResolve from '@@/resolve-view';\n\nconst RouterContext = createContext<RouterInstance<Route, ReactNode> | null>(\n null\n);\n\ntype Props = {\n children?: ReactNode;\n routes: Route[] | Route;\n resolveView?: typeof defaultResolve;\n} & Omit<Options<ReactNode>, 'onLoadingChange'>;\n\n/**\n * Base Router Component.\n * @group Components\n */\nexport function Router({\n router,\n children\n}: {\n children?: ReactNode;\n router: RouterInstance<Route, ReactNode>;\n}) {\n const viewRef = useRef<ReactNode>(getCurrentView(router));\n const subscribe = useCallback(\n (onStoreChange: () => void) =>\n listen(router, (view) => {\n viewRef.current = view;\n onStoreChange();\n }),\n [router]\n );\n const getSnapshot = useCallback(() => viewRef.current, []);\n // `getServerSnapshot` is required by the native implementation when the\n // Router is rendered inside server-rendered content(e.g. resolveServerView).\n const getServerSnapshot = useCallback(() => getCurrentView(router), [router]);\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n return (\n <RouterContext.Provider value={router}>\n {children === undefined ? (\n view\n ) : (\n <ViewProvider value={view}>{children}</ViewProvider>\n )}\n </RouterContext.Provider>\n );\n}\n\nexport function createRouter(\n routes: Route | Route[],\n history: History,\n {\n resolveView = defaultResolve,\n ...options\n }: Options<ReactNode> & {resolveView?: ResolveView<Route, ReactNode>} = {}\n): RouterInstance<Route, ReactNode> {\n return create(routes, history, resolveView, options);\n}\n\nfunction useNewRouter(\n {routes, children, ...options}: Props,\n createHistory: () => History\n) {\n const [tracked, rest] = splitProps(options, ['baseUrl', 'currentView']);\n const {baseUrl, currentView} = tracked;\n const [loading, setLoading] = useState<LoadStatus>();\n // Initial options are baked in at creation: the cold-start resolve fires\n // from the subscribe effect(children effects run first) before the\n // setOptions effect below runs, and the default errorHandler would let\n // listen's refresh().catch(noop) swallow a first failure, leaving the\n // view blank forever.\n const router = useMemo(\n () =>\n createRouter(routes, createHistory(), {\n ...options,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n }),\n // Only the tracked options belong to the deps: option updates flow\n // through the setOptions effect below instead of recreating the router.\n [routes, createHistory, baseUrl, currentView]\n );\n\n // Options are refreshed on every commit, so `onLoadingChange` and the\n // callback options always see the latest closure.\n useEffect(() => {\n setOptions(router, {\n ...rest,\n onLoadingChange(status) {\n setLoading(status && {key: uniqId(), status});\n }\n });\n }, [router, rest]);\n\n const r = useMemo(\n () => <Router router={router}>{children}</Router>,\n [router, children]\n );\n\n return <LoadingContext.Provider value={loading}>{r}</LoadingContext.Provider>;\n}\n\n/**\n * History mode Router Component.\n * @group Components\n */\nexport function HistoryRouter(props: Props) {\n return useNewRouter(props, createBrowserHistory);\n}\n\n/**\n * Hash mode Router Component.\n * @group Components\n */\nexport function HashRouter(props: Props) {\n return useNewRouter(props, createHashHistory);\n}\n\n/**\n * Memory mode Router Component.\n * @group Components\n */\nexport function MemoryRouter({\n initialEntries,\n initialIndex,\n ...props\n}: Props & MemoryHistoryOptions) {\n const createHistory = useMemo(\n () => () => createMemoryHistory({initialEntries, initialIndex}),\n [initialEntries, initialIndex]\n );\n return useNewRouter(props, createHistory);\n}\n\n/**\n * Get Router instance.\n * @group Hooks\n * @returns Router Instance\n */\nexport function useRouter() {\n const router = useContext(RouterContext);\n if (!router) {\n throw new Error('useRouter() must be used within a <Router> component');\n }\n return router;\n}\n","import {createBrowserHistory, createMemoryHistory, createPath} from 'history';\nimport {ReactElement, ReactNode} from 'react';\nimport {create, resolve, toLocation} from '@native-router/core';\nimport type {\n HistoryState,\n Location,\n Options,\n RouterInstance\n} from '@native-router/core';\nimport {isString} from '@native-router/core/util';\nimport {Router} from './components/Router';\nimport {\n createHydrateResolveView,\n getViewData,\n resolveViewServer\n} from './resolve-view';\nimport type {Route} from './types';\n\nconst defaultHydrateKey = '_nativeRouterReactSSRData';\n\n/**\n * Serialize the SSR payload for embedding in a script element.\n * `JSON.stringify` does not escape `<`, U+2028 and U+2029,\n * so route data like `</script>` would break out of the script element.\n * @param payload the payload to serialize\n * @returns the escaped JSON string\n */\nfunction serializePayload(payload: {\n data?: any[];\n location: Location;\n index: number;\n}) {\n return JSON.stringify(payload)\n .replace(/</g, '\\\\u003c')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nexport function resolveServerViewBase(\n router: RouterInstance<Route, ReactNode>,\n location: Location,\n options?: {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n }\n) {\n return resolve<Route, ReactNode>(router, location).then((view) => {\n const data = getViewData(view as ReactElement);\n const index =\n (router.history.location.state as HistoryState | undefined)?.index || 0;\n return (\n <>\n <Router router={router}>{view}</Router>\n <script\n {...options?.scriptAttributes}\n suppressHydrationWarning\n // eslint-disable-next-line @eslint-react/dom-no-dangerously-set-innerhtml -- serialized state for hydration\n dangerouslySetInnerHTML={{\n __html: `window.${\n options?.hydrateKey || defaultHydrateKey\n } = ${serializePayload({data, location, index})};`\n }}\n />\n </>\n );\n });\n}\n\nexport function resolveServerView(\n routes: Route | Route[],\n location: Location | string,\n {\n scriptAttributes,\n hydrateKey,\n ...options\n }: Options<ReactElement> & {\n scriptAttributes?: Record<string, string>;\n hydrateKey?: string;\n } = {}\n) {\n const router = create(\n routes,\n createMemoryHistory({initialEntries: [location]}),\n resolveViewServer,\n options\n );\n\n return resolveServerViewBase(\n router,\n isString(location) ? toLocation(router, location) : location,\n {\n scriptAttributes,\n hydrateKey\n }\n );\n}\n\n/**\n * Hydrate the SSR result of {@link resolveServerView} on the client.\n * The router is bound to the browser history(aligned with the index\n * in the SSR payload), so navigation after hydration updates the address bar.\n * @param routes routes config, must match the server side\n * @param options options, `hydrateKey` must match the server side\n * @returns the resolved view and the router instance, for example:\n * `const {view, router} = await hydrate(routes);`\n * `hydrateRoot(root, <Router router={router}>{view}</Router>)`\n * @group Methods\n */\nexport function hydrate(\n routes: Route | Route[],\n options?: Options<ReactElement> & {\n hydrateKey?: string;\n }\n): Promise<{view: ReactNode; router: RouterInstance<Route, ReactNode>}> {\n const {\n data,\n location,\n index = 0\n } = (window as any)[options?.hydrateKey || defaultHydrateKey] as {\n data: any[];\n location: Location;\n index?: number;\n };\n const history = createBrowserHistory();\n history.replace(createPath(history.location), {index});\n const router = create(\n routes,\n history,\n createHydrateResolveView(data),\n options\n );\n return resolve<Route, ReactNode>(router, location).then((view) => ({\n view,\n router\n }));\n}\n"],"mappings":"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"}
|