UNPKG

react-best-router

Version:

In larger React applications, it is usually necessary to use a Router to handle relationships between pages and navigate between them. Are you using other Router libraries? Have you encountered any areas that are not very useful? For example, defining nes

2 lines (1 loc) 5.64 kB
import{createContext as t,useContext as e,useMemo as n,createElement as r,Fragment as a,Children as o,useEffect as c,useState as i,useLayoutEffect as s}from"react";const u=t(null);function p(){const t=e(u);if(!t)throw"Invalid call outside of Router";return t}function l(t){const e=t.split("/").map(t=>(t||"").trim()),n=e.length,r=e.reduce((t,e,r)=>"."===e||""===e&&0!==r&&r!==n-1?t:".."===e?t.slice(0,-1):[...t,e],[]).join("/");return r.length>1&&"/"===r.at(-1)?r.slice(0,-1):r}function h(t){const e=function(t){const e=[];let n=0,r=t;r=r.replace(/\\\(/,"@@#").replace(/\\\)/,"#@@"),r=r.replace(/(?<S>\/)?:(?<N>[a-z0-9_]+)(?<R>\(.+?\))?(?<M>[*?+])?/gi,(function(t,r="",a="",o="",c=""){const i="*"===c||"+"===c?`(?<${a}>${o||`(${r}[a-z0-9_-]+)`}${c})`:`${r}${c}(?<${a}>${o||"([a-z0-9_-]+)"}${c})`,s=`@@${n++}@@`;return e.push([s,i]),s}));let a=0;r=r.replace(/(?<S>\/)?(?<R>\(.+?\))(?<M>[*?+])?/gi,(function(t,r="",o="",c=""){const i="*"===c||"+"===c?`(?<$${++a}>${o}${c})`:`${r}${c}(?<$${++a}>${o}${c})`,s=`@@${n++}@@`;return e.push([s,i]),s})),r=r.replace(/\?/g,"\\?").replace(/\*/g,"\\*").replace(/\+/g,"\\+").replace(/\./g,"\\.").replace(/\//g,"\\/"),e.forEach(([t,e])=>r=r.replace(t,e)),r=r.replace(/@@#/g,"(").replace(/#@@/g,")");try{return new RegExp(`^${r}$`,"i")}catch(e){throw"Invalid pattern: "+t}}(t);return t=>{const{pathname:n,searchParams:r}=new URL(t,location.origin),a=null==e?void 0:e.exec(decodeURIComponent(n));return{state:!!a,params:(null==a?void 0:a.groups)||{},query:r}}}function f(t,e,n){if(n&&n.prefix===n.pattern){const e=`Invalid nesting '${n.pattern} -> ${t}'`;throw new Error(e)}e=e||function(t){const e=/[.*()[\]?+]/,n=t.split("/"),r=n.slice(0).reverse().findIndex(t=>!e.test(t));return(r>0?n.slice(0,-r):n).join("/")}(t);const r=`/${function(t){let e=t,n="";for(;e;)n=`${e.prefix}/${n}`,e=e.parent;return n}(n)}/${t}`,a=h((o=l(o=r)).length>1&&"/"===o.at(-1)?o.slice(0,-1):o);var o;const c={parent:n,pattern:t,prefix:e,match:a};return c.match=t=>(c.result=a(t),c.result),c}const d=t(null);function g(){return e(d)}function v(t){const{pathname:e}=new URL(t,location.origin);return e}function $(t,e,n){return n.startsWith("/")?l(`${v(t)}/${n}`):function(t,e){return l(`${t}/${e}`)}(v(e),n)}function w(t){const{base:e,state:r,driver:a}=p(),o=g();return n(()=>{if(!(null==o?void 0:o.result))throw"Invalid call outside of Route";const n=function(t,e){return l("/"+e.slice(t.length)).split("?")[0]}(e,r.path),{params:c,query:i}=o.result;return t&&c&&Object.entries(c).forEach(([e,n])=>{const r=t[e];c[e]=r?r(String(n)):n}),{path:n,params:c,query:i,push:t=>a.push({path:$(e,r.path,t)}),back:()=>a.back(),forward:()=>a.forward(),go:t=>a.go(t),replace:t=>a.replace({path:$(e,r.path,t)})}},[r,o,a])}function b({navRef:t}){const{parser:e}=t||{},o=w(e);return n(()=>t&&(t.current=o),[o,t]),r(a)}function m(t){return n(()=>y(t),[t])}function y(t){return{parser:t,current:void 0}}function E(t){const{side:e,children:c}=t,i=function(t,e){const n=o.toArray(e).filter(t=>!!t),r=n.filter(e=>e.type===t);return n.length===r.length?r.map(t=>{var e;return null===(e=t.props)||void 0===e?void 0:e.pattern}):[]}(...e),{state:s}=p(),u=g(),l=n(()=>i.map(t=>f(t,"",u)),[i.join(":"),s.path,u]);return!l[0]||l.some(t=>t.match(s.path).state)?r(a,null):c}function k(t){const e=w(),{to:n}=t;return c(()=>e.push(n),[e,n]),r(a,null)}function R(t){const{pattern:e="/(.*)?",prefix:o,navigator:c}=t,{render:i,children:s,fallback:u,redirect:l}=t,{state:h}=p(),v=g(),$=n(()=>f(e,o,v),[e,o,v]),w=$.match(h.path).state;if(!w&&!u)return r(a,null);if(w&&l)return r(k,{to:l});const m=i?i(s):s;return r(d.Provider,{value:$},c&&r(b,{navRef:c}),w?m:u,w&&u&&r(E,{side:[R,m]},u))}function x(t){return{...t,path:l(t.path)}}function S(t){const{driver:e,base:a="/",navigator:o,children:c,render:p,fallback:l}=t,[h,f]=i(()=>x(e.current())),d=n(()=>({base:a,state:h,driver:e}),[a,h,e]);return s(()=>e.subscribe(t=>f(x(t))),[e,h]),r(u.Provider,{value:d},r(R,{pattern:a+"/(.*)?",prefix:a,render:p,navigator:o,fallback:l},c))}function I(){const t=()=>{const{pathname:t,search:e}=location;return{path:`${t}${e}`}};return{current:t,push:t=>{history.pushState(t,t.path,t.path);const e=new PopStateEvent("popstate",{state:t});window.dispatchEvent(e)},replace:t=>{history.replaceState(t,t.path,t.path);const e=new PopStateEvent("popstate",{state:t});window.dispatchEvent(e)},go:t=>history.go(t),back:()=>history.back(),forward:()=>history.forward(),subscribe:e=>{const n=n=>{e(n.state||t())};return window.addEventListener("popstate",n),()=>window.removeEventListener("popstate",n)}}}function L(){return n(()=>I(),[])}function P(){const t=()=>({path:location.hash.slice(1)||"/"});return{current:t,push:t=>{location.hash=t.path},replace:t=>{location.hash=t.path},go:t=>history.go(t),back:()=>history.back(),forward:()=>history.forward(),subscribe:e=>{const n=()=>e(t());return window.addEventListener("hashchange",n),()=>window.removeEventListener("hashchange",n)}}}function j(){return n(()=>P(),[])}function q(t={path:"/"}){let e,n=[t],r=0;const a=(a,o=!1)=>{a<0&&(a=0),a>n.length-1&&(a=n.length-1),(a!==r||o)&&(r=a,null==e||e(n[r]||t))};return{subscribe:t=>(e=t,()=>e=void 0),current:()=>n[r]||t,replace:t=>{n=n.slice(0,r+1),n[r]=t,a(n.length-1,!0)},push:t=>{n=n.slice(0,r+1),n.push(t),a(n.length-1)},go:t=>a(r+t),back:()=>a(r-1),forward:()=>a(r+1)}}function z(t={path:"/"}){return n(()=>q(t),[t])}export{b as NavigatorForwarder,R as Route,S as Router,I as createBrowserDriver,P as createHashDriver,q as createMemoryDriver,y as createNavigatorRef,x as normalizeState,L as useBrowserDriver,j as useHashDriver,z as useMemoryDriver,w as useNavigator,m as useNavigatorRef};