From 9d425d7f7e2bb727c4becf26d4f044e0d5ee9a59 Mon Sep 17 00:00:00 2001 From: Enrique Date: Sun, 20 Oct 2024 11:33:18 +0200 Subject: [PATCH] new version --- build/assets/img/logos/SMARTY.png | Bin 0 -> 128598 bytes build/static/js/main.379c5e92.js | 3 + build/static/js/main.379c5e92.js.LICENSE.txt | 78 +++++++++++++++++++ build/static/js/main.379c5e92.js.map | 1 + public/assets/img/logos/SMARTY.png | Bin 0 -> 128598 bytes 5 files changed, 82 insertions(+) create mode 100644 build/assets/img/logos/SMARTY.png create mode 100644 build/static/js/main.379c5e92.js create mode 100644 build/static/js/main.379c5e92.js.LICENSE.txt create mode 100644 build/static/js/main.379c5e92.js.map create mode 100644 public/assets/img/logos/SMARTY.png diff --git a/build/assets/img/logos/SMARTY.png b/build/assets/img/logos/SMARTY.png new file mode 100644 index 0000000000000000000000000000000000000000..d1d55650798c6b760038d894baef120b7edd301f GIT binary patch literal 128598 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 OA5|qS#cHT^`2PVdHNh(Y literal 0 HcmV?d00001 diff --git a/build/static/js/main.379c5e92.js b/build/static/js/main.379c5e92.js new file mode 100644 index 00000000..8e287281 --- /dev/null +++ b/build/static/js/main.379c5e92.js @@ -0,0 +1,3 @@ +/*! For license information please see main.379c5e92.js.LICENSE.txt */ +(()=>{var e={694:(e,n)=>{var t;!function(){"use strict";var a={}.hasOwnProperty;function o(){for(var e="",n=0;n{"use strict";e.exports=function(e,n,t,a,o,r,i,l){if(!e){var s;if(void 0===n)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[t,a,o,r,i,l],c=0;(s=new Error(n.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},463:(e,n,t)=>{"use strict";var a=t(791),o=t(296);function r(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t

