raviger 4.1.0 → 4.1.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/CHANGELOG.md +4 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [4.1.2] - 2022-11-02
|
|
8
|
+
### Fixed
|
|
9
|
+
- `useHash` undefined error from missing prop on event
|
|
10
|
+
|
|
7
11
|
## [4.1.0] - 2022-04-24
|
|
8
12
|
### Added
|
|
9
13
|
- Support for React 18
|
package/dist/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react");const e=t.createContext(""),n=t.createContext(null);function RouterProvider({basePath:r="",path:a,children:o}){return t.createElement(e.Provider,{value:r},t.createElement(n.Provider,{value:null!=a?a:null},o))}let r=!0;try{r=void 0===window}catch(t){}const a=new Set;let o=!1,s=!1,u=[0,0];function shouldCancelNavigation(){return u=[window.scrollX,window.scrollY],o?s:Array.from(a).some((t=>{const e=t();return!!e&&(s=!window.confirm(e),o=!0,setTimeout((()=>{o=!1,s=!1}),0),s)}))}function usePath(e){const r=t.useContext(n),a=useBasePath();e=e||a;const[,o]=t.useState(getFormattedPath(e));return useLocationChange(t.useCallback((({path:t})=>o(t)),[]),{basePath:e,inheritBasePath:!e,onInitial:!0}),r||getFormattedPath(e)}function useBasePath(){return t.useContext(e)}function useFullPath(){const[e,n]=t.useState(getCurrentPath());return useLocationChange(t.useCallback((({path:t})=>n(t)),[]),{inheritBasePath:!1}),e||"/"}function getCurrentPath(){return r?"/":window.location.pathname||"/"}function getCurrentHash(){if(r){const t="/",e=t.indexOf("#");return t.substring(e)}return window.location.hash}function useLocationChange(e,{inheritBasePath:n=!0,basePath:a="",isActive:o,onInitial:s=!1}={}){if(r)return;const u=useBasePath();n&&u&&(a=u);const i=t.useRef(e);t.useLayoutEffect((()=>{i.current=e}));const c=t.useCallback((()=>{(void 0===o||isPredicateActive(o))&&(shouldCancelNavigation()||i.current(getFormattedLocation(a)))}),[o,a]);t.useLayoutEffect((()=>(window.addEventListener("popstate",c),()=>window.removeEventListener("popstate",c))),[c]),function useMountedLayout(e,n,{onInitial:r=!1}={}){const a=t.useRef(r);t.useLayoutEffect((()=>{a.current?e():a.current=!0}),n)}((()=>{(void 0===o||isPredicateActive(o))&&i.current(getFormattedLocation(a))}),[a,o],{onInitial:s})}function getRavigerHistory(){return r?{scrollRestoration:"manual",state:null}:{scrollRestoration:window.history.scrollRestoration,state:window.history.state}}function getFormattedPath(t){const e=getCurrentPath(),n=t&&!function isPathInBase(t,e){return!!(t&&e&&e.toLowerCase().startsWith(t.toLowerCase()))}(t,e);return null===e||n?null:decodeURIComponent(t?e.replace(function basePathMatcher(t){return new RegExp("^"+t,"i")}(t),"")||"/":e)}function getFormattedLocation(t){const e=getFormattedPath(t);return{basePath:t,path:e,pathname:e,fullPath:getCurrentPath(),search:window.location.search,hash:getCurrentHash(),host:window.location.host,hostname:window.location.hostname,href:window.location.href,origin:window.location.origin}}function isPredicateActive(t){return function isFunction(t){return!!t&&"function"==typeof t}(t)?t():t}const i=[null,null];function usePathOptions(t,{basePath:e,matchTrailingSlash:n=!0}){const r=useMatchers(Array.isArray(t)?t:[t]);return[trailingMatch(usePath(e),n),r]}function useMatchers(e){return t.useMemo((()=>e.map(createRouteMatcher)),[(n=e,[...n].sort().join(":"))]);var n}function getMatchParams(t,e){let n=null;const r=e.find((({regex:e})=>(n=t.match(e),!!n)));if(!r||null===n)return i;const a=r.props.reduce(((t,e,r)=>(t[e]=n[r+1],t)),{});return[r,a]}function createRouteMatcher(t){var e,n;return{path:t,regex:new RegExp(`${"*"===t.substr(0,1)?"":"^"}${(n=t,n.replace(/[-\\^$+?.()|[\]{}]/g,"\\$&")).replace(/:[a-zA-Z]+/g,"([^/]+)").replace(/\*/g,"")}${"*"===t.substr(-1)?"":"$"}`,"i"),props:(null!==(e=t.match(/:[a-zA-Z]+/g))&&void 0!==e?e:[]).map((t=>t.substr(1)))}}function trailingMatch(t,e){return null===t||e&&t&&"/"===t[t.length-1]&&t.length>1&&(t=t.substring(0,t.length-1)),t}let c="";function navigate(t,e){if("string"!=typeof t)throw new Error('"url" must be a string, was provided a(n) '+typeof t);if(Array.isArray(null==e?void 0:e.query))throw new Error('"query" a serializable object or URLSearchParams');if(shouldCancelNavigation())return;if((null==e?void 0:e.query)&&(t+="?"+new URLSearchParams(e.query).toString()),c=t,function isAbsolute(t){return/^(?:[a-z]+:)?\/\//i.test(t)}(t)&&!function isCurrentOrigin(t){return window.location.origin===new URL(t).origin}(t))return void window.location.assign(t);(null==e?void 0:e.replace)?window.history.replaceState(null==e?void 0:e.state,"",t):window.history.pushState(null==e?void 0:e.state,"",t);const n=new PopStateEvent("popstate");n.__tag="raviger:navigation",dispatchEvent(n)}function useQueryParams(e=parseQuery,n=serializeQuery){const[r,a]=t.useState(getQueryString()),o=t.useCallback(((t,{replace:a=!0}={})=>{let o=getCurrentPath();t=a?t:{...e(r),...t};const s=n(t).toString();s&&(o+="?"+s),a||(o+=getCurrentHash()),navigate(o)}),[r,e,n]);return useLocationChange(t.useCallback((()=>a(getQueryString())),[])),[e(r),o]}function parseQuery(t){const e=new URLSearchParams(t);return Object.fromEntries(e.entries())}function serializeQuery(t){return new URLSearchParams(Object.entries(t).filter((([,t])=>null!==t))).toString()}function getQueryString(){if(r){const t="/",e=t.indexOf("?");return-1===e?"":t.substring(e+1)}return window.location.search}function useRedirect(e,n,{query:r,replace:a=!0,merge:o=!0}={}){const s=usePath(),[u]=useQueryParams(),i=getCurrentHash();let c=n;const l=new URLSearchParams({...o?u:{},...r}).toString();l&&(c+="?"+l),o&&i&&i.length&&(c+=i),t.useLayoutEffect((()=>{s===e&&navigate(c,{replace:a})}),[e,c,a,s])}const l=t.forwardRef((function Link({href:e,basePath:n,...r},a){e=getLinkHref(e,n=useLinkBasePath(n));const{onClick:o,target:s}=r,u=t.useCallback((t=>{try{o&&o(t)}catch(e){throw t.preventDefault(),e}(function shouldTrap(t,e){return!t.defaultPrevented&&0===t.button&&!(e||"_self"===e)&&!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)})(t,s)&&(t.preventDefault(),navigate(t.currentTarget.href))}),[o,s]);return t.createElement("a",{...r,href:e,onClick:u,ref:a})}));const h=t.forwardRef((function ActiveLink({basePath:e,className:n,exactActiveClass:r,activeClass:a,...o},s){e=useLinkBasePath(e);const u=useFullPath();let{href:i}=o;return i=function absolutePathName(t){return t.startsWith("/")?t:new URL(t,document.baseURI).pathname}(getLinkHref(i,e)),r&&u===i&&(n=`${null!=n?n:""} ${r}`.trim()),a&&u.startsWith(i)&&(n=`${null!=n?n:""} ${a}`.trim()),t.createElement(l,{...o,basePath:e,className:n,ref:s})}));function useLinkBasePath(t){const e=useBasePath();return"/"===t?"":t||e}function getLinkHref(t,e=""){return t.startsWith("/")?e+t:t}exports.ActiveLink=h,exports.Link=l,exports.Redirect=function Redirect({to:t,query:e,replace:n=!0,merge:r=!0}){return useRedirect(usePath(),t,{query:e,replace:n,merge:r}),null},exports.RouterProvider=RouterProvider,exports.navigate=navigate,exports.useBasePath=useBasePath,exports.useFullPath=useFullPath,exports.useHash=function useHash({stripHash:e=!0}={}){const[n,r]=t.useState(window.location.hash),a=t.useCallback((()=>{const t=window.location.hash;t!==n&&r(t)}),[r,n]);return t.useLayoutEffect((()=>(window.addEventListener("hashchange",a,!1),()=>window.removeEventListener("hashchange",a))),[a]),useLocationChange(a),e?n.substring(1):n},exports.useHistory=function useHistory(){const[e,n]=t.useState(getRavigerHistory());return useLocationChange(t.useCallback((()=>n(getRavigerHistory())),[n])),e},exports.useLocationChange=useLocationChange,exports.useMatch=function useMatch(t,e={}){var n;const[r,a]=usePathOptions(t,e),o=a.find((({regex:t})=>null==r?void 0:r.match(t)));return null!==(n=null==o?void 0:o.path)&&void 0!==n?n:null},exports.useNavigate=function useNavigate(e=""){const n=useBasePath();return t.useCallback(((t,r)=>{const a=e||n;navigate(t.startsWith("/")?a+t:t,r)}),[n,e])},exports.useNavigationPrompt=function useNavigationPrompt(e=!0,n="Are you sure you want to leave this page?"){r||(t.useLayoutEffect((()=>{const onPopStateNavigation=()=>{shouldCancelNavigation()&&function undoNavigation(t){window.history.pushState(null,null,t),setTimeout((()=>{window.scrollTo(...u)}),0)}(c)};return window.addEventListener("popstate",onPopStateNavigation),()=>window.removeEventListener("popstate",onPopStateNavigation)}),[]),t.useLayoutEffect((()=>{const handler=t=>{if(e)return t?function cancelNavigation(t,e){return t.preventDefault(),t.returnValue=e,e}(t,n):n};return function addInterceptor(t){window.addEventListener("beforeunload",t),a.add(t)}(handler),()=>function removeInterceptor(t){window.removeEventListener("beforeunload",t),a.delete(t)}(handler)}),[e,n]))},exports.usePath=usePath,exports.usePathParams=function usePathParams(t,e={}){const n=!Array.isArray(t),[r,a]=usePathOptions(t,e);if(null===r)return n?null:i;const[o,s]=getMatchParams(r,a);return o?n?s:[o.path,s]:n?null:i},exports.useQueryParams=useQueryParams,exports.useRedirect=useRedirect,exports.useRoutes=function useRoutes(e,{basePath:n="",routeProps:r={},overridePathParams:a=!0,matchTrailingSlash:o=!0}={}){const s=usePath(n)&&getFormattedPath(n);!function useRedirectDetection(e,n){const[,r]=t.useState({}),a=t.useCallback((()=>r({})),[]);t.useLayoutEffect((()=>{n!==getFormattedPath(e)&&a()}),[a,e,n])}(n,usePath(n));const u=function useMatchRoute(t,e,{routeProps:n,overridePathParams:r,matchTrailingSlash:a}){e=trailingMatch(e,a);const o=useMatchers(Object.keys(t));if(null===e)return null;const[s,u]=getMatchParams(e,o);return s?t[s.path](r?{...u,...n}:{...n,...u}):null}(e,s,{routeProps:r,overridePathParams:a,matchTrailingSlash:o});return u&&null!==s?t.createElement(RouterProvider,{basePath:n,path:s},u):null};
|
|
2
2
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sources":["../src/context.tsx","../src/node.ts","../src/intercept.ts","../src/location.ts","../src/hooks.ts","../src/typeChecks.ts","../src/router.tsx","../src/navigate.ts","../src/querystring.ts","../src/redirect.ts","../src/Link.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\n\nconst BasePathContext = createContext('')\nconst PathContext = createContext<string | null>(null)\n\nexport { BasePathContext }\nexport { PathContext }\n\nexport function useRouter(): { basePath: string; path: string | null } {\n const [basePath, path] = [useContext(BasePathContext), useContext(PathContext)]\n return useMemo(() => ({ basePath, path }), [basePath, path])\n}\n\nexport function RouterProvider({\n basePath = '',\n path,\n children,\n}: {\n basePath?: string\n path?: string\n children?: React.ReactNode\n}): JSX.Element {\n return (\n // The ordering here is important, the basePath will change less often\n // So putting it on the outside reduces its need to re-render\n <BasePathContext.Provider value={basePath}>\n <PathContext.Provider value={path ?? null}>{children}</PathContext.Provider>\n </BasePathContext.Provider>\n )\n}\n","let ssrPath = '/'\nlet isNode = true\ntry {\n isNode = window === undefined\n} catch (e) {} // eslint-disable-line no-empty\n\nexport { isNode }\nexport function getSsrPath(): string {\n return ssrPath\n}\nexport function setSsrPath(path: string): void {\n ssrPath = path\n}\n","const interceptors = new Set<() => string | void>()\n\nexport const defaultPrompt = 'Are you sure you want to leave this page?'\n\nlet hasIntercepted = false\nlet hasUserCancelled = false\nlet lastScroll = [0, 0] as [number, number]\n\nexport function shouldCancelNavigation(): boolean {\n lastScroll = [window.scrollX, window.scrollY]\n if (hasIntercepted) return hasUserCancelled\n\n // confirm if any interceptors return true\n return Array.from(interceptors).some((interceptor) => {\n const prompt = interceptor()\n if (!prompt) return false\n\n // cancel navigation if user declines\n hasUserCancelled = !window.confirm(prompt) // eslint-disable-line no-alert\n\n // track user response so that multiple interceptors don't prompt\n hasIntercepted = true\n\n // reset so that future navigation attempts are prompted\n setTimeout(() => {\n hasIntercepted = false\n hasUserCancelled = false\n }, 0)\n\n return hasUserCancelled\n })\n}\n\nexport function addInterceptor(handler: () => string | void): void {\n window.addEventListener('beforeunload', handler)\n interceptors.add(handler)\n}\n\nexport function removeInterceptor(handler: () => string | void): void {\n window.removeEventListener('beforeunload', handler)\n interceptors.delete(handler)\n}\n\nexport function undoNavigation(lastPath: string): void {\n window.history.pushState(null, null as unknown as string, lastPath)\n setTimeout(() => {\n window.scrollTo(...lastScroll)\n }, 0)\n}\n","import { useState, useCallback, useRef, useContext, useLayoutEffect } from 'react'\n\nimport { BasePathContext, PathContext } from './context'\nimport { useMountedLayout } from './hooks'\nimport { getSsrPath, isNode } from './node'\nimport { shouldCancelNavigation } from './intercept'\nimport { isFunction } from './typeChecks'\n\nexport interface RavigerLocation {\n /** The current path; alias of `pathname` */\n path: string | null\n /** The current path; alias of `path` */\n pathname: string | null\n /** The full path, ignores any `basePath` in the context */\n fullPath: string\n basePath?: string\n search: string\n hash: string\n host: string\n hostname: string\n href: string\n origin: string\n}\n\nexport interface RavigerHistory {\n scrollRestoration: 'auto' | 'manual'\n state: unknown\n}\n\nexport interface LocationChangeSetFn {\n (location: RavigerLocation): void\n}\nexport interface LocationChangeOptionParams {\n inheritBasePath?: boolean\n basePath?: string\n isActive?: boolean | (() => boolean)\n onInitial?: boolean\n}\n\nexport function usePath(basePath?: string): string | null {\n const contextPath = useContext(PathContext)\n const contextBasePath = useBasePath() // hooks can't be called conditionally\n basePath = basePath || contextBasePath\n\n // Don't bother tracking the actual path, it can get out of sync\n // due to React parent/child render ordering, especially with onmount navigation\n // See issues:\n // https://github.com/kyeotic/raviger/issues/116\n // https://github.com/kyeotic/raviger/issues/64\n //\n // This is just used to force a re-render\n const [, setPath] = useState(getFormattedPath(basePath))\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, {\n basePath,\n inheritBasePath: !basePath,\n // Use on initial to handle to force state updates from on-mount navigation\n onInitial: true,\n })\n\n return contextPath || getFormattedPath(basePath)\n}\n\nexport function useBasePath(): string {\n return useContext(BasePathContext)\n}\n\nexport function useFullPath(): string {\n const [path, setPath] = useState<string | null>(getCurrentPath())\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, { inheritBasePath: false })\n\n return path || '/'\n}\n\nexport function useHash({ stripHash = true } = {}): string {\n const [hash, setHash] = useState(window.location.hash)\n const handleHash = useCallback(\n ({ hash: newHash }) => {\n if (newHash === hash) return\n setHash(newHash)\n },\n [setHash, hash]\n )\n\n useLayoutEffect(() => {\n window.addEventListener('hashchange', handleHash, false)\n return () => window.removeEventListener('hashchange', handleHash)\n }, [handleHash])\n\n useLocationChange(handleHash)\n return stripHash ? hash.substring(1) : hash\n}\n\nexport function getCurrentPath(): string {\n return isNode ? getSsrPath() : window.location.pathname || '/'\n}\n\nexport function getCurrentHash(): string {\n if (isNode) {\n const path = getSsrPath()\n const hashIndex = path.indexOf('#')\n return path.substring(hashIndex)\n }\n return window.location.hash\n}\n\nexport function useLocationChange(\n setFn: LocationChangeSetFn,\n {\n inheritBasePath = true,\n basePath = '',\n isActive,\n onInitial = false,\n }: LocationChangeOptionParams = {}\n): void {\n if (isNode) return\n\n // All hooks after this are conditional, but the runtime can't actually change\n /* eslint-disable react-hooks/rules-of-hooks */\n\n const routerBasePath = useBasePath()\n if (inheritBasePath && routerBasePath) basePath = routerBasePath\n\n const setRef = useRef<LocationChangeSetFn>(setFn)\n useLayoutEffect(() => {\n // setFn could be an in-render declared callback, making it unstable\n // This is a method of using an often-changing callback from React Hooks\n // https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback\n // While not recommended, it is the best current (16.9) available method\n // For reducing the useEffect cleanup from setFn changing every render\n setRef.current = setFn\n })\n\n const onPopState = useCallback(() => {\n // No predicate defaults true\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n if (shouldCancelNavigation()) return\n setRef.current(getFormattedLocation(basePath))\n }, [isActive, basePath])\n\n useLayoutEffect(() => {\n window.addEventListener('popstate', onPopState)\n return () => window.removeEventListener('popstate', onPopState)\n }, [onPopState])\n\n // When the basePath changes re-check the path after the render completes\n // This allows nested contexts to get an up-to-date formatted path\n useMountedLayout(\n () => {\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n setRef.current(getFormattedLocation(basePath))\n },\n [basePath, isActive],\n { onInitial }\n )\n}\n\nexport function useHistory(): RavigerHistory {\n const [history, setHistory] = useState(getRavigerHistory())\n useLocationChange(useCallback(() => setHistory(getRavigerHistory()), [setHistory]))\n return history\n}\n\nfunction getRavigerHistory(): RavigerHistory {\n if (isNode) return { scrollRestoration: 'manual', state: null }\n return {\n scrollRestoration: window.history.scrollRestoration,\n state: window.history.state,\n }\n}\n\n/**\n * Returns the current path after decoding. If basePath is provided it will be removed from the front of the path.\n * If basePath is provided and the path does not begin with it will return null\n * @param {string} basePath basePath, if any\n * @return {string | null} returns path with basePath prefix removed, or null if basePath is provided and missing\n */\nexport function getFormattedPath(basePath: string): string | null {\n const path = getCurrentPath()\n const baseMissing = basePath && !isPathInBase(basePath, path)\n if (path === null || baseMissing) return null\n return decodeURIComponent(!basePath ? path : path.replace(basePathMatcher(basePath), '') || '/')\n}\n\nfunction getFormattedLocation(basePath: string): RavigerLocation {\n const path = getFormattedPath(basePath)\n return {\n basePath,\n path,\n pathname: path,\n fullPath: getCurrentPath(),\n search: window.location.search,\n hash: getCurrentHash(),\n host: window.location.host,\n hostname: window.location.hostname,\n href: window.location.href,\n origin: window.location.origin,\n }\n}\n\nfunction isPredicateActive(predicate: boolean | (() => boolean)): boolean {\n return isFunction(predicate) ? predicate() : predicate\n}\n\nfunction basePathMatcher(basePath: string): RegExp {\n return new RegExp('^' + basePath, 'i')\n}\n\nfunction isPathInBase(basePath: string, path: string): boolean {\n return !!(basePath && path && path.toLowerCase().startsWith(basePath.toLowerCase()))\n}\n","import { useLayoutEffect, useRef } from 'react'\n\nexport function useMountedLayout(\n fn: () => unknown,\n deps: React.DependencyList | undefined,\n { onInitial = false } = {}\n): void {\n const hasMounted = useRef(onInitial)\n useLayoutEffect(() => {\n if (!hasMounted.current) hasMounted.current = true\n else fn()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n","// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types\nexport function isFunction(obj: unknown): obj is Function {\n return !!obj && typeof obj === 'function'\n}\n","import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\n\nimport { RouterProvider } from './context'\nimport { isNode, setSsrPath, getSsrPath } from './node'\nimport { getFormattedPath, usePath } from './location'\nimport type { NonEmptyRecord, Split, ValueOf } from './types'\n\nconst emptyPathResult: [null, null] = [null, null]\n\nexport interface PathParamOptions {\n basePath?: string\n matchTrailingSlash?: boolean\n}\nexport interface RouteOptionParams extends PathParamOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routeProps?: { [k: string]: any }\n overridePathParams?: boolean\n}\ninterface RouteMatcher {\n path: string\n regex: RegExp\n props: string[]\n}\n\ntype ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [\n infer Head,\n ...infer Tail\n]\n ? Head extends `:${infer Name}`\n ? { [N in Name]: string } & ExtractPathParams<Path, Tail>\n : ExtractPathParams<Path, Tail>\n : unknown\n\nexport type Routes<Path extends string> = {\n [P in Path]: (\n params: NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ) => JSX.Element\n}\n\nexport function useRoutes<Path extends string>(\n routes: Routes<Path>,\n {\n basePath = '',\n routeProps = {},\n overridePathParams = true,\n matchTrailingSlash = true,\n }: RouteOptionParams = {}\n): JSX.Element | null {\n /*\n This is a hack to setup a listener for the path while always using this latest path\n The issue with usePath is that, in order to not re-render nested components when\n their parent router changes the path, it uses the context's path\n But since that path has to get _set_ here in useRoutes something has to give\n If usePath returns latest it causes render thrashing\n If useRoutes hacks itself into the latest path nothing bad happens (...afaik)\n */\n const path = usePath(basePath) && getFormattedPath(basePath)\n\n // Handle potential <Redirect /> use in routes\n useRedirectDetection(basePath, usePath(basePath))\n\n // Get the current route\n const route = useMatchRoute(routes, path, {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n })\n\n // No match should not return an empty Provider, just null\n if (!route || path === null) return null\n return (\n <RouterProvider basePath={basePath} path={path}>\n {route}\n </RouterProvider>\n )\n}\n\nfunction useMatchRoute(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routes: { [key: string]: (...props: any) => JSX.Element },\n path: string | null,\n {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n }: Omit<RouteOptionParams, 'basePath' | 'matchTrailingSlash'> & { matchTrailingSlash: boolean }\n) {\n path = trailingMatch(path, matchTrailingSlash)\n const matchers = useMatchers(Object.keys(routes))\n\n if (path === null) return null\n const [routeMatch, props] = getMatchParams(path, matchers)\n\n if (!routeMatch) return null\n\n return routes[routeMatch.path](\n overridePathParams ? { ...props, ...routeProps } : { ...routeProps, ...props }\n )\n}\n\nexport function usePathParams<Path extends string>(\n route: Path,\n options?: PathParamOptions\n): NonEmptyRecord<ExtractPathParams<Path extends `${infer P1}*` ? P1 : Path>> | null\nexport function usePathParams<Path extends string>(\n routes: ReadonlyArray<Path>,\n options?: PathParamOptions\n):\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\nexport function usePathParams<Params extends ReadonlyArray<string> | string>(\n routes: Params,\n options: PathParamOptions = {}\n): Params extends ReadonlyArray<string>\n ?\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\n : Params extends string\n ? NonEmptyRecord<ExtractPathParams<Params extends `${infer P1}*` ? P1 : Params>> | null\n : never {\n const isSingle = !Array.isArray(routes)\n const [path, matchers] = usePathOptions(routes as string | string[], options)\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (path === null) return isSingle ? null : emptyPathResult\n\n const [routeMatch, props] = getMatchParams(path, matchers)\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (!routeMatch) return isSingle ? null : emptyPathResult\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n return isSingle\n ? props\n : ([routeMatch.path, props] as ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>)\n}\n\nexport function useMatch(routes: string | string[], options: PathParamOptions = {}): string | null {\n const [path, matchers] = usePathOptions(routes, options)\n const match = matchers.find(({ regex }) => path?.match(regex))\n\n return match?.path ?? null\n}\n\nfunction usePathOptions(\n routeOrRoutes: string | string[],\n { basePath, matchTrailingSlash = true }: PathParamOptions\n): [string | null, RouteMatcher[]] {\n const routes = (!Array.isArray(routeOrRoutes) ? [routeOrRoutes] : routeOrRoutes) as string[]\n const matchers = useMatchers(routes)\n\n return [trailingMatch(usePath(basePath), matchTrailingSlash), matchers]\n}\n\nfunction useMatchers(routes: string[]): RouteMatcher[] {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => routes.map(createRouteMatcher), [hashParams(routes)])\n}\n\nfunction getMatchParams(\n path: string,\n routeMatchers: RouteMatcher[]\n): [RouteMatcher, Record<string, unknown>] | [null, null] {\n let pathParams: RegExpMatchArray | null = null\n\n // Hacky method for find + map\n const routeMatch = routeMatchers.find(({ regex }) => {\n pathParams = path.match(regex)\n return !!pathParams\n })\n\n if (!routeMatch || pathParams === null) return emptyPathResult\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const props = routeMatch.props.reduce((props: any, prop, i) => {\n // The following `match` can't be null because the above return asserts it\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n props[prop] = pathParams![i + 1]\n return props\n }, {})\n\n return [routeMatch, props]\n}\n\nfunction createRouteMatcher(path: string): RouteMatcher {\n return {\n path,\n regex: new RegExp(\n `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path)\n .replace(/:[a-zA-Z]+/g, '([^/]+)')\n .replace(/\\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`,\n 'i'\n ),\n props: (path.match(/:[a-zA-Z]+/g) ?? []).map((paramName) => paramName.substr(1)),\n }\n}\n\nexport function setPath(path: string): void {\n if (!isNode) {\n throw new Error('This method should only be used in NodeJS environments')\n }\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const url = require('url')\n setSsrPath(url.resolve(getSsrPath(), path))\n}\n\n// React doesn't like when the hook dependency array changes size\n// >> Warning: The final argument passed to useMemo changed size between renders. The order and size of this array must remain constant.\n// It is recommended to use a hashing function to produce a single, stable value\n// https://github.com/facebook/react/issues/14324#issuecomment-441489421\nfunction hashParams(params: string[]): string {\n return [...params].sort().join(':')\n}\n\n// React appears to suppress parent's re-rendering when a child's\n// useLayoutEffect updates internal state\n// the `navigate` call in useRedirect *does* cause usePath/useLocationChange\n// to fire, but without this hack useRoutes suppresses the update\n// TODO: find a better way to cause a synchronous update from useRoutes\nfunction useRedirectDetection(basePath: string, path: string | null) {\n const [, updateState] = useState({})\n const forceRender = useCallback(() => updateState({}), [])\n\n useLayoutEffect(() => {\n if (path !== getFormattedPath(basePath)) {\n forceRender()\n }\n }, [forceRender, basePath, path])\n}\n\nfunction trailingMatch(path: string | null, matchTrailingSlash: boolean): string | null {\n if (path === null) return path\n // path.length > 1 ensure we still match on the root route \"/\" when matchTrailingSlash is set\n if (matchTrailingSlash && path && path[path.length - 1] === '/' && path.length > 1) {\n path = path.substring(0, path.length - 1)\n }\n return path\n}\n\n// Taken from: https://stackoverflow.com/a/3561711\n// modified to NOT ESCAPE \"/\" and \"*\" since we use those as path parts\nfunction escapeRegExp(string: string): string {\n return string.replace(/[-\\\\^$+?.()|[\\]{}]/g, '\\\\$&')\n}\n","import { useCallback, useLayoutEffect } from 'react'\n\nimport { useBasePath } from './location'\nimport { isNode } from './node'\nimport type { QueryParam } from './querystring'\nimport {\n shouldCancelNavigation,\n addInterceptor,\n removeInterceptor,\n defaultPrompt,\n undoNavigation,\n} from './intercept'\n\nexport interface NavigateOptions {\n /**\n * Use a `replace` instead of `push` for navigation\n * @default false */\n replace?: boolean\n /** Values to serialize as a querystring, which will be appended to the `url` */\n query?: QueryParam | URLSearchParams\n /** value to pass as the state/data to history push/replace*/\n state?: unknown\n}\n\nlet lastPath = ''\n\nexport function navigate(url: string, options?: NavigateOptions): void {\n if (typeof url !== 'string') {\n throw new Error(`\"url\" must be a string, was provided a(n) ${typeof url}`)\n }\n\n if (Array.isArray(options?.query)) {\n throw new Error('\"query\" a serializable object or URLSearchParams')\n }\n\n if (shouldCancelNavigation()) return\n if (options?.query) {\n url += '?' + new URLSearchParams(options.query).toString()\n }\n\n lastPath = url\n // if the origin does not match history navigation will fail with\n // \"cannot be created in a document with origin\"\n // When navigating to another domain we must use location instead of history\n if (isAbsolute(url) && !isCurrentOrigin(url)) {\n window.location.assign(url)\n return\n }\n\n if (options?.replace) window.history.replaceState(options?.state, '', url)\n else window.history.pushState(options?.state, '', url)\n\n const event = new PopStateEvent('popstate')\n // Tag the event so navigation can be filtered out from browser events\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(event as any).__tag = 'raviger:navigation'\n dispatchEvent(event)\n}\n\nexport function useNavigationPrompt(predicate = true, prompt: string = defaultPrompt): void {\n if (isNode) return\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const onPopStateNavigation = () => {\n if (shouldCancelNavigation()) {\n undoNavigation(lastPath)\n }\n }\n window.addEventListener('popstate', onPopStateNavigation)\n return () => window.removeEventListener('popstate', onPopStateNavigation)\n }, [])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const handler = (e?: BeforeUnloadEvent): string | void => {\n if (predicate) {\n return e ? cancelNavigation(e, prompt) : prompt\n }\n }\n addInterceptor(handler)\n return () => removeInterceptor(handler)\n }, [predicate, prompt])\n}\n\nfunction cancelNavigation(event: BeforeUnloadEvent, prompt: string) {\n // Cancel the event as stated by the standard.\n event.preventDefault()\n // Chrome requires returnValue to be set.\n event.returnValue = prompt\n // Return value for prompt per spec\n return prompt\n}\n\nexport function useNavigate(optBasePath = ''): typeof navigate {\n const basePath = useBasePath()\n const navigateWithBasePath = useCallback<typeof navigate>(\n (url: string, options?: NavigateOptions) => {\n const base = optBasePath || basePath\n const href = url.startsWith('/') ? base + url : url\n navigate(href, options)\n },\n [basePath, optBasePath]\n )\n return navigateWithBasePath\n}\n\nfunction isAbsolute(url: string) {\n return /^(?:[a-z]+:)?\\/\\//i.test(url)\n}\n\nfunction isCurrentOrigin(url: string) {\n return window.location.origin === new URL(url).origin\n}\n","import { useState, useCallback } from 'react'\n\nimport { navigate } from './navigate'\nimport { isNode, getSsrPath } from './node'\nimport { getCurrentPath, getCurrentHash, useLocationChange } from './location'\n\nexport interface QueryParam {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\nexport interface setQueryParamsOptions {\n replace?: boolean\n}\n\nexport function useQueryParams<T extends QueryParam>(\n parseFn: (query: string) => T = parseQuery,\n serializeFn: (query: Partial<T>) => string = serializeQuery\n): [T, (query: T, options?: setQueryParamsOptions) => void] {\n const [querystring, setQuerystring] = useState(getQueryString())\n const setQueryParams = useCallback(\n (params, { replace = true } = {}) => {\n let path = getCurrentPath()\n params = replace ? params : { ...parseFn(querystring), ...params }\n const serialized = serializeFn(params).toString()\n\n if (serialized) path += '?' + serialized\n if (!replace) path += getCurrentHash()\n\n navigate(path)\n },\n [querystring, parseFn, serializeFn]\n )\n\n // Update state when route changes\n const updateQuery = useCallback(() => setQuerystring(getQueryString()), [])\n\n useLocationChange(updateQuery)\n return [parseFn(querystring), setQueryParams]\n}\n\nfunction parseQuery<T extends QueryParam>(querystring: string): T {\n const q = new URLSearchParams(querystring)\n return Object.fromEntries(q.entries()) as T\n}\n\nfunction serializeQuery<T extends QueryParam>(queryParams: T): string {\n return new URLSearchParams(Object.entries(queryParams).filter(([, v]) => v !== null)).toString()\n}\n\nexport function getQueryString(): string {\n if (isNode) {\n const ssrPath = getSsrPath()\n const queryIndex = ssrPath.indexOf('?')\n return queryIndex === -1 ? '' : ssrPath.substring(queryIndex + 1)\n }\n return window.location.search\n}\n","import { useLayoutEffect } from 'react'\n\nimport { getCurrentHash, usePath } from './location'\nimport { navigate } from './navigate'\nimport { QueryParam, useQueryParams } from './querystring'\n\nexport interface RedirectProps {\n to: string\n query?: QueryParam | URLSearchParams\n replace?: boolean\n merge?: boolean\n}\n\nexport interface UseRedirectProps {\n predicateUrl: string\n targetUrl: string\n queryParams?: QueryParam | URLSearchParams\n replace?: boolean\n}\n\nexport function Redirect({\n to,\n query,\n replace = true,\n merge = true,\n}: RedirectProps): JSX.Element | null {\n useRedirect(usePath(), to, { query, replace, merge })\n return null\n}\n\nexport function useRedirect(\n predicateUrl: string | null,\n targetUrl: string,\n {\n query,\n replace = true,\n merge = true,\n }: { query?: QueryParam; replace?: boolean; merge?: boolean } = {}\n): void {\n const currentPath = usePath()\n const [currentQuery] = useQueryParams()\n const hash = getCurrentHash()\n\n let url = targetUrl\n const targetQuery = new URLSearchParams({\n ...(merge ? currentQuery : {}),\n ...query,\n }).toString()\n if (targetQuery) {\n url += '?' + targetQuery\n }\n if (merge && hash && hash.length) {\n url += hash\n }\n\n useLayoutEffect(() => {\n if (currentPath === predicateUrl) {\n navigate(url, { replace })\n }\n }, [predicateUrl, url, replace, currentPath])\n}\n","import React, { useCallback, forwardRef, Ref } from 'react'\n\nimport { navigate } from './navigate'\nimport { useBasePath, useFullPath } from './location'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n basePath?: string\n children?: React.ReactNode\n}\nexport type LinkRef = HTMLAnchorElement | null\n\nexport interface ActiveLinkProps extends LinkProps {\n activeClass?: string\n exactActiveClass?: string\n}\n\nfunction Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>) {\n basePath = useLinkBasePath(basePath)\n href = getLinkHref(href, basePath)\n\n const { onClick, target } = props\n\n const handleClick = useCallback<React.MouseEventHandler<HTMLAnchorElement>>(\n (e) => {\n try {\n if (onClick) onClick(e)\n } catch (ex) {\n e.preventDefault()\n throw ex\n }\n if (shouldTrap(e, target)) {\n e.preventDefault() // prevent the link from actually navigating\n navigate(e.currentTarget.href)\n }\n },\n [onClick, target]\n )\n\n return <a {...props} href={href} onClick={handleClick} ref={ref} />\n}\n\nconst RefLink = forwardRef<LinkRef, LinkProps>(Link) as (\n props: LinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof Link>\n\nexport default RefLink\nexport { RefLink as Link }\n\nfunction ActiveLink(\n { basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps,\n ref?: Ref<HTMLAnchorElement>\n) {\n basePath = useLinkBasePath(basePath)\n const fullPath = useFullPath()\n\n let { href } = props\n href = absolutePathName(getLinkHref(href, basePath))\n\n if (exactActiveClass && fullPath === href) className += ` ${exactActiveClass}`\n if (activeClass && fullPath.startsWith(href)) className += ` ${activeClass}`\n\n return <RefLink {...props} basePath={basePath} className={className} ref={ref} />\n}\n\nconst ActiveLinkRef = forwardRef<LinkRef, ActiveLinkProps>(ActiveLink) as (\n props: ActiveLinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof ActiveLink>\n\nexport { ActiveLinkRef as ActiveLink }\n\nfunction useLinkBasePath(basePath?: string): string {\n const contextBasePath = useBasePath()\n if (basePath === '/') return ''\n return basePath || contextBasePath\n}\n\nfunction getLinkHref(href: string, basePath = '') {\n return href.startsWith('/') ? basePath + href : href\n}\n\nfunction absolutePathName(href: string): string {\n if (href.startsWith('/')) return href\n return new URL(href, document.baseURI).pathname\n}\n\nfunction shouldTrap(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, target?: string) {\n return (\n !e.defaultPrevented && // onClick prevented default\n e.button === 0 && // ignore everything but left clicks\n !(target || target === '_self') && // don't trap target === blank\n !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n )\n}\n"],"names":["BasePathContext","createContext","PathContext","RouterProvider","basePath","path","children","React","createElement","Provider","value","isNode","undefined","window","e","interceptors","Set","hasIntercepted","hasUserCancelled","lastScroll","shouldCancelNavigation","scrollX","scrollY","Array","from","some","interceptor","prompt","confirm","setTimeout","usePath","contextPath","useContext","contextBasePath","useBasePath","setPath","useState","getFormattedPath","useLocationChange","useCallback","newPath","inheritBasePath","onInitial","useFullPath","getCurrentPath","location","pathname","getCurrentHash","hashIndex","indexOf","substring","hash","setFn","isActive","routerBasePath","setRef","useRef","useLayoutEffect","current","onPopState","isPredicateActive","getFormattedLocation","addEventListener","removeEventListener","useMountedLayout","fn","deps","hasMounted","getRavigerHistory","scrollRestoration","state","history","baseMissing","isPathInBase","toLowerCase","startsWith","decodeURIComponent","replace","basePathMatcher","RegExp","fullPath","search","host","hostname","href","origin","predicate","isFunction","obj","emptyPathResult","usePathOptions","routeOrRoutes","matchTrailingSlash","matchers","useMatchers","isArray","trailingMatch","routes","useMemo","map","createRouteMatcher","params","sort","join","getMatchParams","routeMatchers","pathParams","routeMatch","find","regex","match","props","reduce","prop","i","string","substr","_a","paramName","length","lastPath","navigate","url","options","Error","query","URLSearchParams","toString","isAbsolute","test","isCurrentOrigin","URL","assign","replaceState","pushState","event","PopStateEvent","__tag","dispatchEvent","useQueryParams","parseFn","parseQuery","serializeFn","serializeQuery","querystring","setQuerystring","getQueryString","setQueryParams","serialized","q","Object","fromEntries","entries","queryParams","filter","v","ssrPath","queryIndex","useRedirect","predicateUrl","targetUrl","merge","currentPath","currentQuery","targetQuery","RefLink","forwardRef","Link","ref","getLinkHref","useLinkBasePath","onClick","target","handleClick","ex","preventDefault","shouldTrap","defaultPrevented","button","metaKey","altKey","ctrlKey","shiftKey","currentTarget","ActiveLinkRef","ActiveLink","className","exactActiveClass","activeClass","absolutePathName","document","baseURI","Redirect","to","useHash","stripHash","setHash","handleHash","newHash","useHistory","setHistory","useMatch","useNavigate","optBasePath","base","useNavigationPrompt","onPopStateNavigation","undoNavigation","scrollTo","handler","cancelNavigation","returnValue","addInterceptor","add","removeInterceptor","delete","usePathParams","isSingle","useRoutes","routeProps","overridePathParams","useRedirectDetection","updateState","forceRender","route","useMatchRoute","keys"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","sources":["../src/context.tsx","../src/node.ts","../src/intercept.ts","../src/location.ts","../src/hooks.ts","../src/typeChecks.ts","../src/router.tsx","../src/navigate.ts","../src/querystring.ts","../src/redirect.ts","../src/Link.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\n\nconst BasePathContext = createContext('')\nconst PathContext = createContext<string | null>(null)\n\nexport { BasePathContext }\nexport { PathContext }\n\nexport function useRouter(): { basePath: string; path: string | null } {\n const [basePath, path] = [useContext(BasePathContext), useContext(PathContext)]\n return useMemo(() => ({ basePath, path }), [basePath, path])\n}\n\nexport function RouterProvider({\n basePath = '',\n path,\n children,\n}: {\n basePath?: string\n path?: string\n children?: React.ReactNode\n}): JSX.Element {\n return (\n // The ordering here is important, the basePath will change less often\n // So putting it on the outside reduces its need to re-render\n <BasePathContext.Provider value={basePath}>\n <PathContext.Provider value={path ?? null}>{children}</PathContext.Provider>\n </BasePathContext.Provider>\n )\n}\n","let ssrPath = '/'\nlet isNode = true\ntry {\n isNode = window === undefined\n} catch (e) {} // eslint-disable-line no-empty\n\nexport { isNode }\nexport function getSsrPath(): string {\n return ssrPath\n}\nexport function setSsrPath(path: string): void {\n ssrPath = path\n}\n","const interceptors = new Set<() => string | void>()\n\nexport const defaultPrompt = 'Are you sure you want to leave this page?'\n\nlet hasIntercepted = false\nlet hasUserCancelled = false\nlet lastScroll = [0, 0] as [number, number]\n\nexport function shouldCancelNavigation(): boolean {\n lastScroll = [window.scrollX, window.scrollY]\n if (hasIntercepted) return hasUserCancelled\n\n // confirm if any interceptors return true\n return Array.from(interceptors).some((interceptor) => {\n const prompt = interceptor()\n if (!prompt) return false\n\n // cancel navigation if user declines\n hasUserCancelled = !window.confirm(prompt) // eslint-disable-line no-alert\n\n // track user response so that multiple interceptors don't prompt\n hasIntercepted = true\n\n // reset so that future navigation attempts are prompted\n setTimeout(() => {\n hasIntercepted = false\n hasUserCancelled = false\n }, 0)\n\n return hasUserCancelled\n })\n}\n\nexport function addInterceptor(handler: () => string | void): void {\n window.addEventListener('beforeunload', handler)\n interceptors.add(handler)\n}\n\nexport function removeInterceptor(handler: () => string | void): void {\n window.removeEventListener('beforeunload', handler)\n interceptors.delete(handler)\n}\n\nexport function undoNavigation(lastPath: string): void {\n window.history.pushState(null, null as unknown as string, lastPath)\n setTimeout(() => {\n window.scrollTo(...lastScroll)\n }, 0)\n}\n","import { useState, useCallback, useRef, useContext, useLayoutEffect } from 'react'\n\nimport { BasePathContext, PathContext } from './context'\nimport { useMountedLayout } from './hooks'\nimport { getSsrPath, isNode } from './node'\nimport { shouldCancelNavigation } from './intercept'\nimport { isFunction } from './typeChecks'\n\nexport interface RavigerLocation {\n /** The current path; alias of `pathname` */\n path: string | null\n /** The current path; alias of `path` */\n pathname: string | null\n /** The full path, ignores any `basePath` in the context */\n fullPath: string\n basePath?: string\n search: string\n hash: string\n host: string\n hostname: string\n href: string\n origin: string\n}\n\nexport interface RavigerHistory {\n scrollRestoration: 'auto' | 'manual'\n state: unknown\n}\n\nexport interface LocationChangeSetFn {\n (location: RavigerLocation): void\n}\nexport interface LocationChangeOptionParams {\n inheritBasePath?: boolean\n basePath?: string\n isActive?: boolean | (() => boolean)\n onInitial?: boolean\n}\n\nexport function usePath(basePath?: string): string | null {\n const contextPath = useContext(PathContext)\n const contextBasePath = useBasePath() // hooks can't be called conditionally\n basePath = basePath || contextBasePath\n\n // Don't bother tracking the actual path, it can get out of sync\n // due to React parent/child render ordering, especially with onmount navigation\n // See issues:\n // https://github.com/kyeotic/raviger/issues/116\n // https://github.com/kyeotic/raviger/issues/64\n //\n // This is just used to force a re-render\n const [, setPath] = useState(getFormattedPath(basePath))\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, {\n basePath,\n inheritBasePath: !basePath,\n // Use on initial to handle to force state updates from on-mount navigation\n onInitial: true,\n })\n\n return contextPath || getFormattedPath(basePath)\n}\n\nexport function useBasePath(): string {\n return useContext(BasePathContext)\n}\n\nexport function useFullPath(): string {\n const [path, setPath] = useState<string | null>(getCurrentPath())\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, { inheritBasePath: false })\n\n return path || '/'\n}\n\nexport function useHash({ stripHash = true } = {}): string {\n const [hash, setHash] = useState(window.location.hash)\n const handleHash = useCallback(() => {\n const newHash = window.location.hash\n if (newHash === hash) return\n setHash(newHash)\n }, [setHash, hash])\n\n useLayoutEffect(() => {\n window.addEventListener('hashchange', handleHash, false)\n return () => window.removeEventListener('hashchange', handleHash)\n }, [handleHash])\n\n useLocationChange(handleHash)\n return stripHash ? hash.substring(1) : hash\n}\n\nexport function getCurrentPath(): string {\n return isNode ? getSsrPath() : window.location.pathname || '/'\n}\n\nexport function getCurrentHash(): string {\n if (isNode) {\n const path = getSsrPath()\n const hashIndex = path.indexOf('#')\n return path.substring(hashIndex)\n }\n return window.location.hash\n}\n\nexport function useLocationChange(\n setFn: LocationChangeSetFn,\n {\n inheritBasePath = true,\n basePath = '',\n isActive,\n onInitial = false,\n }: LocationChangeOptionParams = {}\n): void {\n if (isNode) return\n\n // All hooks after this are conditional, but the runtime can't actually change\n /* eslint-disable react-hooks/rules-of-hooks */\n\n const routerBasePath = useBasePath()\n if (inheritBasePath && routerBasePath) basePath = routerBasePath\n\n const setRef = useRef<LocationChangeSetFn>(setFn)\n useLayoutEffect(() => {\n // setFn could be an in-render declared callback, making it unstable\n // This is a method of using an often-changing callback from React Hooks\n // https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback\n // While not recommended, it is the best current (16.9) available method\n // For reducing the useEffect cleanup from setFn changing every render\n setRef.current = setFn\n })\n\n const onPopState = useCallback(() => {\n // No predicate defaults true\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n if (shouldCancelNavigation()) return\n setRef.current(getFormattedLocation(basePath))\n }, [isActive, basePath])\n\n useLayoutEffect(() => {\n window.addEventListener('popstate', onPopState)\n return () => window.removeEventListener('popstate', onPopState)\n }, [onPopState])\n\n // When the basePath changes re-check the path after the render completes\n // This allows nested contexts to get an up-to-date formatted path\n useMountedLayout(\n () => {\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n setRef.current(getFormattedLocation(basePath))\n },\n [basePath, isActive],\n { onInitial }\n )\n}\n\nexport function useHistory(): RavigerHistory {\n const [history, setHistory] = useState(getRavigerHistory())\n useLocationChange(useCallback(() => setHistory(getRavigerHistory()), [setHistory]))\n return history\n}\n\nfunction getRavigerHistory(): RavigerHistory {\n if (isNode) return { scrollRestoration: 'manual', state: null }\n return {\n scrollRestoration: window.history.scrollRestoration,\n state: window.history.state,\n }\n}\n\n/**\n * Returns the current path after decoding. If basePath is provided it will be removed from the front of the path.\n * If basePath is provided and the path does not begin with it will return null\n * @param {string} basePath basePath, if any\n * @return {string | null} returns path with basePath prefix removed, or null if basePath is provided and missing\n */\nexport function getFormattedPath(basePath: string): string | null {\n const path = getCurrentPath()\n const baseMissing = basePath && !isPathInBase(basePath, path)\n if (path === null || baseMissing) return null\n return decodeURIComponent(!basePath ? path : path.replace(basePathMatcher(basePath), '') || '/')\n}\n\nfunction getFormattedLocation(basePath: string): RavigerLocation {\n const path = getFormattedPath(basePath)\n return {\n basePath,\n path,\n pathname: path,\n fullPath: getCurrentPath(),\n search: window.location.search,\n hash: getCurrentHash(),\n host: window.location.host,\n hostname: window.location.hostname,\n href: window.location.href,\n origin: window.location.origin,\n }\n}\n\nfunction isPredicateActive(predicate: boolean | (() => boolean)): boolean {\n return isFunction(predicate) ? predicate() : predicate\n}\n\nfunction basePathMatcher(basePath: string): RegExp {\n return new RegExp('^' + basePath, 'i')\n}\n\nfunction isPathInBase(basePath: string, path: string): boolean {\n return !!(basePath && path && path.toLowerCase().startsWith(basePath.toLowerCase()))\n}\n","import { useLayoutEffect, useRef } from 'react'\n\nexport function useMountedLayout(\n fn: () => unknown,\n deps: React.DependencyList | undefined,\n { onInitial = false } = {}\n): void {\n const hasMounted = useRef(onInitial)\n useLayoutEffect(() => {\n if (!hasMounted.current) hasMounted.current = true\n else fn()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n","// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types\nexport function isFunction(obj: unknown): obj is Function {\n return !!obj && typeof obj === 'function'\n}\n","import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\n\nimport { RouterProvider } from './context'\nimport { isNode, setSsrPath, getSsrPath } from './node'\nimport { getFormattedPath, usePath } from './location'\nimport type { NonEmptyRecord, Split, ValueOf } from './types'\n\nconst emptyPathResult: [null, null] = [null, null]\n\nexport interface PathParamOptions {\n basePath?: string\n matchTrailingSlash?: boolean\n}\nexport interface RouteOptionParams extends PathParamOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routeProps?: { [k: string]: any }\n overridePathParams?: boolean\n}\ninterface RouteMatcher {\n path: string\n regex: RegExp\n props: string[]\n}\n\ntype ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [\n infer Head,\n ...infer Tail\n]\n ? Head extends `:${infer Name}`\n ? { [N in Name]: string } & ExtractPathParams<Path, Tail>\n : ExtractPathParams<Path, Tail>\n : unknown\n\nexport type Routes<Path extends string> = {\n [P in Path]: (\n params: NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ) => JSX.Element\n}\n\nexport function useRoutes<Path extends string>(\n routes: Routes<Path>,\n {\n basePath = '',\n routeProps = {},\n overridePathParams = true,\n matchTrailingSlash = true,\n }: RouteOptionParams = {}\n): JSX.Element | null {\n /*\n This is a hack to setup a listener for the path while always using this latest path\n The issue with usePath is that, in order to not re-render nested components when\n their parent router changes the path, it uses the context's path\n But since that path has to get _set_ here in useRoutes something has to give\n If usePath returns latest it causes render thrashing\n If useRoutes hacks itself into the latest path nothing bad happens (...afaik)\n */\n const path = usePath(basePath) && getFormattedPath(basePath)\n\n // Handle potential <Redirect /> use in routes\n useRedirectDetection(basePath, usePath(basePath))\n\n // Get the current route\n const route = useMatchRoute(routes, path, {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n })\n\n // No match should not return an empty Provider, just null\n if (!route || path === null) return null\n return (\n <RouterProvider basePath={basePath} path={path}>\n {route}\n </RouterProvider>\n )\n}\n\nfunction useMatchRoute(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routes: { [key: string]: (...props: any) => JSX.Element },\n path: string | null,\n {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n }: Omit<RouteOptionParams, 'basePath' | 'matchTrailingSlash'> & { matchTrailingSlash: boolean }\n) {\n path = trailingMatch(path, matchTrailingSlash)\n const matchers = useMatchers(Object.keys(routes))\n\n if (path === null) return null\n const [routeMatch, props] = getMatchParams(path, matchers)\n\n if (!routeMatch) return null\n\n return routes[routeMatch.path](\n overridePathParams ? { ...props, ...routeProps } : { ...routeProps, ...props }\n )\n}\n\nexport function usePathParams<Path extends string>(\n route: Path,\n options?: PathParamOptions\n): NonEmptyRecord<ExtractPathParams<Path extends `${infer P1}*` ? P1 : Path>> | null\nexport function usePathParams<Path extends string>(\n routes: ReadonlyArray<Path>,\n options?: PathParamOptions\n):\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\nexport function usePathParams<Params extends ReadonlyArray<string> | string>(\n routes: Params,\n options: PathParamOptions = {}\n): Params extends ReadonlyArray<string>\n ?\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\n : Params extends string\n ? NonEmptyRecord<ExtractPathParams<Params extends `${infer P1}*` ? P1 : Params>> | null\n : never {\n const isSingle = !Array.isArray(routes)\n const [path, matchers] = usePathOptions(routes as string | string[], options)\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (path === null) return isSingle ? null : emptyPathResult\n\n const [routeMatch, props] = getMatchParams(path, matchers)\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (!routeMatch) return isSingle ? null : emptyPathResult\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n return isSingle\n ? props\n : ([routeMatch.path, props] as ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>)\n}\n\nexport function useMatch(routes: string | string[], options: PathParamOptions = {}): string | null {\n const [path, matchers] = usePathOptions(routes, options)\n const match = matchers.find(({ regex }) => path?.match(regex))\n\n return match?.path ?? null\n}\n\nfunction usePathOptions(\n routeOrRoutes: string | string[],\n { basePath, matchTrailingSlash = true }: PathParamOptions\n): [string | null, RouteMatcher[]] {\n const routes = (!Array.isArray(routeOrRoutes) ? [routeOrRoutes] : routeOrRoutes) as string[]\n const matchers = useMatchers(routes)\n\n return [trailingMatch(usePath(basePath), matchTrailingSlash), matchers]\n}\n\nfunction useMatchers(routes: string[]): RouteMatcher[] {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => routes.map(createRouteMatcher), [hashParams(routes)])\n}\n\nfunction getMatchParams(\n path: string,\n routeMatchers: RouteMatcher[]\n): [RouteMatcher, Record<string, unknown>] | [null, null] {\n let pathParams: RegExpMatchArray | null = null\n\n // Hacky method for find + map\n const routeMatch = routeMatchers.find(({ regex }) => {\n pathParams = path.match(regex)\n return !!pathParams\n })\n\n if (!routeMatch || pathParams === null) return emptyPathResult\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const props = routeMatch.props.reduce((props: any, prop, i) => {\n // The following `match` can't be null because the above return asserts it\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n props[prop] = pathParams![i + 1]\n return props\n }, {})\n\n return [routeMatch, props]\n}\n\nfunction createRouteMatcher(path: string): RouteMatcher {\n return {\n path,\n regex: new RegExp(\n `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path)\n .replace(/:[a-zA-Z]+/g, '([^/]+)')\n .replace(/\\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`,\n 'i'\n ),\n props: (path.match(/:[a-zA-Z]+/g) ?? []).map((paramName) => paramName.substr(1)),\n }\n}\n\nexport function setPath(path: string): void {\n if (!isNode) {\n throw new Error('This method should only be used in NodeJS environments')\n }\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const url = require('url')\n setSsrPath(url.resolve(getSsrPath(), path))\n}\n\n// React doesn't like when the hook dependency array changes size\n// >> Warning: The final argument passed to useMemo changed size between renders. The order and size of this array must remain constant.\n// It is recommended to use a hashing function to produce a single, stable value\n// https://github.com/facebook/react/issues/14324#issuecomment-441489421\nfunction hashParams(params: string[]): string {\n return [...params].sort().join(':')\n}\n\n// React appears to suppress parent's re-rendering when a child's\n// useLayoutEffect updates internal state\n// the `navigate` call in useRedirect *does* cause usePath/useLocationChange\n// to fire, but without this hack useRoutes suppresses the update\n// TODO: find a better way to cause a synchronous update from useRoutes\nfunction useRedirectDetection(basePath: string, path: string | null) {\n const [, updateState] = useState({})\n const forceRender = useCallback(() => updateState({}), [])\n\n useLayoutEffect(() => {\n if (path !== getFormattedPath(basePath)) {\n forceRender()\n }\n }, [forceRender, basePath, path])\n}\n\nfunction trailingMatch(path: string | null, matchTrailingSlash: boolean): string | null {\n if (path === null) return path\n // path.length > 1 ensure we still match on the root route \"/\" when matchTrailingSlash is set\n if (matchTrailingSlash && path && path[path.length - 1] === '/' && path.length > 1) {\n path = path.substring(0, path.length - 1)\n }\n return path\n}\n\n// Taken from: https://stackoverflow.com/a/3561711\n// modified to NOT ESCAPE \"/\" and \"*\" since we use those as path parts\nfunction escapeRegExp(string: string): string {\n return string.replace(/[-\\\\^$+?.()|[\\]{}]/g, '\\\\$&')\n}\n","import { useCallback, useLayoutEffect } from 'react'\n\nimport { useBasePath } from './location'\nimport { isNode } from './node'\nimport type { QueryParam } from './querystring'\nimport {\n shouldCancelNavigation,\n addInterceptor,\n removeInterceptor,\n defaultPrompt,\n undoNavigation,\n} from './intercept'\n\nexport interface NavigateOptions {\n /**\n * Use a `replace` instead of `push` for navigation\n * @default false */\n replace?: boolean\n /** Values to serialize as a querystring, which will be appended to the `url` */\n query?: QueryParam | URLSearchParams\n /** value to pass as the state/data to history push/replace*/\n state?: unknown\n}\n\nlet lastPath = ''\n\nexport function navigate(url: string, options?: NavigateOptions): void {\n if (typeof url !== 'string') {\n throw new Error(`\"url\" must be a string, was provided a(n) ${typeof url}`)\n }\n\n if (Array.isArray(options?.query)) {\n throw new Error('\"query\" a serializable object or URLSearchParams')\n }\n\n if (shouldCancelNavigation()) return\n if (options?.query) {\n url += '?' + new URLSearchParams(options.query).toString()\n }\n\n lastPath = url\n // if the origin does not match history navigation will fail with\n // \"cannot be created in a document with origin\"\n // When navigating to another domain we must use location instead of history\n if (isAbsolute(url) && !isCurrentOrigin(url)) {\n window.location.assign(url)\n return\n }\n\n if (options?.replace) window.history.replaceState(options?.state, '', url)\n else window.history.pushState(options?.state, '', url)\n\n const event = new PopStateEvent('popstate')\n // Tag the event so navigation can be filtered out from browser events\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(event as any).__tag = 'raviger:navigation'\n dispatchEvent(event)\n}\n\nexport function useNavigationPrompt(predicate = true, prompt: string = defaultPrompt): void {\n if (isNode) return\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const onPopStateNavigation = () => {\n if (shouldCancelNavigation()) {\n undoNavigation(lastPath)\n }\n }\n window.addEventListener('popstate', onPopStateNavigation)\n return () => window.removeEventListener('popstate', onPopStateNavigation)\n }, [])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const handler = (e?: BeforeUnloadEvent): string | void => {\n if (predicate) {\n return e ? cancelNavigation(e, prompt) : prompt\n }\n }\n addInterceptor(handler)\n return () => removeInterceptor(handler)\n }, [predicate, prompt])\n}\n\nfunction cancelNavigation(event: BeforeUnloadEvent, prompt: string) {\n // Cancel the event as stated by the standard.\n event.preventDefault()\n // Chrome requires returnValue to be set.\n event.returnValue = prompt\n // Return value for prompt per spec\n return prompt\n}\n\nexport function useNavigate(optBasePath = ''): typeof navigate {\n const basePath = useBasePath()\n const navigateWithBasePath = useCallback<typeof navigate>(\n (url: string, options?: NavigateOptions) => {\n const base = optBasePath || basePath\n const href = url.startsWith('/') ? base + url : url\n navigate(href, options)\n },\n [basePath, optBasePath]\n )\n return navigateWithBasePath\n}\n\nfunction isAbsolute(url: string) {\n return /^(?:[a-z]+:)?\\/\\//i.test(url)\n}\n\nfunction isCurrentOrigin(url: string) {\n return window.location.origin === new URL(url).origin\n}\n","import { useState, useCallback } from 'react'\n\nimport { navigate } from './navigate'\nimport { isNode, getSsrPath } from './node'\nimport { getCurrentPath, getCurrentHash, useLocationChange } from './location'\n\nexport interface QueryParam {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\nexport interface setQueryParamsOptions {\n replace?: boolean\n}\n\nexport function useQueryParams<T extends QueryParam>(\n parseFn: (query: string) => T = parseQuery,\n serializeFn: (query: Partial<T>) => string = serializeQuery\n): [T, (query: T, options?: setQueryParamsOptions) => void] {\n const [querystring, setQuerystring] = useState(getQueryString())\n const setQueryParams = useCallback(\n (params, { replace = true } = {}) => {\n let path = getCurrentPath()\n params = replace ? params : { ...parseFn(querystring), ...params }\n const serialized = serializeFn(params).toString()\n\n if (serialized) path += '?' + serialized\n if (!replace) path += getCurrentHash()\n\n navigate(path)\n },\n [querystring, parseFn, serializeFn]\n )\n\n // Update state when route changes\n const updateQuery = useCallback(() => setQuerystring(getQueryString()), [])\n\n useLocationChange(updateQuery)\n return [parseFn(querystring), setQueryParams]\n}\n\nfunction parseQuery<T extends QueryParam>(querystring: string): T {\n const q = new URLSearchParams(querystring)\n return Object.fromEntries(q.entries()) as T\n}\n\nfunction serializeQuery<T extends QueryParam>(queryParams: T): string {\n return new URLSearchParams(Object.entries(queryParams).filter(([, v]) => v !== null)).toString()\n}\n\nexport function getQueryString(): string {\n if (isNode) {\n const ssrPath = getSsrPath()\n const queryIndex = ssrPath.indexOf('?')\n return queryIndex === -1 ? '' : ssrPath.substring(queryIndex + 1)\n }\n return window.location.search\n}\n","import { useLayoutEffect } from 'react'\n\nimport { getCurrentHash, usePath } from './location'\nimport { navigate } from './navigate'\nimport { QueryParam, useQueryParams } from './querystring'\n\nexport interface RedirectProps {\n to: string\n query?: QueryParam | URLSearchParams\n replace?: boolean\n merge?: boolean\n}\n\nexport interface UseRedirectProps {\n predicateUrl: string\n targetUrl: string\n queryParams?: QueryParam | URLSearchParams\n replace?: boolean\n}\n\nexport function Redirect({\n to,\n query,\n replace = true,\n merge = true,\n}: RedirectProps): JSX.Element | null {\n useRedirect(usePath(), to, { query, replace, merge })\n return null\n}\n\nexport function useRedirect(\n predicateUrl: string | null,\n targetUrl: string,\n {\n query,\n replace = true,\n merge = true,\n }: { query?: QueryParam; replace?: boolean; merge?: boolean } = {}\n): void {\n const currentPath = usePath()\n const [currentQuery] = useQueryParams()\n const hash = getCurrentHash()\n\n let url = targetUrl\n const targetQuery = new URLSearchParams({\n ...(merge ? currentQuery : {}),\n ...query,\n }).toString()\n if (targetQuery) {\n url += '?' + targetQuery\n }\n if (merge && hash && hash.length) {\n url += hash\n }\n\n useLayoutEffect(() => {\n if (currentPath === predicateUrl) {\n navigate(url, { replace })\n }\n }, [predicateUrl, url, replace, currentPath])\n}\n","import React, { useCallback, forwardRef, Ref } from 'react'\n\nimport { navigate } from './navigate'\nimport { useBasePath, useFullPath } from './location'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n basePath?: string\n children?: React.ReactNode\n}\nexport type LinkRef = HTMLAnchorElement | null\n\nexport interface ActiveLinkProps extends LinkProps {\n activeClass?: string\n exactActiveClass?: string\n}\n\nfunction Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>) {\n basePath = useLinkBasePath(basePath)\n href = getLinkHref(href, basePath)\n\n const { onClick, target } = props\n\n const handleClick = useCallback<React.MouseEventHandler<HTMLAnchorElement>>(\n (e) => {\n try {\n if (onClick) onClick(e)\n } catch (ex) {\n e.preventDefault()\n throw ex\n }\n if (shouldTrap(e, target)) {\n e.preventDefault() // prevent the link from actually navigating\n navigate(e.currentTarget.href)\n }\n },\n [onClick, target]\n )\n\n return <a {...props} href={href} onClick={handleClick} ref={ref} />\n}\n\nconst RefLink = forwardRef<LinkRef, LinkProps>(Link) as (\n props: LinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof Link>\n\nexport default RefLink\nexport { RefLink as Link }\n\nfunction ActiveLink(\n { basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps,\n ref?: Ref<HTMLAnchorElement>\n) {\n basePath = useLinkBasePath(basePath)\n const fullPath = useFullPath()\n\n let { href } = props\n href = absolutePathName(getLinkHref(href, basePath))\n\n if (exactActiveClass && fullPath === href)\n className = `${className ?? ``} ${exactActiveClass}`.trim()\n if (activeClass && fullPath.startsWith(href))\n className = `${className ?? ``} ${activeClass}`.trim()\n\n return <RefLink {...props} basePath={basePath} className={className} ref={ref} />\n}\n\nconst ActiveLinkRef = forwardRef<LinkRef, ActiveLinkProps>(ActiveLink) as (\n props: ActiveLinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof ActiveLink>\n\nexport { ActiveLinkRef as ActiveLink }\n\nfunction useLinkBasePath(basePath?: string): string {\n const contextBasePath = useBasePath()\n if (basePath === '/') return ''\n return basePath || contextBasePath\n}\n\nfunction getLinkHref(href: string, basePath = '') {\n return href.startsWith('/') ? basePath + href : href\n}\n\nfunction absolutePathName(href: string): string {\n if (href.startsWith('/')) return href\n return new URL(href, document.baseURI).pathname\n}\n\nfunction shouldTrap(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, target?: string) {\n return (\n !e.defaultPrevented && // onClick prevented default\n e.button === 0 && // ignore everything but left clicks\n !(target || target === '_self') && // don't trap target === blank\n !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n )\n}\n"],"names":["BasePathContext","createContext","PathContext","RouterProvider","basePath","path","children","React","createElement","Provider","value","isNode","undefined","window","e","interceptors","Set","hasIntercepted","hasUserCancelled","lastScroll","shouldCancelNavigation","scrollX","scrollY","Array","from","some","interceptor","prompt","confirm","setTimeout","usePath","contextPath","useContext","contextBasePath","useBasePath","setPath","useState","getFormattedPath","useLocationChange","useCallback","newPath","inheritBasePath","onInitial","useFullPath","getCurrentPath","location","pathname","getCurrentHash","hashIndex","indexOf","substring","hash","setFn","isActive","routerBasePath","setRef","useRef","useLayoutEffect","current","onPopState","isPredicateActive","getFormattedLocation","addEventListener","removeEventListener","useMountedLayout","fn","deps","hasMounted","getRavigerHistory","scrollRestoration","state","history","baseMissing","isPathInBase","toLowerCase","startsWith","decodeURIComponent","replace","basePathMatcher","RegExp","fullPath","search","host","hostname","href","origin","predicate","isFunction","obj","emptyPathResult","usePathOptions","routeOrRoutes","matchTrailingSlash","matchers","useMatchers","isArray","trailingMatch","routes","useMemo","map","createRouteMatcher","params","sort","join","getMatchParams","routeMatchers","pathParams","routeMatch","find","regex","match","props","reduce","prop","i","string","substr","_a","paramName","length","lastPath","navigate","url","options","Error","query","URLSearchParams","toString","isAbsolute","test","isCurrentOrigin","URL","assign","replaceState","pushState","event","PopStateEvent","__tag","dispatchEvent","useQueryParams","parseFn","parseQuery","serializeFn","serializeQuery","querystring","setQuerystring","getQueryString","setQueryParams","serialized","q","Object","fromEntries","entries","queryParams","filter","v","ssrPath","queryIndex","useRedirect","predicateUrl","targetUrl","merge","currentPath","currentQuery","targetQuery","RefLink","forwardRef","Link","ref","getLinkHref","useLinkBasePath","onClick","target","handleClick","ex","preventDefault","shouldTrap","defaultPrevented","button","metaKey","altKey","ctrlKey","shiftKey","currentTarget","ActiveLinkRef","ActiveLink","className","exactActiveClass","activeClass","absolutePathName","document","baseURI","trim","Redirect","to","useHash","stripHash","setHash","handleHash","newHash","useHistory","setHistory","useMatch","useNavigate","optBasePath","base","useNavigationPrompt","onPopStateNavigation","undoNavigation","scrollTo","handler","cancelNavigation","returnValue","addInterceptor","add","removeInterceptor","delete","usePathParams","isSingle","useRoutes","routeProps","overridePathParams","useRedirectDetection","updateState","forceRender","route","useMatchRoute","keys"],"mappings":"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"}
|
package/dist/module.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t,{createContext as e,useRef as n,useLayoutEffect as r,useContext as a,useState as o,useCallback as i,useMemo as s,forwardRef as u}from"react";const c=e(""),l=e(null);function RouterProvider({basePath:e="",path:n,children:r}){return t.createElement(c.Provider,{value:e},t.createElement(l.Provider,{value:null!=n?n:null},r))}let h=!0;try{h=void 0===window}catch(t){}const g=new Set;let d=!1,f=!1,P=[0,0];function shouldCancelNavigation(){return P=[window.scrollX,window.scrollY],d?f:Array.from(g).some((t=>{const e=t();return!!e&&(f=!window.confirm(e),d=!0,setTimeout((()=>{d=!1,f=!1}),0),f)}))}function usePath(t){const e=a(l),n=useBasePath();t=t||n;const[,r]=o(getFormattedPath(t));return useLocationChange(i((({path:t})=>r(t)),[]),{basePath:t,inheritBasePath:!t,onInitial:!0}),e||getFormattedPath(t)}function useBasePath(){return a(c)}function useFullPath(){const[t,e]=o(getCurrentPath());return useLocationChange(i((({path:t})=>e(t)),[]),{inheritBasePath:!1}),t||"/"}function useHash({stripHash:t=!0}={}){const[e,n]=o(window.location.hash),a=i(((
|
|
1
|
+
import t,{createContext as e,useRef as n,useLayoutEffect as r,useContext as a,useState as o,useCallback as i,useMemo as s,forwardRef as u}from"react";const c=e(""),l=e(null);function RouterProvider({basePath:e="",path:n,children:r}){return t.createElement(c.Provider,{value:e},t.createElement(l.Provider,{value:null!=n?n:null},r))}let h=!0;try{h=void 0===window}catch(t){}const g=new Set;let d=!1,f=!1,P=[0,0];function shouldCancelNavigation(){return P=[window.scrollX,window.scrollY],d?f:Array.from(g).some((t=>{const e=t();return!!e&&(f=!window.confirm(e),d=!0,setTimeout((()=>{d=!1,f=!1}),0),f)}))}function usePath(t){const e=a(l),n=useBasePath();t=t||n;const[,r]=o(getFormattedPath(t));return useLocationChange(i((({path:t})=>r(t)),[]),{basePath:t,inheritBasePath:!t,onInitial:!0}),e||getFormattedPath(t)}function useBasePath(){return a(c)}function useFullPath(){const[t,e]=o(getCurrentPath());return useLocationChange(i((({path:t})=>e(t)),[]),{inheritBasePath:!1}),t||"/"}function useHash({stripHash:t=!0}={}){const[e,n]=o(window.location.hash),a=i((()=>{const t=window.location.hash;t!==e&&n(t)}),[n,e]);return r((()=>(window.addEventListener("hashchange",a,!1),()=>window.removeEventListener("hashchange",a))),[a]),useLocationChange(a),t?e.substring(1):e}function getCurrentPath(){return h?"/":window.location.pathname||"/"}function getCurrentHash(){if(h){const t="/",e=t.indexOf("#");return t.substring(e)}return window.location.hash}function useLocationChange(t,{inheritBasePath:e=!0,basePath:a="",isActive:o,onInitial:s=!1}={}){if(h)return;const u=useBasePath();e&&u&&(a=u);const c=n(t);r((()=>{c.current=t}));const l=i((()=>{(void 0===o||isPredicateActive(o))&&(shouldCancelNavigation()||c.current(getFormattedLocation(a)))}),[o,a]);r((()=>(window.addEventListener("popstate",l),()=>window.removeEventListener("popstate",l))),[l]),function useMountedLayout(t,e,{onInitial:a=!1}={}){const o=n(a);r((()=>{o.current?t():o.current=!0}),e)}((()=>{(void 0===o||isPredicateActive(o))&&c.current(getFormattedLocation(a))}),[a,o],{onInitial:s})}function useHistory(){const[t,e]=o(getRavigerHistory());return useLocationChange(i((()=>e(getRavigerHistory())),[e])),t}function getRavigerHistory(){return h?{scrollRestoration:"manual",state:null}:{scrollRestoration:window.history.scrollRestoration,state:window.history.state}}function getFormattedPath(t){const e=getCurrentPath(),n=t&&!function isPathInBase(t,e){return!!(t&&e&&e.toLowerCase().startsWith(t.toLowerCase()))}(t,e);return null===e||n?null:decodeURIComponent(t?e.replace(function basePathMatcher(t){return new RegExp("^"+t,"i")}(t),"")||"/":e)}function getFormattedLocation(t){const e=getFormattedPath(t);return{basePath:t,path:e,pathname:e,fullPath:getCurrentPath(),search:window.location.search,hash:getCurrentHash(),host:window.location.host,hostname:window.location.hostname,href:window.location.href,origin:window.location.origin}}function isPredicateActive(t){return function isFunction(t){return!!t&&"function"==typeof t}(t)?t():t}const w=[null,null];function useRoutes(e,{basePath:n="",routeProps:a={},overridePathParams:s=!0,matchTrailingSlash:u=!0}={}){const c=usePath(n)&&getFormattedPath(n);!function useRedirectDetection(t,e){const[,n]=o({}),a=i((()=>n({})),[]);r((()=>{e!==getFormattedPath(t)&&a()}),[a,t,e])}(n,usePath(n));const l=function useMatchRoute(t,e,{routeProps:n,overridePathParams:r,matchTrailingSlash:a}){e=trailingMatch(e,a);const o=useMatchers(Object.keys(t));if(null===e)return null;const[i,s]=getMatchParams(e,o);return i?t[i.path](r?{...s,...n}:{...n,...s}):null}(e,c,{routeProps:a,overridePathParams:s,matchTrailingSlash:u});return l&&null!==c?t.createElement(RouterProvider,{basePath:n,path:c},l):null}function usePathParams(t,e={}){const n=!Array.isArray(t),[r,a]=usePathOptions(t,e);if(null===r)return n?null:w;const[o,i]=getMatchParams(r,a);return o?n?i:[o.path,i]:n?null:w}function useMatch(t,e={}){var n;const[r,a]=usePathOptions(t,e),o=a.find((({regex:t})=>null==r?void 0:r.match(t)));return null!==(n=null==o?void 0:o.path)&&void 0!==n?n:null}function usePathOptions(t,{basePath:e,matchTrailingSlash:n=!0}){const r=useMatchers(Array.isArray(t)?t:[t]);return[trailingMatch(usePath(e),n),r]}function useMatchers(t){return s((()=>t.map(createRouteMatcher)),[(e=t,[...e].sort().join(":"))]);var e}function getMatchParams(t,e){let n=null;const r=e.find((({regex:e})=>(n=t.match(e),!!n)));if(!r||null===n)return w;const a=r.props.reduce(((t,e,r)=>(t[e]=n[r+1],t)),{});return[r,a]}function createRouteMatcher(t){var e,n;return{path:t,regex:new RegExp(`${"*"===t.substr(0,1)?"":"^"}${(n=t,n.replace(/[-\\^$+?.()|[\]{}]/g,"\\$&")).replace(/:[a-zA-Z]+/g,"([^/]+)").replace(/\*/g,"")}${"*"===t.substr(-1)?"":"$"}`,"i"),props:(null!==(e=t.match(/:[a-zA-Z]+/g))&&void 0!==e?e:[]).map((t=>t.substr(1)))}}function trailingMatch(t,e){return null===t||e&&t&&"/"===t[t.length-1]&&t.length>1&&(t=t.substring(0,t.length-1)),t}let v="";function navigate(t,e){if("string"!=typeof t)throw new Error('"url" must be a string, was provided a(n) '+typeof t);if(Array.isArray(null==e?void 0:e.query))throw new Error('"query" a serializable object or URLSearchParams');if(shouldCancelNavigation())return;if((null==e?void 0:e.query)&&(t+="?"+new URLSearchParams(e.query).toString()),v=t,function isAbsolute(t){return/^(?:[a-z]+:)?\/\//i.test(t)}(t)&&!function isCurrentOrigin(t){return window.location.origin===new URL(t).origin}(t))return void window.location.assign(t);(null==e?void 0:e.replace)?window.history.replaceState(null==e?void 0:e.state,"",t):window.history.pushState(null==e?void 0:e.state,"",t);const n=new PopStateEvent("popstate");n.__tag="raviger:navigation",dispatchEvent(n)}function useNavigationPrompt(t=!0,e="Are you sure you want to leave this page?"){h||(r((()=>{const onPopStateNavigation=()=>{shouldCancelNavigation()&&function undoNavigation(t){window.history.pushState(null,null,t),setTimeout((()=>{window.scrollTo(...P)}),0)}(v)};return window.addEventListener("popstate",onPopStateNavigation),()=>window.removeEventListener("popstate",onPopStateNavigation)}),[]),r((()=>{const handler=n=>{if(t)return n?function cancelNavigation(t,e){return t.preventDefault(),t.returnValue=e,e}(n,e):e};return function addInterceptor(t){window.addEventListener("beforeunload",t),g.add(t)}(handler),()=>function removeInterceptor(t){window.removeEventListener("beforeunload",t),g.delete(t)}(handler)}),[t,e]))}function useNavigate(t=""){const e=useBasePath();return i(((n,r)=>{const a=t||e;navigate(n.startsWith("/")?a+n:n,r)}),[e,t])}function useQueryParams(t=parseQuery,e=serializeQuery){const[n,r]=o(getQueryString()),a=i(((r,{replace:a=!0}={})=>{let o=getCurrentPath();r=a?r:{...t(n),...r};const i=e(r).toString();i&&(o+="?"+i),a||(o+=getCurrentHash()),navigate(o)}),[n,t,e]);return useLocationChange(i((()=>r(getQueryString())),[])),[t(n),a]}function parseQuery(t){const e=new URLSearchParams(t);return Object.fromEntries(e.entries())}function serializeQuery(t){return new URLSearchParams(Object.entries(t).filter((([,t])=>null!==t))).toString()}function getQueryString(){if(h){const t="/",e=t.indexOf("?");return-1===e?"":t.substring(e+1)}return window.location.search}function Redirect({to:t,query:e,replace:n=!0,merge:r=!0}){return useRedirect(usePath(),t,{query:e,replace:n,merge:r}),null}function useRedirect(t,e,{query:n,replace:a=!0,merge:o=!0}={}){const i=usePath(),[s]=useQueryParams(),u=getCurrentHash();let c=e;const l=new URLSearchParams({...o?s:{},...n}).toString();l&&(c+="?"+l),o&&u&&u.length&&(c+=u),r((()=>{i===t&&navigate(c,{replace:a})}),[t,c,a,i])}const m=u((function Link({href:e,basePath:n,...r},a){e=getLinkHref(e,n=useLinkBasePath(n));const{onClick:o,target:s}=r,u=i((t=>{try{o&&o(t)}catch(e){throw t.preventDefault(),e}(function shouldTrap(t,e){return!t.defaultPrevented&&0===t.button&&!(e||"_self"===e)&&!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)})(t,s)&&(t.preventDefault(),navigate(t.currentTarget.href))}),[o,s]);return t.createElement("a",{...r,href:e,onClick:u,ref:a})}));const p=u((function ActiveLink({basePath:e,className:n,exactActiveClass:r,activeClass:a,...o},i){e=useLinkBasePath(e);const s=useFullPath();let{href:u}=o;return u=function absolutePathName(t){return t.startsWith("/")?t:new URL(t,document.baseURI).pathname}(getLinkHref(u,e)),r&&s===u&&(n=`${null!=n?n:""} ${r}`.trim()),a&&s.startsWith(u)&&(n=`${null!=n?n:""} ${a}`.trim()),t.createElement(m,{...o,basePath:e,className:n,ref:i})}));function useLinkBasePath(t){const e=useBasePath();return"/"===t?"":t||e}function getLinkHref(t,e=""){return t.startsWith("/")?e+t:t}export{p as ActiveLink,m as Link,Redirect,RouterProvider,navigate,useBasePath,useFullPath,useHash,useHistory,useLocationChange,useMatch,useNavigate,useNavigationPrompt,usePath,usePathParams,useQueryParams,useRedirect,useRoutes};
|
|
2
2
|
//# sourceMappingURL=module.js.map
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","sources":["../src/context.tsx","../src/node.ts","../src/intercept.ts","../src/location.ts","../src/hooks.ts","../src/typeChecks.ts","../src/router.tsx","../src/navigate.ts","../src/querystring.ts","../src/redirect.ts","../src/Link.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\n\nconst BasePathContext = createContext('')\nconst PathContext = createContext<string | null>(null)\n\nexport { BasePathContext }\nexport { PathContext }\n\nexport function useRouter(): { basePath: string; path: string | null } {\n const [basePath, path] = [useContext(BasePathContext), useContext(PathContext)]\n return useMemo(() => ({ basePath, path }), [basePath, path])\n}\n\nexport function RouterProvider({\n basePath = '',\n path,\n children,\n}: {\n basePath?: string\n path?: string\n children?: React.ReactNode\n}): JSX.Element {\n return (\n // The ordering here is important, the basePath will change less often\n // So putting it on the outside reduces its need to re-render\n <BasePathContext.Provider value={basePath}>\n <PathContext.Provider value={path ?? null}>{children}</PathContext.Provider>\n </BasePathContext.Provider>\n )\n}\n","let ssrPath = '/'\nlet isNode = true\ntry {\n isNode = window === undefined\n} catch (e) {} // eslint-disable-line no-empty\n\nexport { isNode }\nexport function getSsrPath(): string {\n return ssrPath\n}\nexport function setSsrPath(path: string): void {\n ssrPath = path\n}\n","const interceptors = new Set<() => string | void>()\n\nexport const defaultPrompt = 'Are you sure you want to leave this page?'\n\nlet hasIntercepted = false\nlet hasUserCancelled = false\nlet lastScroll = [0, 0] as [number, number]\n\nexport function shouldCancelNavigation(): boolean {\n lastScroll = [window.scrollX, window.scrollY]\n if (hasIntercepted) return hasUserCancelled\n\n // confirm if any interceptors return true\n return Array.from(interceptors).some((interceptor) => {\n const prompt = interceptor()\n if (!prompt) return false\n\n // cancel navigation if user declines\n hasUserCancelled = !window.confirm(prompt) // eslint-disable-line no-alert\n\n // track user response so that multiple interceptors don't prompt\n hasIntercepted = true\n\n // reset so that future navigation attempts are prompted\n setTimeout(() => {\n hasIntercepted = false\n hasUserCancelled = false\n }, 0)\n\n return hasUserCancelled\n })\n}\n\nexport function addInterceptor(handler: () => string | void): void {\n window.addEventListener('beforeunload', handler)\n interceptors.add(handler)\n}\n\nexport function removeInterceptor(handler: () => string | void): void {\n window.removeEventListener('beforeunload', handler)\n interceptors.delete(handler)\n}\n\nexport function undoNavigation(lastPath: string): void {\n window.history.pushState(null, null as unknown as string, lastPath)\n setTimeout(() => {\n window.scrollTo(...lastScroll)\n }, 0)\n}\n","import { useState, useCallback, useRef, useContext, useLayoutEffect } from 'react'\n\nimport { BasePathContext, PathContext } from './context'\nimport { useMountedLayout } from './hooks'\nimport { getSsrPath, isNode } from './node'\nimport { shouldCancelNavigation } from './intercept'\nimport { isFunction } from './typeChecks'\n\nexport interface RavigerLocation {\n /** The current path; alias of `pathname` */\n path: string | null\n /** The current path; alias of `path` */\n pathname: string | null\n /** The full path, ignores any `basePath` in the context */\n fullPath: string\n basePath?: string\n search: string\n hash: string\n host: string\n hostname: string\n href: string\n origin: string\n}\n\nexport interface RavigerHistory {\n scrollRestoration: 'auto' | 'manual'\n state: unknown\n}\n\nexport interface LocationChangeSetFn {\n (location: RavigerLocation): void\n}\nexport interface LocationChangeOptionParams {\n inheritBasePath?: boolean\n basePath?: string\n isActive?: boolean | (() => boolean)\n onInitial?: boolean\n}\n\nexport function usePath(basePath?: string): string | null {\n const contextPath = useContext(PathContext)\n const contextBasePath = useBasePath() // hooks can't be called conditionally\n basePath = basePath || contextBasePath\n\n // Don't bother tracking the actual path, it can get out of sync\n // due to React parent/child render ordering, especially with onmount navigation\n // See issues:\n // https://github.com/kyeotic/raviger/issues/116\n // https://github.com/kyeotic/raviger/issues/64\n //\n // This is just used to force a re-render\n const [, setPath] = useState(getFormattedPath(basePath))\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, {\n basePath,\n inheritBasePath: !basePath,\n // Use on initial to handle to force state updates from on-mount navigation\n onInitial: true,\n })\n\n return contextPath || getFormattedPath(basePath)\n}\n\nexport function useBasePath(): string {\n return useContext(BasePathContext)\n}\n\nexport function useFullPath(): string {\n const [path, setPath] = useState<string | null>(getCurrentPath())\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, { inheritBasePath: false })\n\n return path || '/'\n}\n\nexport function useHash({ stripHash = true } = {}): string {\n const [hash, setHash] = useState(window.location.hash)\n const handleHash = useCallback(\n ({ hash: newHash }) => {\n if (newHash === hash) return\n setHash(newHash)\n },\n [setHash, hash]\n )\n\n useLayoutEffect(() => {\n window.addEventListener('hashchange', handleHash, false)\n return () => window.removeEventListener('hashchange', handleHash)\n }, [handleHash])\n\n useLocationChange(handleHash)\n return stripHash ? hash.substring(1) : hash\n}\n\nexport function getCurrentPath(): string {\n return isNode ? getSsrPath() : window.location.pathname || '/'\n}\n\nexport function getCurrentHash(): string {\n if (isNode) {\n const path = getSsrPath()\n const hashIndex = path.indexOf('#')\n return path.substring(hashIndex)\n }\n return window.location.hash\n}\n\nexport function useLocationChange(\n setFn: LocationChangeSetFn,\n {\n inheritBasePath = true,\n basePath = '',\n isActive,\n onInitial = false,\n }: LocationChangeOptionParams = {}\n): void {\n if (isNode) return\n\n // All hooks after this are conditional, but the runtime can't actually change\n /* eslint-disable react-hooks/rules-of-hooks */\n\n const routerBasePath = useBasePath()\n if (inheritBasePath && routerBasePath) basePath = routerBasePath\n\n const setRef = useRef<LocationChangeSetFn>(setFn)\n useLayoutEffect(() => {\n // setFn could be an in-render declared callback, making it unstable\n // This is a method of using an often-changing callback from React Hooks\n // https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback\n // While not recommended, it is the best current (16.9) available method\n // For reducing the useEffect cleanup from setFn changing every render\n setRef.current = setFn\n })\n\n const onPopState = useCallback(() => {\n // No predicate defaults true\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n if (shouldCancelNavigation()) return\n setRef.current(getFormattedLocation(basePath))\n }, [isActive, basePath])\n\n useLayoutEffect(() => {\n window.addEventListener('popstate', onPopState)\n return () => window.removeEventListener('popstate', onPopState)\n }, [onPopState])\n\n // When the basePath changes re-check the path after the render completes\n // This allows nested contexts to get an up-to-date formatted path\n useMountedLayout(\n () => {\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n setRef.current(getFormattedLocation(basePath))\n },\n [basePath, isActive],\n { onInitial }\n )\n}\n\nexport function useHistory(): RavigerHistory {\n const [history, setHistory] = useState(getRavigerHistory())\n useLocationChange(useCallback(() => setHistory(getRavigerHistory()), [setHistory]))\n return history\n}\n\nfunction getRavigerHistory(): RavigerHistory {\n if (isNode) return { scrollRestoration: 'manual', state: null }\n return {\n scrollRestoration: window.history.scrollRestoration,\n state: window.history.state,\n }\n}\n\n/**\n * Returns the current path after decoding. If basePath is provided it will be removed from the front of the path.\n * If basePath is provided and the path does not begin with it will return null\n * @param {string} basePath basePath, if any\n * @return {string | null} returns path with basePath prefix removed, or null if basePath is provided and missing\n */\nexport function getFormattedPath(basePath: string): string | null {\n const path = getCurrentPath()\n const baseMissing = basePath && !isPathInBase(basePath, path)\n if (path === null || baseMissing) return null\n return decodeURIComponent(!basePath ? path : path.replace(basePathMatcher(basePath), '') || '/')\n}\n\nfunction getFormattedLocation(basePath: string): RavigerLocation {\n const path = getFormattedPath(basePath)\n return {\n basePath,\n path,\n pathname: path,\n fullPath: getCurrentPath(),\n search: window.location.search,\n hash: getCurrentHash(),\n host: window.location.host,\n hostname: window.location.hostname,\n href: window.location.href,\n origin: window.location.origin,\n }\n}\n\nfunction isPredicateActive(predicate: boolean | (() => boolean)): boolean {\n return isFunction(predicate) ? predicate() : predicate\n}\n\nfunction basePathMatcher(basePath: string): RegExp {\n return new RegExp('^' + basePath, 'i')\n}\n\nfunction isPathInBase(basePath: string, path: string): boolean {\n return !!(basePath && path && path.toLowerCase().startsWith(basePath.toLowerCase()))\n}\n","import { useLayoutEffect, useRef } from 'react'\n\nexport function useMountedLayout(\n fn: () => unknown,\n deps: React.DependencyList | undefined,\n { onInitial = false } = {}\n): void {\n const hasMounted = useRef(onInitial)\n useLayoutEffect(() => {\n if (!hasMounted.current) hasMounted.current = true\n else fn()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n","// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types\nexport function isFunction(obj: unknown): obj is Function {\n return !!obj && typeof obj === 'function'\n}\n","import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\n\nimport { RouterProvider } from './context'\nimport { isNode, setSsrPath, getSsrPath } from './node'\nimport { getFormattedPath, usePath } from './location'\nimport type { NonEmptyRecord, Split, ValueOf } from './types'\n\nconst emptyPathResult: [null, null] = [null, null]\n\nexport interface PathParamOptions {\n basePath?: string\n matchTrailingSlash?: boolean\n}\nexport interface RouteOptionParams extends PathParamOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routeProps?: { [k: string]: any }\n overridePathParams?: boolean\n}\ninterface RouteMatcher {\n path: string\n regex: RegExp\n props: string[]\n}\n\ntype ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [\n infer Head,\n ...infer Tail\n]\n ? Head extends `:${infer Name}`\n ? { [N in Name]: string } & ExtractPathParams<Path, Tail>\n : ExtractPathParams<Path, Tail>\n : unknown\n\nexport type Routes<Path extends string> = {\n [P in Path]: (\n params: NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ) => JSX.Element\n}\n\nexport function useRoutes<Path extends string>(\n routes: Routes<Path>,\n {\n basePath = '',\n routeProps = {},\n overridePathParams = true,\n matchTrailingSlash = true,\n }: RouteOptionParams = {}\n): JSX.Element | null {\n /*\n This is a hack to setup a listener for the path while always using this latest path\n The issue with usePath is that, in order to not re-render nested components when\n their parent router changes the path, it uses the context's path\n But since that path has to get _set_ here in useRoutes something has to give\n If usePath returns latest it causes render thrashing\n If useRoutes hacks itself into the latest path nothing bad happens (...afaik)\n */\n const path = usePath(basePath) && getFormattedPath(basePath)\n\n // Handle potential <Redirect /> use in routes\n useRedirectDetection(basePath, usePath(basePath))\n\n // Get the current route\n const route = useMatchRoute(routes, path, {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n })\n\n // No match should not return an empty Provider, just null\n if (!route || path === null) return null\n return (\n <RouterProvider basePath={basePath} path={path}>\n {route}\n </RouterProvider>\n )\n}\n\nfunction useMatchRoute(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routes: { [key: string]: (...props: any) => JSX.Element },\n path: string | null,\n {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n }: Omit<RouteOptionParams, 'basePath' | 'matchTrailingSlash'> & { matchTrailingSlash: boolean }\n) {\n path = trailingMatch(path, matchTrailingSlash)\n const matchers = useMatchers(Object.keys(routes))\n\n if (path === null) return null\n const [routeMatch, props] = getMatchParams(path, matchers)\n\n if (!routeMatch) return null\n\n return routes[routeMatch.path](\n overridePathParams ? { ...props, ...routeProps } : { ...routeProps, ...props }\n )\n}\n\nexport function usePathParams<Path extends string>(\n route: Path,\n options?: PathParamOptions\n): NonEmptyRecord<ExtractPathParams<Path extends `${infer P1}*` ? P1 : Path>> | null\nexport function usePathParams<Path extends string>(\n routes: ReadonlyArray<Path>,\n options?: PathParamOptions\n):\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\nexport function usePathParams<Params extends ReadonlyArray<string> | string>(\n routes: Params,\n options: PathParamOptions = {}\n): Params extends ReadonlyArray<string>\n ?\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\n : Params extends string\n ? NonEmptyRecord<ExtractPathParams<Params extends `${infer P1}*` ? P1 : Params>> | null\n : never {\n const isSingle = !Array.isArray(routes)\n const [path, matchers] = usePathOptions(routes as string | string[], options)\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (path === null) return isSingle ? null : emptyPathResult\n\n const [routeMatch, props] = getMatchParams(path, matchers)\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (!routeMatch) return isSingle ? null : emptyPathResult\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n return isSingle\n ? props\n : ([routeMatch.path, props] as ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>)\n}\n\nexport function useMatch(routes: string | string[], options: PathParamOptions = {}): string | null {\n const [path, matchers] = usePathOptions(routes, options)\n const match = matchers.find(({ regex }) => path?.match(regex))\n\n return match?.path ?? null\n}\n\nfunction usePathOptions(\n routeOrRoutes: string | string[],\n { basePath, matchTrailingSlash = true }: PathParamOptions\n): [string | null, RouteMatcher[]] {\n const routes = (!Array.isArray(routeOrRoutes) ? [routeOrRoutes] : routeOrRoutes) as string[]\n const matchers = useMatchers(routes)\n\n return [trailingMatch(usePath(basePath), matchTrailingSlash), matchers]\n}\n\nfunction useMatchers(routes: string[]): RouteMatcher[] {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => routes.map(createRouteMatcher), [hashParams(routes)])\n}\n\nfunction getMatchParams(\n path: string,\n routeMatchers: RouteMatcher[]\n): [RouteMatcher, Record<string, unknown>] | [null, null] {\n let pathParams: RegExpMatchArray | null = null\n\n // Hacky method for find + map\n const routeMatch = routeMatchers.find(({ regex }) => {\n pathParams = path.match(regex)\n return !!pathParams\n })\n\n if (!routeMatch || pathParams === null) return emptyPathResult\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const props = routeMatch.props.reduce((props: any, prop, i) => {\n // The following `match` can't be null because the above return asserts it\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n props[prop] = pathParams![i + 1]\n return props\n }, {})\n\n return [routeMatch, props]\n}\n\nfunction createRouteMatcher(path: string): RouteMatcher {\n return {\n path,\n regex: new RegExp(\n `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path)\n .replace(/:[a-zA-Z]+/g, '([^/]+)')\n .replace(/\\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`,\n 'i'\n ),\n props: (path.match(/:[a-zA-Z]+/g) ?? []).map((paramName) => paramName.substr(1)),\n }\n}\n\nexport function setPath(path: string): void {\n if (!isNode) {\n throw new Error('This method should only be used in NodeJS environments')\n }\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const url = require('url')\n setSsrPath(url.resolve(getSsrPath(), path))\n}\n\n// React doesn't like when the hook dependency array changes size\n// >> Warning: The final argument passed to useMemo changed size between renders. The order and size of this array must remain constant.\n// It is recommended to use a hashing function to produce a single, stable value\n// https://github.com/facebook/react/issues/14324#issuecomment-441489421\nfunction hashParams(params: string[]): string {\n return [...params].sort().join(':')\n}\n\n// React appears to suppress parent's re-rendering when a child's\n// useLayoutEffect updates internal state\n// the `navigate` call in useRedirect *does* cause usePath/useLocationChange\n// to fire, but without this hack useRoutes suppresses the update\n// TODO: find a better way to cause a synchronous update from useRoutes\nfunction useRedirectDetection(basePath: string, path: string | null) {\n const [, updateState] = useState({})\n const forceRender = useCallback(() => updateState({}), [])\n\n useLayoutEffect(() => {\n if (path !== getFormattedPath(basePath)) {\n forceRender()\n }\n }, [forceRender, basePath, path])\n}\n\nfunction trailingMatch(path: string | null, matchTrailingSlash: boolean): string | null {\n if (path === null) return path\n // path.length > 1 ensure we still match on the root route \"/\" when matchTrailingSlash is set\n if (matchTrailingSlash && path && path[path.length - 1] === '/' && path.length > 1) {\n path = path.substring(0, path.length - 1)\n }\n return path\n}\n\n// Taken from: https://stackoverflow.com/a/3561711\n// modified to NOT ESCAPE \"/\" and \"*\" since we use those as path parts\nfunction escapeRegExp(string: string): string {\n return string.replace(/[-\\\\^$+?.()|[\\]{}]/g, '\\\\$&')\n}\n","import { useCallback, useLayoutEffect } from 'react'\n\nimport { useBasePath } from './location'\nimport { isNode } from './node'\nimport type { QueryParam } from './querystring'\nimport {\n shouldCancelNavigation,\n addInterceptor,\n removeInterceptor,\n defaultPrompt,\n undoNavigation,\n} from './intercept'\n\nexport interface NavigateOptions {\n /**\n * Use a `replace` instead of `push` for navigation\n * @default false */\n replace?: boolean\n /** Values to serialize as a querystring, which will be appended to the `url` */\n query?: QueryParam | URLSearchParams\n /** value to pass as the state/data to history push/replace*/\n state?: unknown\n}\n\nlet lastPath = ''\n\nexport function navigate(url: string, options?: NavigateOptions): void {\n if (typeof url !== 'string') {\n throw new Error(`\"url\" must be a string, was provided a(n) ${typeof url}`)\n }\n\n if (Array.isArray(options?.query)) {\n throw new Error('\"query\" a serializable object or URLSearchParams')\n }\n\n if (shouldCancelNavigation()) return\n if (options?.query) {\n url += '?' + new URLSearchParams(options.query).toString()\n }\n\n lastPath = url\n // if the origin does not match history navigation will fail with\n // \"cannot be created in a document with origin\"\n // When navigating to another domain we must use location instead of history\n if (isAbsolute(url) && !isCurrentOrigin(url)) {\n window.location.assign(url)\n return\n }\n\n if (options?.replace) window.history.replaceState(options?.state, '', url)\n else window.history.pushState(options?.state, '', url)\n\n const event = new PopStateEvent('popstate')\n // Tag the event so navigation can be filtered out from browser events\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(event as any).__tag = 'raviger:navigation'\n dispatchEvent(event)\n}\n\nexport function useNavigationPrompt(predicate = true, prompt: string = defaultPrompt): void {\n if (isNode) return\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const onPopStateNavigation = () => {\n if (shouldCancelNavigation()) {\n undoNavigation(lastPath)\n }\n }\n window.addEventListener('popstate', onPopStateNavigation)\n return () => window.removeEventListener('popstate', onPopStateNavigation)\n }, [])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const handler = (e?: BeforeUnloadEvent): string | void => {\n if (predicate) {\n return e ? cancelNavigation(e, prompt) : prompt\n }\n }\n addInterceptor(handler)\n return () => removeInterceptor(handler)\n }, [predicate, prompt])\n}\n\nfunction cancelNavigation(event: BeforeUnloadEvent, prompt: string) {\n // Cancel the event as stated by the standard.\n event.preventDefault()\n // Chrome requires returnValue to be set.\n event.returnValue = prompt\n // Return value for prompt per spec\n return prompt\n}\n\nexport function useNavigate(optBasePath = ''): typeof navigate {\n const basePath = useBasePath()\n const navigateWithBasePath = useCallback<typeof navigate>(\n (url: string, options?: NavigateOptions) => {\n const base = optBasePath || basePath\n const href = url.startsWith('/') ? base + url : url\n navigate(href, options)\n },\n [basePath, optBasePath]\n )\n return navigateWithBasePath\n}\n\nfunction isAbsolute(url: string) {\n return /^(?:[a-z]+:)?\\/\\//i.test(url)\n}\n\nfunction isCurrentOrigin(url: string) {\n return window.location.origin === new URL(url).origin\n}\n","import { useState, useCallback } from 'react'\n\nimport { navigate } from './navigate'\nimport { isNode, getSsrPath } from './node'\nimport { getCurrentPath, getCurrentHash, useLocationChange } from './location'\n\nexport interface QueryParam {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\nexport interface setQueryParamsOptions {\n replace?: boolean\n}\n\nexport function useQueryParams<T extends QueryParam>(\n parseFn: (query: string) => T = parseQuery,\n serializeFn: (query: Partial<T>) => string = serializeQuery\n): [T, (query: T, options?: setQueryParamsOptions) => void] {\n const [querystring, setQuerystring] = useState(getQueryString())\n const setQueryParams = useCallback(\n (params, { replace = true } = {}) => {\n let path = getCurrentPath()\n params = replace ? params : { ...parseFn(querystring), ...params }\n const serialized = serializeFn(params).toString()\n\n if (serialized) path += '?' + serialized\n if (!replace) path += getCurrentHash()\n\n navigate(path)\n },\n [querystring, parseFn, serializeFn]\n )\n\n // Update state when route changes\n const updateQuery = useCallback(() => setQuerystring(getQueryString()), [])\n\n useLocationChange(updateQuery)\n return [parseFn(querystring), setQueryParams]\n}\n\nfunction parseQuery<T extends QueryParam>(querystring: string): T {\n const q = new URLSearchParams(querystring)\n return Object.fromEntries(q.entries()) as T\n}\n\nfunction serializeQuery<T extends QueryParam>(queryParams: T): string {\n return new URLSearchParams(Object.entries(queryParams).filter(([, v]) => v !== null)).toString()\n}\n\nexport function getQueryString(): string {\n if (isNode) {\n const ssrPath = getSsrPath()\n const queryIndex = ssrPath.indexOf('?')\n return queryIndex === -1 ? '' : ssrPath.substring(queryIndex + 1)\n }\n return window.location.search\n}\n","import { useLayoutEffect } from 'react'\n\nimport { getCurrentHash, usePath } from './location'\nimport { navigate } from './navigate'\nimport { QueryParam, useQueryParams } from './querystring'\n\nexport interface RedirectProps {\n to: string\n query?: QueryParam | URLSearchParams\n replace?: boolean\n merge?: boolean\n}\n\nexport interface UseRedirectProps {\n predicateUrl: string\n targetUrl: string\n queryParams?: QueryParam | URLSearchParams\n replace?: boolean\n}\n\nexport function Redirect({\n to,\n query,\n replace = true,\n merge = true,\n}: RedirectProps): JSX.Element | null {\n useRedirect(usePath(), to, { query, replace, merge })\n return null\n}\n\nexport function useRedirect(\n predicateUrl: string | null,\n targetUrl: string,\n {\n query,\n replace = true,\n merge = true,\n }: { query?: QueryParam; replace?: boolean; merge?: boolean } = {}\n): void {\n const currentPath = usePath()\n const [currentQuery] = useQueryParams()\n const hash = getCurrentHash()\n\n let url = targetUrl\n const targetQuery = new URLSearchParams({\n ...(merge ? currentQuery : {}),\n ...query,\n }).toString()\n if (targetQuery) {\n url += '?' + targetQuery\n }\n if (merge && hash && hash.length) {\n url += hash\n }\n\n useLayoutEffect(() => {\n if (currentPath === predicateUrl) {\n navigate(url, { replace })\n }\n }, [predicateUrl, url, replace, currentPath])\n}\n","import React, { useCallback, forwardRef, Ref } from 'react'\n\nimport { navigate } from './navigate'\nimport { useBasePath, useFullPath } from './location'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n basePath?: string\n children?: React.ReactNode\n}\nexport type LinkRef = HTMLAnchorElement | null\n\nexport interface ActiveLinkProps extends LinkProps {\n activeClass?: string\n exactActiveClass?: string\n}\n\nfunction Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>) {\n basePath = useLinkBasePath(basePath)\n href = getLinkHref(href, basePath)\n\n const { onClick, target } = props\n\n const handleClick = useCallback<React.MouseEventHandler<HTMLAnchorElement>>(\n (e) => {\n try {\n if (onClick) onClick(e)\n } catch (ex) {\n e.preventDefault()\n throw ex\n }\n if (shouldTrap(e, target)) {\n e.preventDefault() // prevent the link from actually navigating\n navigate(e.currentTarget.href)\n }\n },\n [onClick, target]\n )\n\n return <a {...props} href={href} onClick={handleClick} ref={ref} />\n}\n\nconst RefLink = forwardRef<LinkRef, LinkProps>(Link) as (\n props: LinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof Link>\n\nexport default RefLink\nexport { RefLink as Link }\n\nfunction ActiveLink(\n { basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps,\n ref?: Ref<HTMLAnchorElement>\n) {\n basePath = useLinkBasePath(basePath)\n const fullPath = useFullPath()\n\n let { href } = props\n href = absolutePathName(getLinkHref(href, basePath))\n\n if (exactActiveClass && fullPath === href) className += ` ${exactActiveClass}`\n if (activeClass && fullPath.startsWith(href)) className += ` ${activeClass}`\n\n return <RefLink {...props} basePath={basePath} className={className} ref={ref} />\n}\n\nconst ActiveLinkRef = forwardRef<LinkRef, ActiveLinkProps>(ActiveLink) as (\n props: ActiveLinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof ActiveLink>\n\nexport { ActiveLinkRef as ActiveLink }\n\nfunction useLinkBasePath(basePath?: string): string {\n const contextBasePath = useBasePath()\n if (basePath === '/') return ''\n return basePath || contextBasePath\n}\n\nfunction getLinkHref(href: string, basePath = '') {\n return href.startsWith('/') ? basePath + href : href\n}\n\nfunction absolutePathName(href: string): string {\n if (href.startsWith('/')) return href\n return new URL(href, document.baseURI).pathname\n}\n\nfunction shouldTrap(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, target?: string) {\n return (\n !e.defaultPrevented && // onClick prevented default\n e.button === 0 && // ignore everything but left clicks\n !(target || target === '_self') && // don't trap target === blank\n !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n )\n}\n"],"names":["BasePathContext","createContext","PathContext","RouterProvider","basePath","path","children","React","createElement","Provider","value","isNode","undefined","window","e","interceptors","Set","hasIntercepted","hasUserCancelled","lastScroll","shouldCancelNavigation","scrollX","scrollY","Array","from","some","interceptor","prompt","confirm","setTimeout","usePath","contextPath","useContext","contextBasePath","useBasePath","setPath","useState","getFormattedPath","useLocationChange","useCallback","newPath","inheritBasePath","onInitial","useFullPath","getCurrentPath","useHash","stripHash","hash","setHash","location","handleHash","newHash","useLayoutEffect","addEventListener","removeEventListener","substring","pathname","getCurrentHash","hashIndex","indexOf","setFn","isActive","routerBasePath","setRef","useRef","current","onPopState","isPredicateActive","getFormattedLocation","useMountedLayout","fn","deps","hasMounted","useHistory","history","setHistory","getRavigerHistory","scrollRestoration","state","baseMissing","isPathInBase","toLowerCase","startsWith","decodeURIComponent","replace","basePathMatcher","RegExp","fullPath","search","host","hostname","href","origin","predicate","isFunction","obj","emptyPathResult","useRoutes","routes","routeProps","overridePathParams","matchTrailingSlash","useRedirectDetection","updateState","forceRender","route","useMatchRoute","trailingMatch","matchers","useMatchers","Object","keys","routeMatch","props","getMatchParams","usePathParams","options","isSingle","isArray","usePathOptions","useMatch","match","find","regex","_a","routeOrRoutes","useMemo","map","createRouteMatcher","params","sort","join","routeMatchers","pathParams","reduce","prop","i","string","substr","paramName","length","lastPath","navigate","url","Error","query","URLSearchParams","toString","isAbsolute","test","isCurrentOrigin","URL","assign","replaceState","pushState","event","PopStateEvent","__tag","dispatchEvent","useNavigationPrompt","onPopStateNavigation","undoNavigation","scrollTo","handler","cancelNavigation","preventDefault","returnValue","addInterceptor","add","removeInterceptor","delete","useNavigate","optBasePath","base","useQueryParams","parseFn","parseQuery","serializeFn","serializeQuery","querystring","setQuerystring","getQueryString","setQueryParams","serialized","q","fromEntries","entries","queryParams","filter","v","ssrPath","queryIndex","Redirect","to","merge","useRedirect","predicateUrl","targetUrl","currentPath","currentQuery","targetQuery","RefLink","forwardRef","Link","ref","getLinkHref","useLinkBasePath","onClick","target","handleClick","ex","shouldTrap","defaultPrevented","button","metaKey","altKey","ctrlKey","shiftKey","currentTarget","ActiveLinkRef","ActiveLink","className","exactActiveClass","activeClass","absolutePathName","document","baseURI"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"module.js","sources":["../src/context.tsx","../src/node.ts","../src/intercept.ts","../src/location.ts","../src/hooks.ts","../src/typeChecks.ts","../src/router.tsx","../src/navigate.ts","../src/querystring.ts","../src/redirect.ts","../src/Link.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\n\nconst BasePathContext = createContext('')\nconst PathContext = createContext<string | null>(null)\n\nexport { BasePathContext }\nexport { PathContext }\n\nexport function useRouter(): { basePath: string; path: string | null } {\n const [basePath, path] = [useContext(BasePathContext), useContext(PathContext)]\n return useMemo(() => ({ basePath, path }), [basePath, path])\n}\n\nexport function RouterProvider({\n basePath = '',\n path,\n children,\n}: {\n basePath?: string\n path?: string\n children?: React.ReactNode\n}): JSX.Element {\n return (\n // The ordering here is important, the basePath will change less often\n // So putting it on the outside reduces its need to re-render\n <BasePathContext.Provider value={basePath}>\n <PathContext.Provider value={path ?? null}>{children}</PathContext.Provider>\n </BasePathContext.Provider>\n )\n}\n","let ssrPath = '/'\nlet isNode = true\ntry {\n isNode = window === undefined\n} catch (e) {} // eslint-disable-line no-empty\n\nexport { isNode }\nexport function getSsrPath(): string {\n return ssrPath\n}\nexport function setSsrPath(path: string): void {\n ssrPath = path\n}\n","const interceptors = new Set<() => string | void>()\n\nexport const defaultPrompt = 'Are you sure you want to leave this page?'\n\nlet hasIntercepted = false\nlet hasUserCancelled = false\nlet lastScroll = [0, 0] as [number, number]\n\nexport function shouldCancelNavigation(): boolean {\n lastScroll = [window.scrollX, window.scrollY]\n if (hasIntercepted) return hasUserCancelled\n\n // confirm if any interceptors return true\n return Array.from(interceptors).some((interceptor) => {\n const prompt = interceptor()\n if (!prompt) return false\n\n // cancel navigation if user declines\n hasUserCancelled = !window.confirm(prompt) // eslint-disable-line no-alert\n\n // track user response so that multiple interceptors don't prompt\n hasIntercepted = true\n\n // reset so that future navigation attempts are prompted\n setTimeout(() => {\n hasIntercepted = false\n hasUserCancelled = false\n }, 0)\n\n return hasUserCancelled\n })\n}\n\nexport function addInterceptor(handler: () => string | void): void {\n window.addEventListener('beforeunload', handler)\n interceptors.add(handler)\n}\n\nexport function removeInterceptor(handler: () => string | void): void {\n window.removeEventListener('beforeunload', handler)\n interceptors.delete(handler)\n}\n\nexport function undoNavigation(lastPath: string): void {\n window.history.pushState(null, null as unknown as string, lastPath)\n setTimeout(() => {\n window.scrollTo(...lastScroll)\n }, 0)\n}\n","import { useState, useCallback, useRef, useContext, useLayoutEffect } from 'react'\n\nimport { BasePathContext, PathContext } from './context'\nimport { useMountedLayout } from './hooks'\nimport { getSsrPath, isNode } from './node'\nimport { shouldCancelNavigation } from './intercept'\nimport { isFunction } from './typeChecks'\n\nexport interface RavigerLocation {\n /** The current path; alias of `pathname` */\n path: string | null\n /** The current path; alias of `path` */\n pathname: string | null\n /** The full path, ignores any `basePath` in the context */\n fullPath: string\n basePath?: string\n search: string\n hash: string\n host: string\n hostname: string\n href: string\n origin: string\n}\n\nexport interface RavigerHistory {\n scrollRestoration: 'auto' | 'manual'\n state: unknown\n}\n\nexport interface LocationChangeSetFn {\n (location: RavigerLocation): void\n}\nexport interface LocationChangeOptionParams {\n inheritBasePath?: boolean\n basePath?: string\n isActive?: boolean | (() => boolean)\n onInitial?: boolean\n}\n\nexport function usePath(basePath?: string): string | null {\n const contextPath = useContext(PathContext)\n const contextBasePath = useBasePath() // hooks can't be called conditionally\n basePath = basePath || contextBasePath\n\n // Don't bother tracking the actual path, it can get out of sync\n // due to React parent/child render ordering, especially with onmount navigation\n // See issues:\n // https://github.com/kyeotic/raviger/issues/116\n // https://github.com/kyeotic/raviger/issues/64\n //\n // This is just used to force a re-render\n const [, setPath] = useState(getFormattedPath(basePath))\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, {\n basePath,\n inheritBasePath: !basePath,\n // Use on initial to handle to force state updates from on-mount navigation\n onInitial: true,\n })\n\n return contextPath || getFormattedPath(basePath)\n}\n\nexport function useBasePath(): string {\n return useContext(BasePathContext)\n}\n\nexport function useFullPath(): string {\n const [path, setPath] = useState<string | null>(getCurrentPath())\n const onChange = useCallback(({ path: newPath }) => setPath(newPath), [])\n useLocationChange(onChange, { inheritBasePath: false })\n\n return path || '/'\n}\n\nexport function useHash({ stripHash = true } = {}): string {\n const [hash, setHash] = useState(window.location.hash)\n const handleHash = useCallback(() => {\n const newHash = window.location.hash\n if (newHash === hash) return\n setHash(newHash)\n }, [setHash, hash])\n\n useLayoutEffect(() => {\n window.addEventListener('hashchange', handleHash, false)\n return () => window.removeEventListener('hashchange', handleHash)\n }, [handleHash])\n\n useLocationChange(handleHash)\n return stripHash ? hash.substring(1) : hash\n}\n\nexport function getCurrentPath(): string {\n return isNode ? getSsrPath() : window.location.pathname || '/'\n}\n\nexport function getCurrentHash(): string {\n if (isNode) {\n const path = getSsrPath()\n const hashIndex = path.indexOf('#')\n return path.substring(hashIndex)\n }\n return window.location.hash\n}\n\nexport function useLocationChange(\n setFn: LocationChangeSetFn,\n {\n inheritBasePath = true,\n basePath = '',\n isActive,\n onInitial = false,\n }: LocationChangeOptionParams = {}\n): void {\n if (isNode) return\n\n // All hooks after this are conditional, but the runtime can't actually change\n /* eslint-disable react-hooks/rules-of-hooks */\n\n const routerBasePath = useBasePath()\n if (inheritBasePath && routerBasePath) basePath = routerBasePath\n\n const setRef = useRef<LocationChangeSetFn>(setFn)\n useLayoutEffect(() => {\n // setFn could be an in-render declared callback, making it unstable\n // This is a method of using an often-changing callback from React Hooks\n // https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback\n // While not recommended, it is the best current (16.9) available method\n // For reducing the useEffect cleanup from setFn changing every render\n setRef.current = setFn\n })\n\n const onPopState = useCallback(() => {\n // No predicate defaults true\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n if (shouldCancelNavigation()) return\n setRef.current(getFormattedLocation(basePath))\n }, [isActive, basePath])\n\n useLayoutEffect(() => {\n window.addEventListener('popstate', onPopState)\n return () => window.removeEventListener('popstate', onPopState)\n }, [onPopState])\n\n // When the basePath changes re-check the path after the render completes\n // This allows nested contexts to get an up-to-date formatted path\n useMountedLayout(\n () => {\n if (isActive !== undefined && !isPredicateActive(isActive)) return\n setRef.current(getFormattedLocation(basePath))\n },\n [basePath, isActive],\n { onInitial }\n )\n}\n\nexport function useHistory(): RavigerHistory {\n const [history, setHistory] = useState(getRavigerHistory())\n useLocationChange(useCallback(() => setHistory(getRavigerHistory()), [setHistory]))\n return history\n}\n\nfunction getRavigerHistory(): RavigerHistory {\n if (isNode) return { scrollRestoration: 'manual', state: null }\n return {\n scrollRestoration: window.history.scrollRestoration,\n state: window.history.state,\n }\n}\n\n/**\n * Returns the current path after decoding. If basePath is provided it will be removed from the front of the path.\n * If basePath is provided and the path does not begin with it will return null\n * @param {string} basePath basePath, if any\n * @return {string | null} returns path with basePath prefix removed, or null if basePath is provided and missing\n */\nexport function getFormattedPath(basePath: string): string | null {\n const path = getCurrentPath()\n const baseMissing = basePath && !isPathInBase(basePath, path)\n if (path === null || baseMissing) return null\n return decodeURIComponent(!basePath ? path : path.replace(basePathMatcher(basePath), '') || '/')\n}\n\nfunction getFormattedLocation(basePath: string): RavigerLocation {\n const path = getFormattedPath(basePath)\n return {\n basePath,\n path,\n pathname: path,\n fullPath: getCurrentPath(),\n search: window.location.search,\n hash: getCurrentHash(),\n host: window.location.host,\n hostname: window.location.hostname,\n href: window.location.href,\n origin: window.location.origin,\n }\n}\n\nfunction isPredicateActive(predicate: boolean | (() => boolean)): boolean {\n return isFunction(predicate) ? predicate() : predicate\n}\n\nfunction basePathMatcher(basePath: string): RegExp {\n return new RegExp('^' + basePath, 'i')\n}\n\nfunction isPathInBase(basePath: string, path: string): boolean {\n return !!(basePath && path && path.toLowerCase().startsWith(basePath.toLowerCase()))\n}\n","import { useLayoutEffect, useRef } from 'react'\n\nexport function useMountedLayout(\n fn: () => unknown,\n deps: React.DependencyList | undefined,\n { onInitial = false } = {}\n): void {\n const hasMounted = useRef(onInitial)\n useLayoutEffect(() => {\n if (!hasMounted.current) hasMounted.current = true\n else fn()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n","// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types\nexport function isFunction(obj: unknown): obj is Function {\n return !!obj && typeof obj === 'function'\n}\n","import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\n\nimport { RouterProvider } from './context'\nimport { isNode, setSsrPath, getSsrPath } from './node'\nimport { getFormattedPath, usePath } from './location'\nimport type { NonEmptyRecord, Split, ValueOf } from './types'\n\nconst emptyPathResult: [null, null] = [null, null]\n\nexport interface PathParamOptions {\n basePath?: string\n matchTrailingSlash?: boolean\n}\nexport interface RouteOptionParams extends PathParamOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routeProps?: { [k: string]: any }\n overridePathParams?: boolean\n}\ninterface RouteMatcher {\n path: string\n regex: RegExp\n props: string[]\n}\n\ntype ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [\n infer Head,\n ...infer Tail\n]\n ? Head extends `:${infer Name}`\n ? { [N in Name]: string } & ExtractPathParams<Path, Tail>\n : ExtractPathParams<Path, Tail>\n : unknown\n\nexport type Routes<Path extends string> = {\n [P in Path]: (\n params: NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ) => JSX.Element\n}\n\nexport function useRoutes<Path extends string>(\n routes: Routes<Path>,\n {\n basePath = '',\n routeProps = {},\n overridePathParams = true,\n matchTrailingSlash = true,\n }: RouteOptionParams = {}\n): JSX.Element | null {\n /*\n This is a hack to setup a listener for the path while always using this latest path\n The issue with usePath is that, in order to not re-render nested components when\n their parent router changes the path, it uses the context's path\n But since that path has to get _set_ here in useRoutes something has to give\n If usePath returns latest it causes render thrashing\n If useRoutes hacks itself into the latest path nothing bad happens (...afaik)\n */\n const path = usePath(basePath) && getFormattedPath(basePath)\n\n // Handle potential <Redirect /> use in routes\n useRedirectDetection(basePath, usePath(basePath))\n\n // Get the current route\n const route = useMatchRoute(routes, path, {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n })\n\n // No match should not return an empty Provider, just null\n if (!route || path === null) return null\n return (\n <RouterProvider basePath={basePath} path={path}>\n {route}\n </RouterProvider>\n )\n}\n\nfunction useMatchRoute(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n routes: { [key: string]: (...props: any) => JSX.Element },\n path: string | null,\n {\n routeProps,\n overridePathParams,\n matchTrailingSlash,\n }: Omit<RouteOptionParams, 'basePath' | 'matchTrailingSlash'> & { matchTrailingSlash: boolean }\n) {\n path = trailingMatch(path, matchTrailingSlash)\n const matchers = useMatchers(Object.keys(routes))\n\n if (path === null) return null\n const [routeMatch, props] = getMatchParams(path, matchers)\n\n if (!routeMatch) return null\n\n return routes[routeMatch.path](\n overridePathParams ? { ...props, ...routeProps } : { ...routeProps, ...props }\n )\n}\n\nexport function usePathParams<Path extends string>(\n route: Path,\n options?: PathParamOptions\n): NonEmptyRecord<ExtractPathParams<Path extends `${infer P1}*` ? P1 : Path>> | null\nexport function usePathParams<Path extends string>(\n routes: ReadonlyArray<Path>,\n options?: PathParamOptions\n):\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\nexport function usePathParams<Params extends ReadonlyArray<string> | string>(\n routes: Params,\n options: PathParamOptions = {}\n): Params extends ReadonlyArray<string>\n ?\n | ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>\n | [null, null]\n : Params extends string\n ? NonEmptyRecord<ExtractPathParams<Params extends `${infer P1}*` ? P1 : Params>> | null\n : never {\n const isSingle = !Array.isArray(routes)\n const [path, matchers] = usePathOptions(routes as string | string[], options)\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (path === null) return isSingle ? null : emptyPathResult\n\n const [routeMatch, props] = getMatchParams(path, matchers)\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n if (!routeMatch) return isSingle ? null : emptyPathResult\n\n // @ts-expect-error inference is not carried forward and I don't know how to resolve this type\n return isSingle\n ? props\n : ([routeMatch.path, props] as ValueOf<{\n [P in typeof routes[number]]: [\n P,\n NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>\n ]\n }>)\n}\n\nexport function useMatch(routes: string | string[], options: PathParamOptions = {}): string | null {\n const [path, matchers] = usePathOptions(routes, options)\n const match = matchers.find(({ regex }) => path?.match(regex))\n\n return match?.path ?? null\n}\n\nfunction usePathOptions(\n routeOrRoutes: string | string[],\n { basePath, matchTrailingSlash = true }: PathParamOptions\n): [string | null, RouteMatcher[]] {\n const routes = (!Array.isArray(routeOrRoutes) ? [routeOrRoutes] : routeOrRoutes) as string[]\n const matchers = useMatchers(routes)\n\n return [trailingMatch(usePath(basePath), matchTrailingSlash), matchers]\n}\n\nfunction useMatchers(routes: string[]): RouteMatcher[] {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => routes.map(createRouteMatcher), [hashParams(routes)])\n}\n\nfunction getMatchParams(\n path: string,\n routeMatchers: RouteMatcher[]\n): [RouteMatcher, Record<string, unknown>] | [null, null] {\n let pathParams: RegExpMatchArray | null = null\n\n // Hacky method for find + map\n const routeMatch = routeMatchers.find(({ regex }) => {\n pathParams = path.match(regex)\n return !!pathParams\n })\n\n if (!routeMatch || pathParams === null) return emptyPathResult\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const props = routeMatch.props.reduce((props: any, prop, i) => {\n // The following `match` can't be null because the above return asserts it\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n props[prop] = pathParams![i + 1]\n return props\n }, {})\n\n return [routeMatch, props]\n}\n\nfunction createRouteMatcher(path: string): RouteMatcher {\n return {\n path,\n regex: new RegExp(\n `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path)\n .replace(/:[a-zA-Z]+/g, '([^/]+)')\n .replace(/\\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`,\n 'i'\n ),\n props: (path.match(/:[a-zA-Z]+/g) ?? []).map((paramName) => paramName.substr(1)),\n }\n}\n\nexport function setPath(path: string): void {\n if (!isNode) {\n throw new Error('This method should only be used in NodeJS environments')\n }\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const url = require('url')\n setSsrPath(url.resolve(getSsrPath(), path))\n}\n\n// React doesn't like when the hook dependency array changes size\n// >> Warning: The final argument passed to useMemo changed size between renders. The order and size of this array must remain constant.\n// It is recommended to use a hashing function to produce a single, stable value\n// https://github.com/facebook/react/issues/14324#issuecomment-441489421\nfunction hashParams(params: string[]): string {\n return [...params].sort().join(':')\n}\n\n// React appears to suppress parent's re-rendering when a child's\n// useLayoutEffect updates internal state\n// the `navigate` call in useRedirect *does* cause usePath/useLocationChange\n// to fire, but without this hack useRoutes suppresses the update\n// TODO: find a better way to cause a synchronous update from useRoutes\nfunction useRedirectDetection(basePath: string, path: string | null) {\n const [, updateState] = useState({})\n const forceRender = useCallback(() => updateState({}), [])\n\n useLayoutEffect(() => {\n if (path !== getFormattedPath(basePath)) {\n forceRender()\n }\n }, [forceRender, basePath, path])\n}\n\nfunction trailingMatch(path: string | null, matchTrailingSlash: boolean): string | null {\n if (path === null) return path\n // path.length > 1 ensure we still match on the root route \"/\" when matchTrailingSlash is set\n if (matchTrailingSlash && path && path[path.length - 1] === '/' && path.length > 1) {\n path = path.substring(0, path.length - 1)\n }\n return path\n}\n\n// Taken from: https://stackoverflow.com/a/3561711\n// modified to NOT ESCAPE \"/\" and \"*\" since we use those as path parts\nfunction escapeRegExp(string: string): string {\n return string.replace(/[-\\\\^$+?.()|[\\]{}]/g, '\\\\$&')\n}\n","import { useCallback, useLayoutEffect } from 'react'\n\nimport { useBasePath } from './location'\nimport { isNode } from './node'\nimport type { QueryParam } from './querystring'\nimport {\n shouldCancelNavigation,\n addInterceptor,\n removeInterceptor,\n defaultPrompt,\n undoNavigation,\n} from './intercept'\n\nexport interface NavigateOptions {\n /**\n * Use a `replace` instead of `push` for navigation\n * @default false */\n replace?: boolean\n /** Values to serialize as a querystring, which will be appended to the `url` */\n query?: QueryParam | URLSearchParams\n /** value to pass as the state/data to history push/replace*/\n state?: unknown\n}\n\nlet lastPath = ''\n\nexport function navigate(url: string, options?: NavigateOptions): void {\n if (typeof url !== 'string') {\n throw new Error(`\"url\" must be a string, was provided a(n) ${typeof url}`)\n }\n\n if (Array.isArray(options?.query)) {\n throw new Error('\"query\" a serializable object or URLSearchParams')\n }\n\n if (shouldCancelNavigation()) return\n if (options?.query) {\n url += '?' + new URLSearchParams(options.query).toString()\n }\n\n lastPath = url\n // if the origin does not match history navigation will fail with\n // \"cannot be created in a document with origin\"\n // When navigating to another domain we must use location instead of history\n if (isAbsolute(url) && !isCurrentOrigin(url)) {\n window.location.assign(url)\n return\n }\n\n if (options?.replace) window.history.replaceState(options?.state, '', url)\n else window.history.pushState(options?.state, '', url)\n\n const event = new PopStateEvent('popstate')\n // Tag the event so navigation can be filtered out from browser events\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(event as any).__tag = 'raviger:navigation'\n dispatchEvent(event)\n}\n\nexport function useNavigationPrompt(predicate = true, prompt: string = defaultPrompt): void {\n if (isNode) return\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const onPopStateNavigation = () => {\n if (shouldCancelNavigation()) {\n undoNavigation(lastPath)\n }\n }\n window.addEventListener('popstate', onPopStateNavigation)\n return () => window.removeEventListener('popstate', onPopStateNavigation)\n }, [])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useLayoutEffect(() => {\n const handler = (e?: BeforeUnloadEvent): string | void => {\n if (predicate) {\n return e ? cancelNavigation(e, prompt) : prompt\n }\n }\n addInterceptor(handler)\n return () => removeInterceptor(handler)\n }, [predicate, prompt])\n}\n\nfunction cancelNavigation(event: BeforeUnloadEvent, prompt: string) {\n // Cancel the event as stated by the standard.\n event.preventDefault()\n // Chrome requires returnValue to be set.\n event.returnValue = prompt\n // Return value for prompt per spec\n return prompt\n}\n\nexport function useNavigate(optBasePath = ''): typeof navigate {\n const basePath = useBasePath()\n const navigateWithBasePath = useCallback<typeof navigate>(\n (url: string, options?: NavigateOptions) => {\n const base = optBasePath || basePath\n const href = url.startsWith('/') ? base + url : url\n navigate(href, options)\n },\n [basePath, optBasePath]\n )\n return navigateWithBasePath\n}\n\nfunction isAbsolute(url: string) {\n return /^(?:[a-z]+:)?\\/\\//i.test(url)\n}\n\nfunction isCurrentOrigin(url: string) {\n return window.location.origin === new URL(url).origin\n}\n","import { useState, useCallback } from 'react'\n\nimport { navigate } from './navigate'\nimport { isNode, getSsrPath } from './node'\nimport { getCurrentPath, getCurrentHash, useLocationChange } from './location'\n\nexport interface QueryParam {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\nexport interface setQueryParamsOptions {\n replace?: boolean\n}\n\nexport function useQueryParams<T extends QueryParam>(\n parseFn: (query: string) => T = parseQuery,\n serializeFn: (query: Partial<T>) => string = serializeQuery\n): [T, (query: T, options?: setQueryParamsOptions) => void] {\n const [querystring, setQuerystring] = useState(getQueryString())\n const setQueryParams = useCallback(\n (params, { replace = true } = {}) => {\n let path = getCurrentPath()\n params = replace ? params : { ...parseFn(querystring), ...params }\n const serialized = serializeFn(params).toString()\n\n if (serialized) path += '?' + serialized\n if (!replace) path += getCurrentHash()\n\n navigate(path)\n },\n [querystring, parseFn, serializeFn]\n )\n\n // Update state when route changes\n const updateQuery = useCallback(() => setQuerystring(getQueryString()), [])\n\n useLocationChange(updateQuery)\n return [parseFn(querystring), setQueryParams]\n}\n\nfunction parseQuery<T extends QueryParam>(querystring: string): T {\n const q = new URLSearchParams(querystring)\n return Object.fromEntries(q.entries()) as T\n}\n\nfunction serializeQuery<T extends QueryParam>(queryParams: T): string {\n return new URLSearchParams(Object.entries(queryParams).filter(([, v]) => v !== null)).toString()\n}\n\nexport function getQueryString(): string {\n if (isNode) {\n const ssrPath = getSsrPath()\n const queryIndex = ssrPath.indexOf('?')\n return queryIndex === -1 ? '' : ssrPath.substring(queryIndex + 1)\n }\n return window.location.search\n}\n","import { useLayoutEffect } from 'react'\n\nimport { getCurrentHash, usePath } from './location'\nimport { navigate } from './navigate'\nimport { QueryParam, useQueryParams } from './querystring'\n\nexport interface RedirectProps {\n to: string\n query?: QueryParam | URLSearchParams\n replace?: boolean\n merge?: boolean\n}\n\nexport interface UseRedirectProps {\n predicateUrl: string\n targetUrl: string\n queryParams?: QueryParam | URLSearchParams\n replace?: boolean\n}\n\nexport function Redirect({\n to,\n query,\n replace = true,\n merge = true,\n}: RedirectProps): JSX.Element | null {\n useRedirect(usePath(), to, { query, replace, merge })\n return null\n}\n\nexport function useRedirect(\n predicateUrl: string | null,\n targetUrl: string,\n {\n query,\n replace = true,\n merge = true,\n }: { query?: QueryParam; replace?: boolean; merge?: boolean } = {}\n): void {\n const currentPath = usePath()\n const [currentQuery] = useQueryParams()\n const hash = getCurrentHash()\n\n let url = targetUrl\n const targetQuery = new URLSearchParams({\n ...(merge ? currentQuery : {}),\n ...query,\n }).toString()\n if (targetQuery) {\n url += '?' + targetQuery\n }\n if (merge && hash && hash.length) {\n url += hash\n }\n\n useLayoutEffect(() => {\n if (currentPath === predicateUrl) {\n navigate(url, { replace })\n }\n }, [predicateUrl, url, replace, currentPath])\n}\n","import React, { useCallback, forwardRef, Ref } from 'react'\n\nimport { navigate } from './navigate'\nimport { useBasePath, useFullPath } from './location'\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n basePath?: string\n children?: React.ReactNode\n}\nexport type LinkRef = HTMLAnchorElement | null\n\nexport interface ActiveLinkProps extends LinkProps {\n activeClass?: string\n exactActiveClass?: string\n}\n\nfunction Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>) {\n basePath = useLinkBasePath(basePath)\n href = getLinkHref(href, basePath)\n\n const { onClick, target } = props\n\n const handleClick = useCallback<React.MouseEventHandler<HTMLAnchorElement>>(\n (e) => {\n try {\n if (onClick) onClick(e)\n } catch (ex) {\n e.preventDefault()\n throw ex\n }\n if (shouldTrap(e, target)) {\n e.preventDefault() // prevent the link from actually navigating\n navigate(e.currentTarget.href)\n }\n },\n [onClick, target]\n )\n\n return <a {...props} href={href} onClick={handleClick} ref={ref} />\n}\n\nconst RefLink = forwardRef<LinkRef, LinkProps>(Link) as (\n props: LinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof Link>\n\nexport default RefLink\nexport { RefLink as Link }\n\nfunction ActiveLink(\n { basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps,\n ref?: Ref<HTMLAnchorElement>\n) {\n basePath = useLinkBasePath(basePath)\n const fullPath = useFullPath()\n\n let { href } = props\n href = absolutePathName(getLinkHref(href, basePath))\n\n if (exactActiveClass && fullPath === href)\n className = `${className ?? ``} ${exactActiveClass}`.trim()\n if (activeClass && fullPath.startsWith(href))\n className = `${className ?? ``} ${activeClass}`.trim()\n\n return <RefLink {...props} basePath={basePath} className={className} ref={ref} />\n}\n\nconst ActiveLinkRef = forwardRef<LinkRef, ActiveLinkProps>(ActiveLink) as (\n props: ActiveLinkProps & { ref?: React.ForwardedRef<HTMLAnchorElement> }\n) => ReturnType<typeof ActiveLink>\n\nexport { ActiveLinkRef as ActiveLink }\n\nfunction useLinkBasePath(basePath?: string): string {\n const contextBasePath = useBasePath()\n if (basePath === '/') return ''\n return basePath || contextBasePath\n}\n\nfunction getLinkHref(href: string, basePath = '') {\n return href.startsWith('/') ? basePath + href : href\n}\n\nfunction absolutePathName(href: string): string {\n if (href.startsWith('/')) return href\n return new URL(href, document.baseURI).pathname\n}\n\nfunction shouldTrap(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, target?: string) {\n return (\n !e.defaultPrevented && // onClick prevented default\n e.button === 0 && // ignore everything but left clicks\n !(target || target === '_self') && // don't trap target === blank\n !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n )\n}\n"],"names":["BasePathContext","createContext","PathContext","RouterProvider","basePath","path","children","React","createElement","Provider","value","isNode","undefined","window","e","interceptors","Set","hasIntercepted","hasUserCancelled","lastScroll","shouldCancelNavigation","scrollX","scrollY","Array","from","some","interceptor","prompt","confirm","setTimeout","usePath","contextPath","useContext","contextBasePath","useBasePath","setPath","useState","getFormattedPath","useLocationChange","useCallback","newPath","inheritBasePath","onInitial","useFullPath","getCurrentPath","useHash","stripHash","hash","setHash","location","handleHash","newHash","useLayoutEffect","addEventListener","removeEventListener","substring","pathname","getCurrentHash","hashIndex","indexOf","setFn","isActive","routerBasePath","setRef","useRef","current","onPopState","isPredicateActive","getFormattedLocation","useMountedLayout","fn","deps","hasMounted","useHistory","history","setHistory","getRavigerHistory","scrollRestoration","state","baseMissing","isPathInBase","toLowerCase","startsWith","decodeURIComponent","replace","basePathMatcher","RegExp","fullPath","search","host","hostname","href","origin","predicate","isFunction","obj","emptyPathResult","useRoutes","routes","routeProps","overridePathParams","matchTrailingSlash","useRedirectDetection","updateState","forceRender","route","useMatchRoute","trailingMatch","matchers","useMatchers","Object","keys","routeMatch","props","getMatchParams","usePathParams","options","isSingle","isArray","usePathOptions","useMatch","match","find","regex","_a","routeOrRoutes","useMemo","map","createRouteMatcher","params","sort","join","routeMatchers","pathParams","reduce","prop","i","string","substr","paramName","length","lastPath","navigate","url","Error","query","URLSearchParams","toString","isAbsolute","test","isCurrentOrigin","URL","assign","replaceState","pushState","event","PopStateEvent","__tag","dispatchEvent","useNavigationPrompt","onPopStateNavigation","undoNavigation","scrollTo","handler","cancelNavigation","preventDefault","returnValue","addInterceptor","add","removeInterceptor","delete","useNavigate","optBasePath","base","useQueryParams","parseFn","parseQuery","serializeFn","serializeQuery","querystring","setQuerystring","getQueryString","setQueryParams","serialized","q","fromEntries","entries","queryParams","filter","v","ssrPath","queryIndex","Redirect","to","merge","useRedirect","predicateUrl","targetUrl","currentPath","currentQuery","targetQuery","RefLink","forwardRef","Link","ref","getLinkHref","useLinkBasePath","onClick","target","handleClick","ex","shouldTrap","defaultPrevented","button","metaKey","altKey","ctrlKey","shiftKey","currentTarget","ActiveLinkRef","ActiveLink","className","exactActiveClass","activeClass","absolutePathName","document","baseURI","trim"],"mappings":"sJAEA,MAAMA,EAAkBC,EAAc,IAChCC,EAAcD,EAA6B,MAU3C,SAAUE,gBAAeC,SAC7BA,EAAW,GAAEC,KACbA,EAAIC,SACJA,IAMA,OAGEC,EAAAC,cAACR,EAAgBS,SAAS,CAAAC,MAAON,GAC/BG,EAAAC,cAACN,EAAYO,UAASC,MAAOL,MAAAA,EAAAA,EAAQ,MAAOC,IC1BlD,IACIK,GAAS,EACb,IACEA,OAAoBC,IAAXC,OACT,MAAOC,ICJT,MAAMC,EAAe,IAAIC,IAIzB,IAAIC,GAAiB,EACjBC,GAAmB,EACnBC,EAAa,CAAC,EAAG,YAELC,yBAEd,OADAD,EAAa,CAACN,OAAOQ,QAASR,OAAOS,SACjCL,EAAuBC,EAGpBK,MAAMC,KAAKT,GAAcU,MAAMC,IACpC,MAAMC,EAASD,IACf,QAAKC,IAGLT,GAAoBL,OAAOe,QAAQD,GAGnCV,GAAiB,EAGjBY,YAAW,KACTZ,GAAiB,EACjBC,GAAmB,IAClB,GAEIA,MCUL,SAAUY,QAAQ1B,GACtB,MAAM2B,EAAcC,EAAW9B,GACzB+B,EAAkBC,cACxB9B,EAAWA,GAAY6B,EASvB,MAAM,CAAGE,GAAWC,EAASC,iBAAiBjC,IAS9C,OAPAkC,kBADiBC,GAAY,EAAGlC,KAAMmC,KAAcL,EAAQK,IAAU,IAC1C,CAC1BpC,SAAAA,EACAqC,iBAAkBrC,EAElBsC,WAAW,IAGNX,GAAeM,iBAAiBjC,YAGzB8B,cACd,OAAOF,EAAWhC,YAGJ2C,cACd,MAAOtC,EAAM8B,GAAWC,EAAwBQ,kBAIhD,OAFAN,kBADiBC,GAAY,EAAGlC,KAAMmC,KAAcL,EAAQK,IAAU,IAC1C,CAAEC,iBAAiB,IAExCpC,GAAQ,IAGX,SAAUwC,SAAQC,UAAEA,GAAY,GAAS,IAC7C,MAAOC,EAAMC,GAAWZ,EAASvB,OAAOoC,SAASF,MAC3CG,EAAaX,GAAY,KAC7B,MAAMY,EAAUtC,OAAOoC,SAASF,KAC5BI,IAAYJ,GAChBC,EAAQG,KACP,CAACH,EAASD,IAQb,OANAK,GAAgB,KACdvC,OAAOwC,iBAAiB,aAAcH,GAAY,GAC3C,IAAMrC,OAAOyC,oBAAoB,aAAcJ,KACrD,CAACA,IAEJZ,kBAAkBY,GACXJ,EAAYC,EAAKQ,UAAU,GAAKR,WAGzBH,iBACd,OAAOjC,EF7FK,IE6FmBE,OAAOoC,SAASO,UAAY,aAG7CC,iBACd,GAAI9C,EAAQ,CACV,MAAMN,EFlGI,IEmGJqD,EAAYrD,EAAKsD,QAAQ,KAC/B,OAAOtD,EAAKkD,UAAUG,GAExB,OAAO7C,OAAOoC,SAASF,KAGnB,SAAUT,kBACdsB,GACAnB,gBACEA,GAAkB,EAAIrC,SACtBA,EAAW,GAAEyD,SACbA,EAAQnB,UACRA,GAAY,GACkB,IAEhC,GAAI/B,EAAQ,OAKZ,MAAMmD,EAAiB5B,cACnBO,GAAmBqB,IAAgB1D,EAAW0D,GAElD,MAAMC,EAASC,EAA4BJ,GAC3CR,GAAgB,KAMdW,EAAOE,QAAUL,KAGnB,MAAMM,EAAa3B,GAAY,WAEZ3B,IAAbiD,GAA2BM,kBAAkBN,MAC7CzC,0BACJ2C,EAAOE,QAAQG,qBAAqBhE,OACnC,CAACyD,EAAUzD,IAEdgD,GAAgB,KACdvC,OAAOwC,iBAAiB,WAAYa,GAC7B,IAAMrD,OAAOyC,oBAAoB,WAAYY,KACnD,CAACA,IC5IU,SAAAG,iBACdC,EACAC,GACA7B,UAAEA,GAAY,GAAU,IAExB,MAAM8B,EAAaR,EAAOtB,GAC1BU,GAAgB,KACToB,EAAWP,QACXK,IADoBE,EAAWP,SAAU,IAG7CM,GDsIHF,EACE,WACmBzD,IAAbiD,GAA2BM,kBAAkBN,KACjDE,EAAOE,QAAQG,qBAAqBhE,MAEtC,CAACA,EAAUyD,GACX,CAAEnB,UAAAA,aAIU+B,aACd,MAAOC,EAASC,GAAcvC,EAASwC,qBAEvC,OADAtC,kBAAkBC,GAAY,IAAMoC,EAAWC,sBAAsB,CAACD,KAC/DD,EAGT,SAASE,oBACP,OAAIjE,EAAe,CAAEkE,kBAAmB,SAAUC,MAAO,MAClD,CACLD,kBAAmBhE,OAAO6D,QAAQG,kBAClCC,MAAOjE,OAAO6D,QAAQI,OAUpB,SAAUzC,iBAAiBjC,GAC/B,MAAMC,EAAOuC,iBACPmC,EAAc3E,IA6BtB,SAAS4E,aAAa5E,EAAkBC,GACtC,SAAUD,GAAYC,GAAQA,EAAK4E,cAAcC,WAAW9E,EAAS6E,gBA9BpCD,CAAa5E,EAAUC,GACxD,OAAa,OAATA,GAAiB0E,EAAoB,KAClCI,mBAAoB/E,EAAkBC,EAAK+E,QAuBpD,SAASC,gBAAgBjF,GACvB,OAAO,IAAIkF,OAAO,IAAMlF,EAAU,KAxBwBiF,CAAgBjF,GAAW,KAAO,IAAtDC,GAGxC,SAAS+D,qBAAqBhE,GAC5B,MAAMC,EAAOgC,iBAAiBjC,GAC9B,MAAO,CACLA,SAAAA,EACAC,KAAAA,EACAmD,SAAUnD,EACVkF,SAAU3C,iBACV4C,OAAQ3E,OAAOoC,SAASuC,OACxBzC,KAAMU,iBACNgC,KAAM5E,OAAOoC,SAASwC,KACtBC,SAAU7E,OAAOoC,SAASyC,SAC1BC,KAAM9E,OAAOoC,SAAS0C,KACtBC,OAAQ/E,OAAOoC,SAAS2C,QAI5B,SAASzB,kBAAkB0B,GACzB,OEvMI,SAAUC,WAAWC,GACzB,QAASA,GAAsB,mBAARA,EFsMhBD,CAAWD,GAAaA,IAAcA,EGjM/C,MAAMG,EAAgC,CAAC,KAAM,MAgCvC,SAAUC,UACdC,GACA9F,SACEA,EAAW,GAAE+F,WACbA,EAAa,GAAEC,mBACfA,GAAqB,EAAIC,mBACzBA,GAAqB,GACA,IAUvB,MAAMhG,EAAOyB,QAAQ1B,IAAaiC,iBAAiBjC,IAgLrD,SAASkG,qBAAqBlG,EAAkBC,GAC9C,OAASkG,GAAenE,EAAS,IAC3BoE,EAAcjE,GAAY,IAAMgE,EAAY,KAAK,IAEvDnD,GAAgB,KACV/C,IAASgC,iBAAiBjC,IAC5BoG,MAED,CAACA,EAAapG,EAAUC,IArL3BiG,CAAqBlG,EAAU0B,QAAQ1B,IAGvC,MAAMqG,EAeR,SAASC,cAEPR,EACA7F,GACA8F,WACEA,EAAUC,mBACVA,EAAkBC,mBAClBA,IAGFhG,EAAOsG,cAActG,EAAMgG,GAC3B,MAAMO,EAAWC,YAAYC,OAAOC,KAAKb,IAEzC,GAAa,OAAT7F,EAAe,OAAO,KAC1B,MAAO2G,EAAYC,GAASC,eAAe7G,EAAMuG,GAEjD,OAAKI,EAEEd,EAAOc,EAAW3G,MACvB+F,EAAqB,IAAKa,KAAUd,GAAe,IAAKA,KAAec,IAHjD,KA/BVP,CAAcR,EAAQ7F,EAAM,CACxC8F,WAAAA,EACAC,mBAAAA,EACAC,mBAAAA,IAIF,OAAKI,GAAkB,OAATpG,EAEZE,EAAAC,cAACL,eAAc,CAACC,SAAUA,EAAUC,KAAMA,GACvCoG,GAH+B,cA8CtBU,cACdjB,EACAkB,EAA4B,IAa5B,MAAMC,GAAY9F,MAAM+F,QAAQpB,IACzB7F,EAAMuG,GAAYW,eAAerB,EAA6BkB,GAGrE,GAAa,OAAT/G,EAAe,OAAOgH,EAAW,KAAOrB,EAE5C,MAAOgB,EAAYC,GAASC,eAAe7G,EAAMuG,GAEjD,OAAKI,EAGEK,EACHJ,EACC,CAACD,EAAW3G,KAAM4G,GALCI,EAAW,KAAOrB,WAa5BwB,SAAStB,EAA2BkB,EAA4B,UAC9E,MAAO/G,EAAMuG,GAAYW,eAAerB,EAAQkB,GAC1CK,EAAQb,EAASc,MAAK,EAAGC,MAAAA,KAAYtH,MAAAA,OAAI,EAAJA,EAAMoH,MAAME,KAEvD,OAAsB,QAAfC,EAAAH,MAAAA,OAAK,EAALA,EAAOpH,YAAQ,IAAAuH,EAAAA,EAAA,KAGxB,SAASL,eACPM,GACAzH,SAAEA,EAAQiG,mBAAEA,GAAqB,IAEjC,MACMO,EAAWC,YADAtF,MAAM+F,QAAQO,GAAmCA,EAAlB,CAACA,IAGjD,MAAO,CAAClB,cAAc7E,QAAQ1B,GAAWiG,GAAqBO,GAGhE,SAASC,YAAYX,GAEnB,OAAO4B,GAAQ,IAAM5B,EAAO6B,IAAIC,qBAAqB,EAqDnCC,EArD+C/B,EAsD1D,IAAI+B,GAAQC,OAAOC,KAAK,QADjC,IAAoBF,EAlDpB,SAASf,eACP7G,EACA+H,GAEA,IAAIC,EAAsC,KAG1C,MAAMrB,EAAaoB,EAAcV,MAAK,EAAGC,MAAAA,MACvCU,EAAahI,EAAKoH,MAAME,KACfU,KAGX,IAAKrB,GAA6B,OAAfqB,EAAqB,OAAOrC,EAE/C,MAAMiB,EAAQD,EAAWC,MAAMqB,QAAO,CAACrB,EAAYsB,EAAMC,KAGvDvB,EAAMsB,GAAQF,EAAYG,EAAI,GACvBvB,IACN,IAEH,MAAO,CAACD,EAAYC,GAGtB,SAASe,mBAAmB3H,SAyDNoI,EAxDpB,MAAO,CACLpI,KAAAA,EACAsH,MAAO,IAAIrC,OACT,GAAyB,MAAtBjF,EAAKqI,OAAO,EAAG,GAAa,GAAK,OAqDpBD,EArDuCpI,EAsDpDoI,EAAOrD,QAAQ,sBAAuB,SArDtCA,QAAQ,cAAe,WACvBA,QAAQ,MAAO,MAA0B,MAApB/E,EAAKqI,QAAQ,GAAa,GAAK,MACvD,KAEFzB,OAAqC,QAA7BW,EAAAvH,EAAKoH,MAAM,sBAAkB,IAAAG,EAAAA,EAAA,IAAIG,KAAKY,GAAcA,EAAUD,OAAO,MAqCjF,SAAS/B,cAActG,EAAqBgG,GAC1C,OAAa,OAAThG,GAEAgG,GAAsBhG,GAAkC,MAA1BA,EAAKA,EAAKuI,OAAS,IAAcvI,EAAKuI,OAAS,IAC/EvI,EAAOA,EAAKkD,UAAU,EAAGlD,EAAKuI,OAAS,IAHfvI,EC5N5B,IAAIwI,EAAW,GAEC,SAAAC,SAASC,EAAa3B,GACpC,GAAmB,iBAAR2B,EACT,MAAM,IAAIC,MAAM,oDAAoDD,GAGtE,GAAIxH,MAAM+F,QAAQF,MAAAA,OAAO,EAAPA,EAAS6B,OACzB,MAAM,IAAID,MAAM,oDAGlB,GAAI5H,yBAA0B,OAS9B,IARIgG,MAAAA,SAAAA,EAAS6B,SACXF,GAAO,IAAM,IAAIG,gBAAgB9B,EAAQ6B,OAAOE,YAGlDN,EAAWE,EAmEb,SAASK,WAAWL,GAClB,MAAO,qBAAqBM,KAAKN,GAhE7BK,CAAWL,KAmEjB,SAASO,gBAAgBP,GACvB,OAAOlI,OAAOoC,SAAS2C,SAAW,IAAI2D,IAAIR,GAAKnD,OApEvB0D,CAAgBP,GAEtC,YADAlI,OAAOoC,SAASuG,OAAOT,IAIrB3B,MAAAA,OAAA,EAAAA,EAAShC,SAASvE,OAAO6D,QAAQ+E,aAAarC,MAAAA,OAAA,EAAAA,EAAStC,MAAO,GAAIiE,GACjElI,OAAO6D,QAAQgF,UAAUtC,MAAAA,OAAA,EAAAA,EAAStC,MAAO,GAAIiE,GAElD,MAAMY,EAAQ,IAAIC,cAAc,YAG9BD,EAAcE,MAAQ,qBACxBC,cAAcH,GAGV,SAAUI,oBAAoBlE,GAAY,EAAMlE,ELzDzB,6CK0DvBhB,IAGJyC,GAAgB,KACd,MAAM4G,qBAAuB,KACvB5I,0BLtBJ,SAAU6I,eAAepB,GAC7BhI,OAAO6D,QAAQgF,UAAU,KAAM,KAA2Bb,GAC1DhH,YAAW,KACThB,OAAOqJ,YAAY/I,KAClB,GKmBG8I,CAAepB,IAInB,OADAhI,OAAOwC,iBAAiB,WAAY2G,sBAC7B,IAAMnJ,OAAOyC,oBAAoB,WAAY0G,wBACnD,IAGH5G,GAAgB,KACd,MAAM+G,QAAWrJ,IACf,GAAI+E,EACF,OAAO/E,EAQf,SAASsJ,iBAAiBT,EAA0BhI,GAMlD,OAJAgI,EAAMU,iBAENV,EAAMW,YAAc3I,EAEbA,EAdUyI,CAAiBtJ,EAAGa,GAAUA,GAI7C,OLhDE,SAAU4I,eAAeJ,GAC7BtJ,OAAOwC,iBAAiB,eAAgB8G,GACxCpJ,EAAayJ,IAAIL,GK6CfI,CAAeJ,SACR,IL3CL,SAAUM,kBAAkBN,GAChCtJ,OAAOyC,oBAAoB,eAAgB6G,GAC3CpJ,EAAa2J,OAAOP,GKyCLM,CAAkBN,WAC9B,CAACtE,EAAWlE,KAYD,SAAAgJ,YAAYC,EAAc,IACxC,MAAMxK,EAAW8B,cASjB,OAR6BK,GAC3B,CAACwG,EAAa3B,KACZ,MAAMyD,EAAOD,GAAexK,EAE5B0I,SADaC,EAAI7D,WAAW,KAAO2F,EAAO9B,EAAMA,EACjC3B,KAEjB,CAAChH,EAAUwK,aCvFCE,eACdC,EAAgCC,WAChCC,EAA6CC,gBAE7C,MAAOC,EAAaC,GAAkBhJ,EAASiJ,kBACzCC,EAAiB/I,GACrB,CAAC0F,GAAU7C,QAAAA,GAAU,GAAS,MAC5B,IAAI/E,EAAOuC,iBACXqF,EAAS7C,EAAU6C,EAAS,IAAK8C,EAAQI,MAAiBlD,GAC1D,MAAMsD,EAAaN,EAAYhD,GAAQkB,WAEnCoC,IAAYlL,GAAQ,IAAMkL,GACzBnG,IAAS/E,GAAQoD,kBAEtBqF,SAASzI,KAEX,CAAC8K,EAAaJ,EAASE,IAOzB,OADA3I,kBAFoBC,GAAY,IAAM6I,EAAeC,mBAAmB,KAGjE,CAACN,EAAQI,GAAcG,GAGhC,SAASN,WAAiCG,GACxC,MAAMK,EAAI,IAAItC,gBAAgBiC,GAC9B,OAAOrE,OAAO2E,YAAYD,EAAEE,WAG9B,SAASR,eAAqCS,GAC5C,OAAO,IAAIzC,gBAAgBpC,OAAO4E,QAAQC,GAAaC,QAAO,EAAI,CAAAC,KAAa,OAANA,KAAa1C,oBAGxEkC,iBACd,GAAI1K,EAAQ,CACV,MAAMmL,EPpDI,IOqDJC,EAAaD,EAAQnI,QAAQ,KACnC,OAAuB,IAAhBoI,EAAoB,GAAKD,EAAQvI,UAAUwI,EAAa,GAEjE,OAAOlL,OAAOoC,SAASuC,OCpCT,SAAAwG,UAASC,GACvBA,EAAEhD,MACFA,EAAK7D,QACLA,GAAU,EAAI8G,MACdA,GAAQ,IAGR,OADAC,YAAYrK,UAAWmK,EAAI,CAAEhD,MAAAA,EAAO7D,QAAAA,EAAS8G,MAAAA,IACtC,cAGOC,YACdC,EACAC,GACApD,MACEA,EAAK7D,QACLA,GAAU,EAAI8G,MACdA,GAAQ,GACsD,IAEhE,MAAMI,EAAcxK,WACbyK,GAAgBzB,iBACjB/H,EAAOU,iBAEb,IAAIsF,EAAMsD,EACV,MAAMG,EAAc,IAAItD,gBAAgB,IAClCgD,EAAQK,EAAe,MACxBtD,IACFE,WACCqD,IACFzD,GAAO,IAAMyD,GAEXN,GAASnJ,GAAQA,EAAK6F,SACxBG,GAAOhG,GAGTK,GAAgB,KACVkJ,IAAgBF,GAClBtD,SAASC,EAAK,CAAE3D,QAAAA,MAEjB,CAACgH,EAAcrD,EAAK3D,EAASkH,ICjBlC,MAAMG,EAAUC,GAzBhB,SAASC,MAAKhH,KAAEA,EAAIvF,SAAEA,KAAa6G,GAAoB2F,GAErDjH,EAAOkH,YAAYlH,EADnBvF,EAAW0M,gBAAgB1M,IAG3B,MAAM2M,QAAEA,EAAOC,OAAEA,GAAW/F,EAEtBgG,EAAc1K,GACjBzB,IACC,IACMiM,GAASA,EAAQjM,GACrB,MAAOoM,GAEP,MADApM,EAAEuJ,iBACI6C,GA2Dd,SAASC,WAAWrM,EAAoDkM,GACtE,OACGlM,EAAEsM,kBACU,IAAbtM,EAAEuM,UACAL,GAAqB,UAAXA,MACVlM,EAAEwM,SAAWxM,EAAEyM,QAAUzM,EAAE0M,SAAW1M,EAAE2M,WA9DpCN,CAAWrM,EAAGkM,KAChBlM,EAAEuJ,iBACFvB,SAAShI,EAAE4M,cAAc/H,SAG7B,CAACoH,EAASC,IAGZ,OAAOzM,EAAOC,cAAA,IAAA,IAAAyG,EAAOtB,KAAMA,EAAMoH,QAASE,EAAaL,IAAKA,OA4B9D,MAAMe,EAAgBjB,GAlBtB,SAASkB,YACPxN,SAAEA,EAAQyN,UAAEA,EAASC,iBAAEA,EAAgBC,YAAEA,KAAgB9G,GACzD2F,GAEAxM,EAAW0M,gBAAgB1M,GAC3B,MAAMmF,EAAW5C,cAEjB,IAAIgD,KAAEA,GAASsB,EAQf,OAPAtB,EA0BF,SAASqI,iBAAiBrI,GACxB,OAAIA,EAAKT,WAAW,KAAaS,EAC1B,IAAI4D,IAAI5D,EAAMsI,SAASC,SAAS1K,SA5BhCwK,CAAiBnB,YAAYlH,EAAMvF,IAEtC0N,GAAoBvI,IAAaI,IACnCkI,EAAY,GAAGA,MAAAA,EAAAA,EAAa,MAAMC,IAAmBK,QACnDJ,GAAexI,EAASL,WAAWS,KACrCkI,EAAY,GAAGA,MAAAA,EAAAA,EAAa,MAAME,IAAcI,QAE3C5N,gBAACkM,EAAO,IAAKxF,EAAO7G,SAAUA,EAAUyN,UAAWA,EAAWjB,IAAKA,OAS5E,SAASE,gBAAgB1M,GACvB,MAAM6B,EAAkBC,cACxB,MAAiB,MAAb9B,EAAyB,GACtBA,GAAY6B,EAGrB,SAAS4K,YAAYlH,EAAcvF,EAAW,IAC5C,OAAOuF,EAAKT,WAAW,KAAO9E,EAAWuF,EAAOA"}
|