@typeroute/router 0.11.0 → 0.11.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.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{Component as e,Suspense as t,cloneElement as n,createContext as r,isValidElement as i,lazy as a,memo as o,useCallback as s,useContext as c,useEffect as ee,useInsertionEffect as te,useLayoutEffect as l,useMemo as u,useRef as d,useState as f,useSyncExternalStore as p}from"react";import{inject as m,parse as h}from"regexparam";import{jsx as g}from"react/jsx-runtime";function _(e){return`/${e}`.replaceAll(/\/+/g,`/`).replace(/(.+)\/$/,`$1`)}function v(e){let{keys:t,pattern:n}=h(e);return{pattern:e,keys:t,regex:n,loose:h(e,!0).pattern,weights:e.split(`/`).slice(1).map(e=>e.includes(`*`)?0:e.includes(`:`)?1:2)}}function y(e){return typeof e==`function`?e:t=>{let n=e[`~standard`].validate(t);if(n instanceof Promise)throw Error(`[TypeRoute] Validation can't be async`);if(n.issues)throw Error(`[TypeRoute] Validation failed`,{cause:n.issues});return n.value}}function b(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>`${e}=${encodeURIComponent(S(t))}`).join(`&`)}function x(e){let t=new URLSearchParams(e);return Object.fromEntries([...t.entries()].map(([e,t])=>(t=decodeURIComponent(t),[e,C(t)?JSON.parse(t):t])))}function S(e){return typeof e==`string`&&!C(e)?e:JSON.stringify(e)}function C(e){try{return JSON.parse(e),!0}catch{return!1}}function w(e,t){return _(`${t}/${e}`)}function T(e,t){return(e===t||e.startsWith(`${t}/`))&&(e=e.slice(t.length)||`/`),e}function E(e,t){return[e,b(t)].filter(Boolean).join(`?`)}function D(e){let{pathname:t,search:n}=new URL(e,`http://w`);return{path:t,search:x(n)}}function O({keys:e,regex:t,loose:n},r,i,a){let o=(r?t:n).exec(T(i,a));if(!o)return null;let s={};return e.forEach((e,t)=>{let n=o[t+1];n&&(s[e]=n)}),s}function k(e){return[...e].sort((e,t)=>{let n=e.route._.weights,r=t.route._.weights,i=Math.max(n.length,r.length);for(let e=0;e<i;e++){let t=n[e]??-1,i=r[e]??-1;if(t!==i)return i-t}return 0})}const A=r(null),j=r(null),M=r(null),N=r(null);function P(){let e=c(A);if(e)return e;throw Error(`[TypeRoute] useRouter must be within a router context`)}function F(){let e=c(j);if(e)return e;throw Error(`[TypeRoute] useLocation must be within a router context`)}function I(e){let t=P(),{path:n}=F();return u(()=>t.match(n,e),[t,n,e.from,e.strict,e.params])}function L(){return c(N)}function ne(){return P().navigate}function re(){let e=c(M);return u(()=>e?.route._.handles??[],[e])}function R(e){let t=I({from:e});if(t)return t.params;throw Error(`[TypeRoute] Can't read params for non-matching route ${e}`)}function z(e){let t=P(),{search:n,path:r}=F(),i=t.getRoute(e),a=u(()=>i._.validate(n),[i,n]);return[a,X((e,n)=>{e=typeof e==`function`?e(a):e;let i=E(r,{...a,...e});t.navigate({url:i,replace:n})})]}var B=class{_;_loc=(e,t)=>{let{state:n}=history,[r,i]=this._??[];return i?.path===e&&r===t&&i.state===n?i:(this._=[t,{path:e,search:x(t),state:n}])[1]};constructor(){if(!window[V]){for(let e of[H,U]){let t=history[e];history[e]=function(...n){t.apply(this,n),dispatchEvent(new Event(e))}}window[V]=1}}location=()=>this._loc(location.pathname,location.search);go=e=>history.go(e);push=e=>{let{url:t,replace:n,state:r}=e;history[n?U:H](r,``,t)};subscribe=e=>(W.forEach(t=>window.addEventListener(t,e)),()=>{W.forEach(t=>window.removeEventListener(t,e))})};const V=Symbol.for(`wmp01`),H=`pushState`,U=`replaceState`,W=[`popstate`,H,U,`hashchange`];var G=class{routes;basePath;history;context;ssrContext;defaultLinkOptions;_;constructor(e){let{routes:t,basePath:n=`/`,history:r,context:i,ssrContext:a,defaultLinkOptions:o}=e;this.routes=Object.values(t),this.basePath=_(n),this.history=r??new B,this.context=i,this.ssrContext=a,this.defaultLinkOptions=o,this._={routeMap:new Map(this.routes.map(e=>[e._.pattern,e]))}}getRoute=e=>{if(typeof e!=`string`)return e;let t=this._.routeMap.get(e);if(!t)throw Error(`[TypeRoute] Route not found for ${e}`);return t};match=(e,t)=>{let{from:n,strict:r,params:i}=t,a=this.getRoute(n),o=O(a._,r,e,this.basePath);return o&&(!i||Object.keys(i).every(e=>i[e]===o[e]))?{route:a,params:o}:null};matchAll=e=>k(this.routes.map(t=>this.match(e,{from:t,strict:!0})).filter(e=>!!e))[0]??null;createUrl=e=>{let{to:t,params:n={},search:r={}}=e,{pattern:i}=this.getRoute(t)._;return E(w(m(i,n),this.basePath),r)};preload=async e=>{let{to:t,params:n={},search:r={}}=e,{preloads:i}=this.getRoute(t)._;await Promise.all(i.map(e=>e({params:n,search:r,context:this.context})))};navigate=e=>{if(typeof e==`number`)this.history.go(e);else if(`url`in e)this.history.push(e);else{let{replace:t,state:n}=e;this.history.push({url:this.createUrl(e),replace:t,state:n})}}},K=class{stack=[];index=0;listeners=new Set;constructor(e=`/`){this.stack.push({...D(e),state:void 0})}location=()=>this.stack[this.index];go=e=>{let t=this.index+e;this.stack[t]&&(this.index=t,this.listeners.forEach(e=>e()))};push=e=>{let{url:t,replace:n,state:r}=e,i={...D(t),state:r};this.stack=this.stack.slice(0,this.index+1),n?this.stack[this.index]=i:this.index=this.stack.push(i)-1,this.listeners.forEach(e=>e())};subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)})},q=class extends B{location=()=>{let{pathname:e,search:t}=new URL(location.hash.slice(1),`http://w`);return this._loc(e,t)};push=e=>{let{url:t,replace:n,state:r}=e;history[n?`replaceState`:`pushState`](r,``,`#${t}`)}};function J(e){let[t]=f(()=>`router`in e?e.router:new G(e)),{subscribe:n,location:r}=t.history,i=p(n,r,r),a=u(()=>t.matchAll(i.path),[t,i.path]);return a||console.error(`[TypeRoute] No matching route for path`,i.path),u(()=>g(A.Provider,{value:t,children:g(j.Provider,{value:i,children:g(M.Provider,{value:a,children:a?.route._.components.reduceRight((e,t)=>g(N.Provider,{value:e,children:g(t,{})}),null)})})}),[t,i,a])}function Y(){return L()}function ie(e){let t=P();return l(()=>t.navigate(e),[]),t.ssrContext&&(t.ssrContext.redirect=t.createUrl(e)),null}function ae(e){let t=P(),{to:r,replace:a,state:o,params:c,search:te,strict:l,preload:f,preloadDelay:p=50,style:m,className:h,activeStyle:_,activeClassName:v,asChild:y,children:b,...x}={...t.defaultLinkOptions,...e},S=d(null),C=d(null),w=t.createUrl(e),T=!!I({from:r,strict:l,params:c}),E=X(()=>t.preload(e)),D=s(()=>{clearTimeout(C.current)},[]),O=s(()=>{D(),C.current=setTimeout(E,p)},[p,D]),k=u(()=>({"data-active":T,style:{...m,...T&&_},className:[h,T&&v].filter(Boolean).join(` `)||void 0}),[T,m,h,_,v]);ee(()=>{if(f===`render`)O();else if(f===`viewport`&&S.current){let e=new IntersectionObserver(e=>e.forEach(e=>{e.isIntersecting?O():D()}));return e.observe(S.current),()=>{e.disconnect(),D()}}return D},[f,O,D]);let A=e=>{x.onClick?.(e),!(e.ctrlKey||e.metaKey||e.shiftKey||e.altKey||e.button!==0||e.defaultPrevented)&&(e.preventDefault(),t.navigate({url:w,replace:a,state:o}))},j=(e,t)=>n=>{t?.(n),f===`intent`&&!n.defaultPrevented&&e()},M={...x,...k,ref:oe(S,x.ref),href:w,onClick:A,onFocus:j(O,x.onFocus),onBlur:j(D,x.onBlur),onPointerEnter:j(O,x.onPointerEnter),onPointerLeave:j(D,x.onPointerLeave)};return y&&i(b)?n(b,M):g(`a`,{...M,children:b})}function oe(e,t){return t?n=>{e.current=n;let r=typeof t==`function`?t(n):void(t.current=n);return r&&(()=>{e.current=null,r()})}:e}function X(e){let t=d(e);return te(()=>{t.current=e},[e]),d(((...e)=>t.current(...e))).current}function Z(e){return()=>L()??g(e,{})}function se(e){return()=>g(t,{fallback:g(e,{}),children:L()})}function ce(t){class n extends e{constructor(e){super(e),this.state={...e}}static getDerivedStateFromError(e){return{error:[e]}}static getDerivedStateFromProps(e,t){return e.children===t.children?t:{...e,error:void 0}}render(){return this.state.error?g(t,{error:this.state.error[0]}):this.props.children}}return()=>g(n,{children:L()})}function Q(e){return new $({...v(_(e)),validate:e=>e,handles:[],components:[],preloads:[]})}function le(){return Q(``)}var $=class e{_;_types;constructor(e){this._=e}route=t=>new e({...this._,...v(_(`${this._.pattern}/${t}`)),p:this});use=t=>{let{_:n}=t;return new e({...this._,handles:[...this._.handles,...n.handles],components:[...this._.components,...n.components],preloads:[...this._.preloads,...n.preloads]}).search(n.validate)};search=t=>(t=y(t),new e({...this._,validate:e=>{let n=this._.validate(e);return{...n,...t({...e,...n})}}}));handle=t=>new e({...this._,handles:[...this._.handles,t]});preload=t=>new e({...this._,preloads:[...this._.preloads,e=>t({...e,search:this._.validate(e.search)})]});component=t=>new e({...this._,components:[...this._.components,o(t)]});index=e=>this.component(Z(e));lazy=e=>{let t=a(async()=>{let t=await e();return`default`in t?t:{default:t}});return this.preload(e).component(t)};suspense=e=>this.component(se(e));error=e=>this.component(ce(e));toString=()=>this._.pattern};export{B as BrowserHistory,q as HashHistory,ae as Link,j as LocationContext,M as MatchContext,K as MemoryHistory,ie as Navigate,Y as Outlet,N as OutletContext,$ as Route,G as Router,A as RouterContext,J as RouterRoot,le as middleware,Q as route,re as useHandles,F as useLocation,I as useMatch,ne as useNavigate,L as useOutlet,R as useParams,P as useRouter,z as useSearch};
1
+ import{Component as e,Suspense as t,cloneElement as n,createContext as r,isValidElement as i,lazy as a,memo as o,useContext as s,useEffect as c,useInsertionEffect as ee,useLayoutEffect as l,useMemo as u,useRef as d,useState as f,useSyncExternalStore as p}from"react";import{inject as m,parse as h}from"regexparam";import{jsx as g}from"react/jsx-runtime";function _(e){return`/${e}`.replaceAll(/\/+/g,`/`).replace(/(.+)\/$/,`$1`)}function v(e){let{keys:t,pattern:n}=h(e);return{pattern:e,keys:t,regex:n,loose:h(e,!0).pattern,weights:e.split(`/`).slice(1).map(e=>e.includes(`*`)?0:e.includes(`:`)?1:2)}}function y(e){return typeof e==`function`?e:t=>{let n=e[`~standard`].validate(t);if(n instanceof Promise)throw Error(`[TypeRoute] Validation can't be async`);if(n.issues)throw Error(`[TypeRoute] Validation failed`,{cause:n.issues});return n.value}}function b(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>`${e}=${encodeURIComponent(S(t))}`).join(`&`)}function x(e){let t={};return new URLSearchParams(e).forEach((e,n)=>{t[n]=C(e)?JSON.parse(e):e}),t}function S(e){return typeof e==`string`&&!C(e)?e:JSON.stringify(e)}function C(e){try{return JSON.parse(e),!0}catch{return!1}}function w(e,t){return _(`${t}/${e}`)}function T(e,t){return(e===t||e.startsWith(`${t}/`))&&(e=e.slice(t.length)||`/`),e}function E(e,t){return[e,b(t)].filter(Boolean).join(`?`)}function D(e){let{pathname:t,search:n}=new URL(e,`http://w`);return{path:t,search:x(n)}}function O({keys:e,regex:t,loose:n},r,i,a){let o=(r?t:n).exec(T(i,a));if(!o)return null;let s={};return e.forEach((e,t)=>{let n=o[t+1];n&&(s[e]=n)}),s}function k(e){return[...e].sort((e,t)=>{let n=e.route._.weights,r=t.route._.weights,i=Math.max(n.length,r.length);for(let e=0;e<i;e++){let t=n[e]??-1,i=r[e]??-1;if(t!==i)return i-t}return 0})}const A=r(null),j=r(null),M=r(null),N=r(null);function P(){let e=s(A);if(e)return e;throw Error(`[TypeRoute] useRouter must be within a router context`)}function F(){let e=s(j);if(e)return e;throw Error(`[TypeRoute] useLocation must be within a router context`)}function I(e){let t=P(),{path:n}=F();return u(()=>t.match(n,e),[t,n,e.from,e.strict,e.params])}function L(){return s(N)}function te(){return P().navigate}function ne(){let e=s(M);return u(()=>e?.route._.handles??[],[e])}function R(e){let t=I({from:e});if(t)return t.params;throw Error(`[TypeRoute] Can't read params for non-matching route ${e}`)}function z(e){let t=P(),{search:n,path:r}=F(),i=t.getRoute(e),a=u(()=>i._.validate(n),[i,n]);return[a,Z((e,n)=>{e=typeof e==`function`?e(a):e;let i=E(r,{...a,...e});t.navigate({url:i,replace:n})})]}var B=class{_loc=(e,t)=>{let{state:n}=history,[r,i]=this._??[];return i?.path===e&&r===t&&i.state===n?i:(this._=[t,{path:e,search:x(t),state:n}])[1]};constructor(){if(!window[V]){for(let e of[H,U]){let t=history[e];history[e]=function(...n){t.apply(this,n),dispatchEvent(new Event(e))}}window[V]=1}}location=()=>this._loc(location.pathname,location.search);go=e=>history.go(e);push=e=>{let{url:t,replace:n,state:r}=e;history[n?U:H](r,``,t)};subscribe=e=>(W.forEach(t=>addEventListener(t,e)),()=>{W.forEach(t=>removeEventListener(t,e))})};const V=Symbol.for(`wmp01`),H=`pushState`,U=`replaceState`,W=[`popstate`,H,U,`hashchange`];var G=class{constructor(e){let{routes:t,basePath:n=`/`,history:r,context:i,ssrContext:a,defaultLinkOptions:o}=e;this.routes=Object.values(t),this.basePath=_(n),this.history=r??new B,this.context=i,this.ssrContext=a,this.defaultLinkOptions=o,this._=new Map(this.routes.map(e=>[e._.pattern,e]))}getRoute=e=>{if(typeof e!=`string`)return e;let t=this._.get(e);if(!t)throw Error(`[TypeRoute] Route not found for ${e}`);return t};match=(e,t)=>{let{from:n,strict:r,params:i}=t,a=this.getRoute(n),o=O(a._,r,e,this.basePath);return o&&(!i||Object.keys(i).every(e=>i[e]===o[e]))?{route:a,params:o}:null};matchAll=e=>k(this.routes.map(t=>this.match(e,{from:t,strict:!0})).filter(e=>!!e))[0]??null;createUrl=e=>{let{to:t,params:n={},search:r={}}=e,{pattern:i}=this.getRoute(t)._;return E(w(m(i,n),this.basePath),r)};preload=async e=>{let{to:t,params:n={},search:r={}}=e,{preloads:i}=this.getRoute(t)._;await Promise.all(i.map(e=>e({params:n,search:r,context:this.context})))};navigate=e=>{if(typeof e==`number`)this.history.go(e);else if(`url`in e)this.history.push(e);else{let{replace:t,state:n}=e;this.history.push({url:this.createUrl(e),replace:t,state:n})}}},K=class{stack=[];index=0;listeners=new Set;constructor(e=`/`){this.stack.push({...D(e),state:void 0})}location=()=>this.stack[this.index];go=e=>{let t=this.index+e;this.stack[t]&&(this.index=t,this.listeners.forEach(e=>e()))};push=e=>{let{url:t,replace:n,state:r}=e,i={...D(t),state:r};this.stack=this.stack.slice(0,this.index+1),n?this.stack[this.index]=i:this.index=this.stack.push(i)-1,this.listeners.forEach(e=>e())};subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)})},q=class extends B{location=()=>{let{pathname:e,search:t}=new URL(location.hash.slice(1),`http://w`);return this._loc(e,t)};push=e=>{let{url:t,replace:n,state:r}=e;history[n?`replaceState`:`pushState`](r,``,`#${t}`)}};function J(e){let[t]=f(()=>`router`in e?e.router:new G(e)),{subscribe:n,location:r}=t.history,i=p(n,r,r),a=u(()=>t.matchAll(i.path),[t,i.path]);return a||console.error(`[TypeRoute] No matching route for path`,i.path),u(()=>g(A.Provider,{value:t,children:g(j.Provider,{value:i,children:g(M.Provider,{value:a,children:a?.route._.components.reduceRight((e,t)=>g(N.Provider,{value:e,children:g(t,{})}),null)})})}),[t,i,a])}function Y(){return L()}function X(e){let t=P();return l(()=>t.navigate(e),[]),t.ssrContext&&(t.ssrContext.redirect=t.createUrl(e)),null}function re(e){let t=P(),{to:r,replace:a,state:o,params:s,search:ee,strict:l,preload:u,preloadDelay:f=50,style:p,className:m,activeStyle:h,activeClassName:_,asChild:v,children:y,...b}={...t.defaultLinkOptions,...e},x=d(null),S=d(null),C=t.createUrl(e),w=!!I({from:r,strict:l,params:s}),T=Z(()=>{clearTimeout(S.current)}),E=Z(()=>{T(),S.current=setTimeout(()=>t.preload(e),f)}),D={"data-active":w,style:{...p,...w&&h},className:[m,w&&_].filter(Boolean).join(` `)||void 0};c(()=>{if(u===`render`)E();else if(u===`viewport`&&x.current){let e=new IntersectionObserver(e=>e.forEach(e=>{e.isIntersecting?E():T()}));return e.observe(x.current),()=>{e.disconnect(),T()}}return T},[u]);let O=e=>{b.onClick?.(e),!(e.ctrlKey||e.metaKey||e.shiftKey||e.altKey||e.button||e.defaultPrevented)&&(e.preventDefault(),t.navigate({url:C,replace:a,state:o}))},k=(e,t)=>n=>{t?.(n),u===`intent`&&!n.defaultPrevented&&e()},A={...b,...D,ref:ie(x,b.ref),href:C,onClick:O,onFocus:k(E,b.onFocus),onBlur:k(T,b.onBlur),onPointerEnter:k(E,b.onPointerEnter),onPointerLeave:k(T,b.onPointerLeave)};return v&&i(y)?n(y,A):g(`a`,{...A,children:y})}function ie(e,t){return t?n=>{e.current=n;let r=typeof t==`function`?t(n):void(t.current=n);return r&&(()=>{e.current=null,r()})}:e}function Z(e){let t=d(e);return ee(()=>{t.current=e},[e]),d(((...e)=>t.current(...e))).current}function ae(e){return()=>L()??g(e,{})}function oe(e){return()=>g(t,{fallback:g(e,{}),children:L()})}function se(t){class n extends e{state={...this.props};static getDerivedStateFromError(e){return{error:[e]}}static getDerivedStateFromProps(e,t){return e.children===t.children?t:{...e,error:void 0}}render(){return this.state.error?g(t,{error:this.state.error[0]}):this.props.children}}return()=>g(n,{children:L()})}function Q(e){return new $({...v(_(e)),validate:e=>e,handles:[],components:[],preloads:[]})}function ce(){return Q(``)}var $=class e{constructor(e){this._=e}route=t=>new e({...this._,...v(_(`${this._.pattern}/${t}`)),p:this});use=t=>{let{_:n}=t;return new e({...this._,handles:[...this._.handles,...n.handles],components:[...this._.components,...n.components],preloads:[...this._.preloads,...n.preloads]}).search(n.validate)};search=t=>(t=y(t),new e({...this._,validate:e=>{let n=this._.validate(e);return{...n,...t({...e,...n})}}}));handle=t=>new e({...this._,handles:[...this._.handles,t]});preload=t=>new e({...this._,preloads:[...this._.preloads,e=>t({...e,search:this._.validate(e.search)})]});component=t=>new e({...this._,components:[...this._.components,o(t)]});index=e=>this.component(ae(e));lazy=e=>this.preload(e).component(a(()=>e().then(e=>`default`in e?e:{default:e})));suspense=e=>this.component(oe(e));error=e=>this.component(se(e));toString=()=>this._.pattern};export{B as BrowserHistory,q as HashHistory,re as Link,j as LocationContext,M as MatchContext,K as MemoryHistory,X as Navigate,Y as Outlet,N as OutletContext,$ as Route,G as Router,A as RouterContext,J as RouterRoot,ce as middleware,Q as route,ne as useHandles,F as useLocation,I as useMatch,te as useNavigate,L as useOutlet,R as useParams,P as useRouter,z as useSearch};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeroute/router",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "license": "MIT",
5
5
  "author": "strblr",
6
6
  "description": "Type-safe React router that just works - simple setup, full autocomplete, 4kB gzipped",