raviger 4.1.2 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # raviger
2
2
 
3
-
4
-
5
3
  <p align="center">
6
4
  <a href="https://bundlephobia.com/package/raviger@latest" alt="Bundlephobia">
7
5
  <img src="https://badgen.net/bundlephobia/min/raviger" /></a>
@@ -16,6 +14,7 @@
16
14
 
17
15
  Zero dependencies. Tiny footprint.
18
16
 
17
+ > Note: Raviger is considered feature complete and will very likely receive only maintainace patches going forward.
19
18
 
20
19
  # Installation
21
20
 
package/dist/Link.d.ts CHANGED
@@ -4,18 +4,18 @@ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement>
4
4
  basePath?: string;
5
5
  children?: React.ReactNode;
6
6
  }
7
- export declare type LinkRef = HTMLAnchorElement | null;
7
+ export type LinkRef = HTMLAnchorElement | null;
8
8
  export interface ActiveLinkProps extends LinkProps {
9
9
  activeClass?: string;
10
10
  exactActiveClass?: string;
11
11
  }
12
- declare function Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>): JSX.Element;
12
+ declare function Link({ href, basePath, ...props }: LinkProps, ref?: Ref<HTMLAnchorElement>): React.JSX.Element;
13
13
  declare const RefLink: (props: LinkProps & {
14
14
  ref?: React.ForwardedRef<HTMLAnchorElement>;
15
15
  }) => ReturnType<typeof Link>;
16
16
  export default RefLink;
17
17
  export { RefLink as Link };
18
- declare function ActiveLink({ basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps, ref?: Ref<HTMLAnchorElement>): JSX.Element;
18
+ declare function ActiveLink({ basePath, className, exactActiveClass, activeClass, ...props }: ActiveLinkProps, ref?: Ref<HTMLAnchorElement>): React.JSX.Element;
19
19
  declare const ActiveLinkRef: (props: ActiveLinkProps & {
20
20
  ref?: React.ForwardedRef<HTMLAnchorElement>;
21
21
  }) => ReturnType<typeof ActiveLink>;
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 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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"}
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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"}
@@ -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 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":"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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":"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"}
package/dist/router.d.ts CHANGED
@@ -10,13 +10,13 @@ export interface RouteOptionParams extends PathParamOptions {
10
10
  };
11
11
  overridePathParams?: boolean;
12
12
  }
13
- declare type ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [
13
+ type ExtractPathParams<Path extends string, Parts = Split<Path, '/'>> = Parts extends [
14
14
  infer Head,
15
15
  ...infer Tail
16
16
  ] ? Head extends `:${infer Name}` ? {
17
17
  [N in Name]: string;
18
18
  } & ExtractPathParams<Path, Tail> : ExtractPathParams<Path, Tail> : unknown;
19
- export declare type Routes<Path extends string> = {
19
+ export type Routes<Path extends string> = {
20
20
  [P in Path]: (params: NonEmptyRecord<ExtractPathParams<P extends `${infer P1}*` ? P1 : P>>) => JSX.Element;
21
21
  };
22
22
  export declare function useRoutes<Path extends string>(routes: Routes<Path>, { basePath, routeProps, overridePathParams, matchTrailingSlash, }?: RouteOptionParams): JSX.Element | null;
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export declare type EmptyRecord = Record<string | number | symbol, never>;
2
- export declare type ValueOf<T> = T[keyof T];
3
- export declare type NonEmptyRecord<Params> = Params extends EmptyRecord ? undefined : {
1
+ export type EmptyRecord = Record<string | number | symbol, never>;
2
+ export type ValueOf<T> = T[keyof T];
3
+ export type NonEmptyRecord<Params> = Params extends EmptyRecord ? undefined : {
4
4
  [Key in keyof Params]: Params[Key];
5
5
  };
6
- export declare type Split<Value extends string, Separator extends string> = Value extends `${infer Head}${Separator}${infer Tail}` ? [Head, ...Split<Tail, Separator>] : Value extends Separator ? [] : [Value];
6
+ export type Split<Value extends string, Separator extends string> = Value extends `${infer Head}${Separator}${infer Tail}` ? [Head, ...Split<Tail, Separator>] : Value extends Separator ? [] : [Value];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "raviger",
3
- "version": "4.1.2",
3
+ "version": "4.2.0",
4
4
  "description": "React routing with hooks",
5
5
  "keywords": [
6
6
  "react",
@@ -30,7 +30,7 @@
30
30
  "lint": "eslint \"{src,test}/**/*.{ts,tsx}\" --ext .js,.ts,.tsx --ignore-pattern node_modules/",
31
31
  "check": "npm run style && npm run lint",
32
32
  "check:ci": "npm run style:ci && npm run lint",
33
- "build:clean": "rimraf dist %% mkdirp dist",
33
+ "build:clean": "rimraf dist && mkdirp dist",
34
34
  "build:compile": "rollup -c",
35
35
  "build:tsc": "tsc",
36
36
  "build": "run-s build:clean build:compile",
@@ -42,7 +42,7 @@
42
42
  "test:coverage:open": "run-s test:coverage coverage:report",
43
43
  "test:unit:ci": "jest --ci --coverage --reporters=default --reporters=jest-junit",
44
44
  "coverage:report": "open coverage/lcov-report/index.html",
45
- "test:ci": "run-s check:ci test:unit:ci size",
45
+ "test:ci": "run-s check:ci test:unit:ci",
46
46
  "size": "run-s build size:check",
47
47
  "size:check": "size-limit",
48
48
  "prepublishOnly": "run-s test:ci",
@@ -60,10 +60,12 @@
60
60
  },
61
61
  "size-limit": [
62
62
  {
63
+ "name": "CommonJS",
63
64
  "path": "dist/main.js",
64
65
  "limit": "2.9kb"
65
66
  },
66
67
  {
68
+ "name": "ESM",
67
69
  "webpack": false,
68
70
  "path": "dist/module.js",
69
71
  "limit": "3.5kb"
@@ -76,8 +78,8 @@
76
78
  "@size-limit/preset-small-lib": "^5.0.2",
77
79
  "@testing-library/jest-dom": "^5.16.4",
78
80
  "@testing-library/react": "^13.1.1",
79
- "@types/react": "^17.0.16",
80
- "@types/react-dom": "^17.0.9",
81
+ "@types/react": "^18.3.18",
82
+ "@types/react-dom": "^18.3.5",
81
83
  "@typescript-eslint/eslint-plugin": "^5.14.0",
82
84
  "@typescript-eslint/parser": "^5.14.0",
83
85
  "eslint": "^8.10.0",
@@ -98,10 +100,10 @@
98
100
  "rollup": "^2.56.1",
99
101
  "rollup-plugin-replace": "^2.2.0",
100
102
  "rollup-plugin-terser": "^7.0.2",
101
- "rollup-plugin-typescript2": "^0.30.0",
102
- "size-limit": "^5.0.2",
103
+ "rollup-plugin-typescript2": "^0.36.0",
104
+ "size-limit": "7.x",
103
105
  "ts-jest": "^27.1.4",
104
- "tslib": "^2.3.0",
106
+ "tslib": "^2.8.1",
105
107
  "typescript": "^4.3.5"
106
108
  }
107
109
  }