waymark 0.2.0 → 0.2.2

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 CHANGED
@@ -457,7 +457,7 @@ userProfile.preload();
457
457
 
458
458
  ### Programmatic navigation
459
459
 
460
- For navigation triggered by code rather than user clicks, use the `useNavigate` hook:
460
+ For navigation triggered by code rather than user clicks, use the `useNavigate` hook (or `router.navigate`):
461
461
 
462
462
  ```tsx
463
463
  import { useNavigate } from "waymark";
@@ -495,14 +495,12 @@ You can also access the router directly via `useRouter()` (or import the router
495
495
  For unsafe navigation that bypasses type checking, you can pass `url` instead of `to`, `params` and `search`. This is useful when you don't know the target URL statically (e.g. external redirects):
496
496
 
497
497
  ```tsx
498
- const router = useRouter();
499
-
500
498
  // Type-safe navigation
501
- router.navigate({ to: userProfile, params: { id: "42" } });
499
+ navigate({ to: userProfile, params: { id: "42" } });
502
500
 
503
501
  // Unsafe navigation - no type checking
504
- router.navigate({ url: "/some/unknown/path" });
505
- router.navigate({ url: "/callback", replace: true, state: { data: 123 } });
502
+ navigate({ url: "/some/unknown/path" });
503
+ navigate({ url: "/callback", replace: true, state: { data: 123 } });
506
504
  ```
507
505
 
508
506
  ### Declarative navigation
@@ -1177,7 +1175,7 @@ The `History` interface defines how Waymark interacts with navigation. All histo
1177
1175
  ```tsx
