clear-react-router 1.0.0 → 1.0.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/dist/components/Link.d.ts +11 -0
- package/dist/components/Router.d.ts +7 -0
- package/dist/context/RouterContext.d.ts +19 -0
- package/dist/hooks/useBeforeUnload.d.ts +1 -0
- package/dist/hooks/useBlocker.d.ts +8 -0
- package/dist/hooks/useHandleNavigation.d.ts +13 -0
- package/dist/hooks/useLatest.d.ts +1 -0
- package/dist/hooks/useLoader.d.ts +8 -0
- package/dist/hooks/useLoaderState.d.ts +1 -0
- package/dist/hooks/useLocation.d.ts +1 -0
- package/dist/hooks/useNavigate.d.ts +2 -0
- package/dist/hooks/useParams.d.ts +1 -0
- package/dist/hooks/useRouterContext.d.ts +4 -0
- package/dist/hooks/useServiceContext.d.ts +3 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/provider/RouterProvider.d.ts +7 -0
- package/dist/types/global.d.ts +34 -0
- package/dist/utils/createLazyComponent.d.ts +4 -0
- package/dist/utils/redirect.d.ts +7 -0
- package/dist/utils/renderElement.d.ts +2 -0
- package/dist/utils/utils.d.ts +5 -0
- package/dist/vite.config.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactElement, MouseEvent, CSSProperties } from 'react';
|
|
2
|
+
type LinkProps = {
|
|
3
|
+
to: string;
|
|
4
|
+
children: ReactElement<{
|
|
5
|
+
onClick: (e: MouseEvent) => void;
|
|
6
|
+
style: CSSProperties;
|
|
7
|
+
}>;
|
|
8
|
+
prefetch?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare const Link: ({ children, to, prefetch }: LinkProps) => import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RouteItem } from '../types/global.ts';
|
|
2
|
+
type RouterProps = {
|
|
3
|
+
routeList: RouteItem[];
|
|
4
|
+
context?: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
export declare const Router: ({ routeList, context: initialContext }: RouterProps) => import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BlockerState, Location, UpdateBlockedRouteProps } from '../types/global.ts';
|
|
2
|
+
export type NavigationContextValue = {
|
|
3
|
+
location: Location;
|
|
4
|
+
params: Record<string, string>;
|
|
5
|
+
blockerState: BlockerState;
|
|
6
|
+
};
|
|
7
|
+
export type ActionsContextValue = {
|
|
8
|
+
updateLocation(route: Location): Promise<void>;
|
|
9
|
+
updateBlockedRoute(arg: UpdateBlockedRouteProps): void;
|
|
10
|
+
prefetchLoader(arg: string): Promise<void>;
|
|
11
|
+
setContext(arg: object): void;
|
|
12
|
+
};
|
|
13
|
+
export type DataContextValue = {
|
|
14
|
+
loaderCache: Record<string, unknown>;
|
|
15
|
+
context: Record<string, unknown>;
|
|
16
|
+
};
|
|
17
|
+
export declare const ActionsContext: import('react').Context<ActionsContextValue>;
|
|
18
|
+
export declare const DataContext: import('react').Context<DataContextValue>;
|
|
19
|
+
export declare const NavigationContext: import('react').Context<NavigationContextValue>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useBeforeUnload: (callback?: () => void) => void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BlockerState, Location, RouteItem, UpdateBlockedRouteProps } from '../types/global.ts';
|
|
2
|
+
type UseHandleNavigation = {
|
|
3
|
+
routeList: RouteItem[];
|
|
4
|
+
setLocation: (arg: Location) => void;
|
|
5
|
+
context: Record<string, unknown>;
|
|
6
|
+
revalidateCache(routeItem?: RouteItem): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export declare const useHandleNavigation: ({ setLocation, routeList, context, revalidateCache }: UseHandleNavigation) => {
|
|
9
|
+
blockerState: BlockerState;
|
|
10
|
+
updateLocation: (nextLocation: Location) => Promise<void>;
|
|
11
|
+
updateBlockedRoute: ({ type, payload }: UpdateBlockedRouteProps) => void;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useLatest: <T>(value: T) => import('react').RefObject<T>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RouteItem } from '../types/global.ts';
|
|
2
|
+
export declare const useLoader: (routeList: RouteItem[]) => {
|
|
3
|
+
loaderCache: Record<string, unknown>;
|
|
4
|
+
loaderError: boolean;
|
|
5
|
+
prefetchLoader: (pathname: string) => Promise<void>;
|
|
6
|
+
revalidateCache: (routeItem?: RouteItem) => Promise<void>;
|
|
7
|
+
isLoadingMap: Record<string, boolean>;
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useLoaderState: <T>() => T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useLocation: () => import('..').Location;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useParams: <T>() => T;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const useNavigationState: () => import('../context/RouterContext').NavigationContextValue;
|
|
2
|
+
export declare const useRouterActions: () => import('../context/RouterContext').ActionsContextValue;
|
|
3
|
+
export declare const useRouterData: () => import('../context/RouterContext').DataContextValue;
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,12 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export { Router } from './components/Router';
|
|
2
|
+
export { Link } from './components/Link';
|
|
3
|
+
export { useNavigate } from './hooks/useNavigate';
|
|
4
|
+
export { useParams } from './hooks/useParams';
|
|
5
|
+
export { useLocation } from './hooks/useLocation';
|
|
6
|
+
export { useLoaderState } from './hooks/useLoaderState';
|
|
7
|
+
export { useBlocker } from './hooks/useBlocker';
|
|
8
|
+
export { useBeforeUnload } from './hooks/useBeforeUnload';
|
|
9
|
+
export { useRouterContext } from './hooks/useRouterContext';
|
|
10
|
+
export { createRouter, parseWindowLocation, comparePaths } from './utils/utils';
|
|
11
|
+
export { redirect } from './utils/redirect';
|
|
12
|
+
export type { ClientRouteItem, RouteItem, Location, BlockerState } from './types/global';
|
package/dist/index.es.js
CHANGED
|
@@ -436,4 +436,4 @@ var l = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t
|
|
|
436
436
|
};
|
|
437
437
|
};
|
|
438
438
|
//#endregion
|
|
439
|
-
export { R as Link, N as Router, x as createRouter, E as redirect, U as useBeforeUnload, H as useBlocker, V as useLoaderState, B as useLocation, L as useNavigate, z as useParams, W as useRouterContext };
|
|
439
|
+
export { R as Link, N as Router, w as comparePaths, x as createRouter, C as parseWindowLocation, E as redirect, U as useBeforeUnload, H as useBlocker, V as useLoaderState, B as useLocation, L as useNavigate, z as useParams, W as useRouterContext };
|
package/dist/index.umd.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
<%s {...props} />
|
|
4
4
|
React keys must be passed directly to JSX without using spread:
|
|
5
5
|
let props = %s;
|
|
6
|
-
<%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require("react"),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),c=n(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=o():t.exports=s()}))(),l=({children:e,setContext:t,context:n,updateBlockedRoute:o,updateLocation:s,location:l,params:u,prefetchLoader:d,loaderCache:f,blockerState:p})=>(0,c.jsx)(r.Provider,{value:{updateLocation:s,updateBlockedRoute:o,prefetchLoader:d,setContext:t},children:(0,c.jsx)(i.Provider,{value:{context:n,loaderCache:f},children:(0,c.jsx)(a.Provider,{value:{blockerState:p,params:u,location:l},children:e})})}),u=(e,n)=>{let r=(0,t.lazy)(()=>e().then(e=>({default:e.default||e})));return()=>(0,c.jsx)(t.Suspense,{fallback:typeof n==`function`?n():n||null,children:(0,c.jsx)(r,{})})},d=e=>typeof e.element==`function`&&e.element.toString().includes(`import(`),f=(e,t=[],n=``)=>{let r=e.path.match(/:[^/]+/g),i=e.path.replaceAll(/:[^/]+(\/|$)/g,``).split(`/`).filter(Boolean),a=e.path.split(`/`),o=r?[...t,...r.map((e,t)=>({key:i[t],value:e.slice(1)}))]:t,s=o.length?`${n}${a.slice(0,a.length-1).join(`/`)}`:e.path,c=d(e)?u(e.element,e.fallback):e.element;return[{...e,path:s,params:o,element:c},...e.children?.flatMap(e=>f(e,o,s))||[]]},p=e=>e.flatMap(e=>f(e,[])),m=e=>{let{pathname:t}=window.location,n=t.split(`/`);return(e||[]).map(e=>({index:n.findIndex(t=>t===e.key),value:e.value})).reduce((e,t)=>({...e,[t.value]:n[t.index+1]}),{})},h=e=>({pathname:e.pathname,search:e.search}),g=(e,t)=>{let n=e.path.split(`/`).filter(Boolean),r=e.params?Object.keys(e.params).length:0,i=t.split(`/`).filter(Boolean);return n.every((e,t)=>e===i[t+ +!!t])&&i.length===n.length+r},_=class{url;search;cause;constructor(e,t){this.url=e,this.search=t,this.cause=`redirect`}},v=(e,t)=>Promise.reject(new _(e,t)),y=e=>{let n=(0,t.useRef)(e);return(0,t.useEffect)(()=>{n.current=e},[e]),n},b=({setLocation:e,routeList:n,context:r,revalidateCache:i})=>{let[a,o]=(0,t.useState)({from:``,to:``}),s=(0,t.useRef)(``),c=y((0,t.useCallback)(async t=>{try{let a=n.find(e=>g(e,t.pathname));a?.beforeLoad&&await a?.beforeLoad(r),e(t),t.pathname!==window.location.pathname&&(history.pushState(null,``,t.pathname),s.current=t.pathname),await i(a),a?.afterLoad&&await a?.afterLoad(r)}catch(t){if(!(t instanceof _))return t;history.replaceState(null,``,`${t.url}${t.search||``}`),e({pathname:t.url,search:t.search})}},[r,i,n,e])),l=(0,t.useCallback)(({type:e,payload:t=``})=>o(n=>n.from===t&&e===`charge`?n:t&&n.from!==t&&e===`charge`?{...n,from:t}:e===`reset`?{...n,to:``}:(e===`process`&&c.current({pathname:n.to}),!n.from&&!n.to?n:{from:``,to:``})),[c]),u=(0,t.useCallback)(async e=>{a.from?o(t=>({...t,to:e.pathname})):await c.current(e)},[a.from,c]);return(0,t.useEffect)(()=>{let t=async t=>{let n=h(t.target.location);s.current===a.from?(o({from:s.current,to:n.pathname}),history.replaceState(null,``,s.current)):e(n)};return window.addEventListener(`popstate`,t),()=>window.removeEventListener(`popstate`,t)},[a.from,e]),(0,t.useEffect)(()=>{let e=h(window.location);c.current(e),s.current=e.pathname},[c]),{blockerState:(0,t.useMemo)(()=>a.from&&a.to?`blocked`:a.from?`charged`:`unblocked`,[a]),updateLocation:u,updateBlockedRoute:l}},x=e=>{let[n,r]=(0,t.useState)({}),[i,a]=(0,t.useState)({}),[o,s]=(0,t.useState)(!1),[c,l]=(0,t.useState)({}),u=(0,t.useCallback)(({key:e,value:t})=>r(n=>({...n,[e]:t})),[]),d=(0,t.useCallback)(e=>{if(!e)return!0;let t=i[e.path];return!!(t&&Date.now()-t<(e.staleTime||0))},[i]),f=(0,t.useCallback)(async e=>{if(e?.loader&&!d(e)){l(t=>({...t,[e.path]:!0})),r(t=>Object.keys(t).filter(t=>t!==e.path).reduce((e,n)=>({...e,[n]:t[n]}),{}));try{s(!1);let t=await e?.loader();a(t=>({...t,[e.path]:Date.now()})),u({key:e.path,value:t})}catch{s(!0)}finally{l(t=>({...t,[e.path]:!1}))}}},[d,u]);return{loaderCache:n,loaderError:o,prefetchLoader:(0,t.useCallback)(async t=>{let n=e.find(e=>g(e,t));n&&await f(n)},[f,e]),revalidateCache:f,isLoadingMap:c}},S=e=>e?typeof e==`function`?(0,c.jsx)(e,{}):e:null,C=`error 404. Page not found`,w=`*`,T=({routeList:e,context:n={}})=>{let[r,i]=(0,t.useState)(h(window.location)),[a,o]=(0,t.useState)(n),s=(0,t.useMemo)(()=>e.find(e=>e.path===w||g(e,r.pathname)),[r.pathname,e]),{loaderError:u,loaderCache:d,prefetchLoader:f,revalidateCache:p,isLoadingMap:_}=x(e),{blockerState:v,updateLocation:y,updateBlockedRoute:T}=b({setLocation:i,routeList:e,context:a,revalidateCache:p}),E=(0,t.useMemo)(()=>s?.params?m(s.params):{},[s]),D=(0,t.useMemo)(()=>({location:r,updateLocation:y,params:E,loaderCache:d,prefetchLoader:f,updateBlockedRoute:T,blockerState:v,context:a,setContext:o}),[v,d,r,E,f,a,T,y]);return s?.loader&&!u&&_[r.pathname]?(0,c.jsx)(l,{...D,children:S(s?.loaderFallback)}):u?(0,c.jsx)(l,{...D,children:S(s?.errorElement)}):(0,c.jsx)(l,{...D,children:S(s?.element)||C})},E=()=>{let e=(0,t.useContext)(a);if(!Object.keys(e).length)throw Error(`useNavigationState must be used within Router component`);return e},D=()=>{let e=(0,t.useContext)(r);if(!Object.keys(e).length)throw Error(`useRouterActions must be used within Router component`);return e},O=()=>{let e=(0,t.useContext)(i);if(!Object.keys(e).length)throw Error(`useRouterData must be used within Router component`);return e},k=()=>{let{updateLocation:e}=D();return(0,t.useCallback)(async t=>t===-1?history.go(-1):await e(t),[e])};e.Link=({children:e,to:t,prefetch:n=!0})=>{let{prefetchLoader:r}=D(),i=k();return(0,c.jsx)(`a`,{style:{cursor:`pointer`},onClick:()=>i({pathname:t}),onMouseOver:()=>n&&r(t),children:e})},e.Router=T,e.createRouter=p,e.redirect=v,e.useBeforeUnload=e=>{(0,t.useEffect)(()=>{let t=t=>{e&&(t.preventDefault(),e())};return window.addEventListener(`beforeunload`,t),()=>window.removeEventListener(`beforeunload`,t)},[e])},e.useBlocker=e=>{let{location:{pathname:n},blockerState:r}=E(),{updateBlockedRoute:i}=D(),a=e();return(0,t.useEffect)(()=>i(a?{type:`charge`,payload:n}:{type:`unblock`}),[a,n,i]),{state:r,process:()=>i({type:`process`}),reset:()=>i({type:`reset`})}},e.useLoaderState=()=>{let{loaderCache:e}=O();return e[window.location.pathname]},e.useLocation=()=>E().location,e.useNavigate=k,e.useParams=()=>{let{params:e}=E();return e},e.useRouterContext=()=>{let{context:e}=O(),{setContext:t}=D();return{context:e,setContext:t}}});
|
|
6
|
+
<%s key={someKey} {...props} />`,o,p,m,p),L[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===E&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require("react"),h=Symbol.for(`react.transitional.element`),g=Symbol.for(`react.portal`),_=Symbol.for(`react.fragment`),v=Symbol.for(`react.strict_mode`),y=Symbol.for(`react.profiler`),b=Symbol.for(`react.consumer`),x=Symbol.for(`react.context`),S=Symbol.for(`react.forward_ref`),C=Symbol.for(`react.suspense`),w=Symbol.for(`react.suspense_list`),T=Symbol.for(`react.memo`),E=Symbol.for(`react.lazy`),D=Symbol.for(`react.activity`),O=Symbol.for(`react.client.reference`),k=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,A=Object.prototype.hasOwnProperty,j=Array.isArray,M=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var N,P={},F=m.react_stack_bottom_frame.bind(m,o)(),I=M(i(o)),L={};e.Fragment=_,e.jsx=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)},e.jsxs=function(e,t,n){var r=1e4>k.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):F,r?M(i(e)):I)}})()})),c=n(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=o():t.exports=s()}))(),l=({children:e,setContext:t,context:n,updateBlockedRoute:o,updateLocation:s,location:l,params:u,prefetchLoader:d,loaderCache:f,blockerState:p})=>(0,c.jsx)(r.Provider,{value:{updateLocation:s,updateBlockedRoute:o,prefetchLoader:d,setContext:t},children:(0,c.jsx)(i.Provider,{value:{context:n,loaderCache:f},children:(0,c.jsx)(a.Provider,{value:{blockerState:p,params:u,location:l},children:e})})}),u=(e,n)=>{let r=(0,t.lazy)(()=>e().then(e=>({default:e.default||e})));return()=>(0,c.jsx)(t.Suspense,{fallback:typeof n==`function`?n():n||null,children:(0,c.jsx)(r,{})})},d=e=>typeof e.element==`function`&&e.element.toString().includes(`import(`),f=(e,t=[],n=``)=>{let r=e.path.match(/:[^/]+/g),i=e.path.replaceAll(/:[^/]+(\/|$)/g,``).split(`/`).filter(Boolean),a=e.path.split(`/`),o=r?[...t,...r.map((e,t)=>({key:i[t],value:e.slice(1)}))]:t,s=o.length?`${n}${a.slice(0,a.length-1).join(`/`)}`:e.path,c=d(e)?u(e.element,e.fallback):e.element;return[{...e,path:s,params:o,element:c},...e.children?.flatMap(e=>f(e,o,s))||[]]},p=e=>e.flatMap(e=>f(e,[])),m=e=>{let{pathname:t}=window.location,n=t.split(`/`);return(e||[]).map(e=>({index:n.findIndex(t=>t===e.key),value:e.value})).reduce((e,t)=>({...e,[t.value]:n[t.index+1]}),{})},h=e=>({pathname:e.pathname,search:e.search}),g=(e,t)=>{let n=e.path.split(`/`).filter(Boolean),r=e.params?Object.keys(e.params).length:0,i=t.split(`/`).filter(Boolean);return n.every((e,t)=>e===i[t+ +!!t])&&i.length===n.length+r},_=class{url;search;cause;constructor(e,t){this.url=e,this.search=t,this.cause=`redirect`}},v=(e,t)=>Promise.reject(new _(e,t)),y=e=>{let n=(0,t.useRef)(e);return(0,t.useEffect)(()=>{n.current=e},[e]),n},b=({setLocation:e,routeList:n,context:r,revalidateCache:i})=>{let[a,o]=(0,t.useState)({from:``,to:``}),s=(0,t.useRef)(``),c=y((0,t.useCallback)(async t=>{try{let a=n.find(e=>g(e,t.pathname));a?.beforeLoad&&await a?.beforeLoad(r),e(t),t.pathname!==window.location.pathname&&(history.pushState(null,``,t.pathname),s.current=t.pathname),await i(a),a?.afterLoad&&await a?.afterLoad(r)}catch(t){if(!(t instanceof _))return t;history.replaceState(null,``,`${t.url}${t.search||``}`),e({pathname:t.url,search:t.search})}},[r,i,n,e])),l=(0,t.useCallback)(({type:e,payload:t=``})=>o(n=>n.from===t&&e===`charge`?n:t&&n.from!==t&&e===`charge`?{...n,from:t}:e===`reset`?{...n,to:``}:(e===`process`&&c.current({pathname:n.to}),!n.from&&!n.to?n:{from:``,to:``})),[c]),u=(0,t.useCallback)(async e=>{a.from?o(t=>({...t,to:e.pathname})):await c.current(e)},[a.from,c]);return(0,t.useEffect)(()=>{let t=async t=>{let n=h(t.target.location);s.current===a.from?(o({from:s.current,to:n.pathname}),history.replaceState(null,``,s.current)):e(n)};return window.addEventListener(`popstate`,t),()=>window.removeEventListener(`popstate`,t)},[a.from,e]),(0,t.useEffect)(()=>{let e=h(window.location);c.current(e),s.current=e.pathname},[c]),{blockerState:(0,t.useMemo)(()=>a.from&&a.to?`blocked`:a.from?`charged`:`unblocked`,[a]),updateLocation:u,updateBlockedRoute:l}},x=e=>{let[n,r]=(0,t.useState)({}),[i,a]=(0,t.useState)({}),[o,s]=(0,t.useState)(!1),[c,l]=(0,t.useState)({}),u=(0,t.useCallback)(({key:e,value:t})=>r(n=>({...n,[e]:t})),[]),d=(0,t.useCallback)(e=>{if(!e)return!0;let t=i[e.path];return!!(t&&Date.now()-t<(e.staleTime||0))},[i]),f=(0,t.useCallback)(async e=>{if(e?.loader&&!d(e)){l(t=>({...t,[e.path]:!0})),r(t=>Object.keys(t).filter(t=>t!==e.path).reduce((e,n)=>({...e,[n]:t[n]}),{}));try{s(!1);let t=await e?.loader();a(t=>({...t,[e.path]:Date.now()})),u({key:e.path,value:t})}catch{s(!0)}finally{l(t=>({...t,[e.path]:!1}))}}},[d,u]);return{loaderCache:n,loaderError:o,prefetchLoader:(0,t.useCallback)(async t=>{let n=e.find(e=>g(e,t));n&&await f(n)},[f,e]),revalidateCache:f,isLoadingMap:c}},S=e=>e?typeof e==`function`?(0,c.jsx)(e,{}):e:null,C=`error 404. Page not found`,w=`*`,T=({routeList:e,context:n={}})=>{let[r,i]=(0,t.useState)(h(window.location)),[a,o]=(0,t.useState)(n),s=(0,t.useMemo)(()=>e.find(e=>e.path===w||g(e,r.pathname)),[r.pathname,e]),{loaderError:u,loaderCache:d,prefetchLoader:f,revalidateCache:p,isLoadingMap:_}=x(e),{blockerState:v,updateLocation:y,updateBlockedRoute:T}=b({setLocation:i,routeList:e,context:a,revalidateCache:p}),E=(0,t.useMemo)(()=>s?.params?m(s.params):{},[s]),D=(0,t.useMemo)(()=>({location:r,updateLocation:y,params:E,loaderCache:d,prefetchLoader:f,updateBlockedRoute:T,blockerState:v,context:a,setContext:o}),[v,d,r,E,f,a,T,y]);return s?.loader&&!u&&_[r.pathname]?(0,c.jsx)(l,{...D,children:S(s?.loaderFallback)}):u?(0,c.jsx)(l,{...D,children:S(s?.errorElement)}):(0,c.jsx)(l,{...D,children:S(s?.element)||C})},E=()=>{let e=(0,t.useContext)(a);if(!Object.keys(e).length)throw Error(`useNavigationState must be used within Router component`);return e},D=()=>{let e=(0,t.useContext)(r);if(!Object.keys(e).length)throw Error(`useRouterActions must be used within Router component`);return e},O=()=>{let e=(0,t.useContext)(i);if(!Object.keys(e).length)throw Error(`useRouterData must be used within Router component`);return e},k=()=>{let{updateLocation:e}=D();return(0,t.useCallback)(async t=>t===-1?history.go(-1):await e(t),[e])};e.Link=({children:e,to:t,prefetch:n=!0})=>{let{prefetchLoader:r}=D(),i=k();return(0,c.jsx)(`a`,{style:{cursor:`pointer`},onClick:()=>i({pathname:t}),onMouseOver:()=>n&&r(t),children:e})},e.Router=T,e.comparePaths=g,e.createRouter=p,e.parseWindowLocation=h,e.redirect=v,e.useBeforeUnload=e=>{(0,t.useEffect)(()=>{let t=t=>{e&&(t.preventDefault(),e())};return window.addEventListener(`beforeunload`,t),()=>window.removeEventListener(`beforeunload`,t)},[e])},e.useBlocker=e=>{let{location:{pathname:n},blockerState:r}=E(),{updateBlockedRoute:i}=D(),a=e();return(0,t.useEffect)(()=>i(a?{type:`charge`,payload:n}:{type:`unblock`}),[a,n,i]),{state:r,process:()=>i({type:`process`}),reset:()=>i({type:`reset`})}},e.useLoaderState=()=>{let{loaderCache:e}=O();return e[window.location.pathname]},e.useLocation=()=>E().location,e.useNavigate=k,e.useParams=()=>{let{params:e}=E();return e},e.useRouterContext=()=>{let{context:e}=O(),{setContext:t}=D();return{context:e,setContext:t}}});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ActionsContextValue, DataContextValue, NavigationContextValue } from '../context/RouterContext';
|
|
3
|
+
type RouterProviderProps = NavigationContextValue & ActionsContextValue & DataContextValue & {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
};
|
|
6
|
+
export declare const RouterProvider: ({ children, setContext, context, updateBlockedRoute, updateLocation, location, params, prefetchLoader, loaderCache, blockerState, }: RouterProviderProps) => import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ComponentType, ReactElement } from 'react';
|
|
2
|
+
export type LazyComponent = () => Promise<{
|
|
3
|
+
default: ComponentType<unknown>;
|
|
4
|
+
}>;
|
|
5
|
+
export type ClientRouteItem = {
|
|
6
|
+
path: string;
|
|
7
|
+
element: (() => ReactElement) | ReactElement | LazyComponent;
|
|
8
|
+
loader?(...args: unknown[]): Promise<unknown>;
|
|
9
|
+
loaderFallback?: (() => ReactElement) | ReactElement;
|
|
10
|
+
errorElement?: (() => ReactElement) | ReactElement;
|
|
11
|
+
fallback?: (() => ReactElement) | ReactElement;
|
|
12
|
+
children?: ClientRouteItem[];
|
|
13
|
+
staleTime?: number;
|
|
14
|
+
beforeLoad?: (context: Record<string, unknown>) => Promise<unknown> | undefined;
|
|
15
|
+
afterLoad?: (context: Record<string, unknown>) => Promise<unknown> | undefined;
|
|
16
|
+
};
|
|
17
|
+
export type RouteItem = ClientRouteItem & {
|
|
18
|
+
element: (() => ReactElement) | ReactElement;
|
|
19
|
+
params?: {
|
|
20
|
+
key: string;
|
|
21
|
+
value: string;
|
|
22
|
+
}[];
|
|
23
|
+
cacheTimestamp?: number;
|
|
24
|
+
};
|
|
25
|
+
export type Location = {
|
|
26
|
+
pathname: string;
|
|
27
|
+
search?: string;
|
|
28
|
+
state?: unknown;
|
|
29
|
+
};
|
|
30
|
+
export type BlockerState = 'blocked' | 'unblocked' | 'charged';
|
|
31
|
+
export type UpdateBlockedRouteProps = {
|
|
32
|
+
type: 'process' | 'reset' | 'charge' | 'unblock';
|
|
33
|
+
payload?: string;
|
|
34
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ClientRouteItem, Location, RouteItem } from '../types/global.ts';
|
|
2
|
+
export declare const createRouter: (clientList: ClientRouteItem[]) => RouteItem[];
|
|
3
|
+
export declare const getParamsObject: (params: RouteItem["params"]) => {};
|
|
4
|
+
export declare const parseWindowLocation: (location: typeof window.location) => Location;
|
|
5
|
+
export declare const comparePaths: (el: RouteItem, pathname: string) => boolean;
|