`,\n * useSubmit(), ``, etc.\n */\nexport type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;\n\n/**\n * Active navigation/fetcher form methods are exposed in lowercase on the\n * RouterState\n */\nexport type FormMethod = LowerCaseFormMethod;\nexport type MutationFormMethod = Exclude;\n\n/**\n * In v7, active navigation/fetcher form methods are exposed in uppercase on the\n * RouterState. This is to align with the normalization done via fetch().\n */\nexport type V7_FormMethod = UpperCaseFormMethod;\nexport type V7_MutationFormMethod = Exclude;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\"\n | \"application/json\"\n | \"text/plain\";\n\n// Thanks https://github.com/sindresorhus/type-fest!\ntype JsonObject = { [Key in string]: JsonValue } & {\n [Key in string]?: JsonValue | undefined;\n};\ntype JsonArray = JsonValue[] | readonly JsonValue[];\ntype JsonPrimitive = string | number | boolean | null;\ntype JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport type Submission =\n | {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n json: undefined;\n text: undefined;\n }\n | {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: undefined;\n json: JsonValue;\n text: undefined;\n }\n | {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: undefined;\n json: undefined;\n text: string;\n };\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: Context;\n}\n\n// TODO: (v7) Change the defaults from any to unknown in and remove Remix wrappers:\n// ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs\n// Also, make them a type alias instead of an interface\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs\n extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs\n extends DataFunctionArgs {}\n\n/**\n * Loaders and actions can return anything except `undefined` (`null` is a\n * valid return value if there is no data to return). Responses are preferred\n * and will ease any future migration to Remix\n */\ntype DataFunctionValue = Response | NonNullable | null;\n\n/**\n * Route loader function signature\n */\nexport type LoaderFunction = {\n (args: LoaderFunctionArgs):\n | Promise\n | DataFunctionValue;\n} & { hydrate?: boolean };\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs):\n | Promise\n | DataFunctionValue;\n}\n\n/**\n * Arguments passed to shouldRevalidate function\n */\nexport interface ShouldRevalidateFunctionArgs {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n text?: Submission[\"text\"];\n formData?: Submission[\"formData\"];\n json?: Submission[\"json\"];\n actionResult?: any;\n defaultShouldRevalidate: boolean;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: ShouldRevalidateFunctionArgs): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set `hasErrorBoundary`\n * from the framework-aware `errorElement` prop\n *\n * @deprecated Use `mapRouteProperties` instead\n */\nexport interface DetectErrorBoundaryFunction {\n (route: AgnosticRouteObject): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set any framework-specific\n * properties from framework-agnostic properties\n */\nexport interface MapRoutePropertiesFunction {\n (route: AgnosticRouteObject): {\n hasErrorBoundary: boolean;\n } & Record;\n}\n\n/**\n * Keys we cannot change from within a lazy() function. We spread all other keys\n * onto the route. Either they're meaningful to the router, or they'll get\n * ignored.\n */\nexport type ImmutableRouteKey =\n | \"lazy\"\n | \"caseSensitive\"\n | \"path\"\n | \"id\"\n | \"index\"\n | \"children\";\n\nexport const immutableRouteKeys = new Set([\n \"lazy\",\n \"caseSensitive\",\n \"path\",\n \"id\",\n \"index\",\n \"children\",\n]);\n\ntype RequireOne = Exclude<\n {\n [K in keyof T]: K extends Key ? Omit & Required> : never;\n }[keyof T],\n undefined\n>;\n\n/**\n * lazy() function to load a route definition, which can add non-matching\n * related properties to a route\n */\nexport interface LazyRouteFunction {\n (): Promise>>;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n lazy?: LazyRouteFunction;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\nexport type RouteManifest = Record;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\nexport type PathParam =\n // check if path is just a wildcard\n Path extends \"*\" | \"/*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise, return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if you could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary, so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n mapRouteProperties: MapRoutePropertiesFunction,\n parentPath: number[] = [],\n manifest: RouteManifest = {}\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !manifest[id],\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = {\n ...route,\n ...mapRouteProperties(route),\n id,\n };\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n ...mapRouteProperties(route),\n id,\n children: undefined,\n };\n manifest[id] = pathOrLayoutRoute;\n\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(\n route.children,\n mapRouteProperties,\n treePath,\n manifest\n );\n }\n\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\nexport interface UIMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: Data;\n handle: Handle;\n}\n\nexport function convertRouteMatchToUiMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UIMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id],\n handle: route.handle,\n };\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array, so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children, so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explode _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then, if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path: string = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n\n const stringify = (p: any) =>\n p == null ? \"\" : typeof p === \"string\" ? p : String(p);\n\n const segments = path\n .split(/\\/+/)\n .map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\" as PathParam;\n // Apply the splat\n return stringify(params[star]);\n }\n\n const keyMatch = segment.match(/^:(\\w+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key as PathParam];\n invariant(optional === \"?\" || param != null, `Missing \":${key}\" param`);\n return stringify(param);\n }\n\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter((segment) => !!segment);\n\n return prefix + segments.join(\"/\");\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, compiledParams] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = compiledParams.reduce>(\n (memo, { paramName, isOptional }, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n const value = captureGroups[index];\n if (isOptional && !value) {\n memo[paramName] = undefined;\n } else {\n memo[paramName] = safelyDecodeURIComponent(value || \"\", paramName);\n }\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\ntype CompiledPathParam = { paramName: string; isOptional?: boolean };\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, CompiledPathParam[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let params: CompiledPathParam[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^${}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)(\\?)?/g, (_: string, paramName: string, isOptional) => {\n params.push({ paramName, isOptional: isOptional != null });\n return isOptional ? \"/?([^\\\\/]+)?\" : \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n params.push({ paramName: \"*\" });\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex, so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, params];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n// Return the array of pathnames for the current route matches - used to\n// generate the routePathnames input for resolveTo()\nexport function getResolveToMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[], v7_relativeSplatPath: boolean) {\n let pathMatches = getPathContributingMatches(matches);\n\n // When v7_relativeSplatPath is enabled, use the full pathname for the leaf\n // match so we include splat values for \".\" links. See:\n // https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329\n if (v7_relativeSplatPath) {\n return pathMatches.map((match, idx) =>\n idx === matches.length - 1 ? match.pathname : match.pathnameBase\n );\n }\n\n return pathMatches.map((match) => match.pathnameBase);\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n // With relative=\"route\" (the default), each leading .. segment means\n // \"go up one route\" instead of \"go up one URL segment\". This is a key\n // difference from how works and a major reason we call this a\n // \"to\" value instead of a \"href\".\n if (!isPathRelative && toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, undefined, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n // If the promise was resolved/rejected with undefined, we'll throw an error as you\n // should always resolve with a value or null\n if (error === undefined && data === undefined) {\n let undefinedError = new Error(\n `Deferred data for key \"${key}\" resolved/rejected with \\`undefined\\`, ` +\n `you must resolve/reject with a value or \\`null\\`.`\n );\n Object.defineProperty(promise, \"_error\", { get: () => undefinedError });\n this.emit(false, key);\n return Promise.reject(undefinedError);\n }\n\n if (data === undefined) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * A redirect response that will force a document reload to the new location.\n * Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirectDocument: RedirectFunction = (url, init) => {\n let response = redirect(url, init);\n response.headers.set(\"X-Remix-Reload-Document\", \"true\");\n return response;\n};\n\nexport type ErrorResponse = {\n status: number;\n statusText: string;\n data: any;\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n *\n * We don't export the class for public use since it's an implementation\n * detail, but we export the interface above so folks can build their own\n * abstractions around instances via isRouteErrorResponse()\n */\nexport class ErrorResponseImpl implements ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n private error?: Error;\n private internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n warning,\n} from \"./history\";\nimport type {\n ActionFunction,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n AgnosticRouteObject,\n DataResult,\n DeferredData,\n DeferredResult,\n DetectErrorBoundaryFunction,\n ErrorResult,\n FormEncType,\n FormMethod,\n HTMLFormMethod,\n ImmutableRouteKey,\n LoaderFunction,\n MapRoutePropertiesFunction,\n MutationFormMethod,\n RedirectResult,\n RouteData,\n RouteManifest,\n ShouldRevalidateFunctionArgs,\n Submission,\n SuccessResult,\n UIMatch,\n V7_FormMethod,\n V7_MutationFormMethod,\n} from \"./utils\";\nimport {\n ErrorResponseImpl,\n ResultType,\n convertRouteMatchToUiMatch,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n getResolveToMatches,\n immutableRouteKeys,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n stripBasename,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the future config for the router\n */\n get future(): FutureConfig;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the window associated with the router\n */\n get window(): RouterInit[\"window\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To | null, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string | null,\n opts?: RouterFetchOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * HMR needs to pass in-flight route updates to React Router\n * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)\n */\n _internalSetRoutes(routes: AgnosticRouteObject[]): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface FutureConfig {\n v7_fetcherPersist: boolean;\n v7_normalizeFormMethod: boolean;\n v7_partialHydration: boolean;\n v7_prependBasename: boolean;\n v7_relativeSplatPath: boolean;\n}\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n routes: AgnosticRouteObject[];\n history: History;\n basename?: string;\n /**\n * @deprecated Use `mapRouteProperties` instead\n */\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n mapRouteProperties?: MapRoutePropertiesFunction;\n future?: Partial;\n hydrationData?: HydrationState;\n window?: Window;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\ntype ViewTransitionOpts = {\n currentLocation: Location;\n nextLocation: Location;\n};\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (\n state: RouterState,\n opts: {\n deletedFetchers: string[];\n unstable_viewTransitionOpts?: ViewTransitionOpts;\n unstable_flushSync: boolean;\n }\n ): void;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UIMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\nexport type RelativeRoutingType = \"route\" | \"path\";\n\n// Allowed for any navigation or fetch\ntype BaseNavigateOrFetchOptions = {\n preventScrollReset?: boolean;\n relative?: RelativeRoutingType;\n unstable_flushSync?: boolean;\n};\n\n// Only allowed for navigations\ntype BaseNavigateOptions = BaseNavigateOrFetchOptions & {\n replace?: boolean;\n state?: any;\n fromRouteId?: string;\n unstable_viewTransition?: boolean;\n};\n\n// Only allowed for submission navigations\ntype BaseSubmissionOptions = {\n formMethod?: HTMLFormMethod;\n formEncType?: FormEncType;\n} & (\n | { formData: FormData; body?: undefined }\n | { formData?: undefined; body: any }\n);\n\n/**\n * Options for a navigate() call for a normal (non-submission) navigation\n */\ntype LinkNavigateOptions = BaseNavigateOptions;\n\n/**\n * Options for a navigate() call for a submission navigation\n */\ntype SubmissionNavigateOptions = BaseNavigateOptions & BaseSubmissionOptions;\n\n/**\n * Options to pass to navigate() for a navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options for a fetch() load\n */\ntype LoadFetchOptions = BaseNavigateOrFetchOptions;\n\n/**\n * Options for a fetch() submission\n */\ntype SubmitFetchOptions = BaseNavigateOrFetchOptions & BaseSubmissionOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions = LoadFetchOptions | SubmitFetchOptions;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n json: undefined;\n text: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: Submission[\"formMethod\"] | undefined;\n formAction: Submission[\"formAction\"] | undefined;\n formEncType: Submission[\"formEncType\"] | undefined;\n formData: Submission[\"formData\"] | undefined;\n json: Submission[\"json\"] | undefined;\n text: Submission[\"text\"] | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: Submission[\"formMethod\"];\n formAction: Submission[\"formAction\"];\n formEncType: Submission[\"formEncType\"];\n formData: Submission[\"formData\"];\n json: Submission[\"json\"];\n text: Submission[\"text\"];\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n text: undefined;\n formData: undefined;\n json: undefined;\n data: TData | undefined;\n };\n Loading: {\n state: \"loading\";\n formMethod: Submission[\"formMethod\"] | undefined;\n formAction: Submission[\"formAction\"] | undefined;\n formEncType: Submission[\"formEncType\"] | undefined;\n text: Submission[\"text\"] | undefined;\n formData: Submission[\"formData\"] | undefined;\n json: Submission[\"json\"] | undefined;\n data: TData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: Submission[\"formMethod\"];\n formAction: Submission[\"formAction\"];\n formEncType: Submission[\"formEncType\"];\n text: Submission[\"text\"];\n formData: Submission[\"formData\"];\n json: Submission[\"json\"];\n data: TData | undefined;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n match: AgnosticDataRouteMatch | null;\n matches: AgnosticDataRouteMatch[] | null;\n controller: AbortController | null;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst defaultMapRouteProperties: MapRoutePropertiesFunction = (route) => ({\n hasErrorBoundary: Boolean(route.hasErrorBoundary),\n});\n\nconst TRANSITIONS_STORAGE_KEY = \"remix-router-transitions\";\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n const routerWindow = init.window\n ? init.window\n : typeof window !== \"undefined\"\n ? window\n : undefined;\n const isBrowser =\n typeof routerWindow !== \"undefined\" &&\n typeof routerWindow.document !== \"undefined\" &&\n typeof routerWindow.document.createElement !== \"undefined\";\n const isServer = !isBrowser;\n\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let mapRouteProperties: MapRoutePropertiesFunction;\n if (init.mapRouteProperties) {\n mapRouteProperties = init.mapRouteProperties;\n } else if (init.detectErrorBoundary) {\n // If they are still using the deprecated version, wrap it with the new API\n let detectErrorBoundary = init.detectErrorBoundary;\n mapRouteProperties = (route) => ({\n hasErrorBoundary: detectErrorBoundary(route),\n });\n } else {\n mapRouteProperties = defaultMapRouteProperties;\n }\n\n // Routes keyed by ID\n let manifest: RouteManifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(\n init.routes,\n mapRouteProperties,\n undefined,\n manifest\n );\n let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined;\n let basename = init.basename || \"/\";\n // Config driven behavior flags\n let future: FutureConfig = {\n v7_fetcherPersist: false,\n v7_normalizeFormMethod: false,\n v7_partialHydration: false,\n v7_prependBasename: false,\n v7_relativeSplatPath: false,\n ...init.future,\n };\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized: boolean;\n let hasLazyRoutes = initialMatches.some((m) => m.route.lazy);\n let hasLoaders = initialMatches.some((m) => m.route.loader);\n if (hasLazyRoutes) {\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n initialized = false;\n } else if (!hasLoaders) {\n // If we've got no loaders to run, then we're good to go\n initialized = true;\n } else if (future.v7_partialHydration) {\n // If partial hydration is enabled, we're initialized so long as we were\n // provided with hydrationData for every route with a loader, and no loaders\n // were marked for explicit hydration\n let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;\n let errors = init.hydrationData ? init.hydrationData.errors : null;\n initialized = initialMatches.every(\n (m) =>\n m.route.loader &&\n m.route.loader.hydrate !== true &&\n ((loaderData && loaderData[m.route.id] !== undefined) ||\n (errors && errors[m.route.id] !== undefined))\n );\n } else {\n // Without partial hydration - we're initialized if we were provided any\n // hydrationData - which is expected to be complete\n initialized = init.hydrationData != null;\n }\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // Should the current navigation enable document.startViewTransition?\n let pendingViewTransitionEnabled = false;\n\n // Store applied view transitions so we can apply them on POP\n let appliedViewTransitions: Map> = new Map<\n string,\n Set\n >();\n\n // Cleanup function for persisting applied transitions to sessionStorage\n let removePageHideEventListener: (() => void) | null = null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidator()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Ref-count mounted fetchers so we know when it's ok to clean them up\n let activeFetchers = new Map();\n\n // Fetchers that have requested a delete when using v7_fetcherPersist,\n // they'll be officially removed after they return to idle\n let deletedFetchers = new Set();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n let blockers = new Map(state.blockers);\n blockers.set(blockerKey!, IDLE_BLOCKER);\n updateState({ blockers });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n if (isBrowser) {\n // FIXME: This feels gross. How can we cleanup the lines between\n // scrollRestoration/appliedTransitions persistance?\n restoreAppliedTransitions(routerWindow, appliedViewTransitions);\n let _saveAppliedTransitions = () =>\n persistAppliedTransitions(routerWindow, appliedViewTransitions);\n routerWindow.addEventListener(\"pagehide\", _saveAppliedTransitions);\n removePageHideEventListener = () =>\n routerWindow.removeEventListener(\"pagehide\", _saveAppliedTransitions);\n }\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location, {\n initialHydration: true,\n });\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n if (removePageHideEventListener) {\n removePageHideEventListener();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(\n newState: Partial,\n opts: {\n flushSync?: boolean;\n viewTransitionOpts?: ViewTransitionOpts;\n } = {}\n ): void {\n state = {\n ...state,\n ...newState,\n };\n\n // Prep fetcher cleanup so we can tell the UI which fetcher data entries\n // can be removed\n let completedFetchers: string[] = [];\n let deletedFetchersKeys: string[] = [];\n\n if (future.v7_fetcherPersist) {\n state.fetchers.forEach((fetcher, key) => {\n if (fetcher.state === \"idle\") {\n if (deletedFetchers.has(key)) {\n // Unmounted from the UI and can be totally removed\n deletedFetchersKeys.push(key);\n } else {\n // Returned to idle but still mounted in the UI, so semi-remains for\n // revalidations and such\n completedFetchers.push(key);\n }\n }\n });\n }\n\n // Iterate over a local copy so that if flushSync is used and we end up\n // removing and adding a new subscriber due to the useCallback dependencies,\n // we don't get ourselves into a loop calling the new subscriber immediately\n [...subscribers].forEach((subscriber) =>\n subscriber(state, {\n deletedFetchers: deletedFetchersKeys,\n unstable_viewTransitionOpts: opts.viewTransitionOpts,\n unstable_flushSync: opts.flushSync === true,\n })\n );\n\n // Remove idle fetchers from state since we only care about in-flight fetchers.\n if (future.v7_fetcherPersist) {\n completedFetchers.forEach((key) => state.fetchers.delete(key));\n deletedFetchersKeys.forEach((key) => deleteFetcher(key));\n }\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>,\n { flushSync }: { flushSync?: boolean } = {}\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n let blockers = state.blockers;\n if (blockers.size > 0) {\n blockers = new Map(blockers);\n blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n let viewTransitionOpts: ViewTransitionOpts | undefined;\n\n // On POP, enable transitions if they were enabled on the original navigation\n if (pendingAction === HistoryAction.Pop) {\n // Forward takes precedence so they behave like the original navigation\n let priorPaths = appliedViewTransitions.get(state.location.pathname);\n if (priorPaths && priorPaths.has(location.pathname)) {\n viewTransitionOpts = {\n currentLocation: state.location,\n nextLocation: location,\n };\n } else if (appliedViewTransitions.has(location.pathname)) {\n // If we don't have a previous forward nav, assume we're popping back to\n // the new location and enable if that location previously enabled\n viewTransitionOpts = {\n currentLocation: location,\n nextLocation: state.location,\n };\n }\n } else if (pendingViewTransitionEnabled) {\n // Store the applied transition on PUSH/REPLACE\n let toPaths = appliedViewTransitions.get(state.location.pathname);\n if (toPaths) {\n toPaths.add(location.pathname);\n } else {\n toPaths = new Set([location.pathname]);\n appliedViewTransitions.set(state.location.pathname, toPaths);\n }\n viewTransitionOpts = {\n currentLocation: state.location,\n nextLocation: location,\n };\n }\n\n updateState(\n {\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers,\n },\n {\n viewTransitionOpts,\n flushSync: flushSync === true,\n }\n );\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n pendingViewTransitionEnabled = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To | null,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let normalizedPath = normalizeTo(\n state.location,\n state.matches,\n basename,\n future.v7_prependBasename,\n to,\n future.v7_relativeSplatPath,\n opts?.fromRouteId,\n opts?.relative\n );\n let { path, submission, error } = normalizeNavigateOptions(\n future.v7_normalizeFormMethod,\n false,\n normalizedPath,\n opts\n );\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let flushSync = (opts && opts.unstable_flushSync) === true;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n let blockers = new Map(state.blockers);\n blockers.set(blockerKey!, IDLE_BLOCKER);\n updateState({ blockers });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n enableViewTransition: opts && opts.unstable_viewTransition,\n flushSync,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n initialHydration?: boolean;\n submission?: Submission;\n fetcherSubmission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponseImpl;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n enableViewTransition?: boolean;\n flushSync?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, basename);\n let flushSync = (opts && opts.flushSync) === true;\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(\n location,\n {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n },\n { flushSync }\n );\n return;\n }\n\n // Short circuit if it's only a hash change and not a revalidation or\n // mutation submission.\n //\n // Ignore on initial page loads because since the initial load will always\n // be \"same hash\". For example, on /page#hash and submit a \n // which will default to a navigation to /page\n if (\n state.initialized &&\n !isRevalidationRequired &&\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches }, { flushSync });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace, flushSync }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n loadingNavigation = getLoadingNavigation(location, opts.submission);\n flushSync = false;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.fetcherSubmission,\n opts && opts.replace,\n opts && opts.initialHydration === true,\n flushSync,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts: { replace?: boolean; flushSync?: boolean } = {}\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation = getSubmittingNavigation(location, submission);\n updateState({ navigation }, { flushSync: opts.flushSync === true });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n fetcherSubmission?: Submission,\n replace?: boolean,\n initialHydration?: boolean,\n flushSync?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation =\n overrideNavigation || getLoadingNavigation(location, submission);\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission =\n submission ||\n fetcherSubmission ||\n getSubmissionFromNavigation(loadingNavigation);\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n future.v7_partialHydration && initialHydration === true,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n deletedFetchers,\n fetchLoadMatches,\n fetchRedirectIds,\n routesToUse,\n basename,\n pendingActionData,\n pendingError\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n pendingNavigationLoadId = ++incrementingLoadId;\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n let updatedFetchers = markFetchRedirectsDone();\n completeNavigation(\n location,\n {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n ...(updatedFetchers ? { fetchers: new Map(state.fetchers) } : {}),\n },\n { flushSync }\n );\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n // If we have partialHydration enabled, then don't update the state for the\n // initial data load since iot's not a \"navigation\"\n if (\n !isUninterruptedRevalidation &&\n (!future.v7_partialHydration || !initialHydration)\n ) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher = getLoadingFetcher(\n undefined,\n fetcher ? fetcher.data : undefined\n );\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState(\n {\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n },\n {\n flushSync,\n }\n );\n }\n\n revalidatingFetchers.forEach((rf) => {\n if (fetchControllers.has(rf.key)) {\n abortFetcher(rf.key);\n }\n if (rf.controller) {\n // Fetchers use an independent AbortController so that aborting a fetcher\n // (via deleteFetcher) does not abort the triggering navigation that\n // triggered the revalidation\n fetchControllers.set(rf.key, rf.controller);\n }\n });\n\n // Proxy navigation abort through to revalidation fetchers\n let abortPendingFetchRevalidations = () =>\n revalidatingFetchers.forEach((f) => abortFetcher(f.key));\n if (pendingNavigationController) {\n pendingNavigationController.signal.addEventListener(\n \"abort\",\n abortPendingFetchRevalidations\n );\n }\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n if (pendingNavigationController) {\n pendingNavigationController.signal.removeEventListener(\n \"abort\",\n abortPendingFetchRevalidations\n );\n }\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n if (redirect.idx >= matchesToLoad.length) {\n // If this redirect came from a fetcher make sure we mark it in\n // fetchRedirectIds so it doesn't get revalidated on the next set of\n // loader executions\n let fetcherKey =\n revalidatingFetchers[redirect.idx - matchesToLoad.length].key;\n fetchRedirectIds.add(fetcherKey);\n }\n await startRedirectNavigation(state, redirect.result, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n let updatedFetchers = markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n let shouldUpdateFetchers =\n updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;\n\n return {\n loaderData,\n errors,\n ...(shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {}),\n };\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string | null,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n let flushSync = (opts && opts.unstable_flushSync) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let normalizedPath = normalizeTo(\n state.location,\n state.matches,\n basename,\n future.v7_prependBasename,\n href,\n future.v7_relativeSplatPath,\n routeId,\n opts?.relative\n );\n let matches = matchRoutes(routesToUse, normalizedPath, basename);\n\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: normalizedPath }),\n { flushSync }\n );\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(\n future.v7_normalizeFormMethod,\n true,\n normalizedPath,\n opts\n );\n\n if (error) {\n setFetcherError(key, routeId, error, { flushSync });\n return;\n }\n\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(\n key,\n routeId,\n path,\n match,\n matches,\n flushSync,\n submission\n );\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path });\n handleFetcherLoader(\n key,\n routeId,\n path,\n match,\n matches,\n flushSync,\n submission\n );\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n flushSync: boolean,\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action && !match.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error, { flushSync });\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {\n flushSync,\n });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let originatingLoadId = incrementingLoadId;\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n // When using v7_fetcherPersist, we don't want errors bubbling up to the UI\n // or redirects processed for unmounted fetchers so we just revert them to\n // idle\n if (future.v7_fetcherPersist && deletedFetchers.has(key)) {\n if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n }\n // Let SuccessResult's fall through for revalidation\n } else {\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n if (pendingNavigationLoadId > originatingLoadId) {\n // A new navigation was kicked off after our action started, so that\n // should take precedence over this redirect navigation. We already\n // set isRevalidationRequired so all loaders for the new route should\n // fire unless opted out via shouldRevalidate\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n } else {\n fetchRedirectIds.add(key);\n updateFetcherState(key, getLoadingFetcher(submission));\n return startRedirectNavigation(state, actionResult, {\n fetcherSubmission: submission,\n });\n }\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n nextLocation,\n abortController.signal\n );\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(routesToUse, state.navigation.location, basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher = getLoadingFetcher(submission, actionResult.data);\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n false,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n deletedFetchers,\n fetchLoadMatches,\n fetchRedirectIds,\n routesToUse,\n basename,\n { [match.route.id]: actionResult.data },\n undefined // No need to send through errors since we short circuit above\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher = getLoadingFetcher(\n undefined,\n existingFetcher ? existingFetcher.data : undefined\n );\n state.fetchers.set(staleKey, revalidatingFetcher);\n if (fetchControllers.has(staleKey)) {\n abortFetcher(staleKey);\n }\n if (rf.controller) {\n fetchControllers.set(staleKey, rf.controller);\n }\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let abortPendingFetchRevalidations = () =>\n revalidatingFetchers.forEach((rf) => abortFetcher(rf.key));\n\n abortController.signal.addEventListener(\n \"abort\",\n abortPendingFetchRevalidations\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n abortController.signal.removeEventListener(\n \"abort\",\n abortPendingFetchRevalidations\n );\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n if (redirect.idx >= matchesToLoad.length) {\n // If this redirect came from a fetcher make sure we mark it in\n // fetchRedirectIds so it doesn't get revalidated on the next set of\n // loader executions\n let fetcherKey =\n revalidatingFetchers[redirect.idx - matchesToLoad.length].key;\n fetchRedirectIds.add(fetcherKey);\n }\n return startRedirectNavigation(state, redirect.result);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Since we let revalidations complete even if the submitting fetcher was\n // deleted, only put it back to idle if it hasn't been deleted\n if (state.fetchers.has(key)) {\n let doneFetcher = getDoneFetcher(actionResult.data);\n state.fetchers.set(key, doneFetcher);\n }\n\n abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n fetchers: new Map(state.fetchers),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n flushSync: boolean,\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n updateFetcherState(\n key,\n getLoadingFetcher(\n submission,\n existingFetcher ? existingFetcher.data : undefined\n ),\n { flushSync }\n );\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n\n let originatingLoadId = incrementingLoadId;\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by our our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // We don't want errors bubbling up or redirects followed for unmounted\n // fetchers, so short circuit here if it was removed from the UI\n if (deletedFetchers.has(key)) {\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n if (pendingNavigationLoadId > originatingLoadId) {\n // A new navigation was kicked off after our loader started, so that\n // should take precedence over this redirect navigation\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n } else {\n fetchRedirectIds.add(key);\n await startRedirectNavigation(state, result);\n return;\n }\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n setFetcherError(key, routeId, result.error);\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n updateFetcherState(key, getDoneFetcher(result.data));\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n fetcherSubmission,\n replace,\n }: {\n submission?: Submission;\n fetcherSubmission?: Submission;\n replace?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(state.location, redirect.location, {\n _isRedirect: true,\n });\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n\n if (isBrowser) {\n let isDocumentReload = false;\n\n if (redirect.reloadDocument) {\n // Hard reload if the response contained X-Remix-Reload-Document\n isDocumentReload = true;\n } else if (ABSOLUTE_URL_REGEX.test(redirect.location)) {\n const url = init.history.createURL(redirect.location);\n isDocumentReload =\n // Hard reload if it's an absolute URL to a new origin\n url.origin !== routerWindow.location.origin ||\n // Hard reload if it's an absolute URL that does not match our basename\n stripBasename(url.pathname, basename) == null;\n }\n\n if (isDocumentReload) {\n if (replace) {\n routerWindow.location.replace(redirect.location);\n } else {\n routerWindow.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType } = state.navigation;\n if (\n !submission &&\n !fetcherSubmission &&\n formMethod &&\n formAction &&\n formEncType\n ) {\n submission = getSubmissionFromNavigation(state.navigation);\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n let activeSubmission = submission || fetcherSubmission;\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n activeSubmission &&\n isMutationMethod(activeSubmission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...activeSubmission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // If we have a navigation submission, we will preserve it through the\n // redirect navigation\n let overrideNavigation = getLoadingNavigation(\n redirectLocation,\n submission\n );\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation,\n // Send fetcher submissions through for shouldRevalidate\n fetcherSubmission,\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath\n )\n ),\n ...fetchersToLoad.map((f) => {\n if (f.matches && f.match && f.controller) {\n return callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, f.controller.signal),\n f.match,\n f.matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath\n );\n } else {\n let error: ErrorResult = {\n type: ResultType.error,\n error: getInternalRouterError(404, { pathname: f.path }),\n };\n return error;\n }\n }),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n loaderResults.map(() => request.signal),\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n fetchersToLoad.map((f) => (f.controller ? f.controller.signal : null)),\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function updateFetcherState(\n key: string,\n fetcher: Fetcher,\n opts: { flushSync?: boolean } = {}\n ) {\n state.fetchers.set(key, fetcher);\n updateState(\n { fetchers: new Map(state.fetchers) },\n { flushSync: (opts && opts.flushSync) === true }\n );\n }\n\n function setFetcherError(\n key: string,\n routeId: string,\n error: any,\n opts: { flushSync?: boolean } = {}\n ) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState(\n {\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n },\n { flushSync: (opts && opts.flushSync) === true }\n );\n }\n\n function getFetcher(key: string): Fetcher {\n if (future.v7_fetcherPersist) {\n activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);\n // If this fetcher was previously marked for deletion, unmark it since we\n // have a new instance\n if (deletedFetchers.has(key)) {\n deletedFetchers.delete(key);\n }\n }\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n function deleteFetcher(key: string): void {\n let fetcher = state.fetchers.get(key);\n // Don't abort the controller if this is a deletion of a fetcher.submit()\n // in it's loading phase since - we don't want to abort the corresponding\n // revalidation and want them to complete and land\n if (\n fetchControllers.has(key) &&\n !(fetcher && fetcher.state === \"loading\" && fetchReloadIds.has(key))\n ) {\n abortFetcher(key);\n }\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n deletedFetchers.delete(key);\n state.fetchers.delete(key);\n }\n\n function deleteFetcherAndUpdateState(key: string): void {\n if (future.v7_fetcherPersist) {\n let count = (activeFetchers.get(key) || 0) - 1;\n if (count <= 0) {\n activeFetchers.delete(key);\n deletedFetchers.add(key);\n } else {\n activeFetchers.set(key, count);\n }\n } else {\n deleteFetcher(key);\n }\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher = getDoneFetcher(fetcher.data);\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): boolean {\n let doneKeys = [];\n let updatedFetchers = false;\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n updatedFetchers = true;\n }\n }\n markFetchersDone(doneKeys);\n return updatedFetchers;\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n let blockers = new Map(state.blockers);\n blockers.set(key, newBlocker);\n updateState({ blockers });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || null;\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function getScrollKey(location: Location, matches: AgnosticDataRouteMatch[]) {\n if (getScrollRestorationKey) {\n let key = getScrollRestorationKey(\n location,\n matches.map((m) => convertRouteMatchToUiMatch(m, state.loaderData))\n );\n return key || location.key;\n }\n return location.key;\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollPosition) {\n let key = getScrollKey(location, matches);\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions) {\n let key = getScrollKey(location, matches);\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) {\n manifest = {};\n inFlightDataRoutes = convertRoutesToDataRoutes(\n newRoutes,\n mapRouteProperties,\n undefined,\n manifest\n );\n }\n\n router = {\n get basename() {\n return basename;\n },\n get future() {\n return future;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n get window() {\n return routerWindow;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher: deleteFetcherAndUpdateState,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface StaticHandlerFutureConfig {\n v7_relativeSplatPath: boolean;\n}\n\nexport interface CreateStaticHandlerOptions {\n basename?: string;\n /**\n * @deprecated Use `mapRouteProperties` instead\n */\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n mapRouteProperties?: MapRoutePropertiesFunction;\n future?: Partial;\n}\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: CreateStaticHandlerOptions\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let manifest: RouteManifest = {};\n let basename = (opts ? opts.basename : null) || \"/\";\n let mapRouteProperties: MapRoutePropertiesFunction;\n if (opts?.mapRouteProperties) {\n mapRouteProperties = opts.mapRouteProperties;\n } else if (opts?.detectErrorBoundary) {\n // If they are still using the deprecated version, wrap it with the new API\n let detectErrorBoundary = opts.detectErrorBoundary;\n mapRouteProperties = (route) => ({\n hasErrorBoundary: detectErrorBoundary(route),\n });\n } else {\n mapRouteProperties = defaultMapRouteProperties;\n }\n // Config driven behavior flags\n let future: StaticHandlerFutureConfig = {\n v7_relativeSplatPath: false,\n ...(opts ? opts.future : null),\n };\n\n let dataRoutes = convertRoutesToDataRoutes(\n routes,\n mapRouteProperties,\n undefined,\n manifest\n );\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath,\n { isStaticRequest: true, isRouteRequest, requestContext }\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(\n `${method}() call aborted: ${request.method} ${request.url}`\n );\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (\n isRouteRequest &&\n !routeMatch?.route.loader &&\n !routeMatch?.route.lazy\n ) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter(\n (m) => m.route.loader || m.route.lazy\n );\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n mapRouteProperties,\n basename,\n future.v7_relativeSplatPath,\n { isStaticRequest: true, isRouteRequest, requestContext }\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(\n `${method}() call aborted: ${request.method} ${request.url}`\n );\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: BaseNavigateOrFetchOptions\n): opts is SubmissionNavigateOptions {\n return (\n opts != null &&\n ((\"formData\" in opts && opts.formData != null) ||\n (\"body\" in opts && opts.body !== undefined))\n );\n}\n\nfunction normalizeTo(\n location: Path,\n matches: AgnosticDataRouteMatch[],\n basename: string,\n prependBasename: boolean,\n to: To | null,\n v7_relativeSplatPath: boolean,\n fromRouteId?: string,\n relative?: RelativeRoutingType\n) {\n let contextualMatches: AgnosticDataRouteMatch[];\n let activeRouteMatch: AgnosticDataRouteMatch | undefined;\n if (fromRouteId) {\n // Grab matches up to the calling route so our route-relative logic is\n // relative to the correct source route\n contextualMatches = [];\n for (let match of matches) {\n contextualMatches.push(match);\n if (match.route.id === fromRouteId) {\n activeRouteMatch = match;\n break;\n }\n }\n } else {\n contextualMatches = matches;\n activeRouteMatch = matches[matches.length - 1];\n }\n\n // Resolve the relative path\n let path = resolveTo(\n to ? to : \".\",\n getResolveToMatches(contextualMatches, v7_relativeSplatPath),\n stripBasename(location.pathname, basename) || location.pathname,\n relative === \"path\"\n );\n\n // When `to` is not specified we inherit search/hash from the current\n // location, unlike when to=\".\" and we just inherit the path.\n // See https://github.com/remix-run/remix/issues/927\n if (to == null) {\n path.search = location.search;\n path.hash = location.hash;\n }\n\n // Add an ?index param for matched index routes if we don't already have one\n if (\n (to == null || to === \"\" || to === \".\") &&\n activeRouteMatch &&\n activeRouteMatch.route.index &&\n !hasNakedIndexQuery(path.search)\n ) {\n path.search = path.search\n ? path.search.replace(/^\\?/, \"?index&\")\n : \"?index\";\n }\n\n // If we're operating within a basename, prepend it to the pathname. If\n // this is a root navigation, then just use the raw basename which allows\n // the basename to have full control over the presence of a trailing slash\n // on root actions\n if (prependBasename && basename !== \"/\") {\n path.pathname =\n path.pathname === \"/\" ? basename : joinPaths([basename, path.pathname]);\n }\n\n return createPath(path);\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n normalizeFormMethod: boolean,\n isFetcher: boolean,\n path: string,\n opts?: BaseNavigateOrFetchOptions\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponseImpl;\n} {\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n let getInvalidBodyError = () => ({\n path,\n error: getInternalRouterError(400, { type: \"invalid-body\" }),\n });\n\n // Create a Submission on non-GET navigations\n let rawFormMethod = opts.formMethod || \"get\";\n let formMethod = normalizeFormMethod\n ? (rawFormMethod.toUpperCase() as V7_FormMethod)\n : (rawFormMethod.toLowerCase() as FormMethod);\n let formAction = stripHashFromPath(path);\n\n if (opts.body !== undefined) {\n if (opts.formEncType === \"text/plain\") {\n // text only support POST/PUT/PATCH/DELETE submissions\n if (!isMutationMethod(formMethod)) {\n return getInvalidBodyError();\n }\n\n let text =\n typeof opts.body === \"string\"\n ? opts.body\n : opts.body instanceof FormData ||\n opts.body instanceof URLSearchParams\n ? // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data\n Array.from(opts.body.entries()).reduce(\n (acc, [name, value]) => `${acc}${name}=${value}\\n`,\n \"\"\n )\n : String(opts.body);\n\n return {\n path,\n submission: {\n formMethod,\n formAction,\n formEncType: opts.formEncType,\n formData: undefined,\n json: undefined,\n text,\n },\n };\n } else if (opts.formEncType === \"application/json\") {\n // json only supports POST/PUT/PATCH/DELETE submissions\n if (!isMutationMethod(formMethod)) {\n return getInvalidBodyError();\n }\n\n try {\n let json =\n typeof opts.body === \"string\" ? JSON.parse(opts.body) : opts.body;\n\n return {\n path,\n submission: {\n formMethod,\n formAction,\n formEncType: opts.formEncType,\n formData: undefined,\n json,\n text: undefined,\n },\n };\n } catch (e) {\n return getInvalidBodyError();\n }\n }\n }\n\n invariant(\n typeof FormData === \"function\",\n \"FormData is not available in this environment\"\n );\n\n let searchParams: URLSearchParams;\n let formData: FormData;\n\n if (opts.formData) {\n searchParams = convertFormDataToSearchParams(opts.formData);\n formData = opts.formData;\n } else if (opts.body instanceof FormData) {\n searchParams = convertFormDataToSearchParams(opts.body);\n formData = opts.body;\n } else if (opts.body instanceof URLSearchParams) {\n searchParams = opts.body;\n formData = convertSearchParamsToFormData(searchParams);\n } else if (opts.body == null) {\n searchParams = new URLSearchParams();\n formData = new FormData();\n } else {\n try {\n searchParams = new URLSearchParams(opts.body);\n formData = convertSearchParamsToFormData(searchParams);\n } catch (e) {\n return getInvalidBodyError();\n }\n }\n\n let submission: Submission = {\n formMethod,\n formAction,\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData,\n json: undefined,\n text: undefined,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n // On GET navigation submissions we can drop the ?index param from the\n // resulting location since all loaders will run. But fetcher GET submissions\n // only run a single loader so we need to preserve any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isInitialLoad: boolean,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n deletedFetchers: Set,\n fetchLoadMatches: Map,\n fetchRedirectIds: Set,\n routesToUse: AgnosticDataRouteObject[],\n basename: string | undefined,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n let { route } = match;\n if (route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n\n if (route.loader == null) {\n return false;\n }\n\n if (isInitialLoad) {\n if (route.loader.hydrate) {\n return true;\n }\n return (\n state.loaderData[route.id] === undefined &&\n // Don't re-run if the loader ran and threw an error\n (!state.errors || state.errors[route.id] === undefined)\n );\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.pathname + currentUrl.search ===\n nextUrl.pathname + nextUrl.search ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate:\n // - on initial load (shouldn't be any fetchers then anyway)\n // - if fetcher won't be present in the subsequent render\n // - no longer matches the URL (v7_fetcherPersist=false)\n // - was unmounted but persisted due to v7_fetcherPersist=true\n if (\n isInitialLoad ||\n !matches.some((m) => m.route.id === f.routeId) ||\n deletedFetchers.has(key)\n ) {\n return;\n }\n\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData. Note this is\n // currently only a use-case for Remix HMR where the route tree can change\n // at runtime and remove a route previously loaded via a fetcher\n if (!fetcherMatches) {\n revalidatingFetchers.push({\n key,\n routeId: f.routeId,\n path: f.path,\n matches: null,\n match: null,\n controller: null,\n });\n return;\n }\n\n // Revalidating fetchers are decoupled from the route matches since they\n // load from a static href. They revalidate based on explicit revalidation\n // (submission, useRevalidator, or X-Remix-Revalidate)\n let fetcher = state.fetchers.get(key);\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n\n let shouldRevalidate = false;\n if (fetchRedirectIds.has(key)) {\n // Never trigger a revalidation of an actively redirecting fetcher\n shouldRevalidate = false;\n } else if (cancelledFetcherLoads.includes(key)) {\n // Always revalidate if the fetcher was cancelled\n shouldRevalidate = true;\n } else if (\n fetcher &&\n fetcher.state !== \"idle\" &&\n fetcher.data === undefined\n ) {\n // If the fetcher hasn't ever completed loading yet, then this isn't a\n // revalidation, it would just be a brand new load if an explicit\n // revalidation is required\n shouldRevalidate = isRevalidationRequired;\n } else {\n // Otherwise fall back on any user-defined shouldRevalidate, defaulting\n // to explicit revalidations only\n shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate: isRevalidationRequired,\n });\n }\n\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n routeId: f.routeId,\n path: f.path,\n matches: fetcherMatches,\n match: fetcherMatch,\n controller: new AbortController(),\n });\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: ShouldRevalidateFunctionArgs\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(\n route: AgnosticDataRouteObject,\n mapRouteProperties: MapRoutePropertiesFunction,\n manifest: RouteManifest\n) {\n if (!route.lazy) {\n return;\n }\n\n let lazyRoute = await route.lazy();\n\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates: Record = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue =\n routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];\n\n let isPropertyStaticallyDefined =\n staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n\n warning(\n !isPropertyStaticallyDefined,\n `Route \"${routeToUpdate.id}\" has a static property \"${lazyRouteProperty}\" ` +\n `defined but its lazy function is also returning a value for this property. ` +\n `The lazy route property \"${lazyRouteProperty}\" will be ignored.`\n );\n\n if (\n !isPropertyStaticallyDefined &&\n !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey)\n ) {\n routeUpdates[lazyRouteProperty] =\n lazyRoute[lazyRouteProperty as keyof typeof lazyRoute];\n }\n }\n\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to mapRouteProperties\n Object.assign(routeToUpdate, routeUpdates);\n\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, {\n // To keep things framework agnostic, we use the provided\n // `mapRouteProperties` (or wrapped `detectErrorBoundary`) function to\n // set the framework-aware properties (`element`/`hasErrorBoundary`) since\n // the logic will differ between frameworks.\n ...mapRouteProperties(routeToUpdate),\n lazy: undefined,\n });\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n manifest: RouteManifest,\n mapRouteProperties: MapRoutePropertiesFunction,\n basename: string,\n v7_relativeSplatPath: boolean,\n opts: {\n isStaticRequest?: boolean;\n isRouteRequest?: boolean;\n requestContext?: unknown;\n } = {}\n): Promise {\n let resultType;\n let result;\n let onReject: (() => void) | undefined;\n\n let runHandler = (handler: ActionFunction | LoaderFunction) => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n return Promise.race([\n handler({\n request,\n params: match.params,\n context: opts.requestContext,\n }),\n abortPromise,\n ]);\n };\n\n try {\n let handler = match.route[type];\n\n if (match.route.lazy) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let handlerError;\n let values = await Promise.all([\n // If the handler throws, don't let it immediately bubble out,\n // since we need to let the lazy() execution finish so we know if this\n // route has a boundary that can handle the error\n runHandler(handler).catch((e) => {\n handlerError = e;\n }),\n loadLazyRouteModule(match.route, mapRouteProperties, manifest),\n ]);\n if (handlerError) {\n throw handlerError;\n }\n result = values[0];\n } else {\n // Load lazy route module, then run any returned handler\n await loadLazyRouteModule(match.route, mapRouteProperties, manifest);\n\n handler = match.route[type];\n if (handler) {\n // Handler still run even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n let url = new URL(request.url);\n let pathname = url.pathname + url.search;\n throw getInternalRouterError(405, {\n method: request.method,\n pathname,\n routeId: match.route.id,\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return { type: ResultType.data, data: undefined };\n }\n }\n } else if (!handler) {\n let url = new URL(request.url);\n let pathname = url.pathname + url.search;\n throw getInternalRouterError(404, {\n pathname,\n });\n } else {\n result = await runHandler(handler);\n }\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n location = normalizeTo(\n new URL(request.url),\n matches.slice(0, matches.indexOf(match) + 1),\n basename,\n true,\n location,\n v7_relativeSplatPath\n );\n } else if (!opts.isStaticRequest) {\n // Strip off the protocol+origin for same-origin + same-basename absolute\n // redirects. If this is a static request, we can let it go back to the\n // browser as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (opts.isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n reloadDocument: result.headers.get(\"X-Remix-Reload-Document\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (opts.isRouteRequest) {\n let queryRouteResponse: QueryRouteResponse = {\n type:\n resultType === ResultType.error ? ResultType.error : ResultType.data,\n response: result,\n };\n throw queryRouteResponse;\n }\n\n let data: any;\n\n try {\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n } catch (e) {\n return { type: ResultType.error, error: e };\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponseImpl(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (isDeferredData(result)) {\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: result.init?.status,\n headers: result.init?.headers && new Headers(result.init.headers),\n };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n\n if (formEncType === \"application/json\") {\n init.headers = new Headers({ \"Content-Type\": formEncType });\n init.body = JSON.stringify(submission.json);\n } else if (formEncType === \"text/plain\") {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = submission.text;\n } else if (\n formEncType === \"application/x-www-form-urlencoded\" &&\n submission.formData\n ) {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = convertFormDataToSearchParams(submission.formData);\n } else {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = submission.formData;\n }\n }\n\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, typeof value === \"string\" ? value : value.name);\n }\n\n return searchParams;\n}\n\nfunction convertSearchParamsToFormData(\n searchParams: URLSearchParams\n): FormData {\n let formData = new FormData();\n for (let [key, value] of searchParams.entries()) {\n formData.append(key, value);\n }\n return formData;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match, controller } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (controller && controller.signal.aborted) {\n // Nothing to do for aborted fetchers\n continue;\n } else if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher = getDoneFetcher(result.data);\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route =\n routes.length === 1\n ? routes[0]\n : routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\" | \"invalid-body\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n } else if (type === \"invalid-body\") {\n errorMessage = \"Unable to encode submission body\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponseImpl(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(\n results: DataResult[]\n): { result: RedirectResult; idx: number } | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return { result, idx: i };\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n if (a.pathname !== b.pathname || a.search !== b.search) {\n return false;\n }\n\n if (a.hash === \"\") {\n // /page -> /page#hash\n return b.hash !== \"\";\n } else if (a.hash === b.hash) {\n // /page#hash -> /page#hash\n return true;\n } else if (b.hash !== \"\") {\n // /page#hash -> /page#other\n return true;\n }\n\n // If the hash is removed the browser will re-perform a request to the server\n // /page#hash -> /page\n return false;\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nexport function isDeferredData(value: any): value is DeferredData {\n let deferred: DeferredData = value;\n return (\n deferred &&\n typeof deferred === \"object\" &&\n typeof deferred.data === \"object\" &&\n typeof deferred.subscribe === \"function\" &&\n typeof deferred.cancel === \"function\" &&\n typeof deferred.resolveData === \"function\"\n );\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || obj.type === ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod | V7_FormMethod {\n return validRequestMethods.has(method.toLowerCase() as FormMethod);\n}\n\nfunction isMutationMethod(\n method: string\n): method is MutationFormMethod | V7_MutationFormMethod {\n return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: (AgnosticDataRouteMatch | null)[],\n results: DataResult[],\n signals: (AbortSignal | null)[],\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match!.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n let signal = signals[index];\n invariant(\n signal,\n \"Expected an AbortSignal for revalidating fetcher deferred result\"\n );\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n\nfunction getSubmissionFromNavigation(\n navigation: Navigation\n): Submission | undefined {\n let { formMethod, formAction, formEncType, text, formData, json } =\n navigation;\n if (!formMethod || !formAction || !formEncType) {\n return;\n }\n\n if (text != null) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData: undefined,\n json: undefined,\n text,\n };\n } else if (formData != null) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData,\n json: undefined,\n text: undefined,\n };\n } else if (json !== undefined) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData: undefined,\n json,\n text: undefined,\n };\n }\n}\n\nfunction getLoadingNavigation(\n location: Location,\n submission?: Submission\n): NavigationStates[\"Loading\"] {\n if (submission) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n };\n return navigation;\n } else {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n };\n return navigation;\n }\n}\n\nfunction getSubmittingNavigation(\n location: Location,\n submission: Submission\n): NavigationStates[\"Submitting\"] {\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n };\n return navigation;\n}\n\nfunction getLoadingFetcher(\n submission?: Submission,\n data?: Fetcher[\"data\"]\n): FetcherStates[\"Loading\"] {\n if (submission) {\n let fetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n data,\n };\n return fetcher;\n } else {\n let fetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n data,\n };\n return fetcher;\n }\n}\n\nfunction getSubmittingFetcher(\n submission: Submission,\n existingFetcher?: Fetcher\n): FetcherStates[\"Submitting\"] {\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n data: existingFetcher ? existingFetcher.data : undefined,\n };\n return fetcher;\n}\n\nfunction getDoneFetcher(data: Fetcher[\"data\"]): FetcherStates[\"Idle\"] {\n let fetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n data,\n };\n return fetcher;\n}\n\nfunction restoreAppliedTransitions(\n _window: Window,\n transitions: Map>\n) {\n try {\n let sessionPositions = _window.sessionStorage.getItem(\n TRANSITIONS_STORAGE_KEY\n );\n if (sessionPositions) {\n let json = JSON.parse(sessionPositions);\n for (let [k, v] of Object.entries(json || {})) {\n if (v && Array.isArray(v)) {\n transitions.set(k, new Set(v || []));\n }\n }\n }\n } catch (e) {\n // no-op, use default empty object\n }\n}\n\nfunction persistAppliedTransitions(\n _window: Window,\n transitions: Map>\n) {\n if (transitions.size > 0) {\n let json: Record = {};\n for (let [k, v] of transitions) {\n json[k] = [...v];\n }\n try {\n _window.sessionStorage.setItem(\n TRANSITIONS_STORAGE_KEY,\n JSON.stringify(json)\n );\n } catch (error) {\n warning(\n false,\n `Failed to save applied view transitions in sessionStorage (${error}).`\n );\n }\n }\n}\n\n//#endregion\n","import * as React from \"react\";\nimport type {\n AgnosticIndexRouteObject,\n AgnosticNonIndexRouteObject,\n AgnosticRouteMatch,\n History,\n LazyRouteFunction,\n Location,\n Action as NavigationType,\n RelativeRoutingType,\n Router,\n StaticHandlerContext,\n To,\n TrackedPromise,\n} from \"@remix-run/router\";\n\n// Create react-specific types from the agnostic types in @remix-run/router to\n// export from react-router\nexport interface IndexRouteObject {\n caseSensitive?: AgnosticIndexRouteObject[\"caseSensitive\"];\n path?: AgnosticIndexRouteObject[\"path\"];\n id?: AgnosticIndexRouteObject[\"id\"];\n loader?: AgnosticIndexRouteObject[\"loader\"];\n action?: AgnosticIndexRouteObject[\"action\"];\n hasErrorBoundary?: AgnosticIndexRouteObject[\"hasErrorBoundary\"];\n shouldRevalidate?: AgnosticIndexRouteObject[\"shouldRevalidate\"];\n handle?: AgnosticIndexRouteObject[\"handle\"];\n index: true;\n children?: undefined;\n element?: React.ReactNode | null;\n hydrateFallbackElement?: React.ReactNode | null;\n errorElement?: React.ReactNode | null;\n Component?: React.ComponentType | null;\n HydrateFallback?: React.ComponentType | null;\n ErrorBoundary?: React.ComponentType | null;\n lazy?: LazyRouteFunction;\n}\n\nexport interface NonIndexRouteObject {\n caseSensitive?: AgnosticNonIndexRouteObject[\"caseSensitive\"];\n path?: AgnosticNonIndexRouteObject[\"path\"];\n id?: AgnosticNonIndexRouteObject[\"id\"];\n loader?: AgnosticNonIndexRouteObject[\"loader\"];\n action?: AgnosticNonIndexRouteObject[\"action\"];\n hasErrorBoundary?: AgnosticNonIndexRouteObject[\"hasErrorBoundary\"];\n shouldRevalidate?: AgnosticNonIndexRouteObject[\"shouldRevalidate\"];\n handle?: AgnosticNonIndexRouteObject[\"handle\"];\n index?: false;\n children?: RouteObject[];\n element?: React.ReactNode | null;\n hydrateFallbackElement?: React.ReactNode | null;\n errorElement?: React.ReactNode | null;\n Component?: React.ComponentType | null;\n HydrateFallback?: React.ComponentType | null;\n ErrorBoundary?: React.ComponentType | null;\n lazy?: LazyRouteFunction;\n}\n\nexport type RouteObject = IndexRouteObject | NonIndexRouteObject;\n\nexport type DataRouteObject = RouteObject & {\n children?: DataRouteObject[];\n id: string;\n};\n\nexport interface RouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends RouteObject = RouteObject\n> extends AgnosticRouteMatch {}\n\nexport interface DataRouteMatch extends RouteMatch {}\n\nexport interface DataRouterContextObject\n // Omit `future` since those can be pulled from the `router`\n // `NavigationContext` needs future since it doesn't have a `router` in all cases\n extends Omit {\n router: Router;\n staticContext?: StaticHandlerContext;\n}\n\nexport const DataRouterContext =\n React.createContext(null);\nif (__DEV__) {\n DataRouterContext.displayName = \"DataRouter\";\n}\n\nexport const DataRouterStateContext = React.createContext<\n Router[\"state\"] | null\n>(null);\nif (__DEV__) {\n DataRouterStateContext.displayName = \"DataRouterState\";\n}\n\nexport const AwaitContext = React.createContext(null);\nif (__DEV__) {\n AwaitContext.displayName = \"Await\";\n}\n\nexport interface NavigateOptions {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n relative?: RelativeRoutingType;\n unstable_flushSync?: boolean;\n unstable_viewTransition?: boolean;\n}\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level `` API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport interface Navigator {\n createHref: History[\"createHref\"];\n // Optional for backwards-compat with Router/HistoryRouter usage (edge case)\n encodeLocation?: History[\"encodeLocation\"];\n go: History[\"go\"];\n push(to: To, state?: any, opts?: NavigateOptions): void;\n replace(to: To, state?: any, opts?: NavigateOptions): void;\n}\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n future: {\n v7_relativeSplatPath: boolean;\n };\n}\n\nexport const NavigationContext = React.createContext(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\nexport interface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n isDataRoute: boolean;\n}\n\nexport const RouteContext = React.createContext({\n outlet: null,\n matches: [],\n isDataRoute: false,\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n\nexport const RouteErrorContext = React.createContext(null);\n\nif (__DEV__) {\n RouteErrorContext.displayName = \"RouteError\";\n}\n","import * as React from \"react\";\nimport type {\n Blocker,\n BlockerFunction,\n Location,\n ParamParseKey,\n Params,\n Path,\n PathMatch,\n PathPattern,\n RelativeRoutingType,\n Router as RemixRouter,\n RevalidationState,\n To,\n UIMatch,\n} from \"@remix-run/router\";\nimport {\n IDLE_BLOCKER,\n Action as NavigationType,\n UNSAFE_convertRouteMatchToUiMatch as convertRouteMatchToUiMatch,\n UNSAFE_getResolveToMatches as getResolveToMatches,\n UNSAFE_invariant as invariant,\n isRouteErrorResponse,\n joinPaths,\n matchPath,\n matchRoutes,\n parsePath,\n resolveTo,\n stripBasename,\n UNSAFE_warning as warning,\n} from \"@remix-run/router\";\n\nimport type {\n DataRouteMatch,\n NavigateOptions,\n RouteContextObject,\n RouteMatch,\n RouteObject,\n} from \"./context\";\nimport {\n AwaitContext,\n DataRouterContext,\n DataRouterStateContext,\n LocationContext,\n NavigationContext,\n RouteContext,\n RouteErrorContext,\n} from \"./context\";\n\n/**\n * Returns the full href for the given \"to\" value. This is useful for building\n * custom links that are also accessible and preserve right-click behavior.\n *\n * @see https://reactrouter.com/hooks/use-href\n */\nexport function useHref(\n to: To,\n { relative }: { relative?: RelativeRoutingType } = {}\n): string {\n invariant(\n useInRouterContext(),\n // TODO: This error is probably because they somehow have 2 versions of the\n // router loaded. We can help them understand how to avoid that.\n `useHref() may be used only in the context of a component.`\n );\n\n let { basename, navigator } = React.useContext(NavigationContext);\n let { hash, pathname, search } = useResolvedPath(to, { relative });\n\n let joinedPathname = pathname;\n\n // If we're operating within a basename, prepend it to the pathname prior\n // to creating the href. If this is a root navigation, then just use the raw\n // basename which allows the basename to have full control over the presence\n // of a trailing slash on root links\n if (basename !== \"/\") {\n joinedPathname =\n pathname === \"/\" ? basename : joinPaths([basename, pathname]);\n }\n\n return navigator.createHref({ pathname: joinedPathname, search, hash });\n}\n\n/**\n * Returns true if this component is a descendant of a ``.\n *\n * @see https://reactrouter.com/hooks/use-in-router-context\n */\nexport function useInRouterContext(): boolean {\n return React.useContext(LocationContext) != null;\n}\n\n/**\n * Returns the current location object, which represents the current URL in web\n * browsers.\n *\n * Note: If you're using this it may mean you're doing some of your own\n * \"routing\" in your app, and we'd like to know what your use case is. We may\n * be able to provide something higher-level to better suit your needs.\n *\n * @see https://reactrouter.com/hooks/use-location\n */\nexport function useLocation(): Location {\n invariant(\n useInRouterContext(),\n // TODO: This error is probably because they somehow have 2 versions of the\n // router loaded. We can help them understand how to avoid that.\n `useLocation() may be used only in the context of a component.`\n );\n\n return React.useContext(LocationContext).location;\n}\n\n/**\n * Returns the current navigation action which describes how the router came to\n * the current location, either by a pop, push, or replace on the history stack.\n *\n * @see https://reactrouter.com/hooks/use-navigation-type\n */\nexport function useNavigationType(): NavigationType {\n return React.useContext(LocationContext).navigationType;\n}\n\n/**\n * Returns a PathMatch object if the given pattern matches the current URL.\n * This is useful for components that need to know \"active\" state, e.g.\n * ``.\n *\n * @see https://reactrouter.com/hooks/use-match\n */\nexport function useMatch<\n ParamKey extends ParamParseKey,\n Path extends string\n>(pattern: PathPattern | Path): PathMatch | null {\n invariant(\n useInRouterContext(),\n // TODO: This error is probably because they somehow have 2 versions of the\n // router loaded. We can help them understand how to avoid that.\n `useMatch() may be used only in the context of a component.`\n );\n\n let { pathname } = useLocation();\n return React.useMemo(\n () => matchPath(pattern, pathname),\n [pathname, pattern]\n );\n}\n\n/**\n * The interface for the navigate() function returned from useNavigate().\n */\nexport interface NavigateFunction {\n (to: To, options?: NavigateOptions): void;\n (delta: number): void;\n}\n\nconst navigateEffectWarning =\n `You should call navigate() in a React.useEffect(), not when ` +\n `your component is first rendered.`;\n\n// Mute warnings for calls to useNavigate in SSR environments\nfunction useIsomorphicLayoutEffect(\n cb: Parameters[0]\n) {\n let isStatic = React.useContext(NavigationContext).static;\n if (!isStatic) {\n // We should be able to get rid of this once react 18.3 is released\n // See: https://github.com/facebook/react/pull/26395\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useLayoutEffect(cb);\n }\n}\n\n/**\n * Returns an imperative method for changing the location. Used by ``s, but\n * may also be used by other elements to change the location.\n *\n * @see https://reactrouter.com/hooks/use-navigate\n */\nexport function useNavigate(): NavigateFunction {\n let { isDataRoute } = React.useContext(RouteContext);\n // Conditional usage is OK here because the usage of a data router is static\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return isDataRoute ? useNavigateStable() : useNavigateUnstable();\n}\n\nfunction useNavigateUnstable(): NavigateFunction {\n invariant(\n useInRouterContext(),\n // TODO: This error is probably because they somehow have 2 versions of the\n // router loaded. We can help them understand how to avoid that.\n `useNavigate() may be used only in the context of a component.`\n );\n\n let dataRouterContext = React.useContext(DataRouterContext);\n let { basename, future, navigator } = React.useContext(NavigationContext);\n let { matches } = React.useContext(RouteContext);\n let { pathname: locationPathname } = useLocation();\n\n let routePathnamesJson = JSON.stringify(\n getResolveToMatches(matches, future.v7_relativeSplatPath)\n );\n\n let activeRef = React.useRef(false);\n useIsomorphicLayoutEffect(() => {\n activeRef.current = true;\n });\n\n let navigate: NavigateFunction = React.useCallback(\n (to: To | number, options: NavigateOptions = {}) => {\n warning(activeRef.current, navigateEffectWarning);\n\n // Short circuit here since if this happens on first render the navigate\n // is useless because we haven't wired up our history listener yet\n if (!activeRef.current) return;\n\n if (typeof to === \"number\") {\n navigator.go(to);\n return;\n }\n\n let path = resolveTo(\n to,\n JSON.parse(routePathnamesJson),\n locationPathname,\n options.relative === \"path\"\n );\n\n // If we're operating within a basename, prepend it to the pathname prior\n // to handing off to history (but only if we're not in a data router,\n // otherwise it'll prepend the basename inside of the router).\n // If this is a root navigation, then we navigate to the raw basename\n // which allows the basename to have full control over the presence of a\n // trailing slash on root links\n if (dataRouterContext == null && basename !== \"/\") {\n path.pathname =\n path.pathname === \"/\"\n ? basename\n : joinPaths([basename, path.pathname]);\n }\n\n (!!options.replace ? navigator.replace : navigator.push)(\n path,\n options.state,\n options\n );\n },\n [\n basename,\n navigator,\n routePathnamesJson,\n locationPathname,\n dataRouterContext,\n ]\n );\n\n return navigate;\n}\n\nconst OutletContext = React.createContext(null);\n\n/**\n * Returns the context (if provided) for the child route at this level of the route\n * hierarchy.\n * @see https://reactrouter.com/hooks/use-outlet-context\n */\nexport function useOutletContext(): Context {\n return React.useContext(OutletContext) as Context;\n}\n\n/**\n * Returns the element for the child route at this level of the route\n * hierarchy. Used internally by `` to render child routes.\n *\n * @see https://reactrouter.com/hooks/use-outlet\n */\nexport function useOutlet(context?: unknown): React.ReactElement | null {\n let outlet = React.useContext(RouteContext).outlet;\n if (outlet) {\n return (\n {outlet}\n );\n }\n return outlet;\n}\n\n/**\n * Returns an object of key/value pairs of the dynamic params from the current\n * URL that were matched by the route path.\n *\n * @see https://reactrouter.com/hooks/use-params\n */\nexport function useParams<\n ParamsOrKey extends string | Record = string\n>(): Readonly<\n [ParamsOrKey] extends [string] ? Params : Partial\n> {\n let { matches } = React.useContext(RouteContext);\n let routeMatch = matches[matches.length - 1];\n return routeMatch ? (routeMatch.params as any) : {};\n}\n\n/**\n * Resolves the pathname of the given `to` value against the current location.\n *\n * @see https://reactrouter.com/hooks/use-resolved-path\n */\nexport function useResolvedPath(\n to: To,\n { relative }: { relative?: RelativeRoutingType } = {}\n): Path {\n let { future } = React.useContext(NavigationContext);\n let { matches } = React.useContext(RouteContext);\n let { pathname: locationPathname } = useLocation();\n let routePathnamesJson = JSON.stringify(\n getResolveToMatches(matches, future.v7_relativeSplatPath)\n );\n\n return React.useMemo(\n () =>\n resolveTo(\n to,\n JSON.parse(routePathnamesJson),\n locationPathname,\n relative === \"path\"\n ),\n [to, routePathnamesJson, locationPathname, relative]\n );\n}\n\n/**\n * Returns the element of the route that matched the current location, prepared\n * with the correct context to render the remainder of the route tree. Route\n * elements in the tree must render an `` to render their child route's\n * element.\n *\n * @see https://reactrouter.com/hooks/use-routes\n */\nexport function useRoutes(\n routes: RouteObject[],\n locationArg?: Partial | string\n): React.ReactElement | null {\n return useRoutesImpl(routes, locationArg);\n}\n\n// Internal implementation with accept optional param for RouterProvider usage\nexport function useRoutesImpl(\n routes: RouteObject[],\n locationArg?: Partial | string,\n dataRouterState?: RemixRouter[\"state\"],\n future?: RemixRouter[\"future\"]\n): React.ReactElement | null {\n invariant(\n useInRouterContext(),\n // TODO: This error is probably because they somehow have 2 versions of the\n // router loaded. We can help them understand how to avoid that.\n `useRoutes() may be used only in the context of a component.`\n );\n\n let { navigator } = React.useContext(NavigationContext);\n let { matches: parentMatches } = React.useContext(RouteContext);\n let routeMatch = parentMatches[parentMatches.length - 1];\n let parentParams = routeMatch ? routeMatch.params : {};\n let parentPathname = routeMatch ? routeMatch.pathname : \"/\";\n let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : \"/\";\n let parentRoute = routeMatch && routeMatch.route;\n\n if (__DEV__) {\n // You won't get a warning about 2 different under a \n // without a trailing *, but this is a best-effort warning anyway since we\n // cannot even give the warning unless they land at the parent route.\n //\n // Example:\n //\n // \n // {/* This route path MUST end with /* because otherwise\n // it will never match /blog/post/123 */}\n // } />\n // } />\n // \n //\n // function Blog() {\n // return (\n // \n // } />\n // \n // );\n // }\n let parentPath = (parentRoute && parentRoute.path) || \"\";\n warningOnce(\n parentPathname,\n !parentRoute || parentPath.endsWith(\"*\"),\n `You rendered descendant (or called \\`useRoutes()\\`) at ` +\n `\"${parentPathname}\" (under ) but the ` +\n `parent route path has no trailing \"*\". This means if you navigate ` +\n `deeper, the parent won't match anymore and therefore the child ` +\n `routes will never render.\\n\\n` +\n `Please change the parent to .`\n );\n }\n\n let locationFromContext = useLocation();\n\n let location;\n if (locationArg) {\n let parsedLocationArg =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n invariant(\n parentPathnameBase === \"/\" ||\n parsedLocationArg.pathname?.startsWith(parentPathnameBase),\n `When overriding the location using \\`\\` or \\`useRoutes(routes, location)\\`, ` +\n `the location pathname must begin with the portion of the URL pathname that was ` +\n `matched by all parent routes. The current pathname base is \"${parentPathnameBase}\" ` +\n `but pathname \"${parsedLocationArg.pathname}\" was given in the \\`location\\` prop.`\n );\n\n location = parsedLocationArg;\n } else {\n location = locationFromContext;\n }\n\n let pathname = location.pathname || \"/\";\n let remainingPathname =\n parentPathnameBase === \"/\"\n ? pathname\n : pathname.slice(parentPathnameBase.length) || \"/\";\n\n let matches = matchRoutes(routes, { pathname: remainingPathname });\n\n if (__DEV__) {\n warning(\n parentRoute || matches != null,\n `No routes matched location \"${location.pathname}${location.search}${location.hash}\" `\n );\n\n warning(\n matches == null ||\n matches[matches.length - 1].route.element !== undefined ||\n matches[matches.length - 1].route.Component !== undefined ||\n matches[matches.length - 1].route.lazy !== undefined,\n `Matched leaf route at location \"${location.pathname}${location.search}${location.hash}\" ` +\n `does not have an element or Component. This means it will render an with a ` +\n `null value by default resulting in an \"empty\" page.`\n );\n }\n\n let renderedMatches = _renderMatches(\n matches &&\n matches.map((match) =>\n Object.assign({}, match, {\n params: Object.assign({}, parentParams, match.params),\n pathname: joinPaths([\n parentPathnameBase,\n // Re-encode pathnames that were decoded inside matchRoutes\n navigator.encodeLocation\n ? navigator.encodeLocation(match.pathname).pathname\n : match.pathname,\n ]),\n pathnameBase:\n match.pathnameBase === \"/\"\n ? parentPathnameBase\n : joinPaths([\n parentPathnameBase,\n // Re-encode pathnames that were decoded inside matchRoutes\n navigator.encodeLocation\n ? navigator.encodeLocation(match.pathnameBase).pathname\n : match.pathnameBase,\n ]),\n })\n ),\n parentMatches,\n dataRouterState,\n future\n );\n\n // When a user passes in a `locationArg`, the associated routes need to\n // be wrapped in a new `LocationContext.Provider` in order for `useLocation`\n // to use the scoped location instead of the global location.\n if (locationArg && renderedMatches) {\n return (\n \n {renderedMatches}\n \n );\n }\n\n return renderedMatches;\n}\n\nfunction DefaultErrorComponent() {\n let error = useRouteError();\n let message = isRouteErrorResponse(error)\n ? `${error.status} ${error.statusText}`\n : error instanceof Error\n ? error.message\n : JSON.stringify(error);\n let stack = error instanceof Error ? error.stack : null;\n let lightgrey = \"rgba(200,200,200, 0.5)\";\n let preStyles = { padding: \"0.5rem\", backgroundColor: lightgrey };\n let codeStyles = { padding: \"2px 4px\", backgroundColor: lightgrey };\n\n let devInfo = null;\n if (__DEV__) {\n console.error(\n \"Error handled by React Router default ErrorBoundary:\",\n error\n );\n\n devInfo = (\n <>\n