1178
1176
  interface HistoryLike {
1179
1177
  getPath: () => string;
1180
- getSearch: () => string;
1178
+ getSearch: () => Record<string, unknown>;
1181
1179
  getState: () => any;
1182
1180
  go: (delta: number) => void;
1183
1181
  push: (options: HistoryPushOptions) => void;
@@ -1194,11 +1192,11 @@ const path = history.getPath();
1194
1192
  // Returns "/users/42"
1195
1193
  ```
1196
1194
 
1197
- `history.getSearch()` returns the current search string (without `?`):
1195
+ `history.getSearch()` returns the current search parameters as a parsed object:
1198
1196
 
1199
1197
  ```tsx
1200
1198
  const search = history.getSearch();
1201
- // Returns "tab=posts&page=2"
1199
+ // Returns { tab: "posts", page: 2 }
1202
1200
  ```
1203
1201
 
1204
1202
  `history.getState()` returns the current history state:
package/dist/index.d.ts CHANGED
@@ -46,7 +46,7 @@ interface HistoryPushOptions {
46
46
  }
47
47
  interface HistoryLike {
48
48
  getPath: () => string;
49
- getSearch: () => string;
49
+ getSearch: () => Record<string, unknown>;
50
50
  getState: () => any;
51
51
  go: (delta: number) => void;
52
52
  push: (options: HistoryPushOptions) => void;
@@ -142,9 +142,7 @@ declare class Router {
142
142
  readonly routes: RouteList;
143
143
  readonly history: HistoryLike;
144
144
  readonly defaultLinkOptions?: LinkOptions;
145
- readonly _: {
146
- routeMap: Map<string, Route>;
147
- };
145
+ private readonly _;
148
146
  constructor(options: RouterOptions);
149
147
  getRoute<P extends Pattern>(pattern: P | GetRoute<P>): GetRoute<P>;
150
148
  match<P extends Pattern>(path: string, options: MatchOptions<P>): Match<P> | null;
@@ -156,9 +154,11 @@ declare class Router {
156
154
  //#region src/router/browser-history.d.ts
157
155
  declare class BrowserHistory implements HistoryLike {
158
156
  private static patchKey;
157
+ private memo?;
159
158
  constructor();
159
+ protected getSearchMemo: (search: string) => Record<string, unknown>;
160
160
  getPath: () => string;
161
- getSearch: () => string;
161
+ getSearch: () => Record<string, unknown>;
162
162
  getState: () => any;
163
163
  go: (delta: number) => void;
164
164
  push: (options: HistoryPushOptions) => void;
@@ -168,7 +168,7 @@ declare class BrowserHistory implements HistoryLike {
168
168
  //#region src/router/memory-history.d.ts
169
169
  interface MemoryLocation {
170
170
  path: string;
171
- search: string;
171
+ search: Record<string, unknown>;
172
172
  state: any;
173
173
  }
174
174
  declare class MemoryHistory implements HistoryLike {
@@ -178,7 +178,7 @@ declare class MemoryHistory implements HistoryLike {
178
178
  constructor(url?: string);
179
179
  private getCurrent;
180
180
  getPath: () => string;
181
- getSearch: () => string;
181
+ getSearch: () => Record<string, unknown>;
182
182
  getState: () => any;
183
183
  go: (delta: number) => void;
184
184
  push: (options: HistoryPushOptions) => void;
@@ -189,7 +189,7 @@ declare class MemoryHistory implements HistoryLike {
189
189
  declare class HashHistory extends BrowserHistory {
190
190
  private getHashUrl;
191
191
  getPath: () => string;
192
- getSearch: () => string;
192
+ getSearch: () => Record<string, unknown>;
193
193
  push: (options: HistoryPushOptions) => void;
194
194
  }
195
195
  //#endregion
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 l,useLayoutEffect as u,useMemo as d,useRef as ee,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){return 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(`[Waymark] Validation must be synchronous`);if(n.issues)throw Error(`[Waymark] Validation failed`,{cause:n.issues});return n.value}}function b(e){return e.startsWith(`?`)?e.slice(1):e}function x(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>`${e}=${encodeURIComponent(C(t))}`).join(`&`)}function S(e){let t=new URLSearchParams(e);return Object.fromEntries([...t.entries()].map(([e,t])=>(t=decodeURIComponent(t),[e,w(t)?JSON.parse(t):t])))}function C(e){return typeof e==`string`&&!w(e)?e:JSON.stringify(e)}function w(e){try{return JSON.parse(e),!0}catch{return!1}}function T(e,t){return _(`${t}/${e}`)}function E(e,t){return(e===t||e.startsWith(`${t}/`))&&(e=e.slice(t.length)||`/`),e}function D(e,t){return[e,x(t)].filter(Boolean).join(`?`)}function O(e){let{pathname:t,search:n}=new URL(e,`http://w`);return{path:t,search:b(n)}}function k(e,t,n,r){let i=e.exec(E(n,r));if(!i)return null;let a={};return t.forEach((e,t)=>{let n=i[t+1];n&&(a[e]=n)}),a}function A(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 j=r(null),M=r(null),N=r(null);function P(){let e=c(j);if(!e)throw Error(`[Waymark] useRouter must be used within a router context`);return e}function F(){let e=c(M);return d(()=>e?.route._.handles??[],[e])}function I(){return c(N)}function L(e,t){return p(e.history.subscribe,t,t)}function R(){let e=P();return d(()=>e.navigate.bind(e),[e])}function z(){let e=P(),t=L(e,e.history.getPath),n=L(e,e.history.getSearch),r=L(e,e.history.getState);return d(()=>({path:t,search:S(n),state:r}),[t,n,r])}function B(e){let t=P(),n=L(t,t.history.getPath);return d(()=>t.match(n,e),[t,n,e])}function te(e){let t=B({from:e});if(!t)throw Error(`[Waymark] Can't read params for non-matching route: ${e}`);return t.params}function ne(e){let t=B({from:e});if(!t)throw Error(`[Waymark] Can't read search for non-matching route: ${e}`);let n=s(e=>t.route._.mapSearch(S(e)),[t.route]),r=P(),i=L(r,r.history.getSearch);return[d(()=>n(i),[n,i]),s((e,t)=>{let i=n(r.history.getSearch());e=typeof e==`function`?e(i):e;let a=D(r.history.getPath(),{...i,...e});r.navigate({url:a,replace:t})},[r,n])]}var V=class e{static patchKey=Symbol.for(`waymark_history_patch_v01`);constructor(){if(typeof history<`u`&&!Object.hasOwn(window,e.patchKey)){for(let e of[H,U]){let t=history[e];history[e]=function(...n){let r=t.apply(this,n),i=new Event(e);return i.arguments=n,dispatchEvent(i),r}}Object.assign(window,{[e.patchKey]:!0})}}getPath=()=>location.pathname;getSearch=()=>b(location.search);getState=()=>history.state;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 H=`pushState`,U=`replaceState`,W=[`popstate`,H,U,`hashchange`];var G=class{basePath;routes;history;defaultLinkOptions;_;constructor(e){let{basePath:t=`/`,routes:n,history:r,defaultLinkOptions:i}=e;this.basePath=_(t),this.routes=n,this.history=r??new V,this.defaultLinkOptions=i,this._={routeMap:new Map(n.map(e=>[e.pattern,e]))}}getRoute(e){if(typeof e!=`string`)return e;let t=this._.routeMap.get(e);if(!t)throw Error(`[Waymark] Route not found for pattern: ${e}`);return t}match(e,t){let{from:n,strict:r,params:i}=t,a=this.getRoute(n),o=k(r?a._.regex:a._.looseRegex,a._.keys,e,this.basePath);return!o||i&&Object.keys(i).some(e=>i[e]!==o[e])?null:{route:a,params:o}}matchAll(e){return A(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 D(T(m(i,n),this.basePath),r)}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({...O(e),state:void 0})}getCurrent=()=>this.stack[this.index];getPath=()=>this.getCurrent().path;getSearch=()=>this.getCurrent().search;getState=()=>this.getCurrent().state;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={...O(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 V{getHashUrl=()=>location.hash.slice(1)||`/`;getPath=()=>O(this.getHashUrl()).path;getSearch=()=>O(this.getHashUrl()).search;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)),n=L(t,t.history.getPath),r=d(()=>t.matchAll(n),[t,n]);return r||console.error(`[Waymark] No matching route found for path:`,n),d(()=>g(j.Provider,{value:t,children:g(M.Provider,{value:r,children:r?.route._.components.reduceRight((e,t)=>g(N.Provider,{value:e,children:g(t,{})}),null)})}),[t,r])}function Y(){return I()}function X(e){let t=R();return u(()=>t(e),[]),null}function Z(e){let t=P(),{to:r,replace:a,state:o,params:s,search:c,strict:u,preload:f,style:p,className:m,activeStyle:h,activeClassName:_,asChild:v,children:y,...b}={...t.defaultLinkOptions,...e},x=ee(null),S=t.createUrl(e),C=d(()=>t.getRoute(e.to),[t,e.to]),w=!!B({from:C,strict:u,params:s}),T=d(()=>({"data-active":w,style:{...p,...w&&h},className:[m,w&&_].filter(Boolean).join(` `)||void 0}),[w,p,m,h,_]);l(()=>{if(f===`render`)C.preload();else if(f===`viewport`&&x.current){let e=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting&&(C.preload(),e.disconnect())})});return e.observe(x.current),()=>e.disconnect()}},[f,C]);let E=e=>{b.onClick?.(e),!(e.ctrlKey||e.metaKey||e.shiftKey||e.altKey||e.button!==0||e.defaultPrevented)&&(e.preventDefault(),t.navigate({url:S,replace:a,state:o}))},D=e=>{b.onFocus?.(e),f===`intent`&&!e.defaultPrevented&&C.preload()},O=e=>{b.onPointerEnter?.(e),f===`intent`&&!e.defaultPrevented&&C.preload()},k={...b,...T,ref:re(b.ref,x),href:S,onClick:E,onFocus:D,onPointerEnter:O};return v&&i(y)?n(y,k):g(`a`,{...k,children:y})}function re(...e){let t=e.filter(e=>!!e);return t.length<=1?t[0]??null:e=>{let n=[];for(let r of t){let t=Q(r,e);n.push(t??(()=>Q(r,null)))}return()=>n.forEach(e=>e())}}function Q(e,t){if(typeof e==`function`)return e(t);e&&(e.current=t)}function ie(e){return()=>g(t,{fallback:g(e,{}),children:I()})}function ae(t){class n extends e{constructor(e){super(e),this.state={children:e.children,error:null}}static getDerivedStateFromError(e){return{error:[e]}}static getDerivedStateFromProps(e,t){return e.children===t.children?t:{children:e.children,error:null}}render(){return this.state.error?g(t,{error:this.state.error[0]}):this.props.children}}return()=>g(n,{children:I()})}function oe(e){return new $(_(e),e=>e,[],[],[])}var $=class e{pattern;_;constructor(e,t,n,r,i){let{keys:a,pattern:o}=h(e),s=h(e,!0).pattern,c=v(e);this.pattern=e,this._={keys:a,regex:o,looseRegex:s,weights:c,mapSearch:t,handles:n,components:r,preloaded:!1,preloaders:i}}route(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(_(`${this.pattern}/${t}`),n,r,i,a)}search(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return t=y(t),new e(this.pattern,e=>{let r=n(e);return{...r,...t(r)}},r,i,a)}handle(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,[...r,t],i,a)}preloader(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,r,i,[...a,t])}component(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,r,[...i,o(t)],a)}lazy(e){let t=a(async()=>{let t=await e();return{default:o(`default`in t?t.default:t)}});return this.preloader(e).component(t)}suspense(e){return this.component(ie(e))}error(e){return this.component(ae(e))}async preload(){let{preloaded:e,preloaders:t}=this._;e||(this._.preloaded=!0,await Promise.all(t.map(e=>e())))}toString(){return this.pattern}};export{V as BrowserHistory,q as HashHistory,Z as Link,M as MatchContext,K as MemoryHistory,X as Navigate,Y as Outlet,N as OutletContext,$ as Route,G as Router,j as RouterContext,J as RouterRoot,oe as route,F as useHandles,z as useLocation,B as useMatch,R as useNavigate,I as useOutlet,te as useParams,P as useRouter,ne as useSearch,L as useSubscribe};
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 l,useLayoutEffect as u,useMemo as d,useRef as f,useState as p,useSyncExternalStore as m}from"react";import{inject as h,parse as g}from"regexparam";import{jsx as _}from"react/jsx-runtime";function v(e){return`/${e}`.replaceAll(/\/+/g,`/`).replace(/(.+)\/$/,`$1`)}function y(e){return e.split(`/`).slice(1).map(e=>e.includes(`*`)?0:e.includes(`:`)?1:2)}function b(e){return typeof e==`function`?e:t=>{let n=e[`~standard`].validate(t);if(n instanceof Promise)throw Error(`[Waymark] Validation must be synchronous`);if(n.issues)throw Error(`[Waymark] Validation failed`,{cause:n.issues});return n.value}}function x(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>`${e}=${encodeURIComponent(C(t))}`).join(`&`)}function S(e){let t=new URLSearchParams(e);return Object.fromEntries([...t.entries()].map(([e,t])=>(t=decodeURIComponent(t),[e,w(t)?JSON.parse(t):t])))}function C(e){return typeof e==`string`&&!w(e)?e:JSON.stringify(e)}function w(e){try{return JSON.parse(e),!0}catch{return!1}}function T(e,t){return v(`${t}/${e}`)}function E(e,t){return(e===t||e.startsWith(`${t}/`))&&(e=e.slice(t.length)||`/`),e}function D(e,t){return[e,x(t)].filter(Boolean).join(`?`)}function O(e){let{pathname:t,search:n}=new URL(e,`http://w`);return{path:t,search:S(n)}}function k(e,t,n,r){let i=e.exec(E(n,r));if(!i)return null;let a={};return t.forEach((e,t)=>{let n=i[t+1];n&&(a[e]=n)}),a}function A(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 j=r(null),M=r(null),N=r(null);function P(){let e=c(j);if(!e)throw Error(`[Waymark] useRouter must be used within a router context`);return e}function F(){let e=c(M);return d(()=>e?.route._.handles??[],[e])}function I(){return c(N)}function L(e,t){return m(e.history.subscribe,t,t)}function R(){let e=P();return d(()=>e.navigate.bind(e),[e])}function z(){let e=P(),t=L(e,e.history.getPath),n=L(e,e.history.getSearch),r=L(e,e.history.getState);return d(()=>({path:t,search:n,state:r}),[t,n,r])}function B(e){let t=P(),n=L(t,t.history.getPath);return d(()=>t.match(n,e),[t,n,e])}function V(e){let t=B({from:e});if(!t)throw Error(`[Waymark] Can't read params for non-matching route: ${e}`);return t.params}function H(e){let t=P(),n=t.getRoute(e),r=L(t,t.history.getSearch);return[d(()=>n._.mapSearch(r),[n,r]),s((e,r)=>{let i=n._.mapSearch(t.history.getSearch());e=typeof e==`function`?e(i):e;let a=D(t.history.getPath(),{...i,...e});t.navigate({url:a,replace:r})},[t,n])]}var U=class e{static patchKey=Symbol.for(`waymark_history_patch_v01`);memo;constructor(){if(typeof history<`u`&&!(e.patchKey in window)){for(let e of[W,G]){let t=history[e];history[e]=function(...n){let r=t.apply(this,n),i=new Event(e);return i.arguments=n,dispatchEvent(i),r}}window[e.patchKey]=!0}}getSearchMemo=e=>this.memo?.search===e?this.memo.parsed:(this.memo={search:e,parsed:S(e)}).parsed;getPath=()=>location.pathname;getSearch=()=>this.getSearchMemo(location.search);getState=()=>history.state;go=e=>history.go(e);push=e=>{let{url:t,replace:n,state:r}=e;history[n?G:W](r,``,t)};subscribe=e=>(K.forEach(t=>window.addEventListener(t,e)),()=>{K.forEach(t=>window.removeEventListener(t,e))})};const W=`pushState`,G=`replaceState`,K=[`popstate`,W,G,`hashchange`];var q=class{basePath;routes;history;defaultLinkOptions;_;constructor(e){let{basePath:t=`/`,routes:n,history:r,defaultLinkOptions:i}=e;this.basePath=v(t),this.routes=n,this.history=r??new U,this.defaultLinkOptions=i,this._={routeMap:new Map(n.map(e=>[e.pattern,e]))}}getRoute(e){if(typeof e!=`string`)return e;let t=this._.routeMap.get(e);if(!t)throw Error(`[Waymark] Route not found for pattern: ${e}`);return t}match(e,t){let{from:n,strict:r,params:i}=t,a=this.getRoute(n),o=k(r?a._.regex:a._.looseRegex,a._.keys,e,this.basePath);return!o||i&&Object.keys(i).some(e=>i[e]!==o[e])?null:{route:a,params:o}}matchAll(e){return A(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 D(T(h(i,n),this.basePath),r)}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})}}},J=class{stack=[];index=0;listeners=new Set;constructor(e=`/`){this.stack.push({...O(e),state:void 0})}getCurrent=()=>this.stack[this.index];getPath=()=>this.getCurrent().path;getSearch=()=>this.getCurrent().search;getState=()=>this.getCurrent().state;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={...O(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)})},Y=class extends U{getHashUrl=()=>new URL(location.hash.slice(1),`http://w`);getPath=()=>this.getHashUrl().pathname;getSearch=()=>this.getSearchMemo(this.getHashUrl().search);push=e=>{let{url:t,replace:n,state:r}=e;history[n?`replaceState`:`pushState`](r,``,`#${t}`)}};function X(e){let[t]=p(()=>`router`in e?e.router:new q(e)),n=L(t,t.history.getPath),r=d(()=>t.matchAll(n),[t,n]);return r||console.error(`[Waymark] No matching route found for path:`,n),d(()=>_(j.Provider,{value:t,children:_(M.Provider,{value:r,children:r?.route._.components.reduceRight((e,t)=>_(N.Provider,{value:e,children:_(t,{})}),null)})}),[t,r])}function Z(){return I()}function ee(e){let t=R();return u(()=>t(e),[]),null}function te(e){let t=P(),{to:r,replace:a,state:o,params:s,search:c,strict:u,preload:p,style:m,className:h,activeStyle:g,activeClassName:v,asChild:y,children:b,...x}={...t.defaultLinkOptions,...e},S=f(null),C=t.createUrl(e),w=d(()=>t.getRoute(e.to),[t,e.to]),T=!!B({from:w,strict:u,params:s}),E=d(()=>({"data-active":T,style:{...m,...T&&g},className:[h,T&&v].filter(Boolean).join(` `)||void 0}),[T,m,h,g,v]);l(()=>{if(p===`render`)w.preload();else if(p===`viewport`&&S.current){let e=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting&&(w.preload(),e.disconnect())})});return e.observe(S.current),()=>e.disconnect()}},[p,w]);let D=e=>{x.onClick?.(e),!(e.ctrlKey||e.metaKey||e.shiftKey||e.altKey||e.button!==0||e.defaultPrevented)&&(e.preventDefault(),t.navigate({url:C,replace:a,state:o}))},O=e=>{x.onFocus?.(e),p===`intent`&&!e.defaultPrevented&&w.preload()},k=e=>{x.onPointerEnter?.(e),p===`intent`&&!e.defaultPrevented&&w.preload()},A={...x,...E,ref:ne(x.ref,S),href:C,onClick:D,onFocus:O,onPointerEnter:k};return y&&i(b)?n(b,A):_(`a`,{...A,children:b})}function ne(...e){let t=e.filter(e=>!!e);return t.length<=1?t[0]??null:e=>{let n=[];for(let r of t){let t=Q(r,e);n.push(t??(()=>Q(r,null)))}return()=>n.forEach(e=>e())}}function Q(e,t){if(typeof e==`function`)return e(t);e&&(e.current=t)}function re(e){return()=>_(t,{fallback:_(e,{}),children:I()})}function ie(t){class n extends e{constructor(e){super(e),this.state={children:e.children,error:null}}static getDerivedStateFromError(e){return{error:[e]}}static getDerivedStateFromProps(e,t){return e.children===t.children?t:{children:e.children,error:null}}render(){return this.state.error?_(t,{error:this.state.error[0]}):this.props.children}}return()=>_(n,{children:I()})}function ae(e){return new $(v(e),e=>e,[],[],[])}var $=class e{pattern;_;constructor(e,t,n,r,i){let{keys:a,pattern:o}=g(e),s=g(e,!0).pattern,c=y(e);this.pattern=e,this._={keys:a,regex:o,looseRegex:s,weights:c,mapSearch:t,handles:n,components:r,preloaded:!1,preloaders:i}}route(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(v(`${this.pattern}/${t}`),n,r,i,a)}search(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return t=b(t),new e(this.pattern,e=>{let r=n(e);return{...r,...t(r)}},r,i,a)}handle(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,[...r,t],i,a)}preloader(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,r,i,[...a,t])}component(t){let{mapSearch:n,handles:r,components:i,preloaders:a}=this._;return new e(this.pattern,n,r,[...i,o(t)],a)}lazy(e){let t=a(async()=>{let t=await e();return{default:o(`default`in t?t.default:t)}});return this.preloader(e).component(t)}suspense(e){return this.component(re(e))}error(e){return this.component(ie(e))}async preload(){let{preloaded:e,preloaders:t}=this._;e||(this._.preloaded=!0,await Promise.all(t.map(e=>e())))}toString(){return this.pattern}};export{U as BrowserHistory,Y as HashHistory,te as Link,M as MatchContext,J as MemoryHistory,ee as Navigate,Z as Outlet,N as OutletContext,$ as Route,q as Router,j as RouterContext,X as RouterRoot,ae as route,F as useHandles,z as useLocation,B as useMatch,R as useNavigate,I as useOutlet,V as useParams,P as useRouter,H as useSearch,L as useSubscribe};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waymark",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "license": "MIT",
5
5
  "author": "strblr",
6
6
  "description": "Lightweight type-safe router for React",
@@ -15,9 +15,9 @@
15
15
  },
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/strblr/waymark"
18
+ "url": "git+https://github.com/strblr/waymark.git"
19
19
  },
20
- "homepage": "https://github.com/strblr/waymark",
20
+ "homepage": "https://strblr.github.io/waymark",
21
21
  "bugs": "https://github.com/strblr/waymark/issues",
22
22
  "keywords": [
23
23
  "react",
@@ -39,9 +39,10 @@
39
39
  "minimal"
40
40
  ],
41
41
  "scripts": {
42
- "build": "tsdown --minify --platform browser",
42
+ "build": "tsc --noEmit && tsdown --minify --platform browser",
43
43
  "copy-readme": "cp ../../README.md README.md",
44
- "prepublishOnly": "bun run build && bun run copy-readme"
44
+ "prepublishOnly": "bun run build && bun run copy-readme",
45
+ "postpublish": "rm -f README.md"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@types/bun": "^1.3.6",