UNPKG

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