UNPKG

182 kBJavaScriptView Raw
1/**
2 * react-router v7.1.5
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11"use strict";
12var __create = Object.create;
13var __defProp = Object.defineProperty;
14var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
15var __getOwnPropNames = Object.getOwnPropertyNames;
16var __getProtoOf = Object.getPrototypeOf;
17var __hasOwnProp = Object.prototype.hasOwnProperty;
18var __export = (target, all) => {
19 for (var name in all)
20 __defProp(target, name, { get: all[name], enumerable: true });
21};
22var __copyProps = (to, from, except, desc) => {
23 if (from && typeof from === "object" || typeof from === "function") {
24 for (let key of __getOwnPropNames(from))
25 if (!__hasOwnProp.call(to, key) && key !== except)
26 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
27 }
28 return to;
29};
30var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
31 // If the importer is in node compatibility mode or this is not an ESM
32 // file that has been converted to a CommonJS file using a Babel-
33 // compatible transform (i.e. "__esModule" has not been set), then set
34 // "default" to the CommonJS "module.exports" for node compatibility.
35 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
36 mod
37));
38var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
39
40// dom-export.ts
41var dom_export_exports = {};
42__export(dom_export_exports, {
43 HydratedRouter: () => HydratedRouter,
44 RouterProvider: () => RouterProvider2
45});
46module.exports = __toCommonJS(dom_export_exports);
47
48// lib/dom-export/dom-router-provider.tsx
49var React10 = __toESM(require("react"));
50var ReactDOM = __toESM(require("react-dom"));
51
52// lib/router/history.ts
53var PopStateEventType = "popstate";
54function createBrowserHistory(options = {}) {
55 function createBrowserLocation(window2, globalHistory) {
56 let { pathname, search, hash } = window2.location;
57 return createLocation(
58 "",
59 { pathname, search, hash },
60 // state defaults to `null` because `window.history.state` does
61 globalHistory.state && globalHistory.state.usr || null,
62 globalHistory.state && globalHistory.state.key || "default"
63 );
64 }
65 function createBrowserHref(window2, to) {
66 return typeof to === "string" ? to : createPath(to);
67 }
68 return getUrlBasedHistory(
69 createBrowserLocation,
70 createBrowserHref,
71 null,
72 options
73 );
74}
75function invariant(value, message) {
76 if (value === false || value === null || typeof value === "undefined") {
77 throw new Error(message);
78 }
79}
80function warning(cond, message) {
81 if (!cond) {
82 if (typeof console !== "undefined") console.warn(message);
83 try {
84 throw new Error(message);
85 } catch (e) {
86 }
87 }
88}
89function createKey() {
90 return Math.random().toString(36).substring(2, 10);
91}
92function getHistoryState(location, index) {
93 return {
94 usr: location.state,
95 key: location.key,
96 idx: index
97 };
98}
99function createLocation(current, to, state = null, key) {
100 let location = {
101 pathname: typeof current === "string" ? current : current.pathname,
102 search: "",
103 hash: "",
104 ...typeof to === "string" ? parsePath(to) : to,
105 state,
106 // TODO: This could be cleaned up. push/replace should probably just take
107 // full Locations now and avoid the need to run through this flow at all
108 // But that's a pretty big refactor to the current test suite so going to
109 // keep as is for the time being and just let any incoming keys take precedence
110 key: to && to.key || key || createKey()
111 };
112 return location;
113}
114function createPath({
115 pathname = "/",
116 search = "",
117 hash = ""
118}) {
119 if (search && search !== "?")
120 pathname += search.charAt(0) === "?" ? search : "?" + search;
121 if (hash && hash !== "#")
122 pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
123 return pathname;
124}
125function parsePath(path) {
126 let parsedPath = {};
127 if (path) {
128 let hashIndex = path.indexOf("#");
129 if (hashIndex >= 0) {
130 parsedPath.hash = path.substring(hashIndex);
131 path = path.substring(0, hashIndex);
132 }
133 let searchIndex = path.indexOf("?");
134 if (searchIndex >= 0) {
135 parsedPath.search = path.substring(searchIndex);
136 path = path.substring(0, searchIndex);
137 }
138 if (path) {
139 parsedPath.pathname = path;
140 }
141 }
142 return parsedPath;
143}
144function getUrlBasedHistory(getLocation, createHref, validateLocation, options = {}) {
145 let { window: window2 = document.defaultView, v5Compat = false } = options;
146 let globalHistory = window2.history;
147 let action = "POP" /* Pop */;
148 let listener = null;
149 let index = getIndex();
150 if (index == null) {
151 index = 0;
152 globalHistory.replaceState({ ...globalHistory.state, idx: index }, "");
153 }
154 function getIndex() {
155 let state = globalHistory.state || { idx: null };
156 return state.idx;
157 }
158 function handlePop() {
159 action = "POP" /* Pop */;
160 let nextIndex = getIndex();
161 let delta = nextIndex == null ? null : nextIndex - index;
162 index = nextIndex;
163 if (listener) {
164 listener({ action, location: history.location, delta });
165 }
166 }
167 function push(to, state) {
168 action = "PUSH" /* Push */;
169 let location = createLocation(history.location, to, state);
170 if (validateLocation) validateLocation(location, to);
171 index = getIndex() + 1;
172 let historyState = getHistoryState(location, index);
173 let url = history.createHref(location);
174 try {
175 globalHistory.pushState(historyState, "", url);
176 } catch (error) {
177 if (error instanceof DOMException && error.name === "DataCloneError") {
178 throw error;
179 }
180 window2.location.assign(url);
181 }
182 if (v5Compat && listener) {
183 listener({ action, location: history.location, delta: 1 });
184 }
185 }
186 function replace2(to, state) {
187 action = "REPLACE" /* Replace */;
188 let location = createLocation(history.location, to, state);
189 if (validateLocation) validateLocation(location, to);
190 index = getIndex();
191 let historyState = getHistoryState(location, index);
192 let url = history.createHref(location);
193 globalHistory.replaceState(historyState, "", url);
194 if (v5Compat && listener) {
195 listener({ action, location: history.location, delta: 0 });
196 }
197 }
198 function createURL(to) {
199 let base = window2.location.origin !== "null" ? window2.location.origin : window2.location.href;
200 let href = typeof to === "string" ? to : createPath(to);
201 href = href.replace(/ $/, "%20");
202 invariant(
203 base,
204 `No window.location.(origin|href) available to create URL for href: ${href}`
205 );
206 return new URL(href, base);
207 }
208 let history = {
209 get action() {
210 return action;
211 },
212 get location() {
213 return getLocation(window2, globalHistory);
214 },
215 listen(fn) {
216 if (listener) {
217 throw new Error("A history only accepts one active listener");
218 }
219 window2.addEventListener(PopStateEventType, handlePop);
220 listener = fn;
221 return () => {
222 window2.removeEventListener(PopStateEventType, handlePop);
223 listener = null;
224 };
225 },
226 createHref(to) {
227 return createHref(window2, to);
228 },
229 createURL,
230 encodeLocation(to) {
231 let url = createURL(to);
232 return {
233 pathname: url.pathname,
234 search: url.search,
235 hash: url.hash
236 };
237 },
238 push,
239 replace: replace2,
240 go(n) {
241 return globalHistory.go(n);
242 }
243 };
244 return history;
245}
246
247// lib/router/utils.ts
248var immutableRouteKeys = /* @__PURE__ */ new Set([
249 "lazy",
250 "caseSensitive",
251 "path",
252 "id",
253 "index",
254 "children"
255]);
256function isIndexRoute(route) {
257 return route.index === true;
258}
259function convertRoutesToDataRoutes(routes, mapRouteProperties2, parentPath = [], manifest = {}) {
260 return routes.map((route, index) => {
261 let treePath = [...parentPath, String(index)];
262 let id = typeof route.id === "string" ? route.id : treePath.join("-");
263 invariant(
264 route.index !== true || !route.children,
265 `Cannot specify children on an index route`
266 );
267 invariant(
268 !manifest[id],
269 `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages`
270 );
271 if (isIndexRoute(route)) {
272 let indexRoute = {
273 ...route,
274 ...mapRouteProperties2(route),
275 id
276 };
277 manifest[id] = indexRoute;
278 return indexRoute;
279 } else {
280 let pathOrLayoutRoute = {
281 ...route,
282 ...mapRouteProperties2(route),
283 id,
284 children: void 0
285 };
286 manifest[id] = pathOrLayoutRoute;
287 if (route.children) {
288 pathOrLayoutRoute.children = convertRoutesToDataRoutes(
289 route.children,
290 mapRouteProperties2,
291 treePath,
292 manifest
293 );
294 }
295 return pathOrLayoutRoute;
296 }
297 });
298}
299function matchRoutes(routes, locationArg, basename = "/") {
300 return matchRoutesImpl(routes, locationArg, basename, false);
301}
302function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
303 let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
304 let pathname = stripBasename(location.pathname || "/", basename);
305 if (pathname == null) {
306 return null;
307 }
308 let branches = flattenRoutes(routes);
309 rankRouteBranches(branches);
310 let matches = null;
311 for (let i = 0; matches == null && i < branches.length; ++i) {
312 let decoded = decodePath(pathname);
313 matches = matchRouteBranch(
314 branches[i],
315 decoded,
316 allowPartial
317 );
318 }
319 return matches;
320}
321function convertRouteMatchToUiMatch(match, loaderData) {
322 let { route, pathname, params } = match;
323 return {
324 id: route.id,
325 pathname,
326 params,
327 data: loaderData[route.id],
328 handle: route.handle
329 };
330}
331function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
332 let flattenRoute = (route, index, relativePath) => {
333 let meta = {
334 relativePath: relativePath === void 0 ? route.path || "" : relativePath,
335 caseSensitive: route.caseSensitive === true,
336 childrenIndex: index,
337 route
338 };
339 if (meta.relativePath.startsWith("/")) {
340 invariant(
341 meta.relativePath.startsWith(parentPath),
342 `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`
343 );
344 meta.relativePath = meta.relativePath.slice(parentPath.length);
345 }
346 let path = joinPaths([parentPath, meta.relativePath]);
347 let routesMeta = parentsMeta.concat(meta);
348 if (route.children && route.children.length > 0) {
349 invariant(
350 // Our types know better, but runtime JS may not!
351 // @ts-expect-error
352 route.index !== true,
353 `Index routes must not have child routes. Please remove all child routes from route path "${path}".`
354 );
355 flattenRoutes(route.children, branches, routesMeta, path);
356 }
357 if (route.path == null && !route.index) {
358 return;
359 }
360 branches.push({
361 path,
362 score: computeScore(path, route.index),
363 routesMeta
364 });
365 };
366 routes.forEach((route, index) => {
367 if (route.path === "" || !route.path?.includes("?")) {
368 flattenRoute(route, index);
369 } else {
370 for (let exploded of explodeOptionalSegments(route.path)) {
371 flattenRoute(route, index, exploded);
372 }
373 }
374 });
375 return branches;
376}
377function explodeOptionalSegments(path) {
378 let segments = path.split("/");
379 if (segments.length === 0) return [];
380 let [first, ...rest] = segments;
381 let isOptional = first.endsWith("?");
382 let required = first.replace(/\?$/, "");
383 if (rest.length === 0) {
384 return isOptional ? [required, ""] : [required];
385 }
386 let restExploded = explodeOptionalSegments(rest.join("/"));
387 let result = [];
388 result.push(
389 ...restExploded.map(
390 (subpath) => subpath === "" ? required : [required, subpath].join("/")
391 )
392 );
393 if (isOptional) {
394 result.push(...restExploded);
395 }
396 return result.map(
397 (exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded
398 );
399}
400function rankRouteBranches(branches) {
401 branches.sort(
402 (a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(
403 a.routesMeta.map((meta) => meta.childrenIndex),
404 b.routesMeta.map((meta) => meta.childrenIndex)
405 )
406 );
407}
408var paramRe = /^:[\w-]+$/;
409var dynamicSegmentValue = 3;
410var indexRouteValue = 2;
411var emptySegmentValue = 1;
412var staticSegmentValue = 10;
413var splatPenalty = -2;
414var isSplat = (s) => s === "*";
415function computeScore(path, index) {
416 let segments = path.split("/");
417 let initialScore = segments.length;
418 if (segments.some(isSplat)) {
419 initialScore += splatPenalty;
420 }
421 if (index) {
422 initialScore += indexRouteValue;
423 }
424 return segments.filter((s) => !isSplat(s)).reduce(
425 (score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue),
426 initialScore
427 );
428}
429function compareIndexes(a, b) {
430 let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
431 return siblings ? (
432 // If two routes are siblings, we should try to match the earlier sibling
433 // first. This allows people to have fine-grained control over the matching
434 // behavior by simply putting routes with identical paths in the order they
435 // want them tried.
436 a[a.length - 1] - b[b.length - 1]
437 ) : (
438 // Otherwise, it doesn't really make sense to rank non-siblings by index,
439 // so they sort equally.
440 0
441 );
442}
443function matchRouteBranch(branch, pathname, allowPartial = false) {
444 let { routesMeta } = branch;
445 let matchedParams = {};
446 let matchedPathname = "/";
447 let matches = [];
448 for (let i = 0; i < routesMeta.length; ++i) {
449 let meta = routesMeta[i];
450 let end = i === routesMeta.length - 1;
451 let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
452 let match = matchPath(
453 { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },
454 remainingPathname
455 );
456 let route = meta.route;
457 if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
458 match = matchPath(
459 {
460 path: meta.relativePath,
461 caseSensitive: meta.caseSensitive,
462 end: false
463 },
464 remainingPathname
465 );
466 }
467 if (!match) {
468 return null;
469 }
470 Object.assign(matchedParams, match.params);
471 matches.push({
472 // TODO: Can this as be avoided?
473 params: matchedParams,
474 pathname: joinPaths([matchedPathname, match.pathname]),
475 pathnameBase: normalizePathname(
476 joinPaths([matchedPathname, match.pathnameBase])
477 ),
478 route
479 });
480 if (match.pathnameBase !== "/") {
481 matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
482 }
483 }
484 return matches;
485}
486function matchPath(pattern, pathname) {
487 if (typeof pattern === "string") {
488 pattern = { path: pattern, caseSensitive: false, end: true };
489 }
490 let [matcher, compiledParams] = compilePath(
491 pattern.path,
492 pattern.caseSensitive,
493 pattern.end
494 );
495 let match = pathname.match(matcher);
496 if (!match) return null;
497 let matchedPathname = match[0];
498 let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
499 let captureGroups = match.slice(1);
500 let params = compiledParams.reduce(
501 (memo2, { paramName, isOptional }, index) => {
502 if (paramName === "*") {
503 let splatValue = captureGroups[index] || "";
504 pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
505 }
506 const value = captureGroups[index];
507 if (isOptional && !value) {
508 memo2[paramName] = void 0;
509 } else {
510 memo2[paramName] = (value || "").replace(/%2F/g, "/");
511 }
512 return memo2;
513 },
514 {}
515 );
516 return {
517 params,
518 pathname: matchedPathname,
519 pathnameBase,
520 pattern
521 };
522}
523function compilePath(path, caseSensitive = false, end = true) {
524 warning(
525 path === "*" || !path.endsWith("*") || path.endsWith("/*"),
526 `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`
527 );
528 let params = [];
529 let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(
530 /\/:([\w-]+)(\?)?/g,
531 (_, paramName, isOptional) => {
532 params.push({ paramName, isOptional: isOptional != null });
533 return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
534 }
535 );
536 if (path.endsWith("*")) {
537 params.push({ paramName: "*" });
538 regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
539 } else if (end) {
540 regexpSource += "\\/*$";
541 } else if (path !== "" && path !== "/") {
542 regexpSource += "(?:(?=\\/|$))";
543 } else {
544 }
545 let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
546 return [matcher, params];
547}
548function decodePath(value) {
549 try {
550 return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
551 } catch (error) {
552 warning(
553 false,
554 `The URL path "${value}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${error}).`
555 );
556 return value;
557 }
558}
559function stripBasename(pathname, basename) {
560 if (basename === "/") return pathname;
561 if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
562 return null;
563 }
564 let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
565 let nextChar = pathname.charAt(startIndex);
566 if (nextChar && nextChar !== "/") {
567 return null;
568 }
569 return pathname.slice(startIndex) || "/";
570}
571function resolvePath(to, fromPathname = "/") {
572 let {
573 pathname: toPathname,
574 search = "",
575 hash = ""
576 } = typeof to === "string" ? parsePath(to) : to;
577 let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
578 return {
579 pathname,
580 search: normalizeSearch(search),
581 hash: normalizeHash(hash)
582 };
583}
584function resolvePathname(relativePath, fromPathname) {
585 let segments = fromPathname.replace(/\/+$/, "").split("/");
586 let relativeSegments = relativePath.split("/");
587 relativeSegments.forEach((segment) => {
588 if (segment === "..") {
589 if (segments.length > 1) segments.pop();
590 } else if (segment !== ".") {
591 segments.push(segment);
592 }
593 });
594 return segments.length > 1 ? segments.join("/") : "/";
595}
596function getInvalidPathError(char, field, dest, path) {
597 return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(
598 path
599 )}]. Please separate it out to the \`to.${dest}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`;
600}
601function getPathContributingMatches(matches) {
602 return matches.filter(
603 (match, index) => index === 0 || match.route.path && match.route.path.length > 0
604 );
605}
606function getResolveToMatches(matches) {
607 let pathMatches = getPathContributingMatches(matches);
608 return pathMatches.map(
609 (match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase
610 );
611}
612function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
613 let to;
614 if (typeof toArg === "string") {
615 to = parsePath(toArg);
616 } else {
617 to = { ...toArg };
618 invariant(
619 !to.pathname || !to.pathname.includes("?"),
620 getInvalidPathError("?", "pathname", "search", to)
621 );
622 invariant(
623 !to.pathname || !to.pathname.includes("#"),
624 getInvalidPathError("#", "pathname", "hash", to)
625 );
626 invariant(
627 !to.search || !to.search.includes("#"),
628 getInvalidPathError("#", "search", "hash", to)
629 );
630 }
631 let isEmptyPath = toArg === "" || to.pathname === "";
632 let toPathname = isEmptyPath ? "/" : to.pathname;
633 let from;
634 if (toPathname == null) {
635 from = locationPathname;
636 } else {
637 let routePathnameIndex = routePathnames.length - 1;
638 if (!isPathRelative && toPathname.startsWith("..")) {
639 let toSegments = toPathname.split("/");
640 while (toSegments[0] === "..") {
641 toSegments.shift();
642 routePathnameIndex -= 1;
643 }
644 to.pathname = toSegments.join("/");
645 }
646 from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
647 }
648 let path = resolvePath(to, from);
649 let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
650 let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
651 if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
652 path.pathname += "/";
653 }
654 return path;
655}
656var joinPaths = (paths) => paths.join("/").replace(/\/\/+/g, "/");
657var normalizePathname = (pathname) => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
658var normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
659var normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
660var DataWithResponseInit = class {
661 constructor(data2, init) {
662 this.type = "DataWithResponseInit";
663 this.data = data2;
664 this.init = init || null;
665 }
666};
667function data(data2, init) {
668 return new DataWithResponseInit(
669 data2,
670 typeof init === "number" ? { status: init } : init
671 );
672}
673var redirect = (url, init = 302) => {
674 let responseInit = init;
675 if (typeof responseInit === "number") {
676 responseInit = { status: responseInit };
677 } else if (typeof responseInit.status === "undefined") {
678 responseInit.status = 302;
679 }
680 let headers = new Headers(responseInit.headers);
681 headers.set("Location", url);
682 return new Response(null, { ...responseInit, headers });
683};
684var ErrorResponseImpl = class {
685 constructor(status, statusText, data2, internal = false) {
686 this.status = status;
687 this.statusText = statusText || "";
688 this.internal = internal;
689 if (data2 instanceof Error) {
690 this.data = data2.toString();
691 this.error = data2;
692 } else {
693 this.data = data2;
694 }
695 }
696};
697function isRouteErrorResponse(error) {
698 return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
699}
700
701// lib/router/router.ts
702var validMutationMethodsArr = [
703 "POST",
704 "PUT",
705 "PATCH",
706 "DELETE"
707];
708var validMutationMethods = new Set(
709 validMutationMethodsArr
710);
711var validRequestMethodsArr = [
712 "GET",
713 ...validMutationMethodsArr
714];
715var validRequestMethods = new Set(validRequestMethodsArr);
716var redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
717var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set([307, 308]);
718var IDLE_NAVIGATION = {
719 state: "idle",
720 location: void 0,
721 formMethod: void 0,
722 formAction: void 0,
723 formEncType: void 0,
724 formData: void 0,
725 json: void 0,
726 text: void 0
727};
728var IDLE_FETCHER = {
729 state: "idle",
730 data: void 0,
731 formMethod: void 0,
732 formAction: void 0,
733 formEncType: void 0,
734 formData: void 0,
735 json: void 0,
736 text: void 0
737};
738var IDLE_BLOCKER = {
739 state: "unblocked",
740 proceed: void 0,
741 reset: void 0,
742 location: void 0
743};
744var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
745var defaultMapRouteProperties = (route) => ({
746 hasErrorBoundary: Boolean(route.hasErrorBoundary)
747});
748var TRANSITIONS_STORAGE_KEY = "remix-router-transitions";
749var ResetLoaderDataSymbol = Symbol("ResetLoaderData");
750function createRouter(init) {
751 const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : void 0;
752 const isBrowser = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
753 invariant(
754 init.routes.length > 0,
755 "You must provide a non-empty routes array to createRouter"
756 );
757 let mapRouteProperties2 = init.mapRouteProperties || defaultMapRouteProperties;
758 let manifest = {};
759 let dataRoutes = convertRoutesToDataRoutes(
760 init.routes,
761 mapRouteProperties2,
762 void 0,
763 manifest
764 );
765 let inFlightDataRoutes;
766 let basename = init.basename || "/";
767 let dataStrategyImpl = init.dataStrategy || defaultDataStrategy;
768 let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation;
769 let future = {
770 ...init.future
771 };
772 let unlistenHistory = null;
773 let subscribers = /* @__PURE__ */ new Set();
774 let savedScrollPositions = null;
775 let getScrollRestorationKey = null;
776 let getScrollPosition = null;
777 let initialScrollRestored = init.hydrationData != null;
778 let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
779 let initialMatchesIsFOW = false;
780 let initialErrors = null;
781 if (initialMatches == null && !patchRoutesOnNavigationImpl) {
782 let error = getInternalRouterError(404, {
783 pathname: init.history.location.pathname
784 });
785 let { matches, route } = getShortCircuitMatches(dataRoutes);
786 initialMatches = matches;
787 initialErrors = { [route.id]: error };
788 }
789 if (initialMatches && !init.hydrationData) {
790 let fogOfWar = checkFogOfWar(
791 initialMatches,
792 dataRoutes,
793 init.history.location.pathname
794 );
795 if (fogOfWar.active) {
796 initialMatches = null;
797 }
798 }
799 let initialized;
800 if (!initialMatches) {
801 initialized = false;
802 initialMatches = [];
803 let fogOfWar = checkFogOfWar(
804 null,
805 dataRoutes,
806 init.history.location.pathname
807 );
808 if (fogOfWar.active && fogOfWar.matches) {
809 initialMatchesIsFOW = true;
810 initialMatches = fogOfWar.matches;
811 }
812 } else if (initialMatches.some((m) => m.route.lazy)) {
813 initialized = false;
814 } else if (!initialMatches.some((m) => m.route.loader)) {
815 initialized = true;
816 } else {
817 let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
818 let errors = init.hydrationData ? init.hydrationData.errors : null;
819 if (errors) {
820 let idx = initialMatches.findIndex(
821 (m) => errors[m.route.id] !== void 0
822 );
823 initialized = initialMatches.slice(0, idx + 1).every((m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
824 } else {
825 initialized = initialMatches.every(
826 (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors)
827 );
828 }
829 }
830 let router2;
831 let state = {
832 historyAction: init.history.action,
833 location: init.history.location,
834 matches: initialMatches,
835 initialized,
836 navigation: IDLE_NAVIGATION,
837 // Don't restore on initial updateState() if we were SSR'd
838 restoreScrollPosition: init.hydrationData != null ? false : null,
839 preventScrollReset: false,
840 revalidation: "idle",
841 loaderData: init.hydrationData && init.hydrationData.loaderData || {},
842 actionData: init.hydrationData && init.hydrationData.actionData || null,
843 errors: init.hydrationData && init.hydrationData.errors || initialErrors,
844 fetchers: /* @__PURE__ */ new Map(),
845 blockers: /* @__PURE__ */ new Map()
846 };
847 let pendingAction = "POP" /* Pop */;
848 let pendingPreventScrollReset = false;
849 let pendingNavigationController;
850 let pendingViewTransitionEnabled = false;
851 let appliedViewTransitions = /* @__PURE__ */ new Map();
852 let removePageHideEventListener = null;
853 let isUninterruptedRevalidation = false;
854 let isRevalidationRequired = false;
855 let cancelledFetcherLoads = /* @__PURE__ */ new Set();
856 let fetchControllers = /* @__PURE__ */ new Map();
857 let incrementingLoadId = 0;
858 let pendingNavigationLoadId = -1;
859 let fetchReloadIds = /* @__PURE__ */ new Map();
860 let fetchRedirectIds = /* @__PURE__ */ new Set();
861 let fetchLoadMatches = /* @__PURE__ */ new Map();
862 let activeFetchers = /* @__PURE__ */ new Map();
863 let fetchersQueuedForDeletion = /* @__PURE__ */ new Set();
864 let blockerFunctions = /* @__PURE__ */ new Map();
865 let unblockBlockerHistoryUpdate = void 0;
866 let pendingRevalidationDfd = null;
867 function initialize() {
868 unlistenHistory = init.history.listen(
869 ({ action: historyAction, location, delta }) => {
870 if (unblockBlockerHistoryUpdate) {
871 unblockBlockerHistoryUpdate();
872 unblockBlockerHistoryUpdate = void 0;
873 return;
874 }
875 warning(
876 blockerFunctions.size === 0 || delta != null,
877 "You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL."
878 );
879 let blockerKey = shouldBlockNavigation({
880 currentLocation: state.location,
881 nextLocation: location,
882 historyAction
883 });
884 if (blockerKey && delta != null) {
885 let nextHistoryUpdatePromise = new Promise((resolve) => {
886 unblockBlockerHistoryUpdate = resolve;
887 });
888 init.history.go(delta * -1);
889 updateBlocker(blockerKey, {
890 state: "blocked",
891 location,
892 proceed() {
893 updateBlocker(blockerKey, {
894 state: "proceeding",
895 proceed: void 0,
896 reset: void 0,
897 location
898 });
899 nextHistoryUpdatePromise.then(() => init.history.go(delta));
900 },
901 reset() {
902 let blockers = new Map(state.blockers);
903 blockers.set(blockerKey, IDLE_BLOCKER);
904 updateState({ blockers });
905 }
906 });
907 return;
908 }
909 return startNavigation(historyAction, location);
910 }
911 );
912 if (isBrowser) {
913 restoreAppliedTransitions(routerWindow, appliedViewTransitions);
914 let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);
915 routerWindow.addEventListener("pagehide", _saveAppliedTransitions);
916 removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions);
917 }
918 if (!state.initialized) {
919 startNavigation("POP" /* Pop */, state.location, {
920 initialHydration: true
921 });
922 }
923 return router2;
924 }
925 function dispose() {
926 if (unlistenHistory) {
927 unlistenHistory();
928 }
929 if (removePageHideEventListener) {
930 removePageHideEventListener();
931 }
932 subscribers.clear();
933 pendingNavigationController && pendingNavigationController.abort();
934 state.fetchers.forEach((_, key) => deleteFetcher(key));
935 state.blockers.forEach((_, key) => deleteBlocker(key));
936 }
937 function subscribe(fn) {
938 subscribers.add(fn);
939 return () => subscribers.delete(fn);
940 }
941 function updateState(newState, opts = {}) {
942 state = {
943 ...state,
944 ...newState
945 };
946 let unmountedFetchers = [];
947 let mountedFetchers = [];
948 state.fetchers.forEach((fetcher, key) => {
949 if (fetcher.state === "idle") {
950 if (fetchersQueuedForDeletion.has(key)) {
951 unmountedFetchers.push(key);
952 } else {
953 mountedFetchers.push(key);
954 }
955 }
956 });
957 fetchersQueuedForDeletion.forEach((key) => {
958 if (!state.fetchers.has(key) && !fetchControllers.has(key)) {
959 unmountedFetchers.push(key);
960 }
961 });
962 [...subscribers].forEach(
963 (subscriber) => subscriber(state, {
964 deletedFetchers: unmountedFetchers,
965 viewTransitionOpts: opts.viewTransitionOpts,
966 flushSync: opts.flushSync === true
967 })
968 );
969 unmountedFetchers.forEach((key) => deleteFetcher(key));
970 mountedFetchers.forEach((key) => state.fetchers.delete(key));
971 }
972 function completeNavigation(location, newState, { flushSync: flushSync2 } = {}) {
973 let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && location.state?._isRedirect !== true;
974 let actionData;
975 if (newState.actionData) {
976 if (Object.keys(newState.actionData).length > 0) {
977 actionData = newState.actionData;
978 } else {
979 actionData = null;
980 }
981 } else if (isActionReload) {
982 actionData = state.actionData;
983 } else {
984 actionData = null;
985 }
986 let loaderData = newState.loaderData ? mergeLoaderData(
987 state.loaderData,
988 newState.loaderData,
989 newState.matches || [],
990 newState.errors
991 ) : state.loaderData;
992 let blockers = state.blockers;
993 if (blockers.size > 0) {
994 blockers = new Map(blockers);
995 blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));
996 }
997 let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && location.state?._isRedirect !== true;
998 if (inFlightDataRoutes) {
999 dataRoutes = inFlightDataRoutes;
1000 inFlightDataRoutes = void 0;
1001 }
1002 if (isUninterruptedRevalidation) {
1003 } else if (pendingAction === "POP" /* Pop */) {
1004 } else if (pendingAction === "PUSH" /* Push */) {
1005 init.history.push(location, location.state);
1006 } else if (pendingAction === "REPLACE" /* Replace */) {
1007 init.history.replace(location, location.state);
1008 }
1009 let viewTransitionOpts;
1010 if (pendingAction === "POP" /* Pop */) {
1011 let priorPaths = appliedViewTransitions.get(state.location.pathname);
1012 if (priorPaths && priorPaths.has(location.pathname)) {
1013 viewTransitionOpts = {
1014 currentLocation: state.location,
1015 nextLocation: location
1016 };
1017 } else if (appliedViewTransitions.has(location.pathname)) {
1018 viewTransitionOpts = {
1019 currentLocation: location,
1020 nextLocation: state.location
1021 };
1022 }
1023 } else if (pendingViewTransitionEnabled) {
1024 let toPaths = appliedViewTransitions.get(state.location.pathname);
1025 if (toPaths) {
1026 toPaths.add(location.pathname);
1027 } else {
1028 toPaths = /* @__PURE__ */ new Set([location.pathname]);
1029 appliedViewTransitions.set(state.location.pathname, toPaths);
1030 }
1031 viewTransitionOpts = {
1032 currentLocation: state.location,
1033 nextLocation: location
1034 };
1035 }
1036 updateState(
1037 {
1038 ...newState,
1039 // matches, errors, fetchers go through as-is
1040 actionData,
1041 loaderData,
1042 historyAction: pendingAction,
1043 location,
1044 initialized: true,
1045 navigation: IDLE_NAVIGATION,
1046 revalidation: "idle",
1047 restoreScrollPosition: getSavedScrollPosition(
1048 location,
1049 newState.matches || state.matches
1050 ),
1051 preventScrollReset,
1052 blockers
1053 },
1054 {
1055 viewTransitionOpts,
1056 flushSync: flushSync2 === true
1057 }
1058 );
1059 pendingAction = "POP" /* Pop */;
1060 pendingPreventScrollReset = false;
1061 pendingViewTransitionEnabled = false;
1062 isUninterruptedRevalidation = false;
1063 isRevalidationRequired = false;
1064 pendingRevalidationDfd?.resolve();
1065 pendingRevalidationDfd = null;
1066 }
1067 async function navigate(to, opts) {
1068 if (typeof to === "number") {
1069 init.history.go(to);
1070 return;
1071 }
1072 let normalizedPath = normalizeTo(
1073 state.location,
1074 state.matches,
1075 basename,
1076 to,
1077 opts?.fromRouteId,
1078 opts?.relative
1079 );
1080 let { path, submission, error } = normalizeNavigateOptions(
1081 false,
1082 normalizedPath,
1083 opts
1084 );
1085 let currentLocation = state.location;
1086 let nextLocation = createLocation(state.location, path, opts && opts.state);
1087 nextLocation = {
1088 ...nextLocation,
1089 ...init.history.encodeLocation(nextLocation)
1090 };
1091 let userReplace = opts && opts.replace != null ? opts.replace : void 0;
1092 let historyAction = "PUSH" /* Push */;
1093 if (userReplace === true) {
1094 historyAction = "REPLACE" /* Replace */;
1095 } else if (userReplace === false) {
1096 } else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
1097 historyAction = "REPLACE" /* Replace */;
1098 }
1099 let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : void 0;
1100 let flushSync2 = (opts && opts.flushSync) === true;
1101 let blockerKey = shouldBlockNavigation({
1102 currentLocation,
1103 nextLocation,
1104 historyAction
1105 });
1106 if (blockerKey) {
1107 updateBlocker(blockerKey, {
1108 state: "blocked",
1109 location: nextLocation,
1110 proceed() {
1111 updateBlocker(blockerKey, {
1112 state: "proceeding",
1113 proceed: void 0,
1114 reset: void 0,
1115 location: nextLocation
1116 });
1117 navigate(to, opts);
1118 },
1119 reset() {
1120 let blockers = new Map(state.blockers);
1121 blockers.set(blockerKey, IDLE_BLOCKER);
1122 updateState({ blockers });
1123 }
1124 });
1125 return;
1126 }
1127 await startNavigation(historyAction, nextLocation, {
1128 submission,
1129 // Send through the formData serialization error if we have one so we can
1130 // render at the right error boundary after we match routes
1131 pendingError: error,
1132 preventScrollReset,
1133 replace: opts && opts.replace,
1134 enableViewTransition: opts && opts.viewTransition,
1135 flushSync: flushSync2
1136 });
1137 }
1138 function revalidate() {
1139 if (!pendingRevalidationDfd) {
1140 pendingRevalidationDfd = createDeferred();
1141 }
1142 interruptActiveLoads();
1143 updateState({ revalidation: "loading" });
1144 let promise = pendingRevalidationDfd.promise;
1145 if (state.navigation.state === "submitting") {
1146 return promise;
1147 }
1148 if (state.navigation.state === "idle") {
1149 startNavigation(state.historyAction, state.location, {
1150 startUninterruptedRevalidation: true
1151 });
1152 return promise;
1153 }
1154 startNavigation(
1155 pendingAction || state.historyAction,
1156 state.navigation.location,
1157 {
1158 overrideNavigation: state.navigation,
1159 // Proxy through any rending view transition
1160 enableViewTransition: pendingViewTransitionEnabled === true
1161 }
1162 );
1163 return promise;
1164 }
1165 async function startNavigation(historyAction, location, opts) {
1166 pendingNavigationController && pendingNavigationController.abort();
1167 pendingNavigationController = null;
1168 pendingAction = historyAction;
1169 isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true;
1170 saveScrollPosition(state.location, state.matches);
1171 pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1172 pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
1173 let routesToUse = inFlightDataRoutes || dataRoutes;
1174 let loadingNavigation = opts && opts.overrideNavigation;
1175 let matches = opts?.initialHydration && state.matches && state.matches.length > 0 && !initialMatchesIsFOW ? (
1176 // `matchRoutes()` has already been called if we're in here via `router.initialize()`
1177 state.matches
1178 ) : matchRoutes(routesToUse, location, basename);
1179 let flushSync2 = (opts && opts.flushSync) === true;
1180 if (matches && state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
1181 completeNavigation(location, { matches }, { flushSync: flushSync2 });
1182 return;
1183 }
1184 let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname);
1185 if (fogOfWar.active && fogOfWar.matches) {
1186 matches = fogOfWar.matches;
1187 }
1188 if (!matches) {
1189 let { error, notFoundMatches, route } = handleNavigational404(
1190 location.pathname
1191 );
1192 completeNavigation(
1193 location,
1194 {
1195 matches: notFoundMatches,
1196 loaderData: {},
1197 errors: {
1198 [route.id]: error
1199 }
1200 },
1201 { flushSync: flushSync2 }
1202 );
1203 return;
1204 }
1205 pendingNavigationController = new AbortController();
1206 let request = createClientSideRequest(
1207 init.history,
1208 location,
1209 pendingNavigationController.signal,
1210 opts && opts.submission
1211 );
1212 let pendingActionResult;
1213 if (opts && opts.pendingError) {
1214 pendingActionResult = [
1215 findNearestBoundary(matches).route.id,
1216 { type: "error" /* error */, error: opts.pendingError }
1217 ];
1218 } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
1219 let actionResult = await handleAction(
1220 request,
1221 location,
1222 opts.submission,
1223 matches,
1224 fogOfWar.active,
1225 { replace: opts.replace, flushSync: flushSync2 }
1226 );
1227 if (actionResult.shortCircuited) {
1228 return;
1229 }
1230 if (actionResult.pendingActionResult) {
1231 let [routeId, result] = actionResult.pendingActionResult;
1232 if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) {
1233 pendingNavigationController = null;
1234 completeNavigation(location, {
1235 matches: actionResult.matches,
1236 loaderData: {},
1237 errors: {
1238 [routeId]: result.error
1239 }
1240 });
1241 return;
1242 }
1243 }
1244 matches = actionResult.matches || matches;
1245 pendingActionResult = actionResult.pendingActionResult;
1246 loadingNavigation = getLoadingNavigation(location, opts.submission);
1247 flushSync2 = false;
1248 fogOfWar.active = false;
1249 request = createClientSideRequest(
1250 init.history,
1251 request.url,
1252 request.signal
1253 );
1254 }
1255 let {
1256 shortCircuited,
1257 matches: updatedMatches,
1258 loaderData,
1259 errors
1260 } = await handleLoaders(
1261 request,
1262 location,
1263 matches,
1264 fogOfWar.active,
1265 loadingNavigation,
1266 opts && opts.submission,
1267 opts && opts.fetcherSubmission,
1268 opts && opts.replace,
1269 opts && opts.initialHydration === true,
1270 flushSync2,
1271 pendingActionResult
1272 );
1273 if (shortCircuited) {
1274 return;
1275 }
1276 pendingNavigationController = null;
1277 completeNavigation(location, {
1278 matches: updatedMatches || matches,
1279 ...getActionDataForCommit(pendingActionResult),
1280 loaderData,
1281 errors
1282 });
1283 }
1284 async function handleAction(request, location, submission, matches, isFogOfWar, opts = {}) {
1285 interruptActiveLoads();
1286 let navigation = getSubmittingNavigation(location, submission);
1287 updateState({ navigation }, { flushSync: opts.flushSync === true });
1288 if (isFogOfWar) {
1289 let discoverResult = await discoverRoutes(
1290 matches,
1291 location.pathname,
1292 request.signal
1293 );
1294 if (discoverResult.type === "aborted") {
1295 return { shortCircuited: true };
1296 } else if (discoverResult.type === "error") {
1297 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1298 return {
1299 matches: discoverResult.partialMatches,
1300 pendingActionResult: [
1301 boundaryId,
1302 {
1303 type: "error" /* error */,
1304 error: discoverResult.error
1305 }
1306 ]
1307 };
1308 } else if (!discoverResult.matches) {
1309 let { notFoundMatches, error, route } = handleNavigational404(
1310 location.pathname
1311 );
1312 return {
1313 matches: notFoundMatches,
1314 pendingActionResult: [
1315 route.id,
1316 {
1317 type: "error" /* error */,
1318 error
1319 }
1320 ]
1321 };
1322 } else {
1323 matches = discoverResult.matches;
1324 }
1325 }
1326 let result;
1327 let actionMatch = getTargetMatch(matches, location);
1328 if (!actionMatch.route.action && !actionMatch.route.lazy) {
1329 result = {
1330 type: "error" /* error */,
1331 error: getInternalRouterError(405, {
1332 method: request.method,
1333 pathname: location.pathname,
1334 routeId: actionMatch.route.id
1335 })
1336 };
1337 } else {
1338 let results = await callDataStrategy(
1339 "action",
1340 state,
1341 request,
1342 [actionMatch],
1343 matches,
1344 null
1345 );
1346 result = results[actionMatch.route.id];
1347 if (request.signal.aborted) {
1348 return { shortCircuited: true };
1349 }
1350 }
1351 if (isRedirectResult(result)) {
1352 let replace2;
1353 if (opts && opts.replace != null) {
1354 replace2 = opts.replace;
1355 } else {
1356 let location2 = normalizeRedirectLocation(
1357 result.response.headers.get("Location"),
1358 new URL(request.url),
1359 basename
1360 );
1361 replace2 = location2 === state.location.pathname + state.location.search;
1362 }
1363 await startRedirectNavigation(request, result, true, {
1364 submission,
1365 replace: replace2
1366 });
1367 return { shortCircuited: true };
1368 }
1369 if (isErrorResult(result)) {
1370 let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
1371 if ((opts && opts.replace) !== true) {
1372 pendingAction = "PUSH" /* Push */;
1373 }
1374 return {
1375 matches,
1376 pendingActionResult: [boundaryMatch.route.id, result]
1377 };
1378 }
1379 return {
1380 matches,
1381 pendingActionResult: [actionMatch.route.id, result]
1382 };
1383 }
1384 async function handleLoaders(request, location, matches, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync2, pendingActionResult) {
1385 let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
1386 let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
1387 let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
1388 if (isFogOfWar) {
1389 if (shouldUpdateNavigationState) {
1390 let actionData = getUpdatedActionData(pendingActionResult);
1391 updateState(
1392 {
1393 navigation: loadingNavigation,
1394 ...actionData !== void 0 ? { actionData } : {}
1395 },
1396 {
1397 flushSync: flushSync2
1398 }
1399 );
1400 }
1401 let discoverResult = await discoverRoutes(
1402 matches,
1403 location.pathname,
1404 request.signal
1405 );
1406 if (discoverResult.type === "aborted") {
1407 return { shortCircuited: true };
1408 } else if (discoverResult.type === "error") {
1409 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1410 return {
1411 matches: discoverResult.partialMatches,
1412 loaderData: {},
1413 errors: {
1414 [boundaryId]: discoverResult.error
1415 }
1416 };
1417 } else if (!discoverResult.matches) {
1418 let { error, notFoundMatches, route } = handleNavigational404(
1419 location.pathname
1420 );
1421 return {
1422 matches: notFoundMatches,
1423 loaderData: {},
1424 errors: {
1425 [route.id]: error
1426 }
1427 };
1428 } else {
1429 matches = discoverResult.matches;
1430 }
1431 }
1432 let routesToUse = inFlightDataRoutes || dataRoutes;
1433 let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
1434 init.history,
1435 state,
1436 matches,
1437 activeSubmission,
1438 location,
1439 initialHydration === true,
1440 isRevalidationRequired,
1441 cancelledFetcherLoads,
1442 fetchersQueuedForDeletion,
1443 fetchLoadMatches,
1444 fetchRedirectIds,
1445 routesToUse,
1446 basename,
1447 pendingActionResult
1448 );
1449 pendingNavigationLoadId = ++incrementingLoadId;
1450 if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
1451 let updatedFetchers2 = markFetchRedirectsDone();
1452 completeNavigation(
1453 location,
1454 {
1455 matches,
1456 loaderData: {},
1457 // Commit pending error if we're short circuiting
1458 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null,
1459 ...getActionDataForCommit(pendingActionResult),
1460 ...updatedFetchers2 ? { fetchers: new Map(state.fetchers) } : {}
1461 },
1462 { flushSync: flushSync2 }
1463 );
1464 return { shortCircuited: true };
1465 }
1466 if (shouldUpdateNavigationState) {
1467 let updates = {};
1468 if (!isFogOfWar) {
1469 updates.navigation = loadingNavigation;
1470 let actionData = getUpdatedActionData(pendingActionResult);
1471 if (actionData !== void 0) {
1472 updates.actionData = actionData;
1473 }
1474 }
1475 if (revalidatingFetchers.length > 0) {
1476 updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers);
1477 }
1478 updateState(updates, { flushSync: flushSync2 });
1479 }
1480 revalidatingFetchers.forEach((rf) => {
1481 abortFetcher(rf.key);
1482 if (rf.controller) {
1483 fetchControllers.set(rf.key, rf.controller);
1484 }
1485 });
1486 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((f) => abortFetcher(f.key));
1487 if (pendingNavigationController) {
1488 pendingNavigationController.signal.addEventListener(
1489 "abort",
1490 abortPendingFetchRevalidations
1491 );
1492 }
1493 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1494 state,
1495 matches,
1496 matchesToLoad,
1497 revalidatingFetchers,
1498 request
1499 );
1500 if (request.signal.aborted) {
1501 return { shortCircuited: true };
1502 }
1503 if (pendingNavigationController) {
1504 pendingNavigationController.signal.removeEventListener(
1505 "abort",
1506 abortPendingFetchRevalidations
1507 );
1508 }
1509 revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));
1510 let redirect2 = findRedirect(loaderResults);
1511 if (redirect2) {
1512 await startRedirectNavigation(request, redirect2.result, true, {
1513 replace: replace2
1514 });
1515 return { shortCircuited: true };
1516 }
1517 redirect2 = findRedirect(fetcherResults);
1518 if (redirect2) {
1519 fetchRedirectIds.add(redirect2.key);
1520 await startRedirectNavigation(request, redirect2.result, true, {
1521 replace: replace2
1522 });
1523 return { shortCircuited: true };
1524 }
1525 let { loaderData, errors } = processLoaderData(
1526 state,
1527 matches,
1528 loaderResults,
1529 pendingActionResult,
1530 revalidatingFetchers,
1531 fetcherResults
1532 );
1533 if (initialHydration && state.errors) {
1534 errors = { ...state.errors, ...errors };
1535 }
1536 let updatedFetchers = markFetchRedirectsDone();
1537 let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
1538 let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
1539 return {
1540 matches,
1541 loaderData,
1542 errors,
1543 ...shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {}
1544 };
1545 }
1546 function getUpdatedActionData(pendingActionResult) {
1547 if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
1548 return {
1549 [pendingActionResult[0]]: pendingActionResult[1].data
1550 };
1551 } else if (state.actionData) {
1552 if (Object.keys(state.actionData).length === 0) {
1553 return null;
1554 } else {
1555 return state.actionData;
1556 }
1557 }
1558 }
1559 function getUpdatedRevalidatingFetchers(revalidatingFetchers) {
1560 revalidatingFetchers.forEach((rf) => {
1561 let fetcher = state.fetchers.get(rf.key);
1562 let revalidatingFetcher = getLoadingFetcher(
1563 void 0,
1564 fetcher ? fetcher.data : void 0
1565 );
1566 state.fetchers.set(rf.key, revalidatingFetcher);
1567 });
1568 return new Map(state.fetchers);
1569 }
1570 async function fetch2(key, routeId, href, opts) {
1571 abortFetcher(key);
1572 let flushSync2 = (opts && opts.flushSync) === true;
1573 let routesToUse = inFlightDataRoutes || dataRoutes;
1574 let normalizedPath = normalizeTo(
1575 state.location,
1576 state.matches,
1577 basename,
1578 href,
1579 routeId,
1580 opts?.relative
1581 );
1582 let matches = matchRoutes(routesToUse, normalizedPath, basename);
1583 let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath);
1584 if (fogOfWar.active && fogOfWar.matches) {
1585 matches = fogOfWar.matches;
1586 }
1587 if (!matches) {
1588 setFetcherError(
1589 key,
1590 routeId,
1591 getInternalRouterError(404, { pathname: normalizedPath }),
1592 { flushSync: flushSync2 }
1593 );
1594 return;
1595 }
1596 let { path, submission, error } = normalizeNavigateOptions(
1597 true,
1598 normalizedPath,
1599 opts
1600 );
1601 if (error) {
1602 setFetcherError(key, routeId, error, { flushSync: flushSync2 });
1603 return;
1604 }
1605 let match = getTargetMatch(matches, path);
1606 let preventScrollReset = (opts && opts.preventScrollReset) === true;
1607 if (submission && isMutationMethod(submission.formMethod)) {
1608 await handleFetcherAction(
1609 key,
1610 routeId,
1611 path,
1612 match,
1613 matches,
1614 fogOfWar.active,
1615 flushSync2,
1616 preventScrollReset,
1617 submission
1618 );
1619 return;
1620 }
1621 fetchLoadMatches.set(key, { routeId, path });
1622 await handleFetcherLoader(
1623 key,
1624 routeId,
1625 path,
1626 match,
1627 matches,
1628 fogOfWar.active,
1629 flushSync2,
1630 preventScrollReset,
1631 submission
1632 );
1633 }
1634 async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync2, preventScrollReset, submission) {
1635 interruptActiveLoads();
1636 fetchLoadMatches.delete(key);
1637 function detectAndHandle405Error(m) {
1638 if (!m.route.action && !m.route.lazy) {
1639 let error = getInternalRouterError(405, {
1640 method: submission.formMethod,
1641 pathname: path,
1642 routeId
1643 });
1644 setFetcherError(key, routeId, error, { flushSync: flushSync2 });
1645 return true;
1646 }
1647 return false;
1648 }
1649 if (!isFogOfWar && detectAndHandle405Error(match)) {
1650 return;
1651 }
1652 let existingFetcher = state.fetchers.get(key);
1653 updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
1654 flushSync: flushSync2
1655 });
1656 let abortController = new AbortController();
1657 let fetchRequest = createClientSideRequest(
1658 init.history,
1659 path,
1660 abortController.signal,
1661 submission
1662 );
1663 if (isFogOfWar) {
1664 let discoverResult = await discoverRoutes(
1665 requestMatches,
1666 path,
1667 fetchRequest.signal
1668 );
1669 if (discoverResult.type === "aborted") {
1670 return;
1671 } else if (discoverResult.type === "error") {
1672 setFetcherError(key, routeId, discoverResult.error, { flushSync: flushSync2 });
1673 return;
1674 } else if (!discoverResult.matches) {
1675 setFetcherError(
1676 key,
1677 routeId,
1678 getInternalRouterError(404, { pathname: path }),
1679 { flushSync: flushSync2 }
1680 );
1681 return;
1682 } else {
1683 requestMatches = discoverResult.matches;
1684 match = getTargetMatch(requestMatches, path);
1685 if (detectAndHandle405Error(match)) {
1686 return;
1687 }
1688 }
1689 }
1690 fetchControllers.set(key, abortController);
1691 let originatingLoadId = incrementingLoadId;
1692 let actionResults = await callDataStrategy(
1693 "action",
1694 state,
1695 fetchRequest,
1696 [match],
1697 requestMatches,
1698 key
1699 );
1700 let actionResult = actionResults[match.route.id];
1701 if (fetchRequest.signal.aborted) {
1702 if (fetchControllers.get(key) === abortController) {
1703 fetchControllers.delete(key);
1704 }
1705 return;
1706 }
1707 if (fetchersQueuedForDeletion.has(key)) {
1708 if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {
1709 updateFetcherState(key, getDoneFetcher(void 0));
1710 return;
1711 }
1712 } else {
1713 if (isRedirectResult(actionResult)) {
1714 fetchControllers.delete(key);
1715 if (pendingNavigationLoadId > originatingLoadId) {
1716 updateFetcherState(key, getDoneFetcher(void 0));
1717 return;
1718 } else {
1719 fetchRedirectIds.add(key);
1720 updateFetcherState(key, getLoadingFetcher(submission));
1721 return startRedirectNavigation(fetchRequest, actionResult, false, {
1722 fetcherSubmission: submission,
1723 preventScrollReset
1724 });
1725 }
1726 }
1727 if (isErrorResult(actionResult)) {
1728 setFetcherError(key, routeId, actionResult.error);
1729 return;
1730 }
1731 }
1732 let nextLocation = state.navigation.location || state.location;
1733 let revalidationRequest = createClientSideRequest(
1734 init.history,
1735 nextLocation,
1736 abortController.signal
1737 );
1738 let routesToUse = inFlightDataRoutes || dataRoutes;
1739 let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;
1740 invariant(matches, "Didn't find any matches after fetcher action");
1741 let loadId = ++incrementingLoadId;
1742 fetchReloadIds.set(key, loadId);
1743 let loadFetcher = getLoadingFetcher(submission, actionResult.data);
1744 state.fetchers.set(key, loadFetcher);
1745 let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
1746 init.history,
1747 state,
1748 matches,
1749 submission,
1750 nextLocation,
1751 false,
1752 isRevalidationRequired,
1753 cancelledFetcherLoads,
1754 fetchersQueuedForDeletion,
1755 fetchLoadMatches,
1756 fetchRedirectIds,
1757 routesToUse,
1758 basename,
1759 [match.route.id, actionResult]
1760 );
1761 revalidatingFetchers.filter((rf) => rf.key !== key).forEach((rf) => {
1762 let staleKey = rf.key;
1763 let existingFetcher2 = state.fetchers.get(staleKey);
1764 let revalidatingFetcher = getLoadingFetcher(
1765 void 0,
1766 existingFetcher2 ? existingFetcher2.data : void 0
1767 );
1768 state.fetchers.set(staleKey, revalidatingFetcher);
1769 abortFetcher(staleKey);
1770 if (rf.controller) {
1771 fetchControllers.set(staleKey, rf.controller);
1772 }
1773 });
1774 updateState({ fetchers: new Map(state.fetchers) });
1775 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((rf) => abortFetcher(rf.key));
1776 abortController.signal.addEventListener(
1777 "abort",
1778 abortPendingFetchRevalidations
1779 );
1780 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1781 state,
1782 matches,
1783 matchesToLoad,
1784 revalidatingFetchers,
1785 revalidationRequest
1786 );
1787 if (abortController.signal.aborted) {
1788 return;
1789 }
1790 abortController.signal.removeEventListener(
1791 "abort",
1792 abortPendingFetchRevalidations
1793 );
1794 fetchReloadIds.delete(key);
1795 fetchControllers.delete(key);
1796 revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));
1797 let redirect2 = findRedirect(loaderResults);
1798 if (redirect2) {
1799 return startRedirectNavigation(
1800 revalidationRequest,
1801 redirect2.result,
1802 false,
1803 { preventScrollReset }
1804 );
1805 }
1806 redirect2 = findRedirect(fetcherResults);
1807 if (redirect2) {
1808 fetchRedirectIds.add(redirect2.key);
1809 return startRedirectNavigation(
1810 revalidationRequest,
1811 redirect2.result,
1812 false,
1813 { preventScrollReset }
1814 );
1815 }
1816 let { loaderData, errors } = processLoaderData(
1817 state,
1818 matches,
1819 loaderResults,
1820 void 0,
1821 revalidatingFetchers,
1822 fetcherResults
1823 );
1824 if (state.fetchers.has(key)) {
1825 let doneFetcher = getDoneFetcher(actionResult.data);
1826 state.fetchers.set(key, doneFetcher);
1827 }
1828 abortStaleFetchLoads(loadId);
1829 if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
1830 invariant(pendingAction, "Expected pending action");
1831 pendingNavigationController && pendingNavigationController.abort();
1832 completeNavigation(state.navigation.location, {
1833 matches,
1834 loaderData,
1835 errors,
1836 fetchers: new Map(state.fetchers)
1837 });
1838 } else {
1839 updateState({
1840 errors,
1841 loaderData: mergeLoaderData(
1842 state.loaderData,
1843 loaderData,
1844 matches,
1845 errors
1846 ),
1847 fetchers: new Map(state.fetchers)
1848 });
1849 isRevalidationRequired = false;
1850 }
1851 }
1852 async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync2, preventScrollReset, submission) {
1853 let existingFetcher = state.fetchers.get(key);
1854 updateFetcherState(
1855 key,
1856 getLoadingFetcher(
1857 submission,
1858 existingFetcher ? existingFetcher.data : void 0
1859 ),
1860 { flushSync: flushSync2 }
1861 );
1862 let abortController = new AbortController();
1863 let fetchRequest = createClientSideRequest(
1864 init.history,
1865 path,
1866 abortController.signal
1867 );
1868 if (isFogOfWar) {
1869 let discoverResult = await discoverRoutes(
1870 matches,
1871 path,
1872 fetchRequest.signal
1873 );
1874 if (discoverResult.type === "aborted") {
1875 return;
1876 } else if (discoverResult.type === "error") {
1877 setFetcherError(key, routeId, discoverResult.error, { flushSync: flushSync2 });
1878 return;
1879 } else if (!discoverResult.matches) {
1880 setFetcherError(
1881 key,
1882 routeId,
1883 getInternalRouterError(404, { pathname: path }),
1884 { flushSync: flushSync2 }
1885 );
1886 return;
1887 } else {
1888 matches = discoverResult.matches;
1889 match = getTargetMatch(matches, path);
1890 }
1891 }
1892 fetchControllers.set(key, abortController);
1893 let originatingLoadId = incrementingLoadId;
1894 let results = await callDataStrategy(
1895 "loader",
1896 state,
1897 fetchRequest,
1898 [match],
1899 matches,
1900 key
1901 );
1902 let result = results[match.route.id];
1903 if (fetchControllers.get(key) === abortController) {
1904 fetchControllers.delete(key);
1905 }
1906 if (fetchRequest.signal.aborted) {
1907 return;
1908 }
1909 if (fetchersQueuedForDeletion.has(key)) {
1910 updateFetcherState(key, getDoneFetcher(void 0));
1911 return;
1912 }
1913 if (isRedirectResult(result)) {
1914 if (pendingNavigationLoadId > originatingLoadId) {
1915 updateFetcherState(key, getDoneFetcher(void 0));
1916 return;
1917 } else {
1918 fetchRedirectIds.add(key);
1919 await startRedirectNavigation(fetchRequest, result, false, {
1920 preventScrollReset
1921 });
1922 return;
1923 }
1924 }
1925 if (isErrorResult(result)) {
1926 setFetcherError(key, routeId, result.error);
1927 return;
1928 }
1929 updateFetcherState(key, getDoneFetcher(result.data));
1930 }
1931 async function startRedirectNavigation(request, redirect2, isNavigation, {
1932 submission,
1933 fetcherSubmission,
1934 preventScrollReset,
1935 replace: replace2
1936 } = {}) {
1937 if (redirect2.response.headers.has("X-Remix-Revalidate")) {
1938 isRevalidationRequired = true;
1939 }
1940 let location = redirect2.response.headers.get("Location");
1941 invariant(location, "Expected a Location header on the redirect Response");
1942 location = normalizeRedirectLocation(
1943 location,
1944 new URL(request.url),
1945 basename
1946 );
1947 let redirectLocation = createLocation(state.location, location, {
1948 _isRedirect: true
1949 });
1950 if (isBrowser) {
1951 let isDocumentReload = false;
1952 if (redirect2.response.headers.has("X-Remix-Reload-Document")) {
1953 isDocumentReload = true;
1954 } else if (ABSOLUTE_URL_REGEX.test(location)) {
1955 const url = init.history.createURL(location);
1956 isDocumentReload = // Hard reload if it's an absolute URL to a new origin
1957 url.origin !== routerWindow.location.origin || // Hard reload if it's an absolute URL that does not match our basename
1958 stripBasename(url.pathname, basename) == null;
1959 }
1960 if (isDocumentReload) {
1961 if (replace2) {
1962 routerWindow.location.replace(location);
1963 } else {
1964 routerWindow.location.assign(location);
1965 }
1966 return;
1967 }
1968 }
1969 pendingNavigationController = null;
1970 let redirectNavigationType = replace2 === true || redirect2.response.headers.has("X-Remix-Replace") ? "REPLACE" /* Replace */ : "PUSH" /* Push */;
1971 let { formMethod, formAction, formEncType } = state.navigation;
1972 if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) {
1973 submission = getSubmissionFromNavigation(state.navigation);
1974 }
1975 let activeSubmission = submission || fetcherSubmission;
1976 if (redirectPreserveMethodStatusCodes.has(redirect2.response.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) {
1977 await startNavigation(redirectNavigationType, redirectLocation, {
1978 submission: {
1979 ...activeSubmission,
1980 formAction: location
1981 },
1982 // Preserve these flags across redirects
1983 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
1984 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
1985 });
1986 } else {
1987 let overrideNavigation = getLoadingNavigation(
1988 redirectLocation,
1989 submission
1990 );
1991 await startNavigation(redirectNavigationType, redirectLocation, {
1992 overrideNavigation,
1993 // Send fetcher submissions through for shouldRevalidate
1994 fetcherSubmission,
1995 // Preserve these flags across redirects
1996 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
1997 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
1998 });
1999 }
2000 }
2001 async function callDataStrategy(type, state2, request, matchesToLoad, matches, fetcherKey) {
2002 let results;
2003 let dataResults = {};
2004 try {
2005 results = await callDataStrategyImpl(
2006 dataStrategyImpl,
2007 type,
2008 state2,
2009 request,
2010 matchesToLoad,
2011 matches,
2012 fetcherKey,
2013 manifest,
2014 mapRouteProperties2
2015 );
2016 } catch (e) {
2017 matchesToLoad.forEach((m) => {
2018 dataResults[m.route.id] = {
2019 type: "error" /* error */,
2020 error: e
2021 };
2022 });
2023 return dataResults;
2024 }
2025 for (let [routeId, result] of Object.entries(results)) {
2026 if (isRedirectDataStrategyResult(result)) {
2027 let response = result.result;
2028 dataResults[routeId] = {
2029 type: "redirect" /* redirect */,
2030 response: normalizeRelativeRoutingRedirectResponse(
2031 response,
2032 request,
2033 routeId,
2034 matches,
2035 basename
2036 )
2037 };
2038 } else {
2039 dataResults[routeId] = await convertDataStrategyResultToDataResult(
2040 result
2041 );
2042 }
2043 }
2044 return dataResults;
2045 }
2046 async function callLoadersAndMaybeResolveData(state2, matches, matchesToLoad, fetchersToLoad, request) {
2047 let loaderResultsPromise = callDataStrategy(
2048 "loader",
2049 state2,
2050 request,
2051 matchesToLoad,
2052 matches,
2053 null
2054 );
2055 let fetcherResultsPromise = Promise.all(
2056 fetchersToLoad.map(async (f) => {
2057 if (f.matches && f.match && f.controller) {
2058 let results = await callDataStrategy(
2059 "loader",
2060 state2,
2061 createClientSideRequest(init.history, f.path, f.controller.signal),
2062 [f.match],
2063 f.matches,
2064 f.key
2065 );
2066 let result = results[f.match.route.id];
2067 return { [f.key]: result };
2068 } else {
2069 return Promise.resolve({
2070 [f.key]: {
2071 type: "error" /* error */,
2072 error: getInternalRouterError(404, {
2073 pathname: f.path
2074 })
2075 }
2076 });
2077 }
2078 })
2079 );
2080 let loaderResults = await loaderResultsPromise;
2081 let fetcherResults = (await fetcherResultsPromise).reduce(
2082 (acc, r) => Object.assign(acc, r),
2083 {}
2084 );
2085 return {
2086 loaderResults,
2087 fetcherResults
2088 };
2089 }
2090 function interruptActiveLoads() {
2091 isRevalidationRequired = true;
2092 fetchLoadMatches.forEach((_, key) => {
2093 if (fetchControllers.has(key)) {
2094 cancelledFetcherLoads.add(key);
2095 }
2096 abortFetcher(key);
2097 });
2098 }
2099 function updateFetcherState(key, fetcher, opts = {}) {
2100 state.fetchers.set(key, fetcher);
2101 updateState(
2102 { fetchers: new Map(state.fetchers) },
2103 { flushSync: (opts && opts.flushSync) === true }
2104 );
2105 }
2106 function setFetcherError(key, routeId, error, opts = {}) {
2107 let boundaryMatch = findNearestBoundary(state.matches, routeId);
2108 deleteFetcher(key);
2109 updateState(
2110 {
2111 errors: {
2112 [boundaryMatch.route.id]: error
2113 },
2114 fetchers: new Map(state.fetchers)
2115 },
2116 { flushSync: (opts && opts.flushSync) === true }
2117 );
2118 }
2119 function getFetcher(key) {
2120 activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2121 if (fetchersQueuedForDeletion.has(key)) {
2122 fetchersQueuedForDeletion.delete(key);
2123 }
2124 return state.fetchers.get(key) || IDLE_FETCHER;
2125 }
2126 function deleteFetcher(key) {
2127 let fetcher = state.fetchers.get(key);
2128 if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
2129 abortFetcher(key);
2130 }
2131 fetchLoadMatches.delete(key);
2132 fetchReloadIds.delete(key);
2133 fetchRedirectIds.delete(key);
2134 fetchersQueuedForDeletion.delete(key);
2135 cancelledFetcherLoads.delete(key);
2136 state.fetchers.delete(key);
2137 }
2138 function queueFetcherForDeletion(key) {
2139 let count = (activeFetchers.get(key) || 0) - 1;
2140 if (count <= 0) {
2141 activeFetchers.delete(key);
2142 fetchersQueuedForDeletion.add(key);
2143 } else {
2144 activeFetchers.set(key, count);
2145 }
2146 updateState({ fetchers: new Map(state.fetchers) });
2147 }
2148 function abortFetcher(key) {
2149 let controller = fetchControllers.get(key);
2150 if (controller) {
2151 controller.abort();
2152 fetchControllers.delete(key);
2153 }
2154 }
2155 function markFetchersDone(keys) {
2156 for (let key of keys) {
2157 let fetcher = getFetcher(key);
2158 let doneFetcher = getDoneFetcher(fetcher.data);
2159 state.fetchers.set(key, doneFetcher);
2160 }
2161 }
2162 function markFetchRedirectsDone() {
2163 let doneKeys = [];
2164 let updatedFetchers = false;
2165 for (let key of fetchRedirectIds) {
2166 let fetcher = state.fetchers.get(key);
2167 invariant(fetcher, `Expected fetcher: ${key}`);
2168 if (fetcher.state === "loading") {
2169 fetchRedirectIds.delete(key);
2170 doneKeys.push(key);
2171 updatedFetchers = true;
2172 }
2173 }
2174 markFetchersDone(doneKeys);
2175 return updatedFetchers;
2176 }
2177 function abortStaleFetchLoads(landedId) {
2178 let yeetedKeys = [];
2179 for (let [key, id] of fetchReloadIds) {
2180 if (id < landedId) {
2181 let fetcher = state.fetchers.get(key);
2182 invariant(fetcher, `Expected fetcher: ${key}`);
2183 if (fetcher.state === "loading") {
2184 abortFetcher(key);
2185 fetchReloadIds.delete(key);
2186 yeetedKeys.push(key);
2187 }
2188 }
2189 }
2190 markFetchersDone(yeetedKeys);
2191 return yeetedKeys.length > 0;
2192 }
2193 function getBlocker(key, fn) {
2194 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2195 if (blockerFunctions.get(key) !== fn) {
2196 blockerFunctions.set(key, fn);
2197 }
2198 return blocker;
2199 }
2200 function deleteBlocker(key) {
2201 state.blockers.delete(key);
2202 blockerFunctions.delete(key);
2203 }
2204 function updateBlocker(key, newBlocker) {
2205 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2206 invariant(
2207 blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked",
2208 `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`
2209 );
2210 let blockers = new Map(state.blockers);
2211 blockers.set(key, newBlocker);
2212 updateState({ blockers });
2213 }
2214 function shouldBlockNavigation({
2215 currentLocation,
2216 nextLocation,
2217 historyAction
2218 }) {
2219 if (blockerFunctions.size === 0) {
2220 return;
2221 }
2222 if (blockerFunctions.size > 1) {
2223 warning(false, "A router only supports one blocker at a time");
2224 }
2225 let entries = Array.from(blockerFunctions.entries());
2226 let [blockerKey, blockerFunction] = entries[entries.length - 1];
2227 let blocker = state.blockers.get(blockerKey);
2228 if (blocker && blocker.state === "proceeding") {
2229 return;
2230 }
2231 if (blockerFunction({ currentLocation, nextLocation, historyAction })) {
2232 return blockerKey;
2233 }
2234 }
2235 function handleNavigational404(pathname) {
2236 let error = getInternalRouterError(404, { pathname });
2237 let routesToUse = inFlightDataRoutes || dataRoutes;
2238 let { matches, route } = getShortCircuitMatches(routesToUse);
2239 return { notFoundMatches: matches, route, error };
2240 }
2241 function enableScrollRestoration(positions, getPosition, getKey) {
2242 savedScrollPositions = positions;
2243 getScrollPosition = getPosition;
2244 getScrollRestorationKey = getKey || null;
2245 if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
2246 initialScrollRestored = true;
2247 let y = getSavedScrollPosition(state.location, state.matches);
2248 if (y != null) {
2249 updateState({ restoreScrollPosition: y });
2250 }
2251 }
2252 return () => {
2253 savedScrollPositions = null;
2254 getScrollPosition = null;
2255 getScrollRestorationKey = null;
2256 };
2257 }
2258 function getScrollKey(location, matches) {
2259 if (getScrollRestorationKey) {
2260 let key = getScrollRestorationKey(
2261 location,
2262 matches.map((m) => convertRouteMatchToUiMatch(m, state.loaderData))
2263 );
2264 return key || location.key;
2265 }
2266 return location.key;
2267 }
2268 function saveScrollPosition(location, matches) {
2269 if (savedScrollPositions && getScrollPosition) {
2270 let key = getScrollKey(location, matches);
2271 savedScrollPositions[key] = getScrollPosition();
2272 }
2273 }
2274 function getSavedScrollPosition(location, matches) {
2275 if (savedScrollPositions) {
2276 let key = getScrollKey(location, matches);
2277 let y = savedScrollPositions[key];
2278 if (typeof y === "number") {
2279 return y;
2280 }
2281 }
2282 return null;
2283 }
2284 function checkFogOfWar(matches, routesToUse, pathname) {
2285 if (patchRoutesOnNavigationImpl) {
2286 if (!matches) {
2287 let fogMatches = matchRoutesImpl(
2288 routesToUse,
2289 pathname,
2290 basename,
2291 true
2292 );
2293 return { active: true, matches: fogMatches || [] };
2294 } else {
2295 if (Object.keys(matches[0].params).length > 0) {
2296 let partialMatches = matchRoutesImpl(
2297 routesToUse,
2298 pathname,
2299 basename,
2300 true
2301 );
2302 return { active: true, matches: partialMatches };
2303 }
2304 }
2305 }
2306 return { active: false, matches: null };
2307 }
2308 async function discoverRoutes(matches, pathname, signal) {
2309 if (!patchRoutesOnNavigationImpl) {
2310 return { type: "success", matches };
2311 }
2312 let partialMatches = matches;
2313 while (true) {
2314 let isNonHMR = inFlightDataRoutes == null;
2315 let routesToUse = inFlightDataRoutes || dataRoutes;
2316 let localManifest = manifest;
2317 try {
2318 await patchRoutesOnNavigationImpl({
2319 path: pathname,
2320 matches: partialMatches,
2321 patch: (routeId, children) => {
2322 if (signal.aborted) return;
2323 patchRoutesImpl(
2324 routeId,
2325 children,
2326 routesToUse,
2327 localManifest,
2328 mapRouteProperties2
2329 );
2330 }
2331 });
2332 } catch (e) {
2333 return { type: "error", error: e, partialMatches };
2334 } finally {
2335 if (isNonHMR && !signal.aborted) {
2336 dataRoutes = [...dataRoutes];
2337 }
2338 }
2339 if (signal.aborted) {
2340 return { type: "aborted" };
2341 }
2342 let newMatches = matchRoutes(routesToUse, pathname, basename);
2343 if (newMatches) {
2344 return { type: "success", matches: newMatches };
2345 }
2346 let newPartialMatches = matchRoutesImpl(
2347 routesToUse,
2348 pathname,
2349 basename,
2350 true
2351 );
2352 if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every(
2353 (m, i) => m.route.id === newPartialMatches[i].route.id
2354 )) {
2355 return { type: "success", matches: null };
2356 }
2357 partialMatches = newPartialMatches;
2358 }
2359 }
2360 function _internalSetRoutes(newRoutes) {
2361 manifest = {};
2362 inFlightDataRoutes = convertRoutesToDataRoutes(
2363 newRoutes,
2364 mapRouteProperties2,
2365 void 0,
2366 manifest
2367 );
2368 }
2369 function patchRoutes(routeId, children) {
2370 let isNonHMR = inFlightDataRoutes == null;
2371 let routesToUse = inFlightDataRoutes || dataRoutes;
2372 patchRoutesImpl(
2373 routeId,
2374 children,
2375 routesToUse,
2376 manifest,
2377 mapRouteProperties2
2378 );
2379 if (isNonHMR) {
2380 dataRoutes = [...dataRoutes];
2381 updateState({});
2382 }
2383 }
2384 router2 = {
2385 get basename() {
2386 return basename;
2387 },
2388 get future() {
2389 return future;
2390 },
2391 get state() {
2392 return state;
2393 },
2394 get routes() {
2395 return dataRoutes;
2396 },
2397 get window() {
2398 return routerWindow;
2399 },
2400 initialize,
2401 subscribe,
2402 enableScrollRestoration,
2403 navigate,
2404 fetch: fetch2,
2405 revalidate,
2406 // Passthrough to history-aware createHref used by useHref so we get proper
2407 // hash-aware URLs in DOM paths
2408 createHref: (to) => init.history.createHref(to),
2409 encodeLocation: (to) => init.history.encodeLocation(to),
2410 getFetcher,
2411 deleteFetcher: queueFetcherForDeletion,
2412 dispose,
2413 getBlocker,
2414 deleteBlocker,
2415 patchRoutes,
2416 _internalFetchControllers: fetchControllers,
2417 // TODO: Remove setRoutes, it's temporary to avoid dealing with
2418 // updating the tree while validating the update algorithm.
2419 _internalSetRoutes
2420 };
2421 return router2;
2422}
2423function isSubmissionNavigation(opts) {
2424 return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== void 0);
2425}
2426function normalizeTo(location, matches, basename, to, fromRouteId, relative) {
2427 let contextualMatches;
2428 let activeRouteMatch;
2429 if (fromRouteId) {
2430 contextualMatches = [];
2431 for (let match of matches) {
2432 contextualMatches.push(match);
2433 if (match.route.id === fromRouteId) {
2434 activeRouteMatch = match;
2435 break;
2436 }
2437 }
2438 } else {
2439 contextualMatches = matches;
2440 activeRouteMatch = matches[matches.length - 1];
2441 }
2442 let path = resolveTo(
2443 to ? to : ".",
2444 getResolveToMatches(contextualMatches),
2445 stripBasename(location.pathname, basename) || location.pathname,
2446 relative === "path"
2447 );
2448 if (to == null) {
2449 path.search = location.search;
2450 path.hash = location.hash;
2451 }
2452 if ((to == null || to === "" || to === ".") && activeRouteMatch) {
2453 let nakedIndex = hasNakedIndexQuery(path.search);
2454 if (activeRouteMatch.route.index && !nakedIndex) {
2455 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
2456 } else if (!activeRouteMatch.route.index && nakedIndex) {
2457 let params = new URLSearchParams(path.search);
2458 let indexValues = params.getAll("index");
2459 params.delete("index");
2460 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
2461 let qs = params.toString();
2462 path.search = qs ? `?${qs}` : "";
2463 }
2464 }
2465 if (basename !== "/") {
2466 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
2467 }
2468 return createPath(path);
2469}
2470function normalizeNavigateOptions(isFetcher, path, opts) {
2471 if (!opts || !isSubmissionNavigation(opts)) {
2472 return { path };
2473 }
2474 if (opts.formMethod && !isValidMethod(opts.formMethod)) {
2475 return {
2476 path,
2477 error: getInternalRouterError(405, { method: opts.formMethod })
2478 };
2479 }
2480 let getInvalidBodyError = () => ({
2481 path,
2482 error: getInternalRouterError(400, { type: "invalid-body" })
2483 });
2484 let rawFormMethod = opts.formMethod || "get";
2485 let formMethod = rawFormMethod.toUpperCase();
2486 let formAction = stripHashFromPath(path);
2487 if (opts.body !== void 0) {
2488 if (opts.formEncType === "text/plain") {
2489 if (!isMutationMethod(formMethod)) {
2490 return getInvalidBodyError();
2491 }
2492 let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ? (
2493 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
2494 Array.from(opts.body.entries()).reduce(
2495 (acc, [name, value]) => `${acc}${name}=${value}
2496`,
2497 ""
2498 )
2499 ) : String(opts.body);
2500 return {
2501 path,
2502 submission: {
2503 formMethod,
2504 formAction,
2505 formEncType: opts.formEncType,
2506 formData: void 0,
2507 json: void 0,
2508 text
2509 }
2510 };
2511 } else if (opts.formEncType === "application/json") {
2512 if (!isMutationMethod(formMethod)) {
2513 return getInvalidBodyError();
2514 }
2515 try {
2516 let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body;
2517 return {
2518 path,
2519 submission: {
2520 formMethod,
2521 formAction,
2522 formEncType: opts.formEncType,
2523 formData: void 0,
2524 json,
2525 text: void 0
2526 }
2527 };
2528 } catch (e) {
2529 return getInvalidBodyError();
2530 }
2531 }
2532 }
2533 invariant(
2534 typeof FormData === "function",
2535 "FormData is not available in this environment"
2536 );
2537 let searchParams;
2538 let formData;
2539 if (opts.formData) {
2540 searchParams = convertFormDataToSearchParams(opts.formData);
2541 formData = opts.formData;
2542 } else if (opts.body instanceof FormData) {
2543 searchParams = convertFormDataToSearchParams(opts.body);
2544 formData = opts.body;
2545 } else if (opts.body instanceof URLSearchParams) {
2546 searchParams = opts.body;
2547 formData = convertSearchParamsToFormData(searchParams);
2548 } else if (opts.body == null) {
2549 searchParams = new URLSearchParams();
2550 formData = new FormData();
2551 } else {
2552 try {
2553 searchParams = new URLSearchParams(opts.body);
2554 formData = convertSearchParamsToFormData(searchParams);
2555 } catch (e) {
2556 return getInvalidBodyError();
2557 }
2558 }
2559 let submission = {
2560 formMethod,
2561 formAction,
2562 formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
2563 formData,
2564 json: void 0,
2565 text: void 0
2566 };
2567 if (isMutationMethod(submission.formMethod)) {
2568 return { path, submission };
2569 }
2570 let parsedPath = parsePath(path);
2571 if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
2572 searchParams.append("index", "");
2573 }
2574 parsedPath.search = `?${searchParams}`;
2575 return { path: createPath(parsedPath), submission };
2576}
2577function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary = false) {
2578 let index = matches.findIndex((m) => m.route.id === boundaryId);
2579 if (index >= 0) {
2580 return matches.slice(0, includeBoundary ? index + 1 : index);
2581 }
2582 return matches;
2583}
2584function getMatchesToLoad(history, state, matches, submission, location, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
2585 let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0;
2586 let currentUrl = history.createURL(state.location);
2587 let nextUrl = history.createURL(location);
2588 let boundaryMatches = matches;
2589 if (initialHydration && state.errors) {
2590 boundaryMatches = getLoaderMatchesUntilBoundary(
2591 matches,
2592 Object.keys(state.errors)[0],
2593 true
2594 );
2595 } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
2596 boundaryMatches = getLoaderMatchesUntilBoundary(
2597 matches,
2598 pendingActionResult[0]
2599 );
2600 }
2601 let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0;
2602 let shouldSkipRevalidation = actionStatus && actionStatus >= 400;
2603 let navigationMatches = boundaryMatches.filter((match, index) => {
2604 let { route } = match;
2605 if (route.lazy) {
2606 return true;
2607 }
2608 if (route.loader == null) {
2609 return false;
2610 }
2611 if (initialHydration) {
2612 return shouldLoadRouteOnHydration(route, state.loaderData, state.errors);
2613 }
2614 if (isNewLoader(state.loaderData, state.matches[index], match)) {
2615 return true;
2616 }
2617 let currentRouteMatch = state.matches[index];
2618 let nextRouteMatch = match;
2619 return shouldRevalidateLoader(match, {
2620 currentUrl,
2621 currentParams: currentRouteMatch.params,
2622 nextUrl,
2623 nextParams: nextRouteMatch.params,
2624 ...submission,
2625 actionResult,
2626 actionStatus,
2627 defaultShouldRevalidate: shouldSkipRevalidation ? false : (
2628 // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
2629 isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
2630 currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)
2631 )
2632 });
2633 });
2634 let revalidatingFetchers = [];
2635 fetchLoadMatches.forEach((f, key) => {
2636 if (initialHydration || !matches.some((m) => m.route.id === f.routeId) || fetchersQueuedForDeletion.has(key)) {
2637 return;
2638 }
2639 let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
2640 if (!fetcherMatches) {
2641 revalidatingFetchers.push({
2642 key,
2643 routeId: f.routeId,
2644 path: f.path,
2645 matches: null,
2646 match: null,
2647 controller: null
2648 });
2649 return;
2650 }
2651 let fetcher = state.fetchers.get(key);
2652 let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
2653 let shouldRevalidate = false;
2654 if (fetchRedirectIds.has(key)) {
2655 shouldRevalidate = false;
2656 } else if (cancelledFetcherLoads.has(key)) {
2657 cancelledFetcherLoads.delete(key);
2658 shouldRevalidate = true;
2659 } else if (fetcher && fetcher.state !== "idle" && fetcher.data === void 0) {
2660 shouldRevalidate = isRevalidationRequired;
2661 } else {
2662 shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {
2663 currentUrl,
2664 currentParams: state.matches[state.matches.length - 1].params,
2665 nextUrl,
2666 nextParams: matches[matches.length - 1].params,
2667 ...submission,
2668 actionResult,
2669 actionStatus,
2670 defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired
2671 });
2672 }
2673 if (shouldRevalidate) {
2674 revalidatingFetchers.push({
2675 key,
2676 routeId: f.routeId,
2677 path: f.path,
2678 matches: fetcherMatches,
2679 match: fetcherMatch,
2680 controller: new AbortController()
2681 });
2682 }
2683 });
2684 return [navigationMatches, revalidatingFetchers];
2685}
2686function shouldLoadRouteOnHydration(route, loaderData, errors) {
2687 if (route.lazy) {
2688 return true;
2689 }
2690 if (!route.loader) {
2691 return false;
2692 }
2693 let hasData = loaderData != null && loaderData[route.id] !== void 0;
2694 let hasError = errors != null && errors[route.id] !== void 0;
2695 if (!hasData && hasError) {
2696 return false;
2697 }
2698 if (typeof route.loader === "function" && route.loader.hydrate === true) {
2699 return true;
2700 }
2701 return !hasData && !hasError;
2702}
2703function isNewLoader(currentLoaderData, currentMatch, match) {
2704 let isNew = (
2705 // [a] -> [a, b]
2706 !currentMatch || // [a, b] -> [a, c]
2707 match.route.id !== currentMatch.route.id
2708 );
2709 let isMissingData = !currentLoaderData.hasOwnProperty(match.route.id);
2710 return isNew || isMissingData;
2711}
2712function isNewRouteInstance(currentMatch, match) {
2713 let currentPath = currentMatch.route.path;
2714 return (
2715 // param change for this match, /users/123 -> /users/456
2716 currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
2717 // e.g. /files/images/avatar.jpg -> files/finances.xls
2718 currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
2719 );
2720}
2721function shouldRevalidateLoader(loaderMatch, arg) {
2722 if (loaderMatch.route.shouldRevalidate) {
2723 let routeChoice = loaderMatch.route.shouldRevalidate(arg);
2724 if (typeof routeChoice === "boolean") {
2725 return routeChoice;
2726 }
2727 }
2728 return arg.defaultShouldRevalidate;
2729}
2730function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties2) {
2731 let childrenToPatch;
2732 if (routeId) {
2733 let route = manifest[routeId];
2734 invariant(
2735 route,
2736 `No route found to patch children into: routeId = ${routeId}`
2737 );
2738 if (!route.children) {
2739 route.children = [];
2740 }
2741 childrenToPatch = route.children;
2742 } else {
2743 childrenToPatch = routesToUse;
2744 }
2745 let uniqueChildren = children.filter(
2746 (newRoute) => !childrenToPatch.some(
2747 (existingRoute) => isSameRoute(newRoute, existingRoute)
2748 )
2749 );
2750 let newRoutes = convertRoutesToDataRoutes(
2751 uniqueChildren,
2752 mapRouteProperties2,
2753 [routeId || "_", "patch", String(childrenToPatch?.length || "0")],
2754 manifest
2755 );
2756 childrenToPatch.push(...newRoutes);
2757}
2758function isSameRoute(newRoute, existingRoute) {
2759 if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) {
2760 return true;
2761 }
2762 if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) {
2763 return false;
2764 }
2765 if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) {
2766 return true;
2767 }
2768 return newRoute.children.every(
2769 (aChild, i) => existingRoute.children?.some((bChild) => isSameRoute(aChild, bChild))
2770 );
2771}
2772async function loadLazyRouteModule(route, mapRouteProperties2, manifest) {
2773 if (!route.lazy) {
2774 return;
2775 }
2776 let lazyRoute = await route.lazy();
2777 if (!route.lazy) {
2778 return;
2779 }
2780 let routeToUpdate = manifest[route.id];
2781 invariant(routeToUpdate, "No route found in manifest");
2782 let routeUpdates = {};
2783 for (let lazyRouteProperty in lazyRoute) {
2784 let staticRouteValue = routeToUpdate[lazyRouteProperty];
2785 let isPropertyStaticallyDefined = staticRouteValue !== void 0 && // This property isn't static since it should always be updated based
2786 // on the route updates
2787 lazyRouteProperty !== "hasErrorBoundary";
2788 warning(
2789 !isPropertyStaticallyDefined,
2790 `Route "${routeToUpdate.id}" has a static property "${lazyRouteProperty}" defined but its lazy function is also returning a value for this property. The lazy route property "${lazyRouteProperty}" will be ignored.`
2791 );
2792 if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) {
2793 routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty];
2794 }
2795 }
2796 Object.assign(routeToUpdate, routeUpdates);
2797 Object.assign(routeToUpdate, {
2798 // To keep things framework agnostic, we use the provided `mapRouteProperties`
2799 // function to set the framework-aware properties (`element`/`hasErrorBoundary`)
2800 // since the logic will differ between frameworks.
2801 ...mapRouteProperties2(routeToUpdate),
2802 lazy: void 0
2803 });
2804}
2805async function defaultDataStrategy({
2806 matches
2807}) {
2808 let matchesToLoad = matches.filter((m) => m.shouldLoad);
2809 let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
2810 return results.reduce(
2811 (acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
2812 {}
2813 );
2814}
2815async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, requestContext) {
2816 let loadRouteDefinitionsPromises = matches.map(
2817 (m) => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties2, manifest) : void 0
2818 );
2819 let dsMatches = matches.map((match, i) => {
2820 let loadRoutePromise = loadRouteDefinitionsPromises[i];
2821 let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id);
2822 let resolve = async (handlerOverride) => {
2823 if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
2824 shouldLoad = true;
2825 }
2826 return shouldLoad ? callLoaderOrAction(
2827 type,
2828 request,
2829 match,
2830 loadRoutePromise,
2831 handlerOverride,
2832 requestContext
2833 ) : Promise.resolve({ type: "data" /* data */, result: void 0 });
2834 };
2835 return {
2836 ...match,
2837 shouldLoad,
2838 resolve
2839 };
2840 });
2841 let results = await dataStrategyImpl({
2842 matches: dsMatches,
2843 request,
2844 params: matches[0].params,
2845 fetcherKey,
2846 context: requestContext
2847 });
2848 try {
2849 await Promise.all(loadRouteDefinitionsPromises);
2850 } catch (e) {
2851 }
2852 return results;
2853}
2854async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, staticContext) {
2855 let result;
2856 let onReject;
2857 let runHandler = (handler) => {
2858 let reject;
2859 let abortPromise = new Promise((_, r) => reject = r);
2860 onReject = () => reject();
2861 request.signal.addEventListener("abort", onReject);
2862 let actualHandler = (ctx) => {
2863 if (typeof handler !== "function") {
2864 return Promise.reject(
2865 new Error(
2866 `You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]`
2867 )
2868 );
2869 }
2870 return handler(
2871 {
2872 request,
2873 params: match.params,
2874 context: staticContext
2875 },
2876 ...ctx !== void 0 ? [ctx] : []
2877 );
2878 };
2879 let handlerPromise = (async () => {
2880 try {
2881 let val = await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler());
2882 return { type: "data", result: val };
2883 } catch (e) {
2884 return { type: "error", result: e };
2885 }
2886 })();
2887 return Promise.race([handlerPromise, abortPromise]);
2888 };
2889 try {
2890 let handler = match.route[type];
2891 if (loadRoutePromise) {
2892 if (handler) {
2893 let handlerError;
2894 let [value] = await Promise.all([
2895 // If the handler throws, don't let it immediately bubble out,
2896 // since we need to let the lazy() execution finish so we know if this
2897 // route has a boundary that can handle the error
2898 runHandler(handler).catch((e) => {
2899 handlerError = e;
2900 }),
2901 loadRoutePromise
2902 ]);
2903 if (handlerError !== void 0) {
2904 throw handlerError;
2905 }
2906 result = value;
2907 } else {
2908 await loadRoutePromise;
2909 handler = match.route[type];
2910 if (handler) {
2911 result = await runHandler(handler);
2912 } else if (type === "action") {
2913 let url = new URL(request.url);
2914 let pathname = url.pathname + url.search;
2915 throw getInternalRouterError(405, {
2916 method: request.method,
2917 pathname,
2918 routeId: match.route.id
2919 });
2920 } else {
2921 return { type: "data" /* data */, result: void 0 };
2922 }
2923 }
2924 } else if (!handler) {
2925 let url = new URL(request.url);
2926 let pathname = url.pathname + url.search;
2927 throw getInternalRouterError(404, {
2928 pathname
2929 });
2930 } else {
2931 result = await runHandler(handler);
2932 }
2933 } catch (e) {
2934 return { type: "error" /* error */, result: e };
2935 } finally {
2936 if (onReject) {
2937 request.signal.removeEventListener("abort", onReject);
2938 }
2939 }
2940 return result;
2941}
2942async function convertDataStrategyResultToDataResult(dataStrategyResult) {
2943 let { result, type } = dataStrategyResult;
2944 if (isResponse(result)) {
2945 let data2;
2946 try {
2947 let contentType = result.headers.get("Content-Type");
2948 if (contentType && /\bapplication\/json\b/.test(contentType)) {
2949 if (result.body == null) {
2950 data2 = null;
2951 } else {
2952 data2 = await result.json();
2953 }
2954 } else {
2955 data2 = await result.text();
2956 }
2957 } catch (e) {
2958 return { type: "error" /* error */, error: e };
2959 }
2960 if (type === "error" /* error */) {
2961 return {
2962 type: "error" /* error */,
2963 error: new ErrorResponseImpl(result.status, result.statusText, data2),
2964 statusCode: result.status,
2965 headers: result.headers
2966 };
2967 }
2968 return {
2969 type: "data" /* data */,
2970 data: data2,
2971 statusCode: result.status,
2972 headers: result.headers
2973 };
2974 }
2975 if (type === "error" /* error */) {
2976 if (isDataWithResponseInit(result)) {
2977 if (result.data instanceof Error) {
2978 return {
2979 type: "error" /* error */,
2980 error: result.data,
2981 statusCode: result.init?.status,
2982 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
2983 };
2984 }
2985 return {
2986 type: "error" /* error */,
2987 error: new ErrorResponseImpl(
2988 result.init?.status || 500,
2989 void 0,
2990 result.data
2991 ),
2992 statusCode: isRouteErrorResponse(result) ? result.status : void 0,
2993 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
2994 };
2995 }
2996 return {
2997 type: "error" /* error */,
2998 error: result,
2999 statusCode: isRouteErrorResponse(result) ? result.status : void 0
3000 };
3001 }
3002 if (isDataWithResponseInit(result)) {
3003 return {
3004 type: "data" /* data */,
3005 data: result.data,
3006 statusCode: result.init?.status,
3007 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
3008 };
3009 }
3010 return { type: "data" /* data */, data: result };
3011}
3012function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) {
3013 let location = response.headers.get("Location");
3014 invariant(
3015 location,
3016 "Redirects returned/thrown from loaders/actions must have a Location header"
3017 );
3018 if (!ABSOLUTE_URL_REGEX.test(location)) {
3019 let trimmedMatches = matches.slice(
3020 0,
3021 matches.findIndex((m) => m.route.id === routeId) + 1
3022 );
3023 location = normalizeTo(
3024 new URL(request.url),
3025 trimmedMatches,
3026 basename,
3027 location
3028 );
3029 response.headers.set("Location", location);
3030 }
3031 return response;
3032}
3033function normalizeRedirectLocation(location, currentUrl, basename) {
3034 if (ABSOLUTE_URL_REGEX.test(location)) {
3035 let normalizedLocation = location;
3036 let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);
3037 let isSameBasename = stripBasename(url.pathname, basename) != null;
3038 if (url.origin === currentUrl.origin && isSameBasename) {
3039 return url.pathname + url.search + url.hash;
3040 }
3041 }
3042 return location;
3043}
3044function createClientSideRequest(history, location, signal, submission) {
3045 let url = history.createURL(stripHashFromPath(location)).toString();
3046 let init = { signal };
3047 if (submission && isMutationMethod(submission.formMethod)) {
3048 let { formMethod, formEncType } = submission;
3049 init.method = formMethod.toUpperCase();
3050 if (formEncType === "application/json") {
3051 init.headers = new Headers({ "Content-Type": formEncType });
3052 init.body = JSON.stringify(submission.json);
3053 } else if (formEncType === "text/plain") {
3054 init.body = submission.text;
3055 } else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) {
3056 init.body = convertFormDataToSearchParams(submission.formData);
3057 } else {
3058 init.body = submission.formData;
3059 }
3060 }
3061 return new Request(url, init);
3062}
3063function convertFormDataToSearchParams(formData) {
3064 let searchParams = new URLSearchParams();
3065 for (let [key, value] of formData.entries()) {
3066 searchParams.append(key, typeof value === "string" ? value : value.name);
3067 }
3068 return searchParams;
3069}
3070function convertSearchParamsToFormData(searchParams) {
3071 let formData = new FormData();
3072 for (let [key, value] of searchParams.entries()) {
3073 formData.append(key, value);
3074 }
3075 return formData;
3076}
3077function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) {
3078 let loaderData = {};
3079 let errors = null;
3080 let statusCode;
3081 let foundError = false;
3082 let loaderHeaders = {};
3083 let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0;
3084 matches.forEach((match) => {
3085 if (!(match.route.id in results)) {
3086 return;
3087 }
3088 let id = match.route.id;
3089 let result = results[id];
3090 invariant(
3091 !isRedirectResult(result),
3092 "Cannot handle redirect results in processLoaderData"
3093 );
3094 if (isErrorResult(result)) {
3095 let error = result.error;
3096 if (pendingError !== void 0) {
3097 error = pendingError;
3098 pendingError = void 0;
3099 }
3100 errors = errors || {};
3101 if (skipLoaderErrorBubbling) {
3102 errors[id] = error;
3103 } else {
3104 let boundaryMatch = findNearestBoundary(matches, id);
3105 if (errors[boundaryMatch.route.id] == null) {
3106 errors[boundaryMatch.route.id] = error;
3107 }
3108 }
3109 if (!isStaticHandler) {
3110 loaderData[id] = ResetLoaderDataSymbol;
3111 }
3112 if (!foundError) {
3113 foundError = true;
3114 statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
3115 }
3116 if (result.headers) {
3117 loaderHeaders[id] = result.headers;
3118 }
3119 } else {
3120 loaderData[id] = result.data;
3121 if (result.statusCode && result.statusCode !== 200 && !foundError) {
3122 statusCode = result.statusCode;
3123 }
3124 if (result.headers) {
3125 loaderHeaders[id] = result.headers;
3126 }
3127 }
3128 });
3129 if (pendingError !== void 0 && pendingActionResult) {
3130 errors = { [pendingActionResult[0]]: pendingError };
3131 loaderData[pendingActionResult[0]] = void 0;
3132 }
3133 return {
3134 loaderData,
3135 errors,
3136 statusCode: statusCode || 200,
3137 loaderHeaders
3138 };
3139}
3140function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) {
3141 let { loaderData, errors } = processRouteLoaderData(
3142 matches,
3143 results,
3144 pendingActionResult
3145 );
3146 revalidatingFetchers.forEach((rf) => {
3147 let { key, match, controller } = rf;
3148 let result = fetcherResults[key];
3149 invariant(result, "Did not find corresponding fetcher result");
3150 if (controller && controller.signal.aborted) {
3151 return;
3152 } else if (isErrorResult(result)) {
3153 let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);
3154 if (!(errors && errors[boundaryMatch.route.id])) {
3155 errors = {
3156 ...errors,
3157 [boundaryMatch.route.id]: result.error
3158 };
3159 }
3160 state.fetchers.delete(key);
3161 } else if (isRedirectResult(result)) {
3162 invariant(false, "Unhandled fetcher revalidation redirect");
3163 } else {
3164 let doneFetcher = getDoneFetcher(result.data);
3165 state.fetchers.set(key, doneFetcher);
3166 }
3167 });
3168 return { loaderData, errors };
3169}
3170function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
3171 let mergedLoaderData = Object.entries(newLoaderData).filter(([, v]) => v !== ResetLoaderDataSymbol).reduce((merged, [k, v]) => {
3172 merged[k] = v;
3173 return merged;
3174 }, {});
3175 for (let match of matches) {
3176 let id = match.route.id;
3177 if (!newLoaderData.hasOwnProperty(id) && loaderData.hasOwnProperty(id) && match.route.loader) {
3178 mergedLoaderData[id] = loaderData[id];
3179 }
3180 if (errors && errors.hasOwnProperty(id)) {
3181 break;
3182 }
3183 }
3184 return mergedLoaderData;
3185}
3186function getActionDataForCommit(pendingActionResult) {
3187 if (!pendingActionResult) {
3188 return {};
3189 }
3190 return isErrorResult(pendingActionResult[1]) ? {
3191 // Clear out prior actionData on errors
3192 actionData: {}
3193 } : {
3194 actionData: {
3195 [pendingActionResult[0]]: pendingActionResult[1].data
3196 }
3197 };
3198}
3199function findNearestBoundary(matches, routeId) {
3200 let eligibleMatches = routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches];
3201 return eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0];
3202}
3203function getShortCircuitMatches(routes) {
3204 let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || {
3205 id: `__shim-error-route__`
3206 };
3207 return {
3208 matches: [
3209 {
3210 params: {},
3211 pathname: "",
3212 pathnameBase: "",
3213 route
3214 }
3215 ],
3216 route
3217 };
3218}
3219function getInternalRouterError(status, {
3220 pathname,
3221 routeId,
3222 method,
3223 type,
3224 message
3225} = {}) {
3226 let statusText = "Unknown Server Error";
3227 let errorMessage = "Unknown @remix-run/router error";
3228 if (status === 400) {
3229 statusText = "Bad Request";
3230 if (method && pathname && routeId) {
3231 errorMessage = `You made a ${method} request to "${pathname}" but did not provide a \`loader\` for route "${routeId}", so there is no way to handle the request.`;
3232 } else if (type === "invalid-body") {
3233 errorMessage = "Unable to encode submission body";
3234 }
3235 } else if (status === 403) {
3236 statusText = "Forbidden";
3237 errorMessage = `Route "${routeId}" does not match URL "${pathname}"`;
3238 } else if (status === 404) {
3239 statusText = "Not Found";
3240 errorMessage = `No route matches URL "${pathname}"`;
3241 } else if (status === 405) {
3242 statusText = "Method Not Allowed";
3243 if (method && pathname && routeId) {
3244 errorMessage = `You made a ${method.toUpperCase()} request to "${pathname}" but did not provide an \`action\` for route "${routeId}", so there is no way to handle the request.`;
3245 } else if (method) {
3246 errorMessage = `Invalid request method "${method.toUpperCase()}"`;
3247 }
3248 }
3249 return new ErrorResponseImpl(
3250 status || 500,
3251 statusText,
3252 new Error(errorMessage),
3253 true
3254 );
3255}
3256function findRedirect(results) {
3257 let entries = Object.entries(results);
3258 for (let i = entries.length - 1; i >= 0; i--) {
3259 let [key, result] = entries[i];
3260 if (isRedirectResult(result)) {
3261 return { key, result };
3262 }
3263 }
3264}
3265function stripHashFromPath(path) {
3266 let parsedPath = typeof path === "string" ? parsePath(path) : path;
3267 return createPath({ ...parsedPath, hash: "" });
3268}
3269function isHashChangeOnly(a, b) {
3270 if (a.pathname !== b.pathname || a.search !== b.search) {
3271 return false;
3272 }
3273 if (a.hash === "") {
3274 return b.hash !== "";
3275 } else if (a.hash === b.hash) {
3276 return true;
3277 } else if (b.hash !== "") {
3278 return true;
3279 }
3280 return false;
3281}
3282function isRedirectDataStrategyResult(result) {
3283 return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
3284}
3285function isErrorResult(result) {
3286 return result.type === "error" /* error */;
3287}
3288function isRedirectResult(result) {
3289 return (result && result.type) === "redirect" /* redirect */;
3290}
3291function isDataWithResponseInit(value) {
3292 return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit";
3293}
3294function isResponse(value) {
3295 return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
3296}
3297function isValidMethod(method) {
3298 return validRequestMethods.has(method.toUpperCase());
3299}
3300function isMutationMethod(method) {
3301 return validMutationMethods.has(method.toUpperCase());
3302}
3303function hasNakedIndexQuery(search) {
3304 return new URLSearchParams(search).getAll("index").some((v) => v === "");
3305}
3306function getTargetMatch(matches, location) {
3307 let search = typeof location === "string" ? parsePath(location).search : location.search;
3308 if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
3309 return matches[matches.length - 1];
3310 }
3311 let pathMatches = getPathContributingMatches(matches);
3312 return pathMatches[pathMatches.length - 1];
3313}
3314function getSubmissionFromNavigation(navigation) {
3315 let { formMethod, formAction, formEncType, text, formData, json } = navigation;
3316 if (!formMethod || !formAction || !formEncType) {
3317 return;
3318 }
3319 if (text != null) {
3320 return {
3321 formMethod,
3322 formAction,
3323 formEncType,
3324 formData: void 0,
3325 json: void 0,
3326 text
3327 };
3328 } else if (formData != null) {
3329 return {
3330 formMethod,
3331 formAction,
3332 formEncType,
3333 formData,
3334 json: void 0,
3335 text: void 0
3336 };
3337 } else if (json !== void 0) {
3338 return {
3339 formMethod,
3340 formAction,
3341 formEncType,
3342 formData: void 0,
3343 json,
3344 text: void 0
3345 };
3346 }
3347}
3348function getLoadingNavigation(location, submission) {
3349 if (submission) {
3350 let navigation = {
3351 state: "loading",
3352 location,
3353 formMethod: submission.formMethod,
3354 formAction: submission.formAction,
3355 formEncType: submission.formEncType,
3356 formData: submission.formData,
3357 json: submission.json,
3358 text: submission.text
3359 };
3360 return navigation;
3361 } else {
3362 let navigation = {
3363 state: "loading",
3364 location,
3365 formMethod: void 0,
3366 formAction: void 0,
3367 formEncType: void 0,
3368 formData: void 0,
3369 json: void 0,
3370 text: void 0
3371 };
3372 return navigation;
3373 }
3374}
3375function getSubmittingNavigation(location, submission) {
3376 let navigation = {
3377 state: "submitting",
3378 location,
3379 formMethod: submission.formMethod,
3380 formAction: submission.formAction,
3381 formEncType: submission.formEncType,
3382 formData: submission.formData,
3383 json: submission.json,
3384 text: submission.text
3385 };
3386 return navigation;
3387}
3388function getLoadingFetcher(submission, data2) {
3389 if (submission) {
3390 let fetcher = {
3391 state: "loading",
3392 formMethod: submission.formMethod,
3393 formAction: submission.formAction,
3394 formEncType: submission.formEncType,
3395 formData: submission.formData,
3396 json: submission.json,
3397 text: submission.text,
3398 data: data2
3399 };
3400 return fetcher;
3401 } else {
3402 let fetcher = {
3403 state: "loading",
3404 formMethod: void 0,
3405 formAction: void 0,
3406 formEncType: void 0,
3407 formData: void 0,
3408 json: void 0,
3409 text: void 0,
3410 data: data2
3411 };
3412 return fetcher;
3413 }
3414}
3415function getSubmittingFetcher(submission, existingFetcher) {
3416 let fetcher = {
3417 state: "submitting",
3418 formMethod: submission.formMethod,
3419 formAction: submission.formAction,
3420 formEncType: submission.formEncType,
3421 formData: submission.formData,
3422 json: submission.json,
3423 text: submission.text,
3424 data: existingFetcher ? existingFetcher.data : void 0
3425 };
3426 return fetcher;
3427}
3428function getDoneFetcher(data2) {
3429 let fetcher = {
3430 state: "idle",
3431 formMethod: void 0,
3432 formAction: void 0,
3433 formEncType: void 0,
3434 formData: void 0,
3435 json: void 0,
3436 text: void 0,
3437 data: data2
3438 };
3439 return fetcher;
3440}
3441function restoreAppliedTransitions(_window, transitions) {
3442 try {
3443 let sessionPositions = _window.sessionStorage.getItem(
3444 TRANSITIONS_STORAGE_KEY
3445 );
3446 if (sessionPositions) {
3447 let json = JSON.parse(sessionPositions);
3448 for (let [k, v] of Object.entries(json || {})) {
3449 if (v && Array.isArray(v)) {
3450 transitions.set(k, new Set(v || []));
3451 }
3452 }
3453 }
3454 } catch (e) {
3455 }
3456}
3457function persistAppliedTransitions(_window, transitions) {
3458 if (transitions.size > 0) {
3459 let json = {};
3460 for (let [k, v] of transitions) {
3461 json[k] = [...v];
3462 }
3463 try {
3464 _window.sessionStorage.setItem(
3465 TRANSITIONS_STORAGE_KEY,
3466 JSON.stringify(json)
3467 );
3468 } catch (error) {
3469 warning(
3470 false,
3471 `Failed to save applied view transitions in sessionStorage (${error}).`
3472 );
3473 }
3474 }
3475}
3476function createDeferred() {
3477 let resolve;
3478 let reject;
3479 let promise = new Promise((res, rej) => {
3480 resolve = async (val) => {
3481 res(val);
3482 try {
3483 await promise;
3484 } catch (e) {
3485 }
3486 };
3487 reject = async (error) => {
3488 rej(error);
3489 try {
3490 await promise;
3491 } catch (e) {
3492 }
3493 };
3494 });
3495 return {
3496 promise,
3497 //@ts-ignore
3498 resolve,
3499 //@ts-ignore
3500 reject
3501 };
3502}
3503
3504// lib/components.tsx
3505var React3 = __toESM(require("react"));
3506
3507// lib/context.ts
3508var React = __toESM(require("react"));
3509var DataRouterContext = React.createContext(null);
3510DataRouterContext.displayName = "DataRouter";
3511var DataRouterStateContext = React.createContext(null);
3512DataRouterStateContext.displayName = "DataRouterState";
3513var ViewTransitionContext = React.createContext({
3514 isTransitioning: false
3515});
3516ViewTransitionContext.displayName = "ViewTransition";
3517var FetchersContext = React.createContext(
3518 /* @__PURE__ */ new Map()
3519);
3520FetchersContext.displayName = "Fetchers";
3521var AwaitContext = React.createContext(null);
3522AwaitContext.displayName = "Await";
3523var NavigationContext = React.createContext(
3524 null
3525);
3526NavigationContext.displayName = "Navigation";
3527var LocationContext = React.createContext(
3528 null
3529);
3530LocationContext.displayName = "Location";
3531var RouteContext = React.createContext({
3532 outlet: null,
3533 matches: [],
3534 isDataRoute: false
3535});
3536RouteContext.displayName = "Route";
3537var RouteErrorContext = React.createContext(null);
3538RouteErrorContext.displayName = "RouteError";
3539
3540// lib/hooks.tsx
3541var React2 = __toESM(require("react"));
3542var ENABLE_DEV_WARNINGS = false;
3543function useInRouterContext() {
3544 return React2.useContext(LocationContext) != null;
3545}
3546function useLocation() {
3547 invariant(
3548 useInRouterContext(),
3549 // TODO: This error is probably because they somehow have 2 versions of the
3550 // router loaded. We can help them understand how to avoid that.
3551 `useLocation() may be used only in the context of a <Router> component.`
3552 );
3553 return React2.useContext(LocationContext).location;
3554}
3555var OutletContext = React2.createContext(null);
3556function useRoutesImpl(routes, locationArg, dataRouterState, future) {
3557 invariant(
3558 useInRouterContext(),
3559 // TODO: This error is probably because they somehow have 2 versions of the
3560 // router loaded. We can help them understand how to avoid that.
3561 `useRoutes() may be used only in the context of a <Router> component.`
3562 );
3563 let { navigator: navigator2, static: isStatic } = React2.useContext(NavigationContext);
3564 let { matches: parentMatches } = React2.useContext(RouteContext);
3565 let routeMatch = parentMatches[parentMatches.length - 1];
3566 let parentParams = routeMatch ? routeMatch.params : {};
3567 let parentPathname = routeMatch ? routeMatch.pathname : "/";
3568 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
3569 let parentRoute = routeMatch && routeMatch.route;
3570 if (ENABLE_DEV_WARNINGS) {
3571 let parentPath = parentRoute && parentRoute.path || "";
3572 warningOnce(
3573 parentPathname,
3574 !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"),
3575 `You rendered descendant <Routes> (or called \`useRoutes()\`) at "${parentPathname}" (under <Route path="${parentPath}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
3576
3577Please change the parent <Route path="${parentPath}"> to <Route path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`
3578 );
3579 }
3580 let locationFromContext = useLocation();
3581 let location;
3582 if (locationArg) {
3583 let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
3584 invariant(
3585 parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase),
3586 `When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${parentPathnameBase}" but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.`
3587 );
3588 location = parsedLocationArg;
3589 } else {
3590 location = locationFromContext;
3591 }
3592 let pathname = location.pathname || "/";
3593 let remainingPathname = pathname;
3594 if (parentPathnameBase !== "/") {
3595 let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
3596 let segments = pathname.replace(/^\//, "").split("/");
3597 remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
3598 }
3599 let matches = !isStatic && dataRouterState && dataRouterState.matches && dataRouterState.matches.length > 0 ? dataRouterState.matches : matchRoutes(routes, { pathname: remainingPathname });
3600 if (ENABLE_DEV_WARNINGS) {
3601 warning(
3602 parentRoute || matches != null,
3603 `No routes matched location "${location.pathname}${location.search}${location.hash}" `
3604 );
3605 warning(
3606 matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0,
3607 `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`
3608 );
3609 }
3610 let renderedMatches = _renderMatches(
3611 matches && matches.map(
3612 (match) => Object.assign({}, match, {
3613 params: Object.assign({}, parentParams, match.params),
3614 pathname: joinPaths([
3615 parentPathnameBase,
3616 // Re-encode pathnames that were decoded inside matchRoutes
3617 navigator2.encodeLocation ? navigator2.encodeLocation(match.pathname).pathname : match.pathname
3618 ]),
3619 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([
3620 parentPathnameBase,
3621 // Re-encode pathnames that were decoded inside matchRoutes
3622 navigator2.encodeLocation ? navigator2.encodeLocation(match.pathnameBase).pathname : match.pathnameBase
3623 ])
3624 })
3625 ),
3626 parentMatches,
3627 dataRouterState,
3628 future
3629 );
3630 if (locationArg && renderedMatches) {
3631 return /* @__PURE__ */ React2.createElement(
3632 LocationContext.Provider,
3633 {
3634 value: {
3635 location: {
3636 pathname: "/",
3637 search: "",
3638 hash: "",
3639 state: null,
3640 key: "default",
3641 ...location
3642 },
3643 navigationType: "POP" /* Pop */
3644 }
3645 },
3646 renderedMatches
3647 );
3648 }
3649 return renderedMatches;
3650}
3651function DefaultErrorComponent() {
3652 let error = useRouteError();
3653 let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
3654 let stack = error instanceof Error ? error.stack : null;
3655 let lightgrey = "rgba(200,200,200, 0.5)";
3656 let preStyles = { padding: "0.5rem", backgroundColor: lightgrey };
3657 let codeStyles = { padding: "2px 4px", backgroundColor: lightgrey };
3658 let devInfo = null;
3659 if (ENABLE_DEV_WARNINGS) {
3660 console.error(
3661 "Error handled by React Router default ErrorBoundary:",
3662 error
3663 );
3664 devInfo = /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("p", null, "\u{1F4BF} Hey developer \u{1F44B}"), /* @__PURE__ */ React2.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "ErrorBoundary"), " or", " ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "errorElement"), " prop on your route."));
3665 }
3666 return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", null, "Unexpected Application Error!"), /* @__PURE__ */ React2.createElement("h3", { style: { fontStyle: "italic" } }, message), stack ? /* @__PURE__ */ React2.createElement("pre", { style: preStyles }, stack) : null, devInfo);
3667}
3668var defaultErrorElement = /* @__PURE__ */ React2.createElement(DefaultErrorComponent, null);
3669var RenderErrorBoundary = class extends React2.Component {
3670 constructor(props) {
3671 super(props);
3672 this.state = {
3673 location: props.location,
3674 revalidation: props.revalidation,
3675 error: props.error
3676 };
3677 }
3678 static getDerivedStateFromError(error) {
3679 return { error };
3680 }
3681 static getDerivedStateFromProps(props, state) {
3682 if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
3683 return {
3684 error: props.error,
3685 location: props.location,
3686 revalidation: props.revalidation
3687 };
3688 }
3689 return {
3690 error: props.error !== void 0 ? props.error : state.error,
3691 location: state.location,
3692 revalidation: props.revalidation || state.revalidation
3693 };
3694 }
3695 componentDidCatch(error, errorInfo) {
3696 console.error(
3697 "React Router caught the following error during render",
3698 error,
3699 errorInfo
3700 );
3701 }
3702 render() {
3703 return this.state.error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement(
3704 RouteErrorContext.Provider,
3705 {
3706 value: this.state.error,
3707 children: this.props.component
3708 }
3709 )) : this.props.children;
3710 }
3711};
3712function RenderedRoute({ routeContext, match, children }) {
3713 let dataRouterContext = React2.useContext(DataRouterContext);
3714 if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
3715 dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
3716 }
3717 return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children);
3718}
3719function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) {
3720 if (matches == null) {
3721 if (!dataRouterState) {
3722 return null;
3723 }
3724 if (dataRouterState.errors) {
3725 matches = dataRouterState.matches;
3726 } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) {
3727 matches = dataRouterState.matches;
3728 } else {
3729 return null;
3730 }
3731 }
3732 let renderedMatches = matches;
3733 let errors = dataRouterState?.errors;
3734 if (errors != null) {
3735 let errorIndex = renderedMatches.findIndex(
3736 (m) => m.route.id && errors?.[m.route.id] !== void 0
3737 );
3738 invariant(
3739 errorIndex >= 0,
3740 `Could not find a matching route for errors on route IDs: ${Object.keys(
3741 errors
3742 ).join(",")}`
3743 );
3744 renderedMatches = renderedMatches.slice(
3745 0,
3746 Math.min(renderedMatches.length, errorIndex + 1)
3747 );
3748 }
3749 let renderFallback = false;
3750 let fallbackIndex = -1;
3751 if (dataRouterState) {
3752 for (let i = 0; i < renderedMatches.length; i++) {
3753 let match = renderedMatches[i];
3754 if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
3755 fallbackIndex = i;
3756 }
3757 if (match.route.id) {
3758 let { loaderData, errors: errors2 } = dataRouterState;
3759 let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0);
3760 if (match.route.lazy || needsToRunLoader) {
3761 renderFallback = true;
3762 if (fallbackIndex >= 0) {
3763 renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
3764 } else {
3765 renderedMatches = [renderedMatches[0]];
3766 }
3767 break;
3768 }
3769 }
3770 }
3771 }
3772 return renderedMatches.reduceRight((outlet, match, index) => {
3773 let error;
3774 let shouldRenderHydrateFallback = false;
3775 let errorElement = null;
3776 let hydrateFallbackElement = null;
3777 if (dataRouterState) {
3778 error = errors && match.route.id ? errors[match.route.id] : void 0;
3779 errorElement = match.route.errorElement || defaultErrorElement;
3780 if (renderFallback) {
3781 if (fallbackIndex < 0 && index === 0) {
3782 warningOnce(
3783 "route-fallback",
3784 false,
3785 "No `HydrateFallback` element provided to render during initial hydration"
3786 );
3787 shouldRenderHydrateFallback = true;
3788 hydrateFallbackElement = null;
3789 } else if (fallbackIndex === index) {
3790 shouldRenderHydrateFallback = true;
3791 hydrateFallbackElement = match.route.hydrateFallbackElement || null;
3792 }
3793 }
3794 }
3795 let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1));
3796 let getChildren = () => {
3797 let children;
3798 if (error) {
3799 children = errorElement;
3800 } else if (shouldRenderHydrateFallback) {
3801 children = hydrateFallbackElement;
3802 } else if (match.route.Component) {
3803 children = /* @__PURE__ */ React2.createElement(match.route.Component, null);
3804 } else if (match.route.element) {
3805 children = match.route.element;
3806 } else {
3807 children = outlet;
3808 }
3809 return /* @__PURE__ */ React2.createElement(
3810 RenderedRoute,
3811 {
3812 match,
3813 routeContext: {
3814 outlet,
3815 matches: matches2,
3816 isDataRoute: dataRouterState != null
3817 },
3818 children
3819 }
3820 );
3821 };
3822 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React2.createElement(
3823 RenderErrorBoundary,
3824 {
3825 location: dataRouterState.location,
3826 revalidation: dataRouterState.revalidation,
3827 component: errorElement,
3828 error,
3829 children: getChildren(),
3830 routeContext: { outlet: null, matches: matches2, isDataRoute: true }
3831 }
3832 ) : getChildren();
3833 }, null);
3834}
3835function getDataRouterConsoleError(hookName) {
3836 return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
3837}
3838function useDataRouterState(hookName) {
3839 let state = React2.useContext(DataRouterStateContext);
3840 invariant(state, getDataRouterConsoleError(hookName));
3841 return state;
3842}
3843function useRouteContext(hookName) {
3844 let route = React2.useContext(RouteContext);
3845 invariant(route, getDataRouterConsoleError(hookName));
3846 return route;
3847}
3848function useCurrentRouteId(hookName) {
3849 let route = useRouteContext(hookName);
3850 let thisRoute = route.matches[route.matches.length - 1];
3851 invariant(
3852 thisRoute.route.id,
3853 `${hookName} can only be used on routes that contain a unique "id"`
3854 );
3855 return thisRoute.route.id;
3856}
3857function useRouteError() {
3858 let error = React2.useContext(RouteErrorContext);
3859 let state = useDataRouterState("useRouteError" /* UseRouteError */);
3860 let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */);
3861 if (error !== void 0) {
3862 return error;
3863 }
3864 return state.errors?.[routeId];
3865}
3866var alreadyWarned = {};
3867function warningOnce(key, cond, message) {
3868 if (!cond && !alreadyWarned[key]) {
3869 alreadyWarned[key] = true;
3870 warning(false, message);
3871 }
3872}
3873
3874// lib/server-runtime/warnings.ts
3875var alreadyWarned2 = {};
3876function warnOnce(condition, message) {
3877 if (!condition && !alreadyWarned2[message]) {
3878 alreadyWarned2[message] = true;
3879 console.warn(message);
3880 }
3881}
3882
3883// lib/components.tsx
3884var ENABLE_DEV_WARNINGS2 = false;
3885function mapRouteProperties(route) {
3886 let updates = {
3887 // Note: this check also occurs in createRoutesFromChildren so update
3888 // there if you change this -- please and thank you!
3889 hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null
3890 };
3891 if (route.Component) {
3892 if (ENABLE_DEV_WARNINGS2) {
3893 if (route.element) {
3894 warning(
3895 false,
3896 "You should not include both `Component` and `element` on your route - `Component` will be used."
3897 );
3898 }
3899 }
3900 Object.assign(updates, {
3901 element: React3.createElement(route.Component),
3902 Component: void 0
3903 });
3904 }
3905 if (route.HydrateFallback) {
3906 if (ENABLE_DEV_WARNINGS2) {
3907 if (route.hydrateFallbackElement) {
3908 warning(
3909 false,
3910 "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used."
3911 );
3912 }
3913 }
3914 Object.assign(updates, {
3915 hydrateFallbackElement: React3.createElement(route.HydrateFallback),
3916 HydrateFallback: void 0
3917 });
3918 }
3919 if (route.ErrorBoundary) {
3920 if (ENABLE_DEV_WARNINGS2) {
3921 if (route.errorElement) {
3922 warning(
3923 false,
3924 "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used."
3925 );
3926 }
3927 }
3928 Object.assign(updates, {
3929 errorElement: React3.createElement(route.ErrorBoundary),
3930 ErrorBoundary: void 0
3931 });
3932 }
3933 return updates;
3934}
3935var Deferred = class {
3936 constructor() {
3937 this.status = "pending";
3938 this.promise = new Promise((resolve, reject) => {
3939 this.resolve = (value) => {
3940 if (this.status === "pending") {
3941 this.status = "resolved";
3942 resolve(value);
3943 }
3944 };
3945 this.reject = (reason) => {
3946 if (this.status === "pending") {
3947 this.status = "rejected";
3948 reject(reason);
3949 }
3950 };
3951 });
3952 }
3953};
3954function RouterProvider({
3955 router: router2,
3956 flushSync: reactDomFlushSyncImpl
3957}) {
3958 let [state, setStateImpl] = React3.useState(router2.state);
3959 let [pendingState, setPendingState] = React3.useState();
3960 let [vtContext, setVtContext] = React3.useState({
3961 isTransitioning: false
3962 });
3963 let [renderDfd, setRenderDfd] = React3.useState();
3964 let [transition, setTransition] = React3.useState();
3965 let [interruption, setInterruption] = React3.useState();
3966 let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
3967 let setState = React3.useCallback(
3968 (newState, { deletedFetchers, flushSync: flushSync2, viewTransitionOpts }) => {
3969 newState.fetchers.forEach((fetcher, key) => {
3970 if (fetcher.data !== void 0) {
3971 fetcherData.current.set(key, fetcher.data);
3972 }
3973 });
3974 deletedFetchers.forEach((key) => fetcherData.current.delete(key));
3975 warnOnce(
3976 flushSync2 === false || reactDomFlushSyncImpl != null,
3977 'You provided the `flushSync` option to a router update, but you are not using the `<RouterProvider>` from `react-router/dom` so `ReactDOM.flushSync()` is unavailable. Please update your app to `import { RouterProvider } from "react-router/dom"` and ensure you have `react-dom` installed as a dependency to use the `flushSync` option.'
3978 );
3979 let isViewTransitionAvailable = router2.window != null && router2.window.document != null && typeof router2.window.document.startViewTransition === "function";
3980 warnOnce(
3981 viewTransitionOpts == null || isViewTransitionAvailable,
3982 "You provided the `viewTransition` option to a router update, but you do not appear to be running in a DOM environment as `window.startViewTransition` is not available."
3983 );
3984 if (!viewTransitionOpts || !isViewTransitionAvailable) {
3985 if (reactDomFlushSyncImpl && flushSync2) {
3986 reactDomFlushSyncImpl(() => setStateImpl(newState));
3987 } else {
3988 React3.startTransition(() => setStateImpl(newState));
3989 }
3990 return;
3991 }
3992 if (reactDomFlushSyncImpl && flushSync2) {
3993 reactDomFlushSyncImpl(() => {
3994 if (transition) {
3995 renderDfd && renderDfd.resolve();
3996 transition.skipTransition();
3997 }
3998 setVtContext({
3999 isTransitioning: true,
4000 flushSync: true,
4001 currentLocation: viewTransitionOpts.currentLocation,
4002 nextLocation: viewTransitionOpts.nextLocation
4003 });
4004 });
4005 let t = router2.window.document.startViewTransition(() => {
4006 reactDomFlushSyncImpl(() => setStateImpl(newState));
4007 });
4008 t.finished.finally(() => {
4009 reactDomFlushSyncImpl(() => {
4010 setRenderDfd(void 0);
4011 setTransition(void 0);
4012 setPendingState(void 0);
4013 setVtContext({ isTransitioning: false });
4014 });
4015 });
4016 reactDomFlushSyncImpl(() => setTransition(t));
4017 return;
4018 }
4019 if (transition) {
4020 renderDfd && renderDfd.resolve();
4021 transition.skipTransition();
4022 setInterruption({
4023 state: newState,
4024 currentLocation: viewTransitionOpts.currentLocation,
4025 nextLocation: viewTransitionOpts.nextLocation
4026 });
4027 } else {
4028 setPendingState(newState);
4029 setVtContext({
4030 isTransitioning: true,
4031 flushSync: false,
4032 currentLocation: viewTransitionOpts.currentLocation,
4033 nextLocation: viewTransitionOpts.nextLocation
4034 });
4035 }
4036 },
4037 [router2.window, reactDomFlushSyncImpl, transition, renderDfd]
4038 );
4039 React3.useLayoutEffect(() => router2.subscribe(setState), [router2, setState]);
4040 React3.useEffect(() => {
4041 if (vtContext.isTransitioning && !vtContext.flushSync) {
4042 setRenderDfd(new Deferred());
4043 }
4044 }, [vtContext]);
4045 React3.useEffect(() => {
4046 if (renderDfd && pendingState && router2.window) {
4047 let newState = pendingState;
4048 let renderPromise = renderDfd.promise;
4049 let transition2 = router2.window.document.startViewTransition(async () => {
4050 React3.startTransition(() => setStateImpl(newState));
4051 await renderPromise;
4052 });
4053 transition2.finished.finally(() => {
4054 setRenderDfd(void 0);
4055 setTransition(void 0);
4056 setPendingState(void 0);
4057 setVtContext({ isTransitioning: false });
4058 });
4059 setTransition(transition2);
4060 }
4061 }, [pendingState, renderDfd, router2.window]);
4062 React3.useEffect(() => {
4063 if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
4064 renderDfd.resolve();
4065 }
4066 }, [renderDfd, transition, state.location, pendingState]);
4067 React3.useEffect(() => {
4068 if (!vtContext.isTransitioning && interruption) {
4069 setPendingState(interruption.state);
4070 setVtContext({
4071 isTransitioning: true,
4072 flushSync: false,
4073 currentLocation: interruption.currentLocation,
4074 nextLocation: interruption.nextLocation
4075 });
4076 setInterruption(void 0);
4077 }
4078 }, [vtContext.isTransitioning, interruption]);
4079 let navigator2 = React3.useMemo(() => {
4080 return {
4081 createHref: router2.createHref,
4082 encodeLocation: router2.encodeLocation,
4083 go: (n) => router2.navigate(n),
4084 push: (to, state2, opts) => router2.navigate(to, {
4085 state: state2,
4086 preventScrollReset: opts?.preventScrollReset
4087 }),
4088 replace: (to, state2, opts) => router2.navigate(to, {
4089 replace: true,
4090 state: state2,
4091 preventScrollReset: opts?.preventScrollReset
4092 })
4093 };
4094 }, [router2]);
4095 let basename = router2.basename || "/";
4096 let dataRouterContext = React3.useMemo(
4097 () => ({
4098 router: router2,
4099 navigator: navigator2,
4100 static: false,
4101 basename
4102 }),
4103 [router2, navigator2, basename]
4104 );
4105 return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(ViewTransitionContext.Provider, { value: vtContext }, /* @__PURE__ */ React3.createElement(
4106 Router,
4107 {
4108 basename,
4109 location: state.location,
4110 navigationType: state.historyAction,
4111 navigator: navigator2
4112 },
4113 /* @__PURE__ */ React3.createElement(
4114 MemoizedDataRoutes,
4115 {
4116 routes: router2.routes,
4117 future: router2.future,
4118 state
4119 }
4120 )
4121 ))))), null);
4122}
4123var MemoizedDataRoutes = React3.memo(DataRoutes);
4124function DataRoutes({
4125 routes,
4126 future,
4127 state
4128}) {
4129 return useRoutesImpl(routes, void 0, state, future);
4130}
4131function Router({
4132 basename: basenameProp = "/",
4133 children = null,
4134 location: locationProp,
4135 navigationType = "POP" /* Pop */,
4136 navigator: navigator2,
4137 static: staticProp = false
4138}) {
4139 invariant(
4140 !useInRouterContext(),
4141 `You cannot render a <Router> inside another <Router>. You should never have more than one in your app.`
4142 );
4143 let basename = basenameProp.replace(/^\/*/, "/");
4144 let navigationContext = React3.useMemo(
4145 () => ({
4146 basename,
4147 navigator: navigator2,
4148 static: staticProp,
4149 future: {}
4150 }),
4151 [basename, navigator2, staticProp]
4152 );
4153 if (typeof locationProp === "string") {
4154 locationProp = parsePath(locationProp);
4155 }
4156 let {
4157 pathname = "/",
4158 search = "",
4159 hash = "",
4160 state = null,
4161 key = "default"
4162 } = locationProp;
4163 let locationContext = React3.useMemo(() => {
4164 let trailingPathname = stripBasename(pathname, basename);
4165 if (trailingPathname == null) {
4166 return null;
4167 }
4168 return {
4169 location: {
4170 pathname: trailingPathname,
4171 search,
4172 hash,
4173 state,
4174 key
4175 },
4176 navigationType
4177 };
4178 }, [basename, pathname, search, hash, state, key, navigationType]);
4179 warning(
4180 locationContext != null,
4181 `<Router basename="${basename}"> is not able to match the URL "${pathname}${search}${hash}" because it does not start with the basename, so the <Router> won't render anything.`
4182 );
4183 if (locationContext == null) {
4184 return null;
4185 }
4186 return /* @__PURE__ */ React3.createElement(NavigationContext.Provider, { value: navigationContext }, /* @__PURE__ */ React3.createElement(LocationContext.Provider, { children, value: locationContext }));
4187}
4188
4189// lib/dom/ssr/components.tsx
4190var React9 = __toESM(require("react"));
4191
4192// lib/dom/ssr/invariant.ts
4193function invariant2(value, message) {
4194 if (value === false || value === null || typeof value === "undefined") {
4195 throw new Error(message);
4196 }
4197}
4198
4199// lib/dom/ssr/routeModules.ts
4200async function loadRouteModule(route, routeModulesCache) {
4201 if (route.id in routeModulesCache) {
4202 return routeModulesCache[route.id];
4203 }
4204 try {
4205 let routeModule = await import(
4206 /* @vite-ignore */
4207 /* webpackIgnore: true */
4208 route.module
4209 );
4210 routeModulesCache[route.id] = routeModule;
4211 return routeModule;
4212 } catch (error) {
4213 console.error(
4214 `Error loading route module \`${route.module}\`, reloading page...`
4215 );
4216 console.error(error);
4217 if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
4218 void 0) {
4219 throw error;
4220 }
4221 window.location.reload();
4222 return new Promise(() => {
4223 });
4224 }
4225}
4226
4227// lib/dom/ssr/links.ts
4228async function prefetchStyleLinks(route, routeModule) {
4229 if (!route.css && !routeModule.links || !isPreloadSupported()) return;
4230 let descriptors = [];
4231 if (route.css) {
4232 descriptors.push(...route.css.map((href) => ({ rel: "stylesheet", href })));
4233 }
4234 if (routeModule.links) {
4235 descriptors.push(...routeModule.links());
4236 }
4237 if (descriptors.length === 0) return;
4238 let styleLinks = [];
4239 for (let descriptor of descriptors) {
4240 if (!isPageLinkDescriptor(descriptor) && descriptor.rel === "stylesheet") {
4241 styleLinks.push({
4242 ...descriptor,
4243 rel: "preload",
4244 as: "style"
4245 });
4246 }
4247 }
4248 let matchingLinks = styleLinks.filter(
4249 (link) => (!link.media || window.matchMedia(link.media).matches) && !document.querySelector(`link[rel="stylesheet"][href="${link.href}"]`)
4250 );
4251 await Promise.all(matchingLinks.map(prefetchStyleLink));
4252}
4253async function prefetchStyleLink(descriptor) {
4254 return new Promise((resolve) => {
4255 let link = document.createElement("link");
4256 Object.assign(link, descriptor);
4257 function removeLink() {
4258 if (document.head.contains(link)) {
4259 document.head.removeChild(link);
4260 }
4261 }
4262 link.onload = () => {
4263 removeLink();
4264 resolve();
4265 };
4266 link.onerror = () => {
4267 removeLink();
4268 resolve();
4269 };
4270 document.head.appendChild(link);
4271 });
4272}
4273function isPageLinkDescriptor(object) {
4274 return object != null && typeof object.page === "string";
4275}
4276var _isPreloadSupported;
4277function isPreloadSupported() {
4278 if (_isPreloadSupported !== void 0) {
4279 return _isPreloadSupported;
4280 }
4281 let el = document.createElement("link");
4282 _isPreloadSupported = el.relList.supports("preload");
4283 el = null;
4284 return _isPreloadSupported;
4285}
4286
4287// lib/dom/ssr/markup.ts
4288function createHtml(html) {
4289 return { __html: html };
4290}
4291
4292// lib/dom/ssr/single-fetch.tsx
4293var React4 = __toESM(require("react"));
4294var import_turbo_stream = require("turbo-stream");
4295
4296// lib/dom/ssr/data.ts
4297async function createRequestInit(request) {
4298 let init = { signal: request.signal };
4299 if (request.method !== "GET") {
4300 init.method = request.method;
4301 let contentType = request.headers.get("Content-Type");
4302 if (contentType && /\bapplication\/json\b/.test(contentType)) {
4303 init.headers = { "Content-Type": contentType };
4304 init.body = JSON.stringify(await request.json());
4305 } else if (contentType && /\btext\/plain\b/.test(contentType)) {
4306 init.headers = { "Content-Type": contentType };
4307 init.body = await request.text();
4308 } else if (contentType && /\bapplication\/x-www-form-urlencoded\b/.test(contentType)) {
4309 init.body = new URLSearchParams(await request.text());
4310 } else {
4311 init.body = await request.formData();
4312 }
4313 }
4314 return init;
4315}
4316
4317// lib/dom/ssr/single-fetch.tsx
4318var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
4319function getSingleFetchDataStrategy(manifest, routeModules, getRouter) {
4320 return async ({ request, matches, fetcherKey }) => {
4321 if (request.method !== "GET") {
4322 return singleFetchActionStrategy(request, matches);
4323 }
4324 if (fetcherKey) {
4325 return singleFetchLoaderFetcherStrategy(request, matches);
4326 }
4327 return singleFetchLoaderNavigationStrategy(
4328 manifest,
4329 routeModules,
4330 getRouter(),
4331 request,
4332 matches
4333 );
4334 };
4335}
4336async function singleFetchActionStrategy(request, matches) {
4337 let actionMatch = matches.find((m) => m.shouldLoad);
4338 invariant2(actionMatch, "No action match found");
4339 let actionStatus = void 0;
4340 let result = await actionMatch.resolve(async (handler) => {
4341 let result2 = await handler(async () => {
4342 let url = singleFetchUrl(request.url);
4343 let init = await createRequestInit(request);
4344 let { data: data2, status } = await fetchAndDecode(url, init);
4345 actionStatus = status;
4346 return unwrapSingleFetchResult(
4347 data2,
4348 actionMatch.route.id
4349 );
4350 });
4351 return result2;
4352 });
4353 if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
4354 return { [actionMatch.route.id]: result };
4355 }
4356 return {
4357 [actionMatch.route.id]: {
4358 type: result.type,
4359 result: data(result.result, actionStatus)
4360 }
4361 };
4362}
4363async function singleFetchLoaderNavigationStrategy(manifest, routeModules, router2, request, matches) {
4364 let routesParams = /* @__PURE__ */ new Set();
4365 let foundOptOutRoute = false;
4366 let routeDfds = matches.map(() => createDeferred2());
4367 let routesLoadedPromise = Promise.all(routeDfds.map((d) => d.promise));
4368 let singleFetchDfd = createDeferred2();
4369 let url = stripIndexParam(singleFetchUrl(request.url));
4370 let init = await createRequestInit(request);
4371 let results = {};
4372 let resolvePromise = Promise.all(
4373 matches.map(
4374 async (m, i) => m.resolve(async (handler) => {
4375 routeDfds[i].resolve();
4376 let manifestRoute = manifest.routes[m.route.id];
4377 if (!m.shouldLoad) {
4378 if (!router2.state.initialized) {
4379 return;
4380 }
4381 if (m.route.id in router2.state.loaderData && manifestRoute && manifestRoute.hasLoader && routeModules[m.route.id]?.shouldRevalidate) {
4382 foundOptOutRoute = true;
4383 return;
4384 }
4385 }
4386 if (manifestRoute && manifestRoute.hasClientLoader) {
4387 if (manifestRoute.hasLoader) {
4388 foundOptOutRoute = true;
4389 }
4390 try {
4391 let result = await fetchSingleLoader(
4392 handler,
4393 url,
4394 init,
4395 m.route.id
4396 );
4397 results[m.route.id] = { type: "data", result };
4398 } catch (e) {
4399 results[m.route.id] = { type: "error", result: e };
4400 }
4401 return;
4402 }
4403 if (manifestRoute && manifestRoute.hasLoader) {
4404 routesParams.add(m.route.id);
4405 }
4406 try {
4407 let result = await handler(async () => {
4408 let data2 = await singleFetchDfd.promise;
4409 return unwrapSingleFetchResults(data2, m.route.id);
4410 });
4411 results[m.route.id] = {
4412 type: "data",
4413 result
4414 };
4415 } catch (e) {
4416 results[m.route.id] = {
4417 type: "error",
4418 result: e
4419 };
4420 }
4421 })
4422 )
4423 );
4424 await routesLoadedPromise;
4425 if ((!router2.state.initialized || routesParams.size === 0) && !window.__reactRouterHdrActive) {
4426 singleFetchDfd.resolve({});
4427 } else {
4428 try {
4429 if (foundOptOutRoute && routesParams.size > 0) {
4430 url.searchParams.set(
4431 "_routes",
4432 matches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
4433 );
4434 }
4435 let data2 = await fetchAndDecode(url, init);
4436 singleFetchDfd.resolve(data2.data);
4437 } catch (e) {
4438 singleFetchDfd.reject(e);
4439 }
4440 }
4441 await resolvePromise;
4442 return results;
4443}
4444async function singleFetchLoaderFetcherStrategy(request, matches) {
4445 let fetcherMatch = matches.find((m) => m.shouldLoad);
4446 invariant2(fetcherMatch, "No fetcher match found");
4447 let result = await fetcherMatch.resolve(async (handler) => {
4448 let url = stripIndexParam(singleFetchUrl(request.url));
4449 let init = await createRequestInit(request);
4450 return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
4451 });
4452 return { [fetcherMatch.route.id]: result };
4453}
4454function fetchSingleLoader(handler, url, init, routeId) {
4455 return handler(async () => {
4456 let singleLoaderUrl = new URL(url);
4457 singleLoaderUrl.searchParams.set("_routes", routeId);
4458 let { data: data2 } = await fetchAndDecode(singleLoaderUrl, init);
4459 return unwrapSingleFetchResults(data2, routeId);
4460 });
4461}
4462function stripIndexParam(url) {
4463 let indexValues = url.searchParams.getAll("index");
4464 url.searchParams.delete("index");
4465 let indexValuesToKeep = [];
4466 for (let indexValue of indexValues) {
4467 if (indexValue) {
4468 indexValuesToKeep.push(indexValue);
4469 }
4470 }
4471 for (let toKeep of indexValuesToKeep) {
4472 url.searchParams.append("index", toKeep);
4473 }
4474 return url;
4475}
4476function singleFetchUrl(reqUrl) {
4477 let url = typeof reqUrl === "string" ? new URL(
4478 reqUrl,
4479 // This can be called during the SSR flow via PrefetchPageLinksImpl so
4480 // don't assume window is available
4481 typeof window === "undefined" ? "server://singlefetch/" : window.location.origin
4482 ) : reqUrl;
4483 if (url.pathname === "/") {
4484 url.pathname = "_root.data";
4485 } else {
4486 url.pathname = `${url.pathname.replace(/\/$/, "")}.data`;
4487 }
4488 return url;
4489}
4490async function fetchAndDecode(url, init) {
4491 let res = await fetch(url, init);
4492 if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
4493 throw new ErrorResponseImpl(404, "Not Found", true);
4494 }
4495 const NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205]);
4496 if (NO_BODY_STATUS_CODES.has(res.status)) {
4497 if (!init.method || init.method === "GET") {
4498 return { status: res.status, data: {} };
4499 } else {
4500 return { status: res.status, data: { data: void 0 } };
4501 }
4502 }
4503 invariant2(res.body, "No response body to decode");
4504 try {
4505 let decoded = await decodeViaTurboStream(res.body, window);
4506 return { status: res.status, data: decoded.value };
4507 } catch (e) {
4508 throw new Error("Unable to decode turbo-stream response");
4509 }
4510}
4511function decodeViaTurboStream(body, global) {
4512 return (0, import_turbo_stream.decode)(body, {
4513 plugins: [
4514 (type, ...rest) => {
4515 if (type === "SanitizedError") {
4516 let [name, message, stack] = rest;
4517 let Constructor = Error;
4518 if (name && name in global && typeof global[name] === "function") {
4519 Constructor = global[name];
4520 }
4521 let error = new Constructor(message);
4522 error.stack = stack;
4523 return { value: error };
4524 }
4525 if (type === "ErrorResponse") {
4526 let [data2, status, statusText] = rest;
4527 return {
4528 value: new ErrorResponseImpl(status, statusText, data2)
4529 };
4530 }
4531 if (type === "SingleFetchRedirect") {
4532 return { value: { [SingleFetchRedirectSymbol]: rest[0] } };
4533 }
4534 if (type === "SingleFetchClassInstance") {
4535 return { value: rest[0] };
4536 }
4537 if (type === "SingleFetchFallback") {
4538 return { value: void 0 };
4539 }
4540 }
4541 ]
4542 });
4543}
4544function unwrapSingleFetchResults(results, routeId) {
4545 let redirect2 = results[SingleFetchRedirectSymbol];
4546 if (redirect2) {
4547 return unwrapSingleFetchResult(redirect2, routeId);
4548 }
4549 return results[routeId] !== void 0 ? unwrapSingleFetchResult(results[routeId], routeId) : null;
4550}
4551function unwrapSingleFetchResult(result, routeId) {
4552 if ("error" in result) {
4553 throw result.error;
4554 } else if ("redirect" in result) {
4555 let headers = {};
4556 if (result.revalidate) {
4557 headers["X-Remix-Revalidate"] = "yes";
4558 }
4559 if (result.reload) {
4560 headers["X-Remix-Reload-Document"] = "yes";
4561 }
4562 if (result.replace) {
4563 headers["X-Remix-Replace"] = "yes";
4564 }
4565 throw redirect(result.redirect, { status: result.status, headers });
4566 } else if ("data" in result) {
4567 return result.data;
4568 } else {
4569 throw new Error(`No response found for routeId "${routeId}"`);
4570 }
4571}
4572function createDeferred2() {
4573 let resolve;
4574 let reject;
4575 let promise = new Promise((res, rej) => {
4576 resolve = async (val) => {
4577 res(val);
4578 try {
4579 await promise;
4580 } catch (e) {
4581 }
4582 };
4583 reject = async (error) => {
4584 rej(error);
4585 try {
4586 await promise;
4587 } catch (e) {
4588 }
4589 };
4590 });
4591 return {
4592 promise,
4593 //@ts-ignore
4594 resolve,
4595 //@ts-ignore
4596 reject
4597 };
4598}
4599
4600// lib/dom/ssr/fog-of-war.ts
4601var React8 = __toESM(require("react"));
4602
4603// lib/dom/ssr/routes.tsx
4604var React7 = __toESM(require("react"));
4605
4606// lib/dom/ssr/errorBoundaries.tsx
4607var React5 = __toESM(require("react"));
4608var RemixErrorBoundary = class extends React5.Component {
4609 constructor(props) {
4610 super(props);
4611 this.state = { error: props.error || null, location: props.location };
4612 }
4613 static getDerivedStateFromError(error) {
4614 return { error };
4615 }
4616 static getDerivedStateFromProps(props, state) {
4617 if (state.location !== props.location) {
4618 return { error: props.error || null, location: props.location };
4619 }
4620 return { error: props.error || state.error, location: state.location };
4621 }
4622 render() {
4623 if (this.state.error) {
4624 return /* @__PURE__ */ React5.createElement(
4625 RemixRootDefaultErrorBoundary,
4626 {
4627 error: this.state.error,
4628 isOutsideRemixApp: true
4629 }
4630 );
4631 } else {
4632 return this.props.children;
4633 }
4634 }
4635};
4636function RemixRootDefaultErrorBoundary({
4637 error,
4638 isOutsideRemixApp
4639}) {
4640 console.error(error);
4641 let heyDeveloper = /* @__PURE__ */ React5.createElement(
4642 "script",
4643 {
4644 dangerouslySetInnerHTML: {
4645 __html: `
4646 console.log(
4647 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this when your app throws errors. Check out https://remix.run/guides/errors for more information."
4648 );
4649 `
4650 }
4651 }
4652 );
4653 if (isRouteErrorResponse(error)) {
4654 return /* @__PURE__ */ React5.createElement(BoundaryShell, { title: "Unhandled Thrown Response!" }, /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, error.status, " ", error.statusText), heyDeveloper);
4655 }
4656 let errorInstance;
4657 if (error instanceof Error) {
4658 errorInstance = error;
4659 } else {
4660 let errorString = error == null ? "Unknown Error" : typeof error === "object" && "toString" in error ? error.toString() : JSON.stringify(error);
4661 errorInstance = new Error(errorString);
4662 }
4663 return /* @__PURE__ */ React5.createElement(
4664 BoundaryShell,
4665 {
4666 title: "Application Error!",
4667 isOutsideRemixApp
4668 },
4669 /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, "Application Error"),
4670 /* @__PURE__ */ React5.createElement(
4671 "pre",
4672 {
4673 style: {
4674 padding: "2rem",
4675 background: "hsla(10, 50%, 50%, 0.1)",
4676 color: "red",
4677 overflow: "auto"
4678 }
4679 },
4680 errorInstance.stack
4681 ),
4682 heyDeveloper
4683 );
4684}
4685function BoundaryShell({
4686 title,
4687 renderScripts,
4688 isOutsideRemixApp,
4689 children
4690}) {
4691 let { routeModules } = useFrameworkContext();
4692 if (routeModules.root?.Layout && !isOutsideRemixApp) {
4693 return children;
4694 }
4695 return /* @__PURE__ */ React5.createElement("html", { lang: "en" }, /* @__PURE__ */ React5.createElement("head", null, /* @__PURE__ */ React5.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ React5.createElement(
4696 "meta",
4697 {
4698 name: "viewport",
4699 content: "width=device-width,initial-scale=1,viewport-fit=cover"
4700 }
4701 ), /* @__PURE__ */ React5.createElement("title", null, title)), /* @__PURE__ */ React5.createElement("body", null, /* @__PURE__ */ React5.createElement("main", { style: { fontFamily: "system-ui, sans-serif", padding: "2rem" } }, children, renderScripts ? /* @__PURE__ */ React5.createElement(Scripts, null) : null)));
4702}
4703
4704// lib/dom/ssr/fallback.tsx
4705var React6 = __toESM(require("react"));
4706function RemixRootDefaultHydrateFallback() {
4707 return /* @__PURE__ */ React6.createElement(BoundaryShell, { title: "Loading...", renderScripts: true }, /* @__PURE__ */ React6.createElement(
4708 "script",
4709 {
4710 dangerouslySetInnerHTML: {
4711 __html: `
4712 console.log(
4713 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this " +
4714 "when your app is loading JS modules and/or running \`clientLoader\` " +
4715 "functions. Check out https://remix.run/route/hydrate-fallback " +
4716 "for more information."
4717 );
4718 `
4719 }
4720 }
4721 ));
4722}
4723
4724// lib/dom/ssr/routes.tsx
4725function groupRoutesByParentId(manifest) {
4726 let routes = {};
4727 Object.values(manifest).forEach((route) => {
4728 if (route) {
4729 let parentId = route.parentId || "";
4730 if (!routes[parentId]) {
4731 routes[parentId] = [];
4732 }
4733 routes[parentId].push(route);
4734 }
4735 });
4736 return routes;
4737}
4738function getRouteComponents(route, routeModule, isSpaMode) {
4739 let Component4 = getRouteModuleComponent(routeModule);
4740 let HydrateFallback = routeModule.HydrateFallback && (!isSpaMode || route.id === "root") ? routeModule.HydrateFallback : route.id === "root" ? RemixRootDefaultHydrateFallback : void 0;
4741 let ErrorBoundary = routeModule.ErrorBoundary ? routeModule.ErrorBoundary : route.id === "root" ? () => /* @__PURE__ */ React7.createElement(RemixRootDefaultErrorBoundary, { error: useRouteError() }) : void 0;
4742 if (route.id === "root" && routeModule.Layout) {
4743 return {
4744 ...Component4 ? {
4745 element: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(Component4, null))
4746 } : { Component: Component4 },
4747 ...ErrorBoundary ? {
4748 errorElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(ErrorBoundary, null))
4749 } : { ErrorBoundary },
4750 ...HydrateFallback ? {
4751 hydrateFallbackElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(HydrateFallback, null))
4752 } : { HydrateFallback }
4753 };
4754 }
4755 return { Component: Component4, ErrorBoundary, HydrateFallback };
4756}
4757function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState, future, isSpaMode) {
4758 return createClientRoutes(
4759 manifest,
4760 routeModulesCache,
4761 initialState,
4762 isSpaMode,
4763 "",
4764 groupRoutesByParentId(manifest),
4765 needsRevalidation
4766 );
4767}
4768function preventInvalidServerHandlerCall(type, route, isSpaMode) {
4769 if (isSpaMode) {
4770 let fn2 = type === "action" ? "serverAction()" : "serverLoader()";
4771 let msg2 = `You cannot call ${fn2} in SPA Mode (routeId: "${route.id}")`;
4772 console.error(msg2);
4773 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg2), true);
4774 }
4775 let fn = type === "action" ? "serverAction()" : "serverLoader()";
4776 let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
4777 if (type === "loader" && !route.hasLoader || type === "action" && !route.hasAction) {
4778 console.error(msg);
4779 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
4780 }
4781}
4782function noActionDefinedError(type, routeId) {
4783 let article = type === "clientAction" ? "a" : "an";
4784 let msg = `Route "${routeId}" does not have ${article} ${type}, but you are trying to submit to it. To fix this, please add ${article} \`${type}\` function to the route`;
4785 console.error(msg);
4786 throw new ErrorResponseImpl(405, "Method Not Allowed", new Error(msg), true);
4787}
4788function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
4789 return (routesByParentId[parentId] || []).map((route) => {
4790 let routeModule = routeModulesCache[route.id];
4791 function fetchServerHandler(singleFetch) {
4792 invariant2(
4793 typeof singleFetch === "function",
4794 "No single fetch function available for route handler"
4795 );
4796 return singleFetch();
4797 }
4798 function fetchServerLoader(singleFetch) {
4799 if (!route.hasLoader) return Promise.resolve(null);
4800 return fetchServerHandler(singleFetch);
4801 }
4802 function fetchServerAction(singleFetch) {
4803 if (!route.hasAction) {
4804 throw noActionDefinedError("action", route.id);
4805 }
4806 return fetchServerHandler(singleFetch);
4807 }
4808 async function prefetchStylesAndCallHandler(handler) {
4809 let cachedModule = routeModulesCache[route.id];
4810 let linkPrefetchPromise = cachedModule ? prefetchStyleLinks(route, cachedModule) : Promise.resolve();
4811 try {
4812 return handler();
4813 } finally {
4814 await linkPrefetchPromise;
4815 }
4816 }
4817 let dataRoute = {
4818 id: route.id,
4819 index: route.index,
4820 path: route.path
4821 };
4822 if (routeModule) {
4823 Object.assign(dataRoute, {
4824 ...dataRoute,
4825 ...getRouteComponents(route, routeModule, isSpaMode),
4826 handle: routeModule.handle,
4827 shouldRevalidate: getShouldRevalidateFunction(
4828 routeModule,
4829 route.id,
4830 needsRevalidation
4831 )
4832 });
4833 let hasInitialData = initialState && initialState.loaderData && route.id in initialState.loaderData;
4834 let initialData = hasInitialData ? initialState?.loaderData?.[route.id] : void 0;
4835 let hasInitialError = initialState && initialState.errors && route.id in initialState.errors;
4836 let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
4837 let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
4838 dataRoute.loader = async ({ request, params }, singleFetch) => {
4839 try {
4840 let result = await prefetchStylesAndCallHandler(async () => {
4841 invariant2(
4842 routeModule,
4843 "No `routeModule` available for critical-route loader"
4844 );
4845 if (!routeModule.clientLoader) {
4846 if (isSpaMode) return null;
4847 return fetchServerLoader(singleFetch);
4848 }
4849 return routeModule.clientLoader({
4850 request,
4851 params,
4852 async serverLoader() {
4853 preventInvalidServerHandlerCall("loader", route, isSpaMode);
4854 if (isHydrationRequest) {
4855 if (hasInitialData) {
4856 return initialData;
4857 }
4858 if (hasInitialError) {
4859 throw initialError;
4860 }
4861 }
4862 return fetchServerLoader(singleFetch);
4863 }
4864 });
4865 });
4866 return result;
4867 } finally {
4868 isHydrationRequest = false;
4869 }
4870 };
4871 dataRoute.loader.hydrate = shouldHydrateRouteLoader(
4872 route,
4873 routeModule,
4874 isSpaMode
4875 );
4876 dataRoute.action = ({ request, params }, singleFetch) => {
4877 return prefetchStylesAndCallHandler(async () => {
4878 invariant2(
4879 routeModule,
4880 "No `routeModule` available for critical-route action"
4881 );
4882 if (!routeModule.clientAction) {
4883 if (isSpaMode) {
4884 throw noActionDefinedError("clientAction", route.id);
4885 }
4886 return fetchServerAction(singleFetch);
4887 }
4888 return routeModule.clientAction({
4889 request,
4890 params,
4891 async serverAction() {
4892 preventInvalidServerHandlerCall("action", route, isSpaMode);
4893 return fetchServerAction(singleFetch);
4894 }
4895 });
4896 });
4897 };
4898 } else {
4899 if (!route.hasClientLoader) {
4900 dataRoute.loader = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
4901 if (isSpaMode) return Promise.resolve(null);
4902 return fetchServerLoader(singleFetch);
4903 });
4904 }
4905 if (!route.hasClientAction) {
4906 dataRoute.action = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
4907 if (isSpaMode) {
4908 throw noActionDefinedError("clientAction", route.id);
4909 }
4910 return fetchServerAction(singleFetch);
4911 });
4912 }
4913 dataRoute.lazy = async () => {
4914 let mod = await loadRouteModuleWithBlockingLinks(
4915 route,
4916 routeModulesCache
4917 );
4918 let lazyRoute = { ...mod };
4919 if (mod.clientLoader) {
4920 let clientLoader = mod.clientLoader;
4921 lazyRoute.loader = (args, singleFetch) => clientLoader({
4922 ...args,
4923 async serverLoader() {
4924 preventInvalidServerHandlerCall("loader", route, isSpaMode);
4925 return fetchServerLoader(singleFetch);
4926 }
4927 });
4928 }
4929 if (mod.clientAction) {
4930 let clientAction = mod.clientAction;
4931 lazyRoute.action = (args, singleFetch) => clientAction({
4932 ...args,
4933 async serverAction() {
4934 preventInvalidServerHandlerCall("action", route, isSpaMode);
4935 return fetchServerAction(singleFetch);
4936 }
4937 });
4938 }
4939 return {
4940 ...lazyRoute.loader ? { loader: lazyRoute.loader } : {},
4941 ...lazyRoute.action ? { action: lazyRoute.action } : {},
4942 hasErrorBoundary: lazyRoute.hasErrorBoundary,
4943 shouldRevalidate: getShouldRevalidateFunction(
4944 lazyRoute,
4945 route.id,
4946 needsRevalidation
4947 ),
4948 handle: lazyRoute.handle,
4949 // No need to wrap these in layout since the root route is never
4950 // loaded via route.lazy()
4951 Component: lazyRoute.Component,
4952 ErrorBoundary: lazyRoute.ErrorBoundary
4953 };
4954 };
4955 }
4956 let children = createClientRoutes(
4957 manifest,
4958 routeModulesCache,
4959 initialState,
4960 isSpaMode,
4961 route.id,
4962 routesByParentId,
4963 needsRevalidation
4964 );
4965 if (children.length > 0) dataRoute.children = children;
4966 return dataRoute;
4967 });
4968}
4969function getShouldRevalidateFunction(route, routeId, needsRevalidation) {
4970 if (needsRevalidation) {
4971 return wrapShouldRevalidateForHdr(
4972 routeId,
4973 route.shouldRevalidate,
4974 needsRevalidation
4975 );
4976 }
4977 if (route.shouldRevalidate) {
4978 let fn = route.shouldRevalidate;
4979 return (opts) => fn({ ...opts, defaultShouldRevalidate: true });
4980 }
4981 return route.shouldRevalidate;
4982}
4983function wrapShouldRevalidateForHdr(routeId, routeShouldRevalidate, needsRevalidation) {
4984 let handledRevalidation = false;
4985 return (arg) => {
4986 if (!handledRevalidation) {
4987 handledRevalidation = true;
4988 return needsRevalidation.has(routeId);
4989 }
4990 return routeShouldRevalidate ? routeShouldRevalidate(arg) : arg.defaultShouldRevalidate;
4991 };
4992}
4993async function loadRouteModuleWithBlockingLinks(route, routeModules) {
4994 let routeModule = await loadRouteModule(route, routeModules);
4995 await prefetchStyleLinks(route, routeModule);
4996 return {
4997 Component: getRouteModuleComponent(routeModule),
4998 ErrorBoundary: routeModule.ErrorBoundary,
4999 clientAction: routeModule.clientAction,
5000 clientLoader: routeModule.clientLoader,
5001 handle: routeModule.handle,
5002 links: routeModule.links,
5003 meta: routeModule.meta,
5004 shouldRevalidate: routeModule.shouldRevalidate
5005 };
5006}
5007function getRouteModuleComponent(routeModule) {
5008 if (routeModule.default == null) return void 0;
5009 let isEmptyObject = typeof routeModule.default === "object" && Object.keys(routeModule.default).length === 0;
5010 if (!isEmptyObject) {
5011 return routeModule.default;
5012 }
5013}
5014function shouldHydrateRouteLoader(route, routeModule, isSpaMode) {
5015 return isSpaMode && route.id !== "root" || routeModule.clientLoader != null && (routeModule.clientLoader.hydrate === true || route.hasLoader !== true);
5016}
5017
5018// lib/dom/ssr/fog-of-war.ts
5019var nextPaths = /* @__PURE__ */ new Set();
5020var discoveredPathsMaxSize = 1e3;
5021var discoveredPaths = /* @__PURE__ */ new Set();
5022var URL_LIMIT = 7680;
5023function isFogOfWarEnabled(isSpaMode) {
5024 return !isSpaMode;
5025}
5026function getPartialManifest(manifest, router2) {
5027 let routeIds = new Set(router2.state.matches.map((m) => m.route.id));
5028 let segments = router2.state.location.pathname.split("/").filter(Boolean);
5029 let paths = ["/"];
5030 segments.pop();
5031 while (segments.length > 0) {
5032 paths.push(`/${segments.join("/")}`);
5033 segments.pop();
5034 }
5035 paths.forEach((path) => {
5036 let matches = matchRoutes(router2.routes, path, router2.basename);
5037 if (matches) {
5038 matches.forEach((m) => routeIds.add(m.route.id));
5039 }
5040 });
5041 let initialRoutes = [...routeIds].reduce(
5042 (acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }),
5043 {}
5044 );
5045 return {
5046 ...manifest,
5047 routes: initialRoutes
5048 };
5049}
5050function getPatchRoutesOnNavigationFunction(manifest, routeModules, isSpaMode, basename) {
5051 if (!isFogOfWarEnabled(isSpaMode)) {
5052 return void 0;
5053 }
5054 return async ({ path, patch }) => {
5055 if (discoveredPaths.has(path)) {
5056 return;
5057 }
5058 await fetchAndApplyManifestPatches(
5059 [path],
5060 manifest,
5061 routeModules,
5062 isSpaMode,
5063 basename,
5064 patch
5065 );
5066 };
5067}
5068function useFogOFWarDiscovery(router2, manifest, routeModules, isSpaMode) {
5069 React8.useEffect(() => {
5070 if (!isFogOfWarEnabled(isSpaMode) || navigator.connection?.saveData === true) {
5071 return;
5072 }
5073 function registerElement(el) {
5074 let path = el.tagName === "FORM" ? el.getAttribute("action") : el.getAttribute("href");
5075 if (!path) {
5076 return;
5077 }
5078 let pathname = el.tagName === "A" ? el.pathname : new URL(path, window.location.origin).pathname;
5079 if (!discoveredPaths.has(pathname)) {
5080 nextPaths.add(pathname);
5081 }
5082 }
5083 async function fetchPatches() {
5084 document.querySelectorAll("a[data-discover], form[data-discover]").forEach(registerElement);
5085 let lazyPaths = Array.from(nextPaths.keys()).filter((path) => {
5086 if (discoveredPaths.has(path)) {
5087 nextPaths.delete(path);
5088 return false;
5089 }
5090 return true;
5091 });
5092 if (lazyPaths.length === 0) {
5093 return;
5094 }
5095 try {
5096 await fetchAndApplyManifestPatches(
5097 lazyPaths,
5098 manifest,
5099 routeModules,
5100 isSpaMode,
5101 router2.basename,
5102 router2.patchRoutes
5103 );
5104 } catch (e) {
5105 console.error("Failed to fetch manifest patches", e);
5106 }
5107 }
5108 let debouncedFetchPatches = debounce(fetchPatches, 100);
5109 fetchPatches();
5110 let observer = new MutationObserver(() => debouncedFetchPatches());
5111 observer.observe(document.documentElement, {
5112 subtree: true,
5113 childList: true,
5114 attributes: true,
5115 attributeFilter: ["data-discover", "href", "action"]
5116 });
5117 return () => observer.disconnect();
5118 }, [isSpaMode, manifest, routeModules, router2]);
5119}
5120async function fetchAndApplyManifestPatches(paths, manifest, routeModules, isSpaMode, basename, patchRoutes) {
5121 let manifestPath = `${basename != null ? basename : "/"}/__manifest`.replace(
5122 /\/+/g,
5123 "/"
5124 );
5125 let url = new URL(manifestPath, window.location.origin);
5126 paths.sort().forEach((path) => url.searchParams.append("p", path));
5127 url.searchParams.set("version", manifest.version);
5128 if (url.toString().length > URL_LIMIT) {
5129 nextPaths.clear();
5130 return;
5131 }
5132 let res = await fetch(url);
5133 if (!res.ok) {
5134 throw new Error(`${res.status} ${res.statusText}`);
5135 } else if (res.status >= 400) {
5136 throw new Error(await res.text());
5137 }
5138 let serverPatches = await res.json();
5139 let knownRoutes = new Set(Object.keys(manifest.routes));
5140 let patches = Object.values(serverPatches).reduce((acc, route) => {
5141 if (route && !knownRoutes.has(route.id)) {
5142 acc[route.id] = route;
5143 }
5144 return acc;
5145 }, {});
5146 Object.assign(manifest.routes, patches);
5147 paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
5148 let parentIds = /* @__PURE__ */ new Set();
5149 Object.values(patches).forEach((patch) => {
5150 if (patch && (!patch.parentId || !patches[patch.parentId])) {
5151 parentIds.add(patch.parentId);
5152 }
5153 });
5154 parentIds.forEach(
5155 (parentId) => patchRoutes(
5156 parentId || null,
5157 createClientRoutes(patches, routeModules, null, isSpaMode, parentId)
5158 )
5159 );
5160}
5161function addToFifoQueue(path, queue) {
5162 if (queue.size >= discoveredPathsMaxSize) {
5163 let first = queue.values().next().value;
5164 queue.delete(first);
5165 }
5166 queue.add(path);
5167}
5168function debounce(callback, wait) {
5169 let timeoutId;
5170 return (...args) => {
5171 window.clearTimeout(timeoutId);
5172 timeoutId = window.setTimeout(() => callback(...args), wait);
5173 };
5174}
5175
5176// lib/dom/ssr/components.tsx
5177function useDataRouterContext() {
5178 let context = React9.useContext(DataRouterContext);
5179 invariant2(
5180 context,
5181 "You must render this element inside a <DataRouterContext.Provider> element"
5182 );
5183 return context;
5184}
5185function useDataRouterStateContext() {
5186 let context = React9.useContext(DataRouterStateContext);
5187 invariant2(
5188 context,
5189 "You must render this element inside a <DataRouterStateContext.Provider> element"
5190 );
5191 return context;
5192}
5193var FrameworkContext = React9.createContext(void 0);
5194FrameworkContext.displayName = "FrameworkContext";
5195function useFrameworkContext() {
5196 let context = React9.useContext(FrameworkContext);
5197 invariant2(
5198 context,
5199 "You must render this element inside a <HydratedRouter> element"
5200 );
5201 return context;
5202}
5203function getActiveMatches(matches, errors, isSpaMode) {
5204 if (isSpaMode && !isHydrated) {
5205 return [matches[0]];
5206 }
5207 if (errors) {
5208 let errorIdx = matches.findIndex((m) => errors[m.route.id] !== void 0);
5209 return matches.slice(0, errorIdx + 1);
5210 }
5211 return matches;
5212}
5213var isHydrated = false;
5214function Scripts(props) {
5215 let { manifest, serverHandoffString, isSpaMode, renderMeta } = useFrameworkContext();
5216 let { router: router2, static: isStatic, staticContext } = useDataRouterContext();
5217 let { matches: routerMatches } = useDataRouterStateContext();
5218 let enableFogOfWar = isFogOfWarEnabled(isSpaMode);
5219 if (renderMeta) {
5220 renderMeta.didRenderScripts = true;
5221 }
5222 let matches = getActiveMatches(routerMatches, null, isSpaMode);
5223 React9.useEffect(() => {
5224 isHydrated = true;
5225 }, []);
5226 let initialScripts = React9.useMemo(() => {
5227 let streamScript = "window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());";
5228 let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};${streamScript}` : " ";
5229 let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
5230${matches.map(
5231 (match, index) => `import * as route${index} from ${JSON.stringify(
5232 manifest.routes[match.route.id].module
5233 )};`
5234 ).join("\n")}
5235 ${enableFogOfWar ? (
5236 // Inline a minimal manifest with the SSR matches
5237 `window.__reactRouterManifest = ${JSON.stringify(
5238 getPartialManifest(manifest, router2),
5239 null,
5240 2
5241 )};`
5242 ) : ""}
5243 window.__reactRouterRouteModules = {${matches.map((match, index) => `${JSON.stringify(match.route.id)}:route${index}`).join(",")}};
5244
5245import(${JSON.stringify(manifest.entry.module)});`;
5246 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
5247 "script",
5248 {
5249 ...props,
5250 suppressHydrationWarning: true,
5251 dangerouslySetInnerHTML: createHtml(contextScript),
5252 type: void 0
5253 }
5254 ), /* @__PURE__ */ React9.createElement(
5255 "script",
5256 {
5257 ...props,
5258 suppressHydrationWarning: true,
5259 dangerouslySetInnerHTML: createHtml(routeModulesScript),
5260 type: "module",
5261 async: true
5262 }
5263 ));
5264 }, []);
5265 let routePreloads = matches.map((match) => {
5266 let route = manifest.routes[match.route.id];
5267 return route ? (route.imports || []).concat([route.module]) : [];
5268 }).flat(1);
5269 let preloads = isHydrated ? [] : manifest.entry.imports.concat(routePreloads);
5270 return isHydrated ? null : /* @__PURE__ */ React9.createElement(React9.Fragment, null, !enableFogOfWar ? /* @__PURE__ */ React9.createElement(
5271 "link",
5272 {
5273 rel: "modulepreload",
5274 href: manifest.url,
5275 crossOrigin: props.crossOrigin
5276 }
5277 ) : null, /* @__PURE__ */ React9.createElement(
5278 "link",
5279 {
5280 rel: "modulepreload",
5281 href: manifest.entry.module,
5282 crossOrigin: props.crossOrigin
5283 }
5284 ), dedupe(preloads).map((path) => /* @__PURE__ */ React9.createElement(
5285 "link",
5286 {
5287 key: path,
5288 rel: "modulepreload",
5289 href: path,
5290 crossOrigin: props.crossOrigin
5291 }
5292 )), initialScripts);
5293}
5294function dedupe(array) {
5295 return [...new Set(array)];
5296}
5297
5298// lib/dom/ssr/errors.ts
5299function deserializeErrors(errors) {
5300 if (!errors) return null;
5301 let entries = Object.entries(errors);
5302 let serialized = {};
5303 for (let [key, val] of entries) {
5304 if (val && val.__type === "RouteErrorResponse") {
5305 serialized[key] = new ErrorResponseImpl(
5306 val.status,
5307 val.statusText,
5308 val.data,
5309 val.internal === true
5310 );
5311 } else if (val && val.__type === "Error") {
5312 if (val.__subType) {
5313 let ErrorConstructor = window[val.__subType];
5314 if (typeof ErrorConstructor === "function") {
5315 try {
5316 let error = new ErrorConstructor(val.message);
5317 error.stack = val.stack;
5318 serialized[key] = error;
5319 } catch (e) {
5320 }
5321 }
5322 }
5323 if (serialized[key] == null) {
5324 let error = new Error(val.message);
5325 error.stack = val.stack;
5326 serialized[key] = error;
5327 }
5328 } else {
5329 serialized[key] = val;
5330 }
5331 }
5332 return serialized;
5333}
5334
5335// lib/dom-export/dom-router-provider.tsx
5336function RouterProvider2(props) {
5337 return /* @__PURE__ */ React10.createElement(RouterProvider, { flushSync: ReactDOM.flushSync, ...props });
5338}
5339
5340// lib/dom-export/hydrated-router.tsx
5341var React11 = __toESM(require("react"));
5342var ssrInfo = null;
5343var router = null;
5344function initSsrInfo() {
5345 if (!ssrInfo && window.__reactRouterContext && window.__reactRouterManifest && window.__reactRouterRouteModules) {
5346 ssrInfo = {
5347 context: window.__reactRouterContext,
5348 manifest: window.__reactRouterManifest,
5349 routeModules: window.__reactRouterRouteModules,
5350 stateDecodingPromise: void 0,
5351 router: void 0,
5352 routerInitialized: false
5353 };
5354 }
5355}
5356function createHydratedRouter() {
5357 initSsrInfo();
5358 if (!ssrInfo) {
5359 throw new Error(
5360 "You must be using the SSR features of React Router in order to skip passing a `router` prop to `<RouterProvider>`"
5361 );
5362 }
5363 let localSsrInfo = ssrInfo;
5364 if (!ssrInfo.stateDecodingPromise) {
5365 let stream = ssrInfo.context.stream;
5366 invariant(stream, "No stream found for single fetch decoding");
5367 ssrInfo.context.stream = void 0;
5368 ssrInfo.stateDecodingPromise = decodeViaTurboStream(stream, window).then((value) => {
5369 ssrInfo.context.state = value.value;
5370 localSsrInfo.stateDecodingPromise.value = true;
5371 }).catch((e) => {
5372 localSsrInfo.stateDecodingPromise.error = e;
5373 });
5374 }
5375 if (ssrInfo.stateDecodingPromise.error) {
5376 throw ssrInfo.stateDecodingPromise.error;
5377 }
5378 if (!ssrInfo.stateDecodingPromise.value) {
5379 throw ssrInfo.stateDecodingPromise;
5380 }
5381 let routes = createClientRoutes(
5382 ssrInfo.manifest.routes,
5383 ssrInfo.routeModules,
5384 ssrInfo.context.state,
5385 ssrInfo.context.isSpaMode
5386 );
5387 let hydrationData = void 0;
5388 if (!ssrInfo.context.isSpaMode) {
5389 hydrationData = {
5390 ...ssrInfo.context.state,
5391 loaderData: { ...ssrInfo.context.state.loaderData }
5392 };
5393 let initialMatches = matchRoutes(
5394 routes,
5395 window.location,
5396 window.__reactRouterContext?.basename
5397 );
5398 if (initialMatches) {
5399 for (let match of initialMatches) {
5400 let routeId = match.route.id;
5401 let route = ssrInfo.routeModules[routeId];
5402 let manifestRoute = ssrInfo.manifest.routes[routeId];
5403 if (route && manifestRoute && shouldHydrateRouteLoader(
5404 manifestRoute,
5405 route,
5406 ssrInfo.context.isSpaMode
5407 ) && (route.HydrateFallback || !manifestRoute.hasLoader)) {
5408 delete hydrationData.loaderData[routeId];
5409 } else if (manifestRoute && !manifestRoute.hasLoader) {
5410 hydrationData.loaderData[routeId] = null;
5411 }
5412 }
5413 }
5414 if (hydrationData && hydrationData.errors) {
5415 hydrationData.errors = deserializeErrors(hydrationData.errors);
5416 }
5417 }
5418 let router2 = createRouter({
5419 routes,
5420 history: createBrowserHistory(),
5421 basename: ssrInfo.context.basename,
5422 hydrationData,
5423 mapRouteProperties,
5424 dataStrategy: getSingleFetchDataStrategy(
5425 ssrInfo.manifest,
5426 ssrInfo.routeModules,
5427 () => router2
5428 ),
5429 patchRoutesOnNavigation: getPatchRoutesOnNavigationFunction(
5430 ssrInfo.manifest,
5431 ssrInfo.routeModules,
5432 ssrInfo.context.isSpaMode,
5433 ssrInfo.context.basename
5434 )
5435 });
5436 ssrInfo.router = router2;
5437 if (router2.state.initialized) {
5438 ssrInfo.routerInitialized = true;
5439 router2.initialize();
5440 }
5441 router2.createRoutesForHMR = /* spacer so ts-ignore does not affect the right hand of the assignment */
5442 createClientRoutesWithHMRRevalidationOptOut;
5443 window.__reactRouterDataRouter = router2;
5444 return router2;
5445}
5446function HydratedRouter() {
5447 if (!router) {
5448 router = createHydratedRouter();
5449 }
5450 let [criticalCss, setCriticalCss] = React11.useState(
5451 process.env.NODE_ENV === "development" ? ssrInfo?.context.criticalCss : void 0
5452 );
5453 if (process.env.NODE_ENV === "development") {
5454 if (ssrInfo) {
5455 window.__reactRouterClearCriticalCss = () => setCriticalCss(void 0);
5456 }
5457 }
5458 let [location, setLocation] = React11.useState(router.state.location);
5459 React11.useLayoutEffect(() => {
5460 if (ssrInfo && ssrInfo.router && !ssrInfo.routerInitialized) {
5461 ssrInfo.routerInitialized = true;
5462 ssrInfo.router.initialize();
5463 }
5464 }, []);
5465 React11.useLayoutEffect(() => {
5466 if (ssrInfo && ssrInfo.router) {
5467 return ssrInfo.router.subscribe((newState) => {
5468 if (newState.location !== location) {
5469 setLocation(newState.location);
5470 }
5471 });
5472 }
5473 }, [location]);
5474 invariant(ssrInfo, "ssrInfo unavailable for HydratedRouter");
5475 useFogOFWarDiscovery(
5476 router,
5477 ssrInfo.manifest,
5478 ssrInfo.routeModules,
5479 ssrInfo.context.isSpaMode
5480 );
5481 return (
5482 // This fragment is important to ensure we match the <ServerRouter> JSX
5483 // structure so that useId values hydrate correctly
5484 /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(
5485 FrameworkContext.Provider,
5486 {
5487 value: {
5488 manifest: ssrInfo.manifest,
5489 routeModules: ssrInfo.routeModules,
5490 future: ssrInfo.context.future,
5491 criticalCss,
5492 isSpaMode: ssrInfo.context.isSpaMode
5493 }
5494 },
5495 /* @__PURE__ */ React11.createElement(RemixErrorBoundary, { location }, /* @__PURE__ */ React11.createElement(RouterProvider2, { router }))
5496 ), /* @__PURE__ */ React11.createElement(React11.Fragment, null))
5497 );
5498}
5499// Annotate the CommonJS export names for ESM import in node:
55000 && (module.exports = {
5501 HydratedRouter,
5502 RouterProvider
5503});