UNPKG

react-router-min

Version:

Only 5k. A lightweight react router component and hooks for ReactJS. Support dyamic routes, multiple routes, base path, presetQuery. useRouter and Link component Provided.

2 lines (1 loc) 7.59 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactRouterMin={},e.React)}(this,(function(e,t){"use strict";const n={type:["history","hash"],cleanUrl:[!0,!1],stripIndex:[!0,!1]},r=/(?<=^\/)|(?!^)\/+(?<!$)|(?=\/$)/g;function a(e){const{base:t,type:n}=e||{};let r=window.location.pathname;if(t&&(r=r.startsWith(`${t}/`)?r.replace(t,""):`${t.match(/\/[^/]+/g).fill("..").join("/")}${r}`),"hash"==n&&"/"==r&&""!==window.location.hash&&(r=window.location.hash.replace(/^#|(?<!\?|#)(?:\?|#).*/g,"")||"/"),e){let{cleanUrl:t,stripIndex:a}=e;if(t||a){let t=r;e.cleanUrl&&(r=r.replace(/\.\w+$/g,"")),e.stripIndex&&(r=r.replace(/((?<=\/)index\.html|(?<=\/)index)$/g,"")),r!=t&&("hash"==n?history.replaceState(null,"",window.location.hash.replace(t,r)):history.replaceState(null,"",window.location.pathname.replace(t,r)))}}return r}function i(e){return"hash"==e?window.location.hash.replace(/^[^\?]+(?=\?)?|(?:#).*$/g,""):window.location.search}function o(e){if(!e)return{};try{"string"==typeof e&&(e=new URLSearchParams(e))}catch{return{}}let t={};for(let[n,r]of e){if(/^{.+}$|^\[.+\]$/.test(r))try{r=JSON.parse(r)}catch{}t[n]=r}return t}function c(e){return""!==(e=e||"")&&!e.startsWith("/")&&(e=`/${e}`),e.endsWith("/")&&(e=e.slice(0,-1)),e}function s(e){if(e&&"object"==typeof e){const t=Object.keys(e).filter((e=>/^[a-zA-Z]/.test(e)));return 0==t.length?null:t.reduce(((t,n)=>(t[n]=e[n],t)),{})}return null}function l(e,t){return e=e||{},t?{...t,...e}:e}function u(e,t){return t?{...t,...Object.keys(t).reduce(((t,n)=>(n in e&&(t[n]=e[n]),t)),{})}:null}function p(e){let t=Object.keys(e).map((t=>{return`${t}=${n=e[t],"object"==typeof n?JSON.stringify(n):n}`;var n})).join("&");return t?`?${t}`:""}function h(e,t){const{cleanUrl:n=!0,stripIndex:r=!0,query:a}=t||{};let i,c;return"string"==typeof e?([i,c]=e.split(/(?<=^[^?]+)\?/),c=o(c),a&&(c={...a,...c})):"object"==typeof e&&e.path&&([i,c]=e.path.split(/(?<=^[^?]+)\?/),c={...a,...o(c),...e.query}),n&&(i=i.replace(/\.\w+$/g,"")),r&&(i=i.replace(/((?<=\/)index\.html|(?<=\/)index)$/g,"")),[`${i}${p(c)}`,{path:i,query:c}]}function f(e){if(/\[\.{0,3}\w+\]/.test(e)){let t=[],n=new RegExp(`^${e.replace(/\[(\.{0,3})(\w+)\]/g,((n,r,a,i,o)=>(o=i+n.length>=e.length,t.push(r?[a]:a),`(${r?o?"(?:[^/]+\\/?)*":"[^/]+(?:\\/[^/]+)*":"[^/]"+(o?"*":"+?")})`)))}$`);return{path:e,pattern:n,params:t,isDynamic:!0}}return{path:e,isDynamic:!1}}function m(e,{path:t,pattern:n,params:r}){if(!n)return e==t;let a=n.exec(e);return!!a&&r.reduce(((e,t,n)=>(Array.isArray(t)?e[t[0]]=a[n+1].split("/"):e[t]=a[n+1],e)),{})}function y(e,t,n,{cleanUrl:a,stripIndex:i}){let o=!1;return e.split(r).reduce(((n,r,c,s)=>(a&&(r=r.replace(/\.\w+$/g,"")),i&&(r=r.replace(/((?<=\/)index\.html|(?<=\/)index)$/g,"")),n[r=r.replace(/\[\.{3}|\[?\w+\]/g,"*")]=n[r]||{},c==s.length-1&&(n[r][""]={...f(e),component:t})&&(o=n[r][""].isDynamic),n[r])),n),o}function d(e,t,n,r){if(t>e.length-1)return n[""];let a=e[t]||"/";return n[a]&&d(e,t+1,n[a],!1)||r&&d(e,t+1,n,!0)||!r&&n["*"]&&d(e,t+1,n["*"],!1)||!r&&n["**"]&&d(e,t+1,n["**"],!0)||null}function $(e,t){let{type:n,base:r}=t||{};n=n||"history",r=c(r);const[a,i]=h(e,t);history.pushState(i,"",`${r}${"hash"==n?"/#":""}${a}`),window.dispatchEvent(new PopStateEvent("popstate",{state:i}))}function g(e,t){let{type:n,base:r}=t||{};n=n||"history",r=c(r);const[a,i]=h(e,t);history.replaceState(i,"",`${r}${"hash"==n?"/#":""}${a}`),window.dispatchEvent(new PopStateEvent("popstate",{state:i}))}function w(e,n,r,a){return t.createElement(e[n++],{...r,...n==e.length&&a},n<e.length&&w(e,n,r,a))}function b({ref:e,_$options:n,href:r,type:a,target:i,query:o,onClick:s,children:l,...u}){const p=c(n.base),[h,f]=t.useState(!1),[m,y]=t.useState(`${p}${r}`),d=u.origin||window.location.origin,w=u.pathname?`${p}${u.pathname}`:window.location.pathname;t.useEffect((()=>{r&&(URL.canParse(r)?r.startsWith(d)?(f(!1),y(URL.parse(r).pathname)):f(!0):r.startsWith("/")?(f(!1),y(`${p}${r}`)):(f(!1),y(new URL(r,`${d}${w}`).pathname)))}),[r]);const b=t.useCallback((e=>{"_blank"===i||u.download||h||(e.preventDefault(),e.stopPropagation()),s&&s(e),m&&!h&&("replace"==a?g(m.substring(p.length),{...n,query:o}):$(m.substring(p.length),{...n,query:o}))}),[s,m,h]);return m?t.createElement("a",{ref:e,href:m,target:i,onClick:b,...u},l):t.createElement("a",{ref:e,target:i,onClick:b,...u},l)}e.Link=function({ref:e,base:n,query:r,options:a,children:i,...o}){return a=a||{},t.createElement(b,{ref:e,_$options:{...a,base:n},origin:origin,query:r,...o},i)},e.createRouter=function({routes:e,config:h}={}){const{...E}=function(e){return e="object"==typeof e&&e||{},Object.keys(n).reduce(((e,t)=>(e[t]=n[t].includes(e[t])?e[t]:n[t][0],e)),{...e,base:c(e.base),presetQuery:s(e.presetQuery)})}(h),{base:x,type:q,presetQuery:j}=E,S=function(e,t){if(!e)return null;if(e&&"object"==typeof e){const n={},r={},a={},i=[];function o({path:e,name:c,Component:s,index:l,children:u},p="",h=[]){e=e||p,c=c||s&&s.name||e.substring(1),s&&h.push(s),u?u.forEach((t=>o(t,`${p}${e}${e.endsWith("/")?"":"/"}`,[...h]))):(!0!==l&&(e=`${p}${e}`),r[c||e]=e,a[c||e]=[...h],i.push({path:e,name:c,Component:s,isDynamic:y(e,c,n,t)}))}return Array.isArray(e)||(e=Object.keys(e).map((t=>({path:t,name:e[t].name||"",Component:e[t]})))),e.forEach((e=>o(e))),{tree:n,names:r,components:a,list:i}}}(e,E),U=t.createContext();function v(e){if("object"==typeof e&&e.name){if(!S)return;const t=S.list.find((t=>t.name==e.name));if(!t||t.isDynamic)return;e.path=t.path,delete e.name}$(e,j?{...E,query:u(o(i(q)),j)}:E)}function k(e){if("object"==typeof e&&e.name){if(!S)return;const t=S.list.find((t=>t.name==e.name));if(!t||t.isDynamic)return;e.path=t.path,delete e.name}g(e,j?{...E,query:u(o(i(q)),j)}:E)}function C(){const{...e}=t.useContext(U);return e}return{useRouter:C,pushUrl:v,replaceUrl:k,Link:function({ref:e,children:n,query:r,...a}){const{origin:c,path:s}=C();return j&&(r=l(r,u(o(i(q)),j))),t.createElement(b,{ref:e,origin:c,pathname:s,query:r,...a,_$options:E},n)},Router:function({path:e,component:n,children:r,...a}){const i=t.useContext(U),o=t.useMemo((()=>f(e)),[e]),c=i.path.startsWith("/")&&m(i.path,o);return!1!==c&&(n?t.createElement(n,{router:i,...a,...c}):t.createElement(t.Fragment,{},t.Children.map(r,(e=>t.isValidElement(e)?t.cloneElement(e,{router:i,...c}):e))))},Main:function({children:e}){const[n,c]=t.useState(a(E)),[s,u]=t.useState(j?l(o(i(q)),j):o(i(q))),h=t.useMemo((()=>({origin:window.location.origin,path:n,query:s,pushUrl:v,replaceUrl:k})),[n,s]),f=t.useMemo((()=>S&&n.startsWith("/")&&d(n.split(r),0,S.tree,!1)),[n]);if(t.useEffect((()=>{if(j){if(!function(e,t){return!t||Object.keys(t).every((t=>t in e))}(o(i(q)),j)){const e=l(s,j);history.replaceState({path:n,query:e},"",`${x}${"hash"==q?"/#":""}${n}${p(e)}`)}}"hash"==q&&""==window.location.hash&&history.replaceState({path:n,query:s},"",`${x}${"hash"==q?"/#":""}${n}${window.location.search}`);const e=e=>{let t=e.state||{path:a(E),query:o(i(q))};c(t.path||"/"),u(t.query||{})};return window.addEventListener("popstate",e),()=>{window.removeEventListener("popstate",e)}}),[]),f){const r=m(n,f),a=e&&t.Children.only(e);return t.createElement(U.Provider||U,{value:h},(a?t.cloneElement:t.createElement)(a||t.Fragment,a?{router:h}:{},w(S.components[f.component],0,{router:h},{...r})))}return t.createElement(U.Provider||U,{value:h},e&&t.Children.map(e,(e=>t.cloneElement(e,{router:h}))))},routerList:S?S.list:[]}},e.pushUrl=$,e.replaceUrl=g}));