💿 Hey developer 👋

\n

\n You can provide a way better UX than this when your app throws errors\n by providing your own ErrorBoundary or{\" \"}\n errorElement prop on your route.\n

\n \n );\n }\n\n return (\n <>\n

Unexpected Application Error!

\n

{message}

\n {stack ?
{stack}
: null}\n {devInfo}\n \n );\n}\n\nconst defaultErrorElement = ;\n\ntype RenderErrorBoundaryProps = React.PropsWithChildren<{\n location: Location;\n revalidation: RevalidationState;\n error: any;\n component: React.ReactNode;\n routeContext: RouteContextObject;\n}>;\n\ntype RenderErrorBoundaryState = {\n location: Location;\n revalidation: RevalidationState;\n error: any;\n};\n\nexport class RenderErrorBoundary extends React.Component<\n RenderErrorBoundaryProps,\n RenderErrorBoundaryState\n> {\n constructor(props: RenderErrorBoundaryProps) {\n super(props);\n this.state = {\n location: props.location,\n revalidation: props.revalidation,\n error: props.error,\n };\n }\n\n static getDerivedStateFromError(error: any) {\n return { error: error };\n }\n\n static getDerivedStateFromProps(\n props: RenderErrorBoundaryProps,\n state: RenderErrorBoundaryState\n ) {\n // When we get into an error state, the user will likely click \"back\" to the\n // previous page that didn't have an error. Because this wraps the entire\n // application, that will have no effect--the error page continues to display.\n // This gives us a mechanism to recover from the error when the location changes.\n //\n // Whether we're in an error state or not, we update the location in state\n // so that when we are in an error state, it gets reset when a new location\n // comes in and the user recovers from the error.\n if (\n state.location !== props.location ||\n (state.revalidation !== \"idle\" && props.revalidation === \"idle\")\n ) {\n return {\n error: props.error,\n location: props.location,\n revalidation: props.revalidation,\n };\n }\n\n // If we're not changing locations, preserve the location but still surface\n // any new errors that may come through. We retain the existing error, we do\n // this because the error provided from the app state may be cleared without\n // the location changing.\n return {\n error: props.error !== undefined ? props.error : state.error,\n location: state.location,\n revalidation: props.revalidation || state.revalidation,\n };\n }\n\n componentDidCatch(error: any, errorInfo: any) {\n console.error(\n \"React Router caught the following error during render\",\n error,\n errorInfo\n );\n }\n\n render() {\n return this.state.error !== undefined ? (\n \n \n \n ) : (\n this.props.children\n );\n }\n}\n\ninterface RenderedRouteProps {\n routeContext: RouteContextObject;\n match: RouteMatch;\n children: React.ReactNode | null;\n}\n\nfunction RenderedRoute({ routeContext, match, children }: RenderedRouteProps) {\n let dataRouterContext = React.useContext(DataRouterContext);\n\n // Track how deep we got in our render pass to emulate SSR componentDidCatch\n // in a DataStaticRouter\n if (\n dataRouterContext &&\n dataRouterContext.static &&\n dataRouterContext.staticContext &&\n (match.route.errorElement || match.route.ErrorBoundary)\n ) {\n dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;\n }\n\n return (\n \n {children}\n \n );\n}\n\nexport function _renderMatches(\n matches: RouteMatch[] | null,\n parentMatches: RouteMatch[] = [],\n dataRouterState: RemixRouter[\"state\"] | null = null,\n future: RemixRouter[\"future\"] | null = null\n): React.ReactElement | null {\n if (matches == null) {\n if (dataRouterState?.errors) {\n // Don't bail if we have data router errors so we can render them in the\n // boundary. Use the pre-matched (or shimmed) matches\n matches = dataRouterState.matches as DataRouteMatch[];\n } else {\n return null;\n }\n }\n\n let renderedMatches = matches;\n\n // If we have data errors, trim matches to the highest error boundary\n let errors = dataRouterState?.errors;\n if (errors != null) {\n let errorIndex = renderedMatches.findIndex(\n (m) => m.route.id && errors?.[m.route.id]\n );\n invariant(\n errorIndex >= 0,\n `Could not find a matching route for errors on route IDs: ${Object.keys(\n errors\n ).join(\",\")}`\n );\n renderedMatches = renderedMatches.slice(\n 0,\n Math.min(renderedMatches.length, errorIndex + 1)\n );\n }\n\n // If we're in a partial hydration mode, detect if we need to render down to\n // a given HydrateFallback while we load the rest of the hydration data\n let renderFallback = false;\n let fallbackIndex = -1;\n if (dataRouterState && future && future.v7_partialHydration) {\n for (let i = 0; i < renderedMatches.length; i++) {\n let match = renderedMatches[i];\n // Track the deepest fallback up until the first route without data\n if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {\n fallbackIndex = i;\n }\n\n if (match.route.id) {\n let { loaderData, errors } = dataRouterState;\n let needsToRunLoader =\n match.route.loader &&\n loaderData[match.route.id] === undefined &&\n (!errors || errors[match.route.id] === undefined);\n if (match.route.lazy || needsToRunLoader) {\n // We found the first route that's not ready to render (waiting on\n // lazy, or has a loader that hasn't run yet). Flag that we need to\n // render a fallback and render up until the appropriate fallback\n renderFallback = true;\n if (fallbackIndex >= 0) {\n renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);\n } else {\n renderedMatches = [renderedMatches[0]];\n }\n break;\n }\n }\n }\n }\n\n return renderedMatches.reduceRight((outlet, match, index) => {\n // Only data routers handle errors/fallbacks\n let error: any;\n let shouldRenderHydrateFallback = false;\n let errorElement: React.ReactNode | null = null;\n let hydrateFallbackElement: React.ReactNode | null = null;\n if (dataRouterState) {\n error = errors && match.route.id ? errors[match.route.id] : undefined;\n errorElement = match.route.errorElement || defaultErrorElement;\n\n if (renderFallback) {\n if (fallbackIndex < 0 && index === 0) {\n warningOnce(\n \"route-fallback\",\n false,\n \"No `HydrateFallback` element provided to render during initial hydration\"\n );\n shouldRenderHydrateFallback = true;\n hydrateFallbackElement = null;\n } else if (fallbackIndex === index) {\n shouldRenderHydrateFallback = true;\n hydrateFallbackElement = match.route.hydrateFallbackElement || null;\n }\n }\n }\n\n let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));\n let getChildren = () => {\n let children: React.ReactNode;\n if (error) {\n children = errorElement;\n } else if (shouldRenderHydrateFallback) {\n children = hydrateFallbackElement;\n } else if (match.route.Component) {\n // Note: This is a de-optimized path since React won't re-use the\n // ReactElement since it's identity changes with each new\n // React.createElement call. We keep this so folks can use\n // `` in `` but generally `Component`\n // usage is only advised in `RouterProvider` when we can convert it to\n // `element` ahead of time.\n children = ;\n } else if (match.route.element) {\n children = match.route.element;\n } else {\n children = outlet;\n }\n return (\n \n );\n };\n // Only wrap in an error boundary within data router usages when we have an\n // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to\n // an ancestor ErrorBoundary/errorElement\n return dataRouterState &&\n (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? (\n \n ) : (\n getChildren()\n );\n }, null as React.ReactElement | null);\n}\n\nenum DataRouterHook {\n UseBlocker = \"useBlocker\",\n UseRevalidator = \"useRevalidator\",\n UseNavigateStable = \"useNavigate\",\n}\n\nenum DataRouterStateHook {\n UseBlocker = \"useBlocker\",\n UseLoaderData = \"useLoaderData\",\n UseActionData = \"useActionData\",\n UseRouteError = \"useRouteError\",\n UseNavigation = \"useNavigation\",\n UseRouteLoaderData = \"useRouteLoaderData\",\n UseMatches = \"useMatches\",\n UseRevalidator = \"useRevalidator\",\n UseNavigateStable = \"useNavigate\",\n UseRouteId = \"useRouteId\",\n}\n\nfunction getDataRouterConsoleError(\n hookName: DataRouterHook | DataRouterStateHook\n) {\n return `${hookName} must be used within a data router. See https://reactrouter.com/routers/picking-a-router.`;\n}\n\nfunction useDataRouterContext(hookName: DataRouterHook) {\n let ctx = React.useContext(DataRouterContext);\n invariant(ctx, getDataRouterConsoleError(hookName));\n return ctx;\n}\n\nfunction useDataRouterState(hookName: DataRouterStateHook) {\n let state = React.useContext(DataRouterStateContext);\n invariant(state, getDataRouterConsoleError(hookName));\n return state;\n}\n\nfunction useRouteContext(hookName: DataRouterStateHook) {\n let route = React.useContext(RouteContext);\n invariant(route, getDataRouterConsoleError(hookName));\n return route;\n}\n\n// Internal version with hookName-aware debugging\nfunction useCurrentRouteId(hookName: DataRouterStateHook) {\n let route = useRouteContext(hookName);\n let thisRoute = route.matches[route.matches.length - 1];\n invariant(\n thisRoute.route.id,\n `${hookName} can only be used on routes that contain a unique \"id\"`\n );\n return thisRoute.route.id;\n}\n\n/**\n * Returns the ID for the nearest contextual route\n */\nexport function useRouteId() {\n return useCurrentRouteId(DataRouterStateHook.UseRouteId);\n}\n\n/**\n * Returns the current navigation, defaulting to an \"idle\" navigation when\n * no navigation is in progress\n */\nexport function useNavigation() {\n let state = useDataRouterState(DataRouterStateHook.UseNavigation);\n return state.navigation;\n}\n\n/**\n * Returns a revalidate function for manually triggering revalidation, as well\n * as the current state of any manual revalidations\n */\nexport function useRevalidator() {\n let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);\n let state = useDataRouterState(DataRouterStateHook.UseRevalidator);\n return React.useMemo(\n () => ({\n revalidate: dataRouterContext.router.revalidate,\n state: state.revalidation,\n }),\n [dataRouterContext.router.revalidate, state.revalidation]\n );\n}\n\n/**\n * Returns the active route matches, useful for accessing loaderData for\n * parent/child routes or the route \"handle\" property\n */\nexport function useMatches(): UIMatch[] {\n let { matches, loaderData } = useDataRouterState(\n DataRouterStateHook.UseMatches\n );\n return React.useMemo(\n () => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)),\n [matches, loaderData]\n );\n}\n\n/**\n * Returns the loader data for the nearest ancestor Route loader\n */\nexport function useLoaderData(): unknown {\n let state = useDataRouterState(DataRouterStateHook.UseLoaderData);\n let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);\n\n if (state.errors && state.errors[routeId] != null) {\n console.error(\n `You cannot \\`useLoaderData\\` in an errorElement (routeId: ${routeId})`\n );\n return undefined;\n }\n return state.loaderData[routeId];\n}\n\n/**\n * Returns the loaderData for the given routeId\n */\nexport function useRouteLoaderData(routeId: string): unknown {\n let state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);\n return state.loaderData[routeId];\n}\n\n/**\n * Returns the action data for the nearest ancestor Route action\n */\nexport function useActionData(): unknown {\n let state = useDataRouterState(DataRouterStateHook.UseActionData);\n let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);\n return state.actionData ? state.actionData[routeId] : undefined;\n}\n\n/**\n * Returns the nearest ancestor Route error, which could be a loader/action\n * error or a render error. This is intended to be called from your\n * ErrorBoundary/errorElement to display a proper error message.\n */\nexport function useRouteError(): unknown {\n let error = React.useContext(RouteErrorContext);\n let state = useDataRouterState(DataRouterStateHook.UseRouteError);\n let routeId = useCurrentRouteId(DataRouterStateHook.UseRouteError);\n\n // If this was a render error, we put it in a RouteError context inside\n // of RenderErrorBoundary\n if (error !== undefined) {\n return error;\n }\n\n // Otherwise look for errors from our data router state\n return state.errors?.[routeId];\n}\n\n/**\n * Returns the happy-path data from the nearest ancestor `` value\n */\nexport function useAsyncValue(): unknown {\n let value = React.useContext(AwaitContext);\n return value?._data;\n}\n\n/**\n * Returns the error from the nearest ancestor `` value\n */\nexport function useAsyncError(): unknown {\n let value = React.useContext(AwaitContext);\n return value?._error;\n}\n\nlet blockerId = 0;\n\n/**\n * Allow the application to block navigations within the SPA and present the\n * user a confirmation dialog to confirm the navigation. Mostly used to avoid\n * using half-filled form data. This does not handle hard-reloads or\n * cross-origin navigations.\n */\nexport function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker {\n let { router, basename } = useDataRouterContext(DataRouterHook.UseBlocker);\n let state = useDataRouterState(DataRouterStateHook.UseBlocker);\n\n let [blockerKey, setBlockerKey] = React.useState(\"\");\n let blockerFunction = React.useCallback(\n (arg) => {\n if (typeof shouldBlock !== \"function\") {\n return !!shouldBlock;\n }\n if (basename === \"/\") {\n return shouldBlock(arg);\n }\n\n // If they provided us a function and we've got an active basename, strip\n // it from the locations we expose to the user to match the behavior of\n // useLocation\n let { currentLocation, nextLocation, historyAction } = arg;\n return shouldBlock({\n currentLocation: {\n ...currentLocation,\n pathname:\n stripBasename(currentLocation.pathname, basename) ||\n currentLocation.pathname,\n },\n nextLocation: {\n ...nextLocation,\n pathname:\n stripBasename(nextLocation.pathname, basename) ||\n nextLocation.pathname,\n },\n historyAction,\n });\n },\n [basename, shouldBlock]\n );\n\n // This effect is in charge of blocker key assignment and deletion (which is\n // tightly coupled to the key)\n React.useEffect(() => {\n let key = String(++blockerId);\n setBlockerKey(key);\n return () => router.deleteBlocker(key);\n }, [router]);\n\n // This effect handles assigning the blockerFunction. This is to handle\n // unstable blocker function identities, and happens only after the prior\n // effect so we don't get an orphaned blockerFunction in the router with a\n // key of \"\". Until then we just have the IDLE_BLOCKER.\n React.useEffect(() => {\n if (blockerKey !== \"\") {\n router.getBlocker(blockerKey, blockerFunction);\n }\n }, [router, blockerKey, blockerFunction]);\n\n // Prefer the blocker from `state` not `router.state` since DataRouterContext\n // is memoized so this ensures we update on blocker state updates\n return blockerKey && state.blockers.has(blockerKey)\n ? state.blockers.get(blockerKey)!\n : IDLE_BLOCKER;\n}\n\n/**\n * Stable version of useNavigate that is used when we are in the context of\n * a RouterProvider.\n */\nfunction useNavigateStable(): NavigateFunction {\n let { router } = useDataRouterContext(DataRouterHook.UseNavigateStable);\n let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);\n\n let activeRef = React.useRef(false);\n useIsomorphicLayoutEffect(() => {\n activeRef.current = true;\n });\n\n let navigate: NavigateFunction = React.useCallback(\n (to: To | number, options: NavigateOptions = {}) => {\n warning(activeRef.current, navigateEffectWarning);\n\n // Short circuit here since if this happens on first render the navigate\n // is useless because we haven't wired up our router subscriber yet\n if (!activeRef.current) return;\n\n if (typeof to === \"number\") {\n router.navigate(to);\n } else {\n router.navigate(to, { fromRouteId: id, ...options });\n }\n },\n [router, id]\n );\n\n return navigate;\n}\n\nconst alreadyWarned: Record = {};\n\nfunction warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n","import type {\n InitialEntry,\n LazyRouteFunction,\n Location,\n MemoryHistory,\n RelativeRoutingType,\n Router as RemixRouter,\n RouterState,\n RouterSubscriber,\n To,\n TrackedPromise,\n} from \"@remix-run/router\";\nimport {\n AbortedDeferredError,\n Action as NavigationType,\n createMemoryHistory,\n UNSAFE_getResolveToMatches as getResolveToMatches,\n UNSAFE_invariant as invariant,\n parsePath,\n resolveTo,\n stripBasename,\n UNSAFE_warning as warning,\n} from \"@remix-run/router\";\nimport * as React from \"react\";\n\nimport type {\n DataRouteObject,\n IndexRouteObject,\n Navigator,\n NonIndexRouteObject,\n RouteMatch,\n RouteObject,\n} from \"./context\";\nimport {\n AwaitContext,\n DataRouterContext,\n DataRouterStateContext,\n LocationContext,\n NavigationContext,\n RouteContext,\n} from \"./context\";\nimport {\n _renderMatches,\n useAsyncValue,\n useInRouterContext,\n useLocation,\n useNavigate,\n useOutlet,\n useRoutes,\n useRoutesImpl,\n} from \"./hooks\";\n\nexport interface FutureConfig {\n v7_relativeSplatPath: boolean;\n v7_startTransition: boolean;\n}\n\nexport interface RouterProviderProps {\n fallbackElement?: React.ReactNode;\n router: RemixRouter;\n // Only accept future flags relevant to rendering behavior\n // routing flags should be accessed via router.future\n future?: Partial>;\n}\n\n/**\n Webpack + React 17 fails to compile on any of the following because webpack\n complains that `startTransition` doesn't exist in `React`:\n * import { startTransition } from \"react\"\n * import * as React from from \"react\";\n \"startTransition\" in React ? React.startTransition(() => setState()) : setState()\n * import * as React from from \"react\";\n \"startTransition\" in React ? React[\"startTransition\"](() => setState()) : setState()\n\n Moving it to a constant such as the following solves the Webpack/React 17 issue:\n * import * as React from from \"react\";\n const START_TRANSITION = \"startTransition\";\n START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()\n\n However, that introduces webpack/terser minification issues in production builds\n in React 18 where minification/obfuscation ends up removing the call of\n React.startTransition entirely from the first half of the ternary. Grabbing\n this exported reference once up front resolves that issue.\n\n See https://github.com/remix-run/react-router/issues/10579\n*/\nconst START_TRANSITION = \"startTransition\";\nconst startTransitionImpl = React[START_TRANSITION];\n\n/**\n * Given a Remix Router instance, render the appropriate UI\n */\nexport function RouterProvider({\n fallbackElement,\n router,\n future,\n}: RouterProviderProps): React.ReactElement {\n let [state, setStateImpl] = React.useState(router.state);\n let { v7_startTransition } = future || {};\n\n let setState = React.useCallback(\n (newState: RouterState) => {\n if (v7_startTransition && startTransitionImpl) {\n startTransitionImpl(() => setStateImpl(newState));\n } else {\n setStateImpl(newState);\n }\n },\n [setStateImpl, v7_startTransition]\n );\n\n // Need to use a layout effect here so we are subscribed early enough to\n // pick up on any render-driven redirects/navigations (useEffect/)\n React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);\n\n React.useEffect(() => {\n warning(\n fallbackElement == null || !router.future.v7_partialHydration,\n \"`` is deprecated when using \" +\n \"`v7_partialHydration`, use a `HydrateFallback` component instead\"\n );\n // Only log this once on initial mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n let navigator = React.useMemo((): Navigator => {\n return {\n createHref: router.createHref,\n encodeLocation: router.encodeLocation,\n go: (n) => router.navigate(n),\n push: (to, state, opts) =>\n router.navigate(to, {\n state,\n preventScrollReset: opts?.preventScrollReset,\n }),\n replace: (to, state, opts) =>\n router.navigate(to, {\n replace: true,\n state,\n preventScrollReset: opts?.preventScrollReset,\n }),\n };\n }, [router]);\n\n let basename = router.basename || \"/\";\n\n let dataRouterContext = React.useMemo(\n () => ({\n router,\n navigator,\n static: false,\n basename,\n }),\n [router, navigator, basename]\n );\n\n // The fragment and {null} here are important! We need them to keep React 18's\n // useId happy when we are server-rendering since we may have a