UNPKG

326 kBJavaScriptView Raw
1/**
2 * react-router v7.7.1
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 */
11var __typeError = (msg) => {
12 throw TypeError(msg);
13};
14var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
15var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
16var __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);
17
18// lib/router/history.ts
19var Action = /* @__PURE__ */ ((Action2) => {
20 Action2["Pop"] = "POP";
21 Action2["Push"] = "PUSH";
22 Action2["Replace"] = "REPLACE";
23 return Action2;
24})(Action || {});
25var PopStateEventType = "popstate";
26function createMemoryHistory(options = {}) {
27 let { initialEntries = ["/"], initialIndex, v5Compat = false } = options;
28 let entries;
29 entries = initialEntries.map(
30 (entry, index2) => createMemoryLocation(
31 entry,
32 typeof entry === "string" ? null : entry.state,
33 index2 === 0 ? "default" : void 0
34 )
35 );
36 let index = clampIndex(
37 initialIndex == null ? entries.length - 1 : initialIndex
38 );
39 let action = "POP" /* Pop */;
40 let listener = null;
41 function clampIndex(n) {
42 return Math.min(Math.max(n, 0), entries.length - 1);
43 }
44 function getCurrentLocation() {
45 return entries[index];
46 }
47 function createMemoryLocation(to, state = null, key) {
48 let location = createLocation(
49 entries ? getCurrentLocation().pathname : "/",
50 to,
51 state,
52 key
53 );
54 warning(
55 location.pathname.charAt(0) === "/",
56 `relative pathnames are not supported in memory history: ${JSON.stringify(
57 to
58 )}`
59 );
60 return location;
61 }
62 function createHref2(to) {
63 return typeof to === "string" ? to : createPath(to);
64 }
65 let history = {
66 get index() {
67 return index;
68 },
69 get action() {
70 return action;
71 },
72 get location() {
73 return getCurrentLocation();
74 },
75 createHref: createHref2,
76 createURL(to) {
77 return new URL(createHref2(to), "http://localhost");
78 },
79 encodeLocation(to) {
80 let path = typeof to === "string" ? parsePath(to) : to;
81 return {
82 pathname: path.pathname || "",
83 search: path.search || "",
84 hash: path.hash || ""
85 };
86 },
87 push(to, state) {
88 action = "PUSH" /* Push */;
89 let nextLocation = createMemoryLocation(to, state);
90 index += 1;
91 entries.splice(index, entries.length, nextLocation);
92 if (v5Compat && listener) {
93 listener({ action, location: nextLocation, delta: 1 });
94 }
95 },
96 replace(to, state) {
97 action = "REPLACE" /* Replace */;
98 let nextLocation = createMemoryLocation(to, state);
99 entries[index] = nextLocation;
100 if (v5Compat && listener) {
101 listener({ action, location: nextLocation, delta: 0 });
102 }
103 },
104 go(delta) {
105 action = "POP" /* Pop */;
106 let nextIndex = clampIndex(index + delta);
107 let nextLocation = entries[nextIndex];
108 index = nextIndex;
109 if (listener) {
110 listener({ action, location: nextLocation, delta });
111 }
112 },
113 listen(fn) {
114 listener = fn;
115 return () => {
116 listener = null;
117 };
118 }
119 };
120 return history;
121}
122function createBrowserHistory(options = {}) {
123 function createBrowserLocation(window2, globalHistory) {
124 let { pathname, search, hash } = window2.location;
125 return createLocation(
126 "",
127 { pathname, search, hash },
128 // state defaults to `null` because `window.history.state` does
129 globalHistory.state && globalHistory.state.usr || null,
130 globalHistory.state && globalHistory.state.key || "default"
131 );
132 }
133 function createBrowserHref(window2, to) {
134 return typeof to === "string" ? to : createPath(to);
135 }
136 return getUrlBasedHistory(
137 createBrowserLocation,
138 createBrowserHref,
139 null,
140 options
141 );
142}
143function createHashHistory(options = {}) {
144 function createHashLocation(window2, globalHistory) {
145 let {
146 pathname = "/",
147 search = "",
148 hash = ""
149 } = parsePath(window2.location.hash.substring(1));
150 if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
151 pathname = "/" + pathname;
152 }
153 return createLocation(
154 "",
155 { pathname, search, hash },
156 // state defaults to `null` because `window.history.state` does
157 globalHistory.state && globalHistory.state.usr || null,
158 globalHistory.state && globalHistory.state.key || "default"
159 );
160 }
161 function createHashHref(window2, to) {
162 let base = window2.document.querySelector("base");
163 let href = "";
164 if (base && base.getAttribute("href")) {
165 let url = window2.location.href;
166 let hashIndex = url.indexOf("#");
167 href = hashIndex === -1 ? url : url.slice(0, hashIndex);
168 }
169 return href + "#" + (typeof to === "string" ? to : createPath(to));
170 }
171 function validateHashLocation(location, to) {
172 warning(
173 location.pathname.charAt(0) === "/",
174 `relative pathnames are not supported in hash history.push(${JSON.stringify(
175 to
176 )})`
177 );
178 }
179 return getUrlBasedHistory(
180 createHashLocation,
181 createHashHref,
182 validateHashLocation,
183 options
184 );
185}
186function invariant(value, message) {
187 if (value === false || value === null || typeof value === "undefined") {
188 throw new Error(message);
189 }
190}
191function warning(cond, message) {
192 if (!cond) {
193 if (typeof console !== "undefined") console.warn(message);
194 try {
195 throw new Error(message);
196 } catch (e) {
197 }
198 }
199}
200function createKey() {
201 return Math.random().toString(36).substring(2, 10);
202}
203function getHistoryState(location, index) {
204 return {
205 usr: location.state,
206 key: location.key,
207 idx: index
208 };
209}
210function createLocation(current, to, state = null, key) {
211 let location = {
212 pathname: typeof current === "string" ? current : current.pathname,
213 search: "",
214 hash: "",
215 ...typeof to === "string" ? parsePath(to) : to,
216 state,
217 // TODO: This could be cleaned up. push/replace should probably just take
218 // full Locations now and avoid the need to run through this flow at all
219 // But that's a pretty big refactor to the current test suite so going to
220 // keep as is for the time being and just let any incoming keys take precedence
221 key: to && to.key || key || createKey()
222 };
223 return location;
224}
225function createPath({
226 pathname = "/",
227 search = "",
228 hash = ""
229}) {
230 if (search && search !== "?")
231 pathname += search.charAt(0) === "?" ? search : "?" + search;
232 if (hash && hash !== "#")
233 pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
234 return pathname;
235}
236function parsePath(path) {
237 let parsedPath = {};
238 if (path) {
239 let hashIndex = path.indexOf("#");
240 if (hashIndex >= 0) {
241 parsedPath.hash = path.substring(hashIndex);
242 path = path.substring(0, hashIndex);
243 }
244 let searchIndex = path.indexOf("?");
245 if (searchIndex >= 0) {
246 parsedPath.search = path.substring(searchIndex);
247 path = path.substring(0, searchIndex);
248 }
249 if (path) {
250 parsedPath.pathname = path;
251 }
252 }
253 return parsedPath;
254}
255function getUrlBasedHistory(getLocation, createHref2, validateLocation, options = {}) {
256 let { window: window2 = document.defaultView, v5Compat = false } = options;
257 let globalHistory = window2.history;
258 let action = "POP" /* Pop */;
259 let listener = null;
260 let index = getIndex();
261 if (index == null) {
262 index = 0;
263 globalHistory.replaceState({ ...globalHistory.state, idx: index }, "");
264 }
265 function getIndex() {
266 let state = globalHistory.state || { idx: null };
267 return state.idx;
268 }
269 function handlePop() {
270 action = "POP" /* Pop */;
271 let nextIndex = getIndex();
272 let delta = nextIndex == null ? null : nextIndex - index;
273 index = nextIndex;
274 if (listener) {
275 listener({ action, location: history.location, delta });
276 }
277 }
278 function push(to, state) {
279 action = "PUSH" /* Push */;
280 let location = createLocation(history.location, to, state);
281 if (validateLocation) validateLocation(location, to);
282 index = getIndex() + 1;
283 let historyState = getHistoryState(location, index);
284 let url = history.createHref(location);
285 try {
286 globalHistory.pushState(historyState, "", url);
287 } catch (error) {
288 if (error instanceof DOMException && error.name === "DataCloneError") {
289 throw error;
290 }
291 window2.location.assign(url);
292 }
293 if (v5Compat && listener) {
294 listener({ action, location: history.location, delta: 1 });
295 }
296 }
297 function replace2(to, state) {
298 action = "REPLACE" /* Replace */;
299 let location = createLocation(history.location, to, state);
300 if (validateLocation) validateLocation(location, to);
301 index = getIndex();
302 let historyState = getHistoryState(location, index);
303 let url = history.createHref(location);
304 globalHistory.replaceState(historyState, "", url);
305 if (v5Compat && listener) {
306 listener({ action, location: history.location, delta: 0 });
307 }
308 }
309 function createURL(to) {
310 return createBrowserURLImpl(to);
311 }
312 let history = {
313 get action() {
314 return action;
315 },
316 get location() {
317 return getLocation(window2, globalHistory);
318 },
319 listen(fn) {
320 if (listener) {
321 throw new Error("A history only accepts one active listener");
322 }
323 window2.addEventListener(PopStateEventType, handlePop);
324 listener = fn;
325 return () => {
326 window2.removeEventListener(PopStateEventType, handlePop);
327 listener = null;
328 };
329 },
330 createHref(to) {
331 return createHref2(window2, to);
332 },
333 createURL,
334 encodeLocation(to) {
335 let url = createURL(to);
336 return {
337 pathname: url.pathname,
338 search: url.search,
339 hash: url.hash
340 };
341 },
342 push,
343 replace: replace2,
344 go(n) {
345 return globalHistory.go(n);
346 }
347 };
348 return history;
349}
350function createBrowserURLImpl(to, isAbsolute = false) {
351 let base = "http://localhost";
352 if (typeof window !== "undefined") {
353 base = window.location.origin !== "null" ? window.location.origin : window.location.href;
354 }
355 invariant(base, "No window.location.(origin|href) available to create URL");
356 let href = typeof to === "string" ? to : createPath(to);
357 href = href.replace(/ $/, "%20");
358 if (!isAbsolute && href.startsWith("//")) {
359 href = base + href;
360 }
361 return new URL(href, base);
362}
363
364// lib/router/utils.ts
365function unstable_createContext(defaultValue) {
366 return { defaultValue };
367}
368var _map;
369var unstable_RouterContextProvider = class {
370 constructor(init) {
371 __privateAdd(this, _map, /* @__PURE__ */ new Map());
372 if (init) {
373 for (let [context, value] of init) {
374 this.set(context, value);
375 }
376 }
377 }
378 get(context) {
379 if (__privateGet(this, _map).has(context)) {
380 return __privateGet(this, _map).get(context);
381 }
382 if (context.defaultValue !== void 0) {
383 return context.defaultValue;
384 }
385 throw new Error("No value found for context");
386 }
387 set(context, value) {
388 __privateGet(this, _map).set(context, value);
389 }
390};
391_map = new WeakMap();
392var unsupportedLazyRouteObjectKeys = /* @__PURE__ */ new Set([
393 "lazy",
394 "caseSensitive",
395 "path",
396 "id",
397 "index",
398 "children"
399]);
400function isUnsupportedLazyRouteObjectKey(key) {
401 return unsupportedLazyRouteObjectKeys.has(
402 key
403 );
404}
405var unsupportedLazyRouteFunctionKeys = /* @__PURE__ */ new Set([
406 "lazy",
407 "caseSensitive",
408 "path",
409 "id",
410 "index",
411 "unstable_middleware",
412 "children"
413]);
414function isUnsupportedLazyRouteFunctionKey(key) {
415 return unsupportedLazyRouteFunctionKeys.has(
416 key
417 );
418}
419function isIndexRoute(route) {
420 return route.index === true;
421}
422function convertRoutesToDataRoutes(routes, mapRouteProperties2, parentPath = [], manifest = {}, allowInPlaceMutations = false) {
423 return routes.map((route, index) => {
424 let treePath = [...parentPath, String(index)];
425 let id = typeof route.id === "string" ? route.id : treePath.join("-");
426 invariant(
427 route.index !== true || !route.children,
428 `Cannot specify children on an index route`
429 );
430 invariant(
431 allowInPlaceMutations || !manifest[id],
432 `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages`
433 );
434 if (isIndexRoute(route)) {
435 let indexRoute = {
436 ...route,
437 ...mapRouteProperties2(route),
438 id
439 };
440 manifest[id] = indexRoute;
441 return indexRoute;
442 } else {
443 let pathOrLayoutRoute = {
444 ...route,
445 ...mapRouteProperties2(route),
446 id,
447 children: void 0
448 };
449 manifest[id] = pathOrLayoutRoute;
450 if (route.children) {
451 pathOrLayoutRoute.children = convertRoutesToDataRoutes(
452 route.children,
453 mapRouteProperties2,
454 treePath,
455 manifest,
456 allowInPlaceMutations
457 );
458 }
459 return pathOrLayoutRoute;
460 }
461 });
462}
463function matchRoutes(routes, locationArg, basename = "/") {
464 return matchRoutesImpl(routes, locationArg, basename, false);
465}
466function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
467 let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
468 let pathname = stripBasename(location.pathname || "/", basename);
469 if (pathname == null) {
470 return null;
471 }
472 let branches = flattenRoutes(routes);
473 rankRouteBranches(branches);
474 let matches = null;
475 for (let i = 0; matches == null && i < branches.length; ++i) {
476 let decoded = decodePath(pathname);
477 matches = matchRouteBranch(
478 branches[i],
479 decoded,
480 allowPartial
481 );
482 }
483 return matches;
484}
485function convertRouteMatchToUiMatch(match, loaderData) {
486 let { route, pathname, params } = match;
487 return {
488 id: route.id,
489 pathname,
490 params,
491 data: loaderData[route.id],
492 handle: route.handle
493 };
494}
495function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
496 let flattenRoute = (route, index, relativePath) => {
497 let meta = {
498 relativePath: relativePath === void 0 ? route.path || "" : relativePath,
499 caseSensitive: route.caseSensitive === true,
500 childrenIndex: index,
501 route
502 };
503 if (meta.relativePath.startsWith("/")) {
504 invariant(
505 meta.relativePath.startsWith(parentPath),
506 `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.`
507 );
508 meta.relativePath = meta.relativePath.slice(parentPath.length);
509 }
510 let path = joinPaths([parentPath, meta.relativePath]);
511 let routesMeta = parentsMeta.concat(meta);
512 if (route.children && route.children.length > 0) {
513 invariant(
514 // Our types know better, but runtime JS may not!
515 // @ts-expect-error
516 route.index !== true,
517 `Index routes must not have child routes. Please remove all child routes from route path "${path}".`
518 );
519 flattenRoutes(route.children, branches, routesMeta, path);
520 }
521 if (route.path == null && !route.index) {
522 return;
523 }
524 branches.push({
525 path,
526 score: computeScore(path, route.index),
527 routesMeta
528 });
529 };
530 routes.forEach((route, index) => {
531 if (route.path === "" || !route.path?.includes("?")) {
532 flattenRoute(route, index);
533 } else {
534 for (let exploded of explodeOptionalSegments(route.path)) {
535 flattenRoute(route, index, exploded);
536 }
537 }
538 });
539 return branches;
540}
541function explodeOptionalSegments(path) {
542 let segments = path.split("/");
543 if (segments.length === 0) return [];
544 let [first, ...rest] = segments;
545 let isOptional = first.endsWith("?");
546 let required = first.replace(/\?$/, "");
547 if (rest.length === 0) {
548 return isOptional ? [required, ""] : [required];
549 }
550 let restExploded = explodeOptionalSegments(rest.join("/"));
551 let result = [];
552 result.push(
553 ...restExploded.map(
554 (subpath) => subpath === "" ? required : [required, subpath].join("/")
555 )
556 );
557 if (isOptional) {
558 result.push(...restExploded);
559 }
560 return result.map(
561 (exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded
562 );
563}
564function rankRouteBranches(branches) {
565 branches.sort(
566 (a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(
567 a.routesMeta.map((meta) => meta.childrenIndex),
568 b.routesMeta.map((meta) => meta.childrenIndex)
569 )
570 );
571}
572var paramRe = /^:[\w-]+$/;
573var dynamicSegmentValue = 3;
574var indexRouteValue = 2;
575var emptySegmentValue = 1;
576var staticSegmentValue = 10;
577var splatPenalty = -2;
578var isSplat = (s) => s === "*";
579function computeScore(path, index) {
580 let segments = path.split("/");
581 let initialScore = segments.length;
582 if (segments.some(isSplat)) {
583 initialScore += splatPenalty;
584 }
585 if (index) {
586 initialScore += indexRouteValue;
587 }
588 return segments.filter((s) => !isSplat(s)).reduce(
589 (score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue),
590 initialScore
591 );
592}
593function compareIndexes(a, b) {
594 let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
595 return siblings ? (
596 // If two routes are siblings, we should try to match the earlier sibling
597 // first. This allows people to have fine-grained control over the matching
598 // behavior by simply putting routes with identical paths in the order they
599 // want them tried.
600 a[a.length - 1] - b[b.length - 1]
601 ) : (
602 // Otherwise, it doesn't really make sense to rank non-siblings by index,
603 // so they sort equally.
604 0
605 );
606}
607function matchRouteBranch(branch, pathname, allowPartial = false) {
608 let { routesMeta } = branch;
609 let matchedParams = {};
610 let matchedPathname = "/";
611 let matches = [];
612 for (let i = 0; i < routesMeta.length; ++i) {
613 let meta = routesMeta[i];
614 let end = i === routesMeta.length - 1;
615 let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
616 let match = matchPath(
617 { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },
618 remainingPathname
619 );
620 let route = meta.route;
621 if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
622 match = matchPath(
623 {
624 path: meta.relativePath,
625 caseSensitive: meta.caseSensitive,
626 end: false
627 },
628 remainingPathname
629 );
630 }
631 if (!match) {
632 return null;
633 }
634 Object.assign(matchedParams, match.params);
635 matches.push({
636 // TODO: Can this as be avoided?
637 params: matchedParams,
638 pathname: joinPaths([matchedPathname, match.pathname]),
639 pathnameBase: normalizePathname(
640 joinPaths([matchedPathname, match.pathnameBase])
641 ),
642 route
643 });
644 if (match.pathnameBase !== "/") {
645 matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
646 }
647 }
648 return matches;
649}
650function generatePath(originalPath, params = {}) {
651 let path = originalPath;
652 if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
653 warning(
654 false,
655 `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(/\*$/, "/*")}".`
656 );
657 path = path.replace(/\*$/, "/*");
658 }
659 const prefix = path.startsWith("/") ? "/" : "";
660 const stringify2 = (p) => p == null ? "" : typeof p === "string" ? p : String(p);
661 const segments = path.split(/\/+/).map((segment, index, array) => {
662 const isLastSegment = index === array.length - 1;
663 if (isLastSegment && segment === "*") {
664 const star = "*";
665 return stringify2(params[star]);
666 }
667 const keyMatch = segment.match(/^:([\w-]+)(\??)$/);
668 if (keyMatch) {
669 const [, key, optional] = keyMatch;
670 let param = params[key];
671 invariant(optional === "?" || param != null, `Missing ":${key}" param`);
672 return stringify2(param);
673 }
674 return segment.replace(/\?$/g, "");
675 }).filter((segment) => !!segment);
676 return prefix + segments.join("/");
677}
678function matchPath(pattern, pathname) {
679 if (typeof pattern === "string") {
680 pattern = { path: pattern, caseSensitive: false, end: true };
681 }
682 let [matcher, compiledParams] = compilePath(
683 pattern.path,
684 pattern.caseSensitive,
685 pattern.end
686 );
687 let match = pathname.match(matcher);
688 if (!match) return null;
689 let matchedPathname = match[0];
690 let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
691 let captureGroups = match.slice(1);
692 let params = compiledParams.reduce(
693 (memo2, { paramName, isOptional }, index) => {
694 if (paramName === "*") {
695 let splatValue = captureGroups[index] || "";
696 pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
697 }
698 const value = captureGroups[index];
699 if (isOptional && !value) {
700 memo2[paramName] = void 0;
701 } else {
702 memo2[paramName] = (value || "").replace(/%2F/g, "/");
703 }
704 return memo2;
705 },
706 {}
707 );
708 return {
709 params,
710 pathname: matchedPathname,
711 pathnameBase,
712 pattern
713 };
714}
715function compilePath(path, caseSensitive = false, end = true) {
716 warning(
717 path === "*" || !path.endsWith("*") || path.endsWith("/*"),
718 `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(/\*$/, "/*")}".`
719 );
720 let params = [];
721 let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(
722 /\/:([\w-]+)(\?)?/g,
723 (_, paramName, isOptional) => {
724 params.push({ paramName, isOptional: isOptional != null });
725 return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
726 }
727 );
728 if (path.endsWith("*")) {
729 params.push({ paramName: "*" });
730 regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
731 } else if (end) {
732 regexpSource += "\\/*$";
733 } else if (path !== "" && path !== "/") {
734 regexpSource += "(?:(?=\\/|$))";
735 } else {
736 }
737 let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
738 return [matcher, params];
739}
740function decodePath(value) {
741 try {
742 return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
743 } catch (error) {
744 warning(
745 false,
746 `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}).`
747 );
748 return value;
749 }
750}
751function stripBasename(pathname, basename) {
752 if (basename === "/") return pathname;
753 if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
754 return null;
755 }
756 let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
757 let nextChar = pathname.charAt(startIndex);
758 if (nextChar && nextChar !== "/") {
759 return null;
760 }
761 return pathname.slice(startIndex) || "/";
762}
763function prependBasename({
764 basename,
765 pathname
766}) {
767 return pathname === "/" ? basename : joinPaths([basename, pathname]);
768}
769function resolvePath(to, fromPathname = "/") {
770 let {
771 pathname: toPathname,
772 search = "",
773 hash = ""
774 } = typeof to === "string" ? parsePath(to) : to;
775 let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
776 return {
777 pathname,
778 search: normalizeSearch(search),
779 hash: normalizeHash(hash)
780 };
781}
782function resolvePathname(relativePath, fromPathname) {
783 let segments = fromPathname.replace(/\/+$/, "").split("/");
784 let relativeSegments = relativePath.split("/");
785 relativeSegments.forEach((segment) => {
786 if (segment === "..") {
787 if (segments.length > 1) segments.pop();
788 } else if (segment !== ".") {
789 segments.push(segment);
790 }
791 });
792 return segments.length > 1 ? segments.join("/") : "/";
793}
794function getInvalidPathError(char, field, dest, path) {
795 return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(
796 path
797 )}]. 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.`;
798}
799function getPathContributingMatches(matches) {
800 return matches.filter(
801 (match, index) => index === 0 || match.route.path && match.route.path.length > 0
802 );
803}
804function getResolveToMatches(matches) {
805 let pathMatches = getPathContributingMatches(matches);
806 return pathMatches.map(
807 (match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase
808 );
809}
810function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
811 let to;
812 if (typeof toArg === "string") {
813 to = parsePath(toArg);
814 } else {
815 to = { ...toArg };
816 invariant(
817 !to.pathname || !to.pathname.includes("?"),
818 getInvalidPathError("?", "pathname", "search", to)
819 );
820 invariant(
821 !to.pathname || !to.pathname.includes("#"),
822 getInvalidPathError("#", "pathname", "hash", to)
823 );
824 invariant(
825 !to.search || !to.search.includes("#"),
826 getInvalidPathError("#", "search", "hash", to)
827 );
828 }
829 let isEmptyPath = toArg === "" || to.pathname === "";
830 let toPathname = isEmptyPath ? "/" : to.pathname;
831 let from;
832 if (toPathname == null) {
833 from = locationPathname;
834 } else {
835 let routePathnameIndex = routePathnames.length - 1;
836 if (!isPathRelative && toPathname.startsWith("..")) {
837 let toSegments = toPathname.split("/");
838 while (toSegments[0] === "..") {
839 toSegments.shift();
840 routePathnameIndex -= 1;
841 }
842 to.pathname = toSegments.join("/");
843 }
844 from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
845 }
846 let path = resolvePath(to, from);
847 let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
848 let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
849 if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
850 path.pathname += "/";
851 }
852 return path;
853}
854var joinPaths = (paths) => paths.join("/").replace(/\/\/+/g, "/");
855var normalizePathname = (pathname) => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
856var normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
857var normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
858var DataWithResponseInit = class {
859 constructor(data2, init) {
860 this.type = "DataWithResponseInit";
861 this.data = data2;
862 this.init = init || null;
863 }
864};
865function data(data2, init) {
866 return new DataWithResponseInit(
867 data2,
868 typeof init === "number" ? { status: init } : init
869 );
870}
871var redirect = (url, init = 302) => {
872 let responseInit = init;
873 if (typeof responseInit === "number") {
874 responseInit = { status: responseInit };
875 } else if (typeof responseInit.status === "undefined") {
876 responseInit.status = 302;
877 }
878 let headers = new Headers(responseInit.headers);
879 headers.set("Location", url);
880 return new Response(null, { ...responseInit, headers });
881};
882var redirectDocument = (url, init) => {
883 let response = redirect(url, init);
884 response.headers.set("X-Remix-Reload-Document", "true");
885 return response;
886};
887var replace = (url, init) => {
888 let response = redirect(url, init);
889 response.headers.set("X-Remix-Replace", "true");
890 return response;
891};
892var ErrorResponseImpl = class {
893 constructor(status, statusText, data2, internal = false) {
894 this.status = status;
895 this.statusText = statusText || "";
896 this.internal = internal;
897 if (data2 instanceof Error) {
898 this.data = data2.toString();
899 this.error = data2;
900 } else {
901 this.data = data2;
902 }
903 }
904};
905function isRouteErrorResponse(error) {
906 return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
907}
908
909// lib/router/router.ts
910var validMutationMethodsArr = [
911 "POST",
912 "PUT",
913 "PATCH",
914 "DELETE"
915];
916var validMutationMethods = new Set(
917 validMutationMethodsArr
918);
919var validRequestMethodsArr = [
920 "GET",
921 ...validMutationMethodsArr
922];
923var validRequestMethods = new Set(validRequestMethodsArr);
924var redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
925var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set([307, 308]);
926var IDLE_NAVIGATION = {
927 state: "idle",
928 location: void 0,
929 formMethod: void 0,
930 formAction: void 0,
931 formEncType: void 0,
932 formData: void 0,
933 json: void 0,
934 text: void 0
935};
936var IDLE_FETCHER = {
937 state: "idle",
938 data: void 0,
939 formMethod: void 0,
940 formAction: void 0,
941 formEncType: void 0,
942 formData: void 0,
943 json: void 0,
944 text: void 0
945};
946var IDLE_BLOCKER = {
947 state: "unblocked",
948 proceed: void 0,
949 reset: void 0,
950 location: void 0
951};
952var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
953var isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
954var defaultMapRouteProperties = (route) => ({
955 hasErrorBoundary: Boolean(route.hasErrorBoundary)
956});
957var TRANSITIONS_STORAGE_KEY = "remix-router-transitions";
958var ResetLoaderDataSymbol = Symbol("ResetLoaderData");
959function createRouter(init) {
960 const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : void 0;
961 const isBrowser2 = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
962 invariant(
963 init.routes.length > 0,
964 "You must provide a non-empty routes array to createRouter"
965 );
966 let hydrationRouteProperties2 = init.hydrationRouteProperties || [];
967 let mapRouteProperties2 = init.mapRouteProperties || defaultMapRouteProperties;
968 let manifest = {};
969 let dataRoutes = convertRoutesToDataRoutes(
970 init.routes,
971 mapRouteProperties2,
972 void 0,
973 manifest
974 );
975 let inFlightDataRoutes;
976 let basename = init.basename || "/";
977 let dataStrategyImpl = init.dataStrategy || defaultDataStrategyWithMiddleware;
978 let future = {
979 unstable_middleware: false,
980 ...init.future
981 };
982 let unlistenHistory = null;
983 let subscribers = /* @__PURE__ */ new Set();
984 let savedScrollPositions2 = null;
985 let getScrollRestorationKey2 = null;
986 let getScrollPosition = null;
987 let initialScrollRestored = init.hydrationData != null;
988 let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
989 let initialMatchesIsFOW = false;
990 let initialErrors = null;
991 let initialized;
992 if (initialMatches == null && !init.patchRoutesOnNavigation) {
993 let error = getInternalRouterError(404, {
994 pathname: init.history.location.pathname
995 });
996 let { matches, route } = getShortCircuitMatches(dataRoutes);
997 initialized = true;
998 initialMatches = matches;
999 initialErrors = { [route.id]: error };
1000 } else {
1001 if (initialMatches && !init.hydrationData) {
1002 let fogOfWar = checkFogOfWar(
1003 initialMatches,
1004 dataRoutes,
1005 init.history.location.pathname
1006 );
1007 if (fogOfWar.active) {
1008 initialMatches = null;
1009 }
1010 }
1011 if (!initialMatches) {
1012 initialized = false;
1013 initialMatches = [];
1014 let fogOfWar = checkFogOfWar(
1015 null,
1016 dataRoutes,
1017 init.history.location.pathname
1018 );
1019 if (fogOfWar.active && fogOfWar.matches) {
1020 initialMatchesIsFOW = true;
1021 initialMatches = fogOfWar.matches;
1022 }
1023 } else if (initialMatches.some((m) => m.route.lazy)) {
1024 initialized = false;
1025 } else if (!initialMatches.some((m) => m.route.loader)) {
1026 initialized = true;
1027 } else {
1028 let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
1029 let errors = init.hydrationData ? init.hydrationData.errors : null;
1030 if (errors) {
1031 let idx = initialMatches.findIndex(
1032 (m) => errors[m.route.id] !== void 0
1033 );
1034 initialized = initialMatches.slice(0, idx + 1).every(
1035 (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors)
1036 );
1037 } else {
1038 initialized = initialMatches.every(
1039 (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors)
1040 );
1041 }
1042 }
1043 }
1044 let router;
1045 let state = {
1046 historyAction: init.history.action,
1047 location: init.history.location,
1048 matches: initialMatches,
1049 initialized,
1050 navigation: IDLE_NAVIGATION,
1051 // Don't restore on initial updateState() if we were SSR'd
1052 restoreScrollPosition: init.hydrationData != null ? false : null,
1053 preventScrollReset: false,
1054 revalidation: "idle",
1055 loaderData: init.hydrationData && init.hydrationData.loaderData || {},
1056 actionData: init.hydrationData && init.hydrationData.actionData || null,
1057 errors: init.hydrationData && init.hydrationData.errors || initialErrors,
1058 fetchers: /* @__PURE__ */ new Map(),
1059 blockers: /* @__PURE__ */ new Map()
1060 };
1061 let pendingAction = "POP" /* Pop */;
1062 let pendingPreventScrollReset = false;
1063 let pendingNavigationController;
1064 let pendingViewTransitionEnabled = false;
1065 let appliedViewTransitions = /* @__PURE__ */ new Map();
1066 let removePageHideEventListener = null;
1067 let isUninterruptedRevalidation = false;
1068 let isRevalidationRequired = false;
1069 let cancelledFetcherLoads = /* @__PURE__ */ new Set();
1070 let fetchControllers = /* @__PURE__ */ new Map();
1071 let incrementingLoadId = 0;
1072 let pendingNavigationLoadId = -1;
1073 let fetchReloadIds = /* @__PURE__ */ new Map();
1074 let fetchRedirectIds = /* @__PURE__ */ new Set();
1075 let fetchLoadMatches = /* @__PURE__ */ new Map();
1076 let activeFetchers = /* @__PURE__ */ new Map();
1077 let fetchersQueuedForDeletion = /* @__PURE__ */ new Set();
1078 let blockerFunctions = /* @__PURE__ */ new Map();
1079 let unblockBlockerHistoryUpdate = void 0;
1080 let pendingRevalidationDfd = null;
1081 function initialize() {
1082 unlistenHistory = init.history.listen(
1083 ({ action: historyAction, location, delta }) => {
1084 if (unblockBlockerHistoryUpdate) {
1085 unblockBlockerHistoryUpdate();
1086 unblockBlockerHistoryUpdate = void 0;
1087 return;
1088 }
1089 warning(
1090 blockerFunctions.size === 0 || delta != null,
1091 "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."
1092 );
1093 let blockerKey = shouldBlockNavigation({
1094 currentLocation: state.location,
1095 nextLocation: location,
1096 historyAction
1097 });
1098 if (blockerKey && delta != null) {
1099 let nextHistoryUpdatePromise = new Promise((resolve) => {
1100 unblockBlockerHistoryUpdate = resolve;
1101 });
1102 init.history.go(delta * -1);
1103 updateBlocker(blockerKey, {
1104 state: "blocked",
1105 location,
1106 proceed() {
1107 updateBlocker(blockerKey, {
1108 state: "proceeding",
1109 proceed: void 0,
1110 reset: void 0,
1111 location
1112 });
1113 nextHistoryUpdatePromise.then(() => init.history.go(delta));
1114 },
1115 reset() {
1116 let blockers = new Map(state.blockers);
1117 blockers.set(blockerKey, IDLE_BLOCKER);
1118 updateState({ blockers });
1119 }
1120 });
1121 return;
1122 }
1123 return startNavigation(historyAction, location);
1124 }
1125 );
1126 if (isBrowser2) {
1127 restoreAppliedTransitions(routerWindow, appliedViewTransitions);
1128 let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);
1129 routerWindow.addEventListener("pagehide", _saveAppliedTransitions);
1130 removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions);
1131 }
1132 if (!state.initialized) {
1133 startNavigation("POP" /* Pop */, state.location, {
1134 initialHydration: true
1135 });
1136 }
1137 return router;
1138 }
1139 function dispose() {
1140 if (unlistenHistory) {
1141 unlistenHistory();
1142 }
1143 if (removePageHideEventListener) {
1144 removePageHideEventListener();
1145 }
1146 subscribers.clear();
1147 pendingNavigationController && pendingNavigationController.abort();
1148 state.fetchers.forEach((_, key) => deleteFetcher(key));
1149 state.blockers.forEach((_, key) => deleteBlocker(key));
1150 }
1151 function subscribe(fn) {
1152 subscribers.add(fn);
1153 return () => subscribers.delete(fn);
1154 }
1155 function updateState(newState, opts = {}) {
1156 if (newState.matches) {
1157 newState.matches = newState.matches.map((m) => {
1158 let route = manifest[m.route.id];
1159 let matchRoute = m.route;
1160 if (matchRoute.element !== route.element || matchRoute.errorElement !== route.errorElement || matchRoute.hydrateFallbackElement !== route.hydrateFallbackElement) {
1161 return {
1162 ...m,
1163 route
1164 };
1165 }
1166 return m;
1167 });
1168 }
1169 state = {
1170 ...state,
1171 ...newState
1172 };
1173 let unmountedFetchers = [];
1174 let mountedFetchers = [];
1175 state.fetchers.forEach((fetcher, key) => {
1176 if (fetcher.state === "idle") {
1177 if (fetchersQueuedForDeletion.has(key)) {
1178 unmountedFetchers.push(key);
1179 } else {
1180 mountedFetchers.push(key);
1181 }
1182 }
1183 });
1184 fetchersQueuedForDeletion.forEach((key) => {
1185 if (!state.fetchers.has(key) && !fetchControllers.has(key)) {
1186 unmountedFetchers.push(key);
1187 }
1188 });
1189 [...subscribers].forEach(
1190 (subscriber) => subscriber(state, {
1191 deletedFetchers: unmountedFetchers,
1192 viewTransitionOpts: opts.viewTransitionOpts,
1193 flushSync: opts.flushSync === true
1194 })
1195 );
1196 unmountedFetchers.forEach((key) => deleteFetcher(key));
1197 mountedFetchers.forEach((key) => state.fetchers.delete(key));
1198 }
1199 function completeNavigation(location, newState, { flushSync } = {}) {
1200 let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && location.state?._isRedirect !== true;
1201 let actionData;
1202 if (newState.actionData) {
1203 if (Object.keys(newState.actionData).length > 0) {
1204 actionData = newState.actionData;
1205 } else {
1206 actionData = null;
1207 }
1208 } else if (isActionReload) {
1209 actionData = state.actionData;
1210 } else {
1211 actionData = null;
1212 }
1213 let loaderData = newState.loaderData ? mergeLoaderData(
1214 state.loaderData,
1215 newState.loaderData,
1216 newState.matches || [],
1217 newState.errors
1218 ) : state.loaderData;
1219 let blockers = state.blockers;
1220 if (blockers.size > 0) {
1221 blockers = new Map(blockers);
1222 blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));
1223 }
1224 let restoreScrollPosition = isUninterruptedRevalidation ? false : getSavedScrollPosition(location, newState.matches || state.matches);
1225 let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && location.state?._isRedirect !== true;
1226 if (inFlightDataRoutes) {
1227 dataRoutes = inFlightDataRoutes;
1228 inFlightDataRoutes = void 0;
1229 }
1230 if (isUninterruptedRevalidation) {
1231 } else if (pendingAction === "POP" /* Pop */) {
1232 } else if (pendingAction === "PUSH" /* Push */) {
1233 init.history.push(location, location.state);
1234 } else if (pendingAction === "REPLACE" /* Replace */) {
1235 init.history.replace(location, location.state);
1236 }
1237 let viewTransitionOpts;
1238 if (pendingAction === "POP" /* Pop */) {
1239 let priorPaths = appliedViewTransitions.get(state.location.pathname);
1240 if (priorPaths && priorPaths.has(location.pathname)) {
1241 viewTransitionOpts = {
1242 currentLocation: state.location,
1243 nextLocation: location
1244 };
1245 } else if (appliedViewTransitions.has(location.pathname)) {
1246 viewTransitionOpts = {
1247 currentLocation: location,
1248 nextLocation: state.location
1249 };
1250 }
1251 } else if (pendingViewTransitionEnabled) {
1252 let toPaths = appliedViewTransitions.get(state.location.pathname);
1253 if (toPaths) {
1254 toPaths.add(location.pathname);
1255 } else {
1256 toPaths = /* @__PURE__ */ new Set([location.pathname]);
1257 appliedViewTransitions.set(state.location.pathname, toPaths);
1258 }
1259 viewTransitionOpts = {
1260 currentLocation: state.location,
1261 nextLocation: location
1262 };
1263 }
1264 updateState(
1265 {
1266 ...newState,
1267 // matches, errors, fetchers go through as-is
1268 actionData,
1269 loaderData,
1270 historyAction: pendingAction,
1271 location,
1272 initialized: true,
1273 navigation: IDLE_NAVIGATION,
1274 revalidation: "idle",
1275 restoreScrollPosition,
1276 preventScrollReset,
1277 blockers
1278 },
1279 {
1280 viewTransitionOpts,
1281 flushSync: flushSync === true
1282 }
1283 );
1284 pendingAction = "POP" /* Pop */;
1285 pendingPreventScrollReset = false;
1286 pendingViewTransitionEnabled = false;
1287 isUninterruptedRevalidation = false;
1288 isRevalidationRequired = false;
1289 pendingRevalidationDfd?.resolve();
1290 pendingRevalidationDfd = null;
1291 }
1292 async function navigate(to, opts) {
1293 if (typeof to === "number") {
1294 init.history.go(to);
1295 return;
1296 }
1297 let normalizedPath = normalizeTo(
1298 state.location,
1299 state.matches,
1300 basename,
1301 to,
1302 opts?.fromRouteId,
1303 opts?.relative
1304 );
1305 let { path, submission, error } = normalizeNavigateOptions(
1306 false,
1307 normalizedPath,
1308 opts
1309 );
1310 let currentLocation = state.location;
1311 let nextLocation = createLocation(state.location, path, opts && opts.state);
1312 nextLocation = {
1313 ...nextLocation,
1314 ...init.history.encodeLocation(nextLocation)
1315 };
1316 let userReplace = opts && opts.replace != null ? opts.replace : void 0;
1317 let historyAction = "PUSH" /* Push */;
1318 if (userReplace === true) {
1319 historyAction = "REPLACE" /* Replace */;
1320 } else if (userReplace === false) {
1321 } else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
1322 historyAction = "REPLACE" /* Replace */;
1323 }
1324 let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : void 0;
1325 let flushSync = (opts && opts.flushSync) === true;
1326 let blockerKey = shouldBlockNavigation({
1327 currentLocation,
1328 nextLocation,
1329 historyAction
1330 });
1331 if (blockerKey) {
1332 updateBlocker(blockerKey, {
1333 state: "blocked",
1334 location: nextLocation,
1335 proceed() {
1336 updateBlocker(blockerKey, {
1337 state: "proceeding",
1338 proceed: void 0,
1339 reset: void 0,
1340 location: nextLocation
1341 });
1342 navigate(to, opts);
1343 },
1344 reset() {
1345 let blockers = new Map(state.blockers);
1346 blockers.set(blockerKey, IDLE_BLOCKER);
1347 updateState({ blockers });
1348 }
1349 });
1350 return;
1351 }
1352 await startNavigation(historyAction, nextLocation, {
1353 submission,
1354 // Send through the formData serialization error if we have one so we can
1355 // render at the right error boundary after we match routes
1356 pendingError: error,
1357 preventScrollReset,
1358 replace: opts && opts.replace,
1359 enableViewTransition: opts && opts.viewTransition,
1360 flushSync
1361 });
1362 }
1363 function revalidate() {
1364 if (!pendingRevalidationDfd) {
1365 pendingRevalidationDfd = createDeferred();
1366 }
1367 interruptActiveLoads();
1368 updateState({ revalidation: "loading" });
1369 let promise = pendingRevalidationDfd.promise;
1370 if (state.navigation.state === "submitting") {
1371 return promise;
1372 }
1373 if (state.navigation.state === "idle") {
1374 startNavigation(state.historyAction, state.location, {
1375 startUninterruptedRevalidation: true
1376 });
1377 return promise;
1378 }
1379 startNavigation(
1380 pendingAction || state.historyAction,
1381 state.navigation.location,
1382 {
1383 overrideNavigation: state.navigation,
1384 // Proxy through any rending view transition
1385 enableViewTransition: pendingViewTransitionEnabled === true
1386 }
1387 );
1388 return promise;
1389 }
1390 async function startNavigation(historyAction, location, opts) {
1391 pendingNavigationController && pendingNavigationController.abort();
1392 pendingNavigationController = null;
1393 pendingAction = historyAction;
1394 isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true;
1395 saveScrollPosition(state.location, state.matches);
1396 pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1397 pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
1398 let routesToUse = inFlightDataRoutes || dataRoutes;
1399 let loadingNavigation = opts && opts.overrideNavigation;
1400 let matches = opts?.initialHydration && state.matches && state.matches.length > 0 && !initialMatchesIsFOW ? (
1401 // `matchRoutes()` has already been called if we're in here via `router.initialize()`
1402 state.matches
1403 ) : matchRoutes(routesToUse, location, basename);
1404 let flushSync = (opts && opts.flushSync) === true;
1405 if (matches && state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
1406 completeNavigation(location, { matches }, { flushSync });
1407 return;
1408 }
1409 let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname);
1410 if (fogOfWar.active && fogOfWar.matches) {
1411 matches = fogOfWar.matches;
1412 }
1413 if (!matches) {
1414 let { error, notFoundMatches, route } = handleNavigational404(
1415 location.pathname
1416 );
1417 completeNavigation(
1418 location,
1419 {
1420 matches: notFoundMatches,
1421 loaderData: {},
1422 errors: {
1423 [route.id]: error
1424 }
1425 },
1426 { flushSync }
1427 );
1428 return;
1429 }
1430 pendingNavigationController = new AbortController();
1431 let request = createClientSideRequest(
1432 init.history,
1433 location,
1434 pendingNavigationController.signal,
1435 opts && opts.submission
1436 );
1437 let scopedContext = new unstable_RouterContextProvider(
1438 init.unstable_getContext ? await init.unstable_getContext() : void 0
1439 );
1440 let pendingActionResult;
1441 if (opts && opts.pendingError) {
1442 pendingActionResult = [
1443 findNearestBoundary(matches).route.id,
1444 { type: "error" /* error */, error: opts.pendingError }
1445 ];
1446 } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
1447 let actionResult = await handleAction(
1448 request,
1449 location,
1450 opts.submission,
1451 matches,
1452 scopedContext,
1453 fogOfWar.active,
1454 opts && opts.initialHydration === true,
1455 { replace: opts.replace, flushSync }
1456 );
1457 if (actionResult.shortCircuited) {
1458 return;
1459 }
1460 if (actionResult.pendingActionResult) {
1461 let [routeId, result] = actionResult.pendingActionResult;
1462 if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) {
1463 pendingNavigationController = null;
1464 completeNavigation(location, {
1465 matches: actionResult.matches,
1466 loaderData: {},
1467 errors: {
1468 [routeId]: result.error
1469 }
1470 });
1471 return;
1472 }
1473 }
1474 matches = actionResult.matches || matches;
1475 pendingActionResult = actionResult.pendingActionResult;
1476 loadingNavigation = getLoadingNavigation(location, opts.submission);
1477 flushSync = false;
1478 fogOfWar.active = false;
1479 request = createClientSideRequest(
1480 init.history,
1481 request.url,
1482 request.signal
1483 );
1484 }
1485 let {
1486 shortCircuited,
1487 matches: updatedMatches,
1488 loaderData,
1489 errors
1490 } = await handleLoaders(
1491 request,
1492 location,
1493 matches,
1494 scopedContext,
1495 fogOfWar.active,
1496 loadingNavigation,
1497 opts && opts.submission,
1498 opts && opts.fetcherSubmission,
1499 opts && opts.replace,
1500 opts && opts.initialHydration === true,
1501 flushSync,
1502 pendingActionResult
1503 );
1504 if (shortCircuited) {
1505 return;
1506 }
1507 pendingNavigationController = null;
1508 completeNavigation(location, {
1509 matches: updatedMatches || matches,
1510 ...getActionDataForCommit(pendingActionResult),
1511 loaderData,
1512 errors
1513 });
1514 }
1515 async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, initialHydration, opts = {}) {
1516 interruptActiveLoads();
1517 let navigation = getSubmittingNavigation(location, submission);
1518 updateState({ navigation }, { flushSync: opts.flushSync === true });
1519 if (isFogOfWar) {
1520 let discoverResult = await discoverRoutes(
1521 matches,
1522 location.pathname,
1523 request.signal
1524 );
1525 if (discoverResult.type === "aborted") {
1526 return { shortCircuited: true };
1527 } else if (discoverResult.type === "error") {
1528 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1529 return {
1530 matches: discoverResult.partialMatches,
1531 pendingActionResult: [
1532 boundaryId,
1533 {
1534 type: "error" /* error */,
1535 error: discoverResult.error
1536 }
1537 ]
1538 };
1539 } else if (!discoverResult.matches) {
1540 let { notFoundMatches, error, route } = handleNavigational404(
1541 location.pathname
1542 );
1543 return {
1544 matches: notFoundMatches,
1545 pendingActionResult: [
1546 route.id,
1547 {
1548 type: "error" /* error */,
1549 error
1550 }
1551 ]
1552 };
1553 } else {
1554 matches = discoverResult.matches;
1555 }
1556 }
1557 let result;
1558 let actionMatch = getTargetMatch(matches, location);
1559 if (!actionMatch.route.action && !actionMatch.route.lazy) {
1560 result = {
1561 type: "error" /* error */,
1562 error: getInternalRouterError(405, {
1563 method: request.method,
1564 pathname: location.pathname,
1565 routeId: actionMatch.route.id
1566 })
1567 };
1568 } else {
1569 let dsMatches = getTargetedDataStrategyMatches(
1570 mapRouteProperties2,
1571 manifest,
1572 request,
1573 matches,
1574 actionMatch,
1575 initialHydration ? [] : hydrationRouteProperties2,
1576 scopedContext
1577 );
1578 let results = await callDataStrategy(
1579 request,
1580 dsMatches,
1581 scopedContext,
1582 null
1583 );
1584 result = results[actionMatch.route.id];
1585 if (!result) {
1586 for (let match of matches) {
1587 if (results[match.route.id]) {
1588 result = results[match.route.id];
1589 break;
1590 }
1591 }
1592 }
1593 if (request.signal.aborted) {
1594 return { shortCircuited: true };
1595 }
1596 }
1597 if (isRedirectResult(result)) {
1598 let replace2;
1599 if (opts && opts.replace != null) {
1600 replace2 = opts.replace;
1601 } else {
1602 let location2 = normalizeRedirectLocation(
1603 result.response.headers.get("Location"),
1604 new URL(request.url),
1605 basename
1606 );
1607 replace2 = location2 === state.location.pathname + state.location.search;
1608 }
1609 await startRedirectNavigation(request, result, true, {
1610 submission,
1611 replace: replace2
1612 });
1613 return { shortCircuited: true };
1614 }
1615 if (isErrorResult(result)) {
1616 let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
1617 if ((opts && opts.replace) !== true) {
1618 pendingAction = "PUSH" /* Push */;
1619 }
1620 return {
1621 matches,
1622 pendingActionResult: [
1623 boundaryMatch.route.id,
1624 result,
1625 actionMatch.route.id
1626 ]
1627 };
1628 }
1629 return {
1630 matches,
1631 pendingActionResult: [actionMatch.route.id, result]
1632 };
1633 }
1634 async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult) {
1635 let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
1636 let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
1637 let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
1638 if (isFogOfWar) {
1639 if (shouldUpdateNavigationState) {
1640 let actionData = getUpdatedActionData(pendingActionResult);
1641 updateState(
1642 {
1643 navigation: loadingNavigation,
1644 ...actionData !== void 0 ? { actionData } : {}
1645 },
1646 {
1647 flushSync
1648 }
1649 );
1650 }
1651 let discoverResult = await discoverRoutes(
1652 matches,
1653 location.pathname,
1654 request.signal
1655 );
1656 if (discoverResult.type === "aborted") {
1657 return { shortCircuited: true };
1658 } else if (discoverResult.type === "error") {
1659 let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
1660 return {
1661 matches: discoverResult.partialMatches,
1662 loaderData: {},
1663 errors: {
1664 [boundaryId]: discoverResult.error
1665 }
1666 };
1667 } else if (!discoverResult.matches) {
1668 let { error, notFoundMatches, route } = handleNavigational404(
1669 location.pathname
1670 );
1671 return {
1672 matches: notFoundMatches,
1673 loaderData: {},
1674 errors: {
1675 [route.id]: error
1676 }
1677 };
1678 } else {
1679 matches = discoverResult.matches;
1680 }
1681 }
1682 let routesToUse = inFlightDataRoutes || dataRoutes;
1683 let { dsMatches, revalidatingFetchers } = getMatchesToLoad(
1684 request,
1685 scopedContext,
1686 mapRouteProperties2,
1687 manifest,
1688 init.history,
1689 state,
1690 matches,
1691 activeSubmission,
1692 location,
1693 initialHydration ? [] : hydrationRouteProperties2,
1694 initialHydration === true,
1695 isRevalidationRequired,
1696 cancelledFetcherLoads,
1697 fetchersQueuedForDeletion,
1698 fetchLoadMatches,
1699 fetchRedirectIds,
1700 routesToUse,
1701 basename,
1702 init.patchRoutesOnNavigation != null,
1703 pendingActionResult
1704 );
1705 pendingNavigationLoadId = ++incrementingLoadId;
1706 if (!init.dataStrategy && !dsMatches.some((m) => m.shouldLoad) && revalidatingFetchers.length === 0) {
1707 let updatedFetchers2 = markFetchRedirectsDone();
1708 completeNavigation(
1709 location,
1710 {
1711 matches,
1712 loaderData: {},
1713 // Commit pending error if we're short circuiting
1714 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null,
1715 ...getActionDataForCommit(pendingActionResult),
1716 ...updatedFetchers2 ? { fetchers: new Map(state.fetchers) } : {}
1717 },
1718 { flushSync }
1719 );
1720 return { shortCircuited: true };
1721 }
1722 if (shouldUpdateNavigationState) {
1723 let updates = {};
1724 if (!isFogOfWar) {
1725 updates.navigation = loadingNavigation;
1726 let actionData = getUpdatedActionData(pendingActionResult);
1727 if (actionData !== void 0) {
1728 updates.actionData = actionData;
1729 }
1730 }
1731 if (revalidatingFetchers.length > 0) {
1732 updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers);
1733 }
1734 updateState(updates, { flushSync });
1735 }
1736 revalidatingFetchers.forEach((rf) => {
1737 abortFetcher(rf.key);
1738 if (rf.controller) {
1739 fetchControllers.set(rf.key, rf.controller);
1740 }
1741 });
1742 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((f) => abortFetcher(f.key));
1743 if (pendingNavigationController) {
1744 pendingNavigationController.signal.addEventListener(
1745 "abort",
1746 abortPendingFetchRevalidations
1747 );
1748 }
1749 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1750 dsMatches,
1751 revalidatingFetchers,
1752 request,
1753 scopedContext
1754 );
1755 if (request.signal.aborted) {
1756 return { shortCircuited: true };
1757 }
1758 if (pendingNavigationController) {
1759 pendingNavigationController.signal.removeEventListener(
1760 "abort",
1761 abortPendingFetchRevalidations
1762 );
1763 }
1764 revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));
1765 let redirect2 = findRedirect(loaderResults);
1766 if (redirect2) {
1767 await startRedirectNavigation(request, redirect2.result, true, {
1768 replace: replace2
1769 });
1770 return { shortCircuited: true };
1771 }
1772 redirect2 = findRedirect(fetcherResults);
1773 if (redirect2) {
1774 fetchRedirectIds.add(redirect2.key);
1775 await startRedirectNavigation(request, redirect2.result, true, {
1776 replace: replace2
1777 });
1778 return { shortCircuited: true };
1779 }
1780 let { loaderData, errors } = processLoaderData(
1781 state,
1782 matches,
1783 loaderResults,
1784 pendingActionResult,
1785 revalidatingFetchers,
1786 fetcherResults
1787 );
1788 if (initialHydration && state.errors) {
1789 errors = { ...state.errors, ...errors };
1790 }
1791 let updatedFetchers = markFetchRedirectsDone();
1792 let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
1793 let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
1794 return {
1795 matches,
1796 loaderData,
1797 errors,
1798 ...shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {}
1799 };
1800 }
1801 function getUpdatedActionData(pendingActionResult) {
1802 if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
1803 return {
1804 [pendingActionResult[0]]: pendingActionResult[1].data
1805 };
1806 } else if (state.actionData) {
1807 if (Object.keys(state.actionData).length === 0) {
1808 return null;
1809 } else {
1810 return state.actionData;
1811 }
1812 }
1813 }
1814 function getUpdatedRevalidatingFetchers(revalidatingFetchers) {
1815 revalidatingFetchers.forEach((rf) => {
1816 let fetcher = state.fetchers.get(rf.key);
1817 let revalidatingFetcher = getLoadingFetcher(
1818 void 0,
1819 fetcher ? fetcher.data : void 0
1820 );
1821 state.fetchers.set(rf.key, revalidatingFetcher);
1822 });
1823 return new Map(state.fetchers);
1824 }
1825 async function fetch2(key, routeId, href, opts) {
1826 abortFetcher(key);
1827 let flushSync = (opts && opts.flushSync) === true;
1828 let routesToUse = inFlightDataRoutes || dataRoutes;
1829 let normalizedPath = normalizeTo(
1830 state.location,
1831 state.matches,
1832 basename,
1833 href,
1834 routeId,
1835 opts?.relative
1836 );
1837 let matches = matchRoutes(routesToUse, normalizedPath, basename);
1838 let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath);
1839 if (fogOfWar.active && fogOfWar.matches) {
1840 matches = fogOfWar.matches;
1841 }
1842 if (!matches) {
1843 setFetcherError(
1844 key,
1845 routeId,
1846 getInternalRouterError(404, { pathname: normalizedPath }),
1847 { flushSync }
1848 );
1849 return;
1850 }
1851 let { path, submission, error } = normalizeNavigateOptions(
1852 true,
1853 normalizedPath,
1854 opts
1855 );
1856 if (error) {
1857 setFetcherError(key, routeId, error, { flushSync });
1858 return;
1859 }
1860 let scopedContext = new unstable_RouterContextProvider(
1861 init.unstable_getContext ? await init.unstable_getContext() : void 0
1862 );
1863 let preventScrollReset = (opts && opts.preventScrollReset) === true;
1864 if (submission && isMutationMethod(submission.formMethod)) {
1865 await handleFetcherAction(
1866 key,
1867 routeId,
1868 path,
1869 matches,
1870 scopedContext,
1871 fogOfWar.active,
1872 flushSync,
1873 preventScrollReset,
1874 submission
1875 );
1876 return;
1877 }
1878 fetchLoadMatches.set(key, { routeId, path });
1879 await handleFetcherLoader(
1880 key,
1881 routeId,
1882 path,
1883 matches,
1884 scopedContext,
1885 fogOfWar.active,
1886 flushSync,
1887 preventScrollReset,
1888 submission
1889 );
1890 }
1891 async function handleFetcherAction(key, routeId, path, requestMatches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
1892 interruptActiveLoads();
1893 fetchLoadMatches.delete(key);
1894 let existingFetcher = state.fetchers.get(key);
1895 updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
1896 flushSync
1897 });
1898 let abortController = new AbortController();
1899 let fetchRequest = createClientSideRequest(
1900 init.history,
1901 path,
1902 abortController.signal,
1903 submission
1904 );
1905 if (isFogOfWar) {
1906 let discoverResult = await discoverRoutes(
1907 requestMatches,
1908 new URL(fetchRequest.url).pathname,
1909 fetchRequest.signal,
1910 key
1911 );
1912 if (discoverResult.type === "aborted") {
1913 return;
1914 } else if (discoverResult.type === "error") {
1915 setFetcherError(key, routeId, discoverResult.error, { flushSync });
1916 return;
1917 } else if (!discoverResult.matches) {
1918 setFetcherError(
1919 key,
1920 routeId,
1921 getInternalRouterError(404, { pathname: path }),
1922 { flushSync }
1923 );
1924 return;
1925 } else {
1926 requestMatches = discoverResult.matches;
1927 }
1928 }
1929 let match = getTargetMatch(requestMatches, path);
1930 if (!match.route.action && !match.route.lazy) {
1931 let error = getInternalRouterError(405, {
1932 method: submission.formMethod,
1933 pathname: path,
1934 routeId
1935 });
1936 setFetcherError(key, routeId, error, { flushSync });
1937 return;
1938 }
1939 fetchControllers.set(key, abortController);
1940 let originatingLoadId = incrementingLoadId;
1941 let fetchMatches = getTargetedDataStrategyMatches(
1942 mapRouteProperties2,
1943 manifest,
1944 fetchRequest,
1945 requestMatches,
1946 match,
1947 hydrationRouteProperties2,
1948 scopedContext
1949 );
1950 let actionResults = await callDataStrategy(
1951 fetchRequest,
1952 fetchMatches,
1953 scopedContext,
1954 key
1955 );
1956 let actionResult = actionResults[match.route.id];
1957 if (fetchRequest.signal.aborted) {
1958 if (fetchControllers.get(key) === abortController) {
1959 fetchControllers.delete(key);
1960 }
1961 return;
1962 }
1963 if (fetchersQueuedForDeletion.has(key)) {
1964 if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {
1965 updateFetcherState(key, getDoneFetcher(void 0));
1966 return;
1967 }
1968 } else {
1969 if (isRedirectResult(actionResult)) {
1970 fetchControllers.delete(key);
1971 if (pendingNavigationLoadId > originatingLoadId) {
1972 updateFetcherState(key, getDoneFetcher(void 0));
1973 return;
1974 } else {
1975 fetchRedirectIds.add(key);
1976 updateFetcherState(key, getLoadingFetcher(submission));
1977 return startRedirectNavigation(fetchRequest, actionResult, false, {
1978 fetcherSubmission: submission,
1979 preventScrollReset
1980 });
1981 }
1982 }
1983 if (isErrorResult(actionResult)) {
1984 setFetcherError(key, routeId, actionResult.error);
1985 return;
1986 }
1987 }
1988 let nextLocation = state.navigation.location || state.location;
1989 let revalidationRequest = createClientSideRequest(
1990 init.history,
1991 nextLocation,
1992 abortController.signal
1993 );
1994 let routesToUse = inFlightDataRoutes || dataRoutes;
1995 let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;
1996 invariant(matches, "Didn't find any matches after fetcher action");
1997 let loadId = ++incrementingLoadId;
1998 fetchReloadIds.set(key, loadId);
1999 let loadFetcher = getLoadingFetcher(submission, actionResult.data);
2000 state.fetchers.set(key, loadFetcher);
2001 let { dsMatches, revalidatingFetchers } = getMatchesToLoad(
2002 revalidationRequest,
2003 scopedContext,
2004 mapRouteProperties2,
2005 manifest,
2006 init.history,
2007 state,
2008 matches,
2009 submission,
2010 nextLocation,
2011 hydrationRouteProperties2,
2012 false,
2013 isRevalidationRequired,
2014 cancelledFetcherLoads,
2015 fetchersQueuedForDeletion,
2016 fetchLoadMatches,
2017 fetchRedirectIds,
2018 routesToUse,
2019 basename,
2020 init.patchRoutesOnNavigation != null,
2021 [match.route.id, actionResult]
2022 );
2023 revalidatingFetchers.filter((rf) => rf.key !== key).forEach((rf) => {
2024 let staleKey = rf.key;
2025 let existingFetcher2 = state.fetchers.get(staleKey);
2026 let revalidatingFetcher = getLoadingFetcher(
2027 void 0,
2028 existingFetcher2 ? existingFetcher2.data : void 0
2029 );
2030 state.fetchers.set(staleKey, revalidatingFetcher);
2031 abortFetcher(staleKey);
2032 if (rf.controller) {
2033 fetchControllers.set(staleKey, rf.controller);
2034 }
2035 });
2036 updateState({ fetchers: new Map(state.fetchers) });
2037 let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((rf) => abortFetcher(rf.key));
2038 abortController.signal.addEventListener(
2039 "abort",
2040 abortPendingFetchRevalidations
2041 );
2042 let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
2043 dsMatches,
2044 revalidatingFetchers,
2045 revalidationRequest,
2046 scopedContext
2047 );
2048 if (abortController.signal.aborted) {
2049 return;
2050 }
2051 abortController.signal.removeEventListener(
2052 "abort",
2053 abortPendingFetchRevalidations
2054 );
2055 fetchReloadIds.delete(key);
2056 fetchControllers.delete(key);
2057 revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));
2058 if (state.fetchers.has(key)) {
2059 let doneFetcher = getDoneFetcher(actionResult.data);
2060 state.fetchers.set(key, doneFetcher);
2061 }
2062 let redirect2 = findRedirect(loaderResults);
2063 if (redirect2) {
2064 return startRedirectNavigation(
2065 revalidationRequest,
2066 redirect2.result,
2067 false,
2068 { preventScrollReset }
2069 );
2070 }
2071 redirect2 = findRedirect(fetcherResults);
2072 if (redirect2) {
2073 fetchRedirectIds.add(redirect2.key);
2074 return startRedirectNavigation(
2075 revalidationRequest,
2076 redirect2.result,
2077 false,
2078 { preventScrollReset }
2079 );
2080 }
2081 let { loaderData, errors } = processLoaderData(
2082 state,
2083 matches,
2084 loaderResults,
2085 void 0,
2086 revalidatingFetchers,
2087 fetcherResults
2088 );
2089 abortStaleFetchLoads(loadId);
2090 if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
2091 invariant(pendingAction, "Expected pending action");
2092 pendingNavigationController && pendingNavigationController.abort();
2093 completeNavigation(state.navigation.location, {
2094 matches,
2095 loaderData,
2096 errors,
2097 fetchers: new Map(state.fetchers)
2098 });
2099 } else {
2100 updateState({
2101 errors,
2102 loaderData: mergeLoaderData(
2103 state.loaderData,
2104 loaderData,
2105 matches,
2106 errors
2107 ),
2108 fetchers: new Map(state.fetchers)
2109 });
2110 isRevalidationRequired = false;
2111 }
2112 }
2113 async function handleFetcherLoader(key, routeId, path, matches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
2114 let existingFetcher = state.fetchers.get(key);
2115 updateFetcherState(
2116 key,
2117 getLoadingFetcher(
2118 submission,
2119 existingFetcher ? existingFetcher.data : void 0
2120 ),
2121 { flushSync }
2122 );
2123 let abortController = new AbortController();
2124 let fetchRequest = createClientSideRequest(
2125 init.history,
2126 path,
2127 abortController.signal
2128 );
2129 if (isFogOfWar) {
2130 let discoverResult = await discoverRoutes(
2131 matches,
2132 new URL(fetchRequest.url).pathname,
2133 fetchRequest.signal,
2134 key
2135 );
2136 if (discoverResult.type === "aborted") {
2137 return;
2138 } else if (discoverResult.type === "error") {
2139 setFetcherError(key, routeId, discoverResult.error, { flushSync });
2140 return;
2141 } else if (!discoverResult.matches) {
2142 setFetcherError(
2143 key,
2144 routeId,
2145 getInternalRouterError(404, { pathname: path }),
2146 { flushSync }
2147 );
2148 return;
2149 } else {
2150 matches = discoverResult.matches;
2151 }
2152 }
2153 let match = getTargetMatch(matches, path);
2154 fetchControllers.set(key, abortController);
2155 let originatingLoadId = incrementingLoadId;
2156 let dsMatches = getTargetedDataStrategyMatches(
2157 mapRouteProperties2,
2158 manifest,
2159 fetchRequest,
2160 matches,
2161 match,
2162 hydrationRouteProperties2,
2163 scopedContext
2164 );
2165 let results = await callDataStrategy(
2166 fetchRequest,
2167 dsMatches,
2168 scopedContext,
2169 key
2170 );
2171 let result = results[match.route.id];
2172 if (fetchControllers.get(key) === abortController) {
2173 fetchControllers.delete(key);
2174 }
2175 if (fetchRequest.signal.aborted) {
2176 return;
2177 }
2178 if (fetchersQueuedForDeletion.has(key)) {
2179 updateFetcherState(key, getDoneFetcher(void 0));
2180 return;
2181 }
2182 if (isRedirectResult(result)) {
2183 if (pendingNavigationLoadId > originatingLoadId) {
2184 updateFetcherState(key, getDoneFetcher(void 0));
2185 return;
2186 } else {
2187 fetchRedirectIds.add(key);
2188 await startRedirectNavigation(fetchRequest, result, false, {
2189 preventScrollReset
2190 });
2191 return;
2192 }
2193 }
2194 if (isErrorResult(result)) {
2195 setFetcherError(key, routeId, result.error);
2196 return;
2197 }
2198 updateFetcherState(key, getDoneFetcher(result.data));
2199 }
2200 async function startRedirectNavigation(request, redirect2, isNavigation, {
2201 submission,
2202 fetcherSubmission,
2203 preventScrollReset,
2204 replace: replace2
2205 } = {}) {
2206 if (redirect2.response.headers.has("X-Remix-Revalidate")) {
2207 isRevalidationRequired = true;
2208 }
2209 let location = redirect2.response.headers.get("Location");
2210 invariant(location, "Expected a Location header on the redirect Response");
2211 location = normalizeRedirectLocation(
2212 location,
2213 new URL(request.url),
2214 basename
2215 );
2216 let redirectLocation = createLocation(state.location, location, {
2217 _isRedirect: true
2218 });
2219 if (isBrowser2) {
2220 let isDocumentReload = false;
2221 if (redirect2.response.headers.has("X-Remix-Reload-Document")) {
2222 isDocumentReload = true;
2223 } else if (isAbsoluteUrl(location)) {
2224 const url = createBrowserURLImpl(location, true);
2225 isDocumentReload = // Hard reload if it's an absolute URL to a new origin
2226 url.origin !== routerWindow.location.origin || // Hard reload if it's an absolute URL that does not match our basename
2227 stripBasename(url.pathname, basename) == null;
2228 }
2229 if (isDocumentReload) {
2230 if (replace2) {
2231 routerWindow.location.replace(location);
2232 } else {
2233 routerWindow.location.assign(location);
2234 }
2235 return;
2236 }
2237 }
2238 pendingNavigationController = null;
2239 let redirectNavigationType = replace2 === true || redirect2.response.headers.has("X-Remix-Replace") ? "REPLACE" /* Replace */ : "PUSH" /* Push */;
2240 let { formMethod, formAction, formEncType } = state.navigation;
2241 if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) {
2242 submission = getSubmissionFromNavigation(state.navigation);
2243 }
2244 let activeSubmission = submission || fetcherSubmission;
2245 if (redirectPreserveMethodStatusCodes.has(redirect2.response.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) {
2246 await startNavigation(redirectNavigationType, redirectLocation, {
2247 submission: {
2248 ...activeSubmission,
2249 formAction: location
2250 },
2251 // Preserve these flags across redirects
2252 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
2253 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
2254 });
2255 } else {
2256 let overrideNavigation = getLoadingNavigation(
2257 redirectLocation,
2258 submission
2259 );
2260 await startNavigation(redirectNavigationType, redirectLocation, {
2261 overrideNavigation,
2262 // Send fetcher submissions through for shouldRevalidate
2263 fetcherSubmission,
2264 // Preserve these flags across redirects
2265 preventScrollReset: preventScrollReset || pendingPreventScrollReset,
2266 enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0
2267 });
2268 }
2269 }
2270 async function callDataStrategy(request, matches, scopedContext, fetcherKey) {
2271 let results;
2272 let dataResults = {};
2273 try {
2274 results = await callDataStrategyImpl(
2275 dataStrategyImpl,
2276 request,
2277 matches,
2278 fetcherKey,
2279 scopedContext,
2280 false
2281 );
2282 } catch (e) {
2283 matches.filter((m) => m.shouldLoad).forEach((m) => {
2284 dataResults[m.route.id] = {
2285 type: "error" /* error */,
2286 error: e
2287 };
2288 });
2289 return dataResults;
2290 }
2291 if (request.signal.aborted) {
2292 return dataResults;
2293 }
2294 for (let [routeId, result] of Object.entries(results)) {
2295 if (isRedirectDataStrategyResult(result)) {
2296 let response = result.result;
2297 dataResults[routeId] = {
2298 type: "redirect" /* redirect */,
2299 response: normalizeRelativeRoutingRedirectResponse(
2300 response,
2301 request,
2302 routeId,
2303 matches,
2304 basename
2305 )
2306 };
2307 } else {
2308 dataResults[routeId] = await convertDataStrategyResultToDataResult(result);
2309 }
2310 }
2311 return dataResults;
2312 }
2313 async function callLoadersAndMaybeResolveData(matches, fetchersToLoad, request, scopedContext) {
2314 let loaderResultsPromise = callDataStrategy(
2315 request,
2316 matches,
2317 scopedContext,
2318 null
2319 );
2320 let fetcherResultsPromise = Promise.all(
2321 fetchersToLoad.map(async (f) => {
2322 if (f.matches && f.match && f.request && f.controller) {
2323 let results = await callDataStrategy(
2324 f.request,
2325 f.matches,
2326 scopedContext,
2327 f.key
2328 );
2329 let result = results[f.match.route.id];
2330 return { [f.key]: result };
2331 } else {
2332 return Promise.resolve({
2333 [f.key]: {
2334 type: "error" /* error */,
2335 error: getInternalRouterError(404, {
2336 pathname: f.path
2337 })
2338 }
2339 });
2340 }
2341 })
2342 );
2343 let loaderResults = await loaderResultsPromise;
2344 let fetcherResults = (await fetcherResultsPromise).reduce(
2345 (acc, r) => Object.assign(acc, r),
2346 {}
2347 );
2348 return {
2349 loaderResults,
2350 fetcherResults
2351 };
2352 }
2353 function interruptActiveLoads() {
2354 isRevalidationRequired = true;
2355 fetchLoadMatches.forEach((_, key) => {
2356 if (fetchControllers.has(key)) {
2357 cancelledFetcherLoads.add(key);
2358 }
2359 abortFetcher(key);
2360 });
2361 }
2362 function updateFetcherState(key, fetcher, opts = {}) {
2363 state.fetchers.set(key, fetcher);
2364 updateState(
2365 { fetchers: new Map(state.fetchers) },
2366 { flushSync: (opts && opts.flushSync) === true }
2367 );
2368 }
2369 function setFetcherError(key, routeId, error, opts = {}) {
2370 let boundaryMatch = findNearestBoundary(state.matches, routeId);
2371 deleteFetcher(key);
2372 updateState(
2373 {
2374 errors: {
2375 [boundaryMatch.route.id]: error
2376 },
2377 fetchers: new Map(state.fetchers)
2378 },
2379 { flushSync: (opts && opts.flushSync) === true }
2380 );
2381 }
2382 function getFetcher(key) {
2383 activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2384 if (fetchersQueuedForDeletion.has(key)) {
2385 fetchersQueuedForDeletion.delete(key);
2386 }
2387 return state.fetchers.get(key) || IDLE_FETCHER;
2388 }
2389 function deleteFetcher(key) {
2390 let fetcher = state.fetchers.get(key);
2391 if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
2392 abortFetcher(key);
2393 }
2394 fetchLoadMatches.delete(key);
2395 fetchReloadIds.delete(key);
2396 fetchRedirectIds.delete(key);
2397 fetchersQueuedForDeletion.delete(key);
2398 cancelledFetcherLoads.delete(key);
2399 state.fetchers.delete(key);
2400 }
2401 function queueFetcherForDeletion(key) {
2402 let count = (activeFetchers.get(key) || 0) - 1;
2403 if (count <= 0) {
2404 activeFetchers.delete(key);
2405 fetchersQueuedForDeletion.add(key);
2406 } else {
2407 activeFetchers.set(key, count);
2408 }
2409 updateState({ fetchers: new Map(state.fetchers) });
2410 }
2411 function abortFetcher(key) {
2412 let controller = fetchControllers.get(key);
2413 if (controller) {
2414 controller.abort();
2415 fetchControllers.delete(key);
2416 }
2417 }
2418 function markFetchersDone(keys) {
2419 for (let key of keys) {
2420 let fetcher = getFetcher(key);
2421 let doneFetcher = getDoneFetcher(fetcher.data);
2422 state.fetchers.set(key, doneFetcher);
2423 }
2424 }
2425 function markFetchRedirectsDone() {
2426 let doneKeys = [];
2427 let updatedFetchers = false;
2428 for (let key of fetchRedirectIds) {
2429 let fetcher = state.fetchers.get(key);
2430 invariant(fetcher, `Expected fetcher: ${key}`);
2431 if (fetcher.state === "loading") {
2432 fetchRedirectIds.delete(key);
2433 doneKeys.push(key);
2434 updatedFetchers = true;
2435 }
2436 }
2437 markFetchersDone(doneKeys);
2438 return updatedFetchers;
2439 }
2440 function abortStaleFetchLoads(landedId) {
2441 let yeetedKeys = [];
2442 for (let [key, id] of fetchReloadIds) {
2443 if (id < landedId) {
2444 let fetcher = state.fetchers.get(key);
2445 invariant(fetcher, `Expected fetcher: ${key}`);
2446 if (fetcher.state === "loading") {
2447 abortFetcher(key);
2448 fetchReloadIds.delete(key);
2449 yeetedKeys.push(key);
2450 }
2451 }
2452 }
2453 markFetchersDone(yeetedKeys);
2454 return yeetedKeys.length > 0;
2455 }
2456 function getBlocker(key, fn) {
2457 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2458 if (blockerFunctions.get(key) !== fn) {
2459 blockerFunctions.set(key, fn);
2460 }
2461 return blocker;
2462 }
2463 function deleteBlocker(key) {
2464 state.blockers.delete(key);
2465 blockerFunctions.delete(key);
2466 }
2467 function updateBlocker(key, newBlocker) {
2468 let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2469 invariant(
2470 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",
2471 `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`
2472 );
2473 let blockers = new Map(state.blockers);
2474 blockers.set(key, newBlocker);
2475 updateState({ blockers });
2476 }
2477 function shouldBlockNavigation({
2478 currentLocation,
2479 nextLocation,
2480 historyAction
2481 }) {
2482 if (blockerFunctions.size === 0) {
2483 return;
2484 }
2485 if (blockerFunctions.size > 1) {
2486 warning(false, "A router only supports one blocker at a time");
2487 }
2488 let entries = Array.from(blockerFunctions.entries());
2489 let [blockerKey, blockerFunction] = entries[entries.length - 1];
2490 let blocker = state.blockers.get(blockerKey);
2491 if (blocker && blocker.state === "proceeding") {
2492 return;
2493 }
2494 if (blockerFunction({ currentLocation, nextLocation, historyAction })) {
2495 return blockerKey;
2496 }
2497 }
2498 function handleNavigational404(pathname) {
2499 let error = getInternalRouterError(404, { pathname });
2500 let routesToUse = inFlightDataRoutes || dataRoutes;
2501 let { matches, route } = getShortCircuitMatches(routesToUse);
2502 return { notFoundMatches: matches, route, error };
2503 }
2504 function enableScrollRestoration(positions, getPosition, getKey) {
2505 savedScrollPositions2 = positions;
2506 getScrollPosition = getPosition;
2507 getScrollRestorationKey2 = getKey || null;
2508 if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
2509 initialScrollRestored = true;
2510 let y = getSavedScrollPosition(state.location, state.matches);
2511 if (y != null) {
2512 updateState({ restoreScrollPosition: y });
2513 }
2514 }
2515 return () => {
2516 savedScrollPositions2 = null;
2517 getScrollPosition = null;
2518 getScrollRestorationKey2 = null;
2519 };
2520 }
2521 function getScrollKey(location, matches) {
2522 if (getScrollRestorationKey2) {
2523 let key = getScrollRestorationKey2(
2524 location,
2525 matches.map((m) => convertRouteMatchToUiMatch(m, state.loaderData))
2526 );
2527 return key || location.key;
2528 }
2529 return location.key;
2530 }
2531 function saveScrollPosition(location, matches) {
2532 if (savedScrollPositions2 && getScrollPosition) {
2533 let key = getScrollKey(location, matches);
2534 savedScrollPositions2[key] = getScrollPosition();
2535 }
2536 }
2537 function getSavedScrollPosition(location, matches) {
2538 if (savedScrollPositions2) {
2539 let key = getScrollKey(location, matches);
2540 let y = savedScrollPositions2[key];
2541 if (typeof y === "number") {
2542 return y;
2543 }
2544 }
2545 return null;
2546 }
2547 function checkFogOfWar(matches, routesToUse, pathname) {
2548 if (init.patchRoutesOnNavigation) {
2549 if (!matches) {
2550 let fogMatches = matchRoutesImpl(
2551 routesToUse,
2552 pathname,
2553 basename,
2554 true
2555 );
2556 return { active: true, matches: fogMatches || [] };
2557 } else {
2558 if (Object.keys(matches[0].params).length > 0) {
2559 let partialMatches = matchRoutesImpl(
2560 routesToUse,
2561 pathname,
2562 basename,
2563 true
2564 );
2565 return { active: true, matches: partialMatches };
2566 }
2567 }
2568 }
2569 return { active: false, matches: null };
2570 }
2571 async function discoverRoutes(matches, pathname, signal, fetcherKey) {
2572 if (!init.patchRoutesOnNavigation) {
2573 return { type: "success", matches };
2574 }
2575 let partialMatches = matches;
2576 while (true) {
2577 let isNonHMR = inFlightDataRoutes == null;
2578 let routesToUse = inFlightDataRoutes || dataRoutes;
2579 let localManifest = manifest;
2580 try {
2581 await init.patchRoutesOnNavigation({
2582 signal,
2583 path: pathname,
2584 matches: partialMatches,
2585 fetcherKey,
2586 patch: (routeId, children) => {
2587 if (signal.aborted) return;
2588 patchRoutesImpl(
2589 routeId,
2590 children,
2591 routesToUse,
2592 localManifest,
2593 mapRouteProperties2,
2594 false
2595 );
2596 }
2597 });
2598 } catch (e) {
2599 return { type: "error", error: e, partialMatches };
2600 } finally {
2601 if (isNonHMR && !signal.aborted) {
2602 dataRoutes = [...dataRoutes];
2603 }
2604 }
2605 if (signal.aborted) {
2606 return { type: "aborted" };
2607 }
2608 let newMatches = matchRoutes(routesToUse, pathname, basename);
2609 if (newMatches) {
2610 return { type: "success", matches: newMatches };
2611 }
2612 let newPartialMatches = matchRoutesImpl(
2613 routesToUse,
2614 pathname,
2615 basename,
2616 true
2617 );
2618 if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every(
2619 (m, i) => m.route.id === newPartialMatches[i].route.id
2620 )) {
2621 return { type: "success", matches: null };
2622 }
2623 partialMatches = newPartialMatches;
2624 }
2625 }
2626 function _internalSetRoutes(newRoutes) {
2627 manifest = {};
2628 inFlightDataRoutes = convertRoutesToDataRoutes(
2629 newRoutes,
2630 mapRouteProperties2,
2631 void 0,
2632 manifest
2633 );
2634 }
2635 function patchRoutes(routeId, children, unstable_allowElementMutations = false) {
2636 let isNonHMR = inFlightDataRoutes == null;
2637 let routesToUse = inFlightDataRoutes || dataRoutes;
2638 patchRoutesImpl(
2639 routeId,
2640 children,
2641 routesToUse,
2642 manifest,
2643 mapRouteProperties2,
2644 unstable_allowElementMutations
2645 );
2646 if (isNonHMR) {
2647 dataRoutes = [...dataRoutes];
2648 updateState({});
2649 }
2650 }
2651 router = {
2652 get basename() {
2653 return basename;
2654 },
2655 get future() {
2656 return future;
2657 },
2658 get state() {
2659 return state;
2660 },
2661 get routes() {
2662 return dataRoutes;
2663 },
2664 get window() {
2665 return routerWindow;
2666 },
2667 initialize,
2668 subscribe,
2669 enableScrollRestoration,
2670 navigate,
2671 fetch: fetch2,
2672 revalidate,
2673 // Passthrough to history-aware createHref used by useHref so we get proper
2674 // hash-aware URLs in DOM paths
2675 createHref: (to) => init.history.createHref(to),
2676 encodeLocation: (to) => init.history.encodeLocation(to),
2677 getFetcher,
2678 deleteFetcher: queueFetcherForDeletion,
2679 dispose,
2680 getBlocker,
2681 deleteBlocker,
2682 patchRoutes,
2683 _internalFetchControllers: fetchControllers,
2684 // TODO: Remove setRoutes, it's temporary to avoid dealing with
2685 // updating the tree while validating the update algorithm.
2686 _internalSetRoutes,
2687 _internalSetStateDoNotUseOrYouWillBreakYourApp(newState) {
2688 updateState(newState);
2689 }
2690 };
2691 return router;
2692}
2693function createStaticHandler(routes, opts) {
2694 invariant(
2695 routes.length > 0,
2696 "You must provide a non-empty routes array to createStaticHandler"
2697 );
2698 let manifest = {};
2699 let basename = (opts ? opts.basename : null) || "/";
2700 let mapRouteProperties2 = opts?.mapRouteProperties || defaultMapRouteProperties;
2701 let dataRoutes = convertRoutesToDataRoutes(
2702 routes,
2703 mapRouteProperties2,
2704 void 0,
2705 manifest
2706 );
2707 async function query(request, {
2708 requestContext,
2709 filterMatchesToLoad,
2710 skipLoaderErrorBubbling,
2711 skipRevalidation,
2712 dataStrategy,
2713 unstable_stream: stream,
2714 unstable_respond: respond
2715 } = {}) {
2716 let url = new URL(request.url);
2717 let method = request.method;
2718 let location = createLocation("", createPath(url), null, "default");
2719 let matches = matchRoutes(dataRoutes, location, basename);
2720 requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2721 let respondOrStreamStaticContext = (ctx) => {
2722 return stream ? stream(
2723 requestContext,
2724 () => Promise.resolve(ctx)
2725 ) : respond ? respond(ctx) : ctx;
2726 };
2727 if (!isValidMethod(method) && method !== "HEAD") {
2728 let error = getInternalRouterError(405, { method });
2729 let { matches: methodNotAllowedMatches, route } = getShortCircuitMatches(dataRoutes);
2730 let staticContext = {
2731 basename,
2732 location,
2733 matches: methodNotAllowedMatches,
2734 loaderData: {},
2735 actionData: null,
2736 errors: {
2737 [route.id]: error
2738 },
2739 statusCode: error.status,
2740 loaderHeaders: {},
2741 actionHeaders: {}
2742 };
2743 return respondOrStreamStaticContext(staticContext);
2744 } else if (!matches) {
2745 let error = getInternalRouterError(404, { pathname: location.pathname });
2746 let { matches: notFoundMatches, route } = getShortCircuitMatches(dataRoutes);
2747 let staticContext = {
2748 basename,
2749 location,
2750 matches: notFoundMatches,
2751 loaderData: {},
2752 actionData: null,
2753 errors: {
2754 [route.id]: error
2755 },
2756 statusCode: error.status,
2757 loaderHeaders: {},
2758 actionHeaders: {}
2759 };
2760 return respondOrStreamStaticContext(staticContext);
2761 }
2762 if (stream || respond && matches.some(
2763 (m) => m.route.unstable_middleware || typeof m.route.lazy === "object" && m.route.lazy.unstable_middleware
2764 )) {
2765 invariant(
2766 requestContext instanceof unstable_RouterContextProvider,
2767 "When using middleware in `staticHandler.query()`, any provided `requestContext` must be an instance of `unstable_RouterContextProvider`"
2768 );
2769 try {
2770 await loadLazyMiddlewareForMatches(
2771 matches,
2772 manifest,
2773 mapRouteProperties2
2774 );
2775 let renderedStaticContext;
2776 let response = await runMiddlewarePipeline(
2777 {
2778 request,
2779 matches,
2780 params: matches[0].params,
2781 // If we're calling middleware then it must be enabled so we can cast
2782 // this to the proper type knowing it's not an `AppLoadContext`
2783 context: requestContext
2784 },
2785 true,
2786 async () => {
2787 if (stream) {
2788 let res2 = await stream(
2789 requestContext,
2790 async (revalidationRequest) => {
2791 let result3 = await queryImpl(
2792 revalidationRequest,
2793 location,
2794 matches,
2795 requestContext,
2796 dataStrategy || null,
2797 skipLoaderErrorBubbling === true,
2798 null,
2799 filterMatchesToLoad || null,
2800 skipRevalidation === true
2801 );
2802 return isResponse(result3) ? result3 : { location, basename, ...result3 };
2803 }
2804 );
2805 return res2;
2806 }
2807 invariant(respond, "Expected respond to be defined");
2808 let result2 = await queryImpl(
2809 request,
2810 location,
2811 matches,
2812 requestContext,
2813 dataStrategy || null,
2814 skipLoaderErrorBubbling === true,
2815 null,
2816 filterMatchesToLoad || null,
2817 skipRevalidation === true
2818 );
2819 if (isResponse(result2)) {
2820 return result2;
2821 }
2822 renderedStaticContext = { location, basename, ...result2 };
2823 let res = await respond(renderedStaticContext);
2824 return res;
2825 },
2826 async (error, routeId) => {
2827 if (isResponse(error)) {
2828 return error;
2829 }
2830 if (renderedStaticContext) {
2831 if (routeId in renderedStaticContext.loaderData) {
2832 renderedStaticContext.loaderData[routeId] = void 0;
2833 }
2834 let staticContext = getStaticContextFromError(
2835 dataRoutes,
2836 renderedStaticContext,
2837 error,
2838 skipLoaderErrorBubbling ? routeId : findNearestBoundary(matches, routeId).route.id
2839 );
2840 return respondOrStreamStaticContext(staticContext);
2841 } else {
2842 let boundaryRouteId = skipLoaderErrorBubbling ? routeId : findNearestBoundary(
2843 matches,
2844 matches.find(
2845 (m) => m.route.id === routeId || m.route.loader
2846 )?.route.id || routeId
2847 ).route.id;
2848 let staticContext = {
2849 matches,
2850 location,
2851 basename,
2852 loaderData: {},
2853 actionData: null,
2854 errors: {
2855 [boundaryRouteId]: error
2856 },
2857 statusCode: isRouteErrorResponse(error) ? error.status : 500,
2858 actionHeaders: {},
2859 loaderHeaders: {}
2860 };
2861 return respondOrStreamStaticContext(staticContext);
2862 }
2863 }
2864 );
2865 invariant(isResponse(response), "Expected a response in query()");
2866 return response;
2867 } catch (e) {
2868 if (isResponse(e)) {
2869 return e;
2870 }
2871 throw e;
2872 }
2873 }
2874 let result = await queryImpl(
2875 request,
2876 location,
2877 matches,
2878 requestContext,
2879 dataStrategy || null,
2880 skipLoaderErrorBubbling === true,
2881 null,
2882 filterMatchesToLoad || null,
2883 skipRevalidation === true
2884 );
2885 if (isResponse(result)) {
2886 return result;
2887 }
2888 return { location, basename, ...result };
2889 }
2890 async function queryRoute(request, {
2891 routeId,
2892 requestContext,
2893 dataStrategy,
2894 unstable_respond: respond
2895 } = {}) {
2896 let url = new URL(request.url);
2897 let method = request.method;
2898 let location = createLocation("", createPath(url), null, "default");
2899 let matches = matchRoutes(dataRoutes, location, basename);
2900 requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2901 if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") {
2902 throw getInternalRouterError(405, { method });
2903 } else if (!matches) {
2904 throw getInternalRouterError(404, { pathname: location.pathname });
2905 }
2906 let match = routeId ? matches.find((m) => m.route.id === routeId) : getTargetMatch(matches, location);
2907 if (routeId && !match) {
2908 throw getInternalRouterError(403, {
2909 pathname: location.pathname,
2910 routeId
2911 });
2912 } else if (!match) {
2913 throw getInternalRouterError(404, { pathname: location.pathname });
2914 }
2915 if (respond && matches.some(
2916 (m) => m.route.unstable_middleware || typeof m.route.lazy === "object" && m.route.lazy.unstable_middleware
2917 )) {
2918 invariant(
2919 requestContext instanceof unstable_RouterContextProvider,
2920 "When using middleware in `staticHandler.queryRoute()`, any provided `requestContext` must be an instance of `unstable_RouterContextProvider`"
2921 );
2922 await loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties2);
2923 let response = await runMiddlewarePipeline(
2924 {
2925 request,
2926 matches,
2927 params: matches[0].params,
2928 // If we're calling middleware then it must be enabled so we can cast
2929 // this to the proper type knowing it's not an `AppLoadContext`
2930 context: requestContext
2931 },
2932 true,
2933 async () => {
2934 let result2 = await queryImpl(
2935 request,
2936 location,
2937 matches,
2938 requestContext,
2939 dataStrategy || null,
2940 false,
2941 match,
2942 null,
2943 false
2944 );
2945 if (isResponse(result2)) {
2946 return respond(result2);
2947 }
2948 let error2 = result2.errors ? Object.values(result2.errors)[0] : void 0;
2949 if (error2 !== void 0) {
2950 throw error2;
2951 }
2952 let value = result2.actionData ? Object.values(result2.actionData)[0] : Object.values(result2.loaderData)[0];
2953 return typeof value === "string" ? new Response(value) : Response.json(value);
2954 },
2955 (error2) => {
2956 if (isResponse(error2)) {
2957 return respond(error2);
2958 }
2959 return new Response(String(error2), {
2960 status: 500,
2961 statusText: "Unexpected Server Error"
2962 });
2963 }
2964 );
2965 return response;
2966 }
2967 let result = await queryImpl(
2968 request,
2969 location,
2970 matches,
2971 requestContext,
2972 dataStrategy || null,
2973 false,
2974 match,
2975 null,
2976 false
2977 );
2978 if (isResponse(result)) {
2979 return result;
2980 }
2981 let error = result.errors ? Object.values(result.errors)[0] : void 0;
2982 if (error !== void 0) {
2983 throw error;
2984 }
2985 if (result.actionData) {
2986 return Object.values(result.actionData)[0];
2987 }
2988 if (result.loaderData) {
2989 return Object.values(result.loaderData)[0];
2990 }
2991 return void 0;
2992 }
2993 async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, skipRevalidation) {
2994 invariant(
2995 request.signal,
2996 "query()/queryRoute() requests must contain an AbortController signal"
2997 );
2998 try {
2999 if (isMutationMethod(request.method)) {
3000 let result2 = await submit(
3001 request,
3002 matches,
3003 routeMatch || getTargetMatch(matches, location),
3004 requestContext,
3005 dataStrategy,
3006 skipLoaderErrorBubbling,
3007 routeMatch != null,
3008 filterMatchesToLoad,
3009 skipRevalidation
3010 );
3011 return result2;
3012 }
3013 let result = await loadRouteData(
3014 request,
3015 matches,
3016 requestContext,
3017 dataStrategy,
3018 skipLoaderErrorBubbling,
3019 routeMatch,
3020 filterMatchesToLoad
3021 );
3022 return isResponse(result) ? result : {
3023 ...result,
3024 actionData: null,
3025 actionHeaders: {}
3026 };
3027 } catch (e) {
3028 if (isDataStrategyResult(e) && isResponse(e.result)) {
3029 if (e.type === "error" /* error */) {
3030 throw e.result;
3031 }
3032 return e.result;
3033 }
3034 if (isRedirectResponse(e)) {
3035 return e;
3036 }
3037 throw e;
3038 }
3039 }
3040 async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest, filterMatchesToLoad, skipRevalidation) {
3041 let result;
3042 if (!actionMatch.route.action && !actionMatch.route.lazy) {
3043 let error = getInternalRouterError(405, {
3044 method: request.method,
3045 pathname: new URL(request.url).pathname,
3046 routeId: actionMatch.route.id
3047 });
3048 if (isRouteRequest) {
3049 throw error;
3050 }
3051 result = {
3052 type: "error" /* error */,
3053 error
3054 };
3055 } else {
3056 let dsMatches = getTargetedDataStrategyMatches(
3057 mapRouteProperties2,
3058 manifest,
3059 request,
3060 matches,
3061 actionMatch,
3062 [],
3063 requestContext
3064 );
3065 let results = await callDataStrategy(
3066 request,
3067 dsMatches,
3068 isRouteRequest,
3069 requestContext,
3070 dataStrategy
3071 );
3072 result = results[actionMatch.route.id];
3073 if (request.signal.aborted) {
3074 throwStaticHandlerAbortedError(request, isRouteRequest);
3075 }
3076 }
3077 if (isRedirectResult(result)) {
3078 throw new Response(null, {
3079 status: result.response.status,
3080 headers: {
3081 Location: result.response.headers.get("Location")
3082 }
3083 });
3084 }
3085 if (isRouteRequest) {
3086 if (isErrorResult(result)) {
3087 throw result.error;
3088 }
3089 return {
3090 matches: [actionMatch],
3091 loaderData: {},
3092 actionData: { [actionMatch.route.id]: result.data },
3093 errors: null,
3094 // Note: statusCode + headers are unused here since queryRoute will
3095 // return the raw Response or value
3096 statusCode: 200,
3097 loaderHeaders: {},
3098 actionHeaders: {}
3099 };
3100 }
3101 if (skipRevalidation) {
3102 if (isErrorResult(result)) {
3103 let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
3104 return {
3105 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
3106 actionData: null,
3107 actionHeaders: {
3108 ...result.headers ? { [actionMatch.route.id]: result.headers } : {}
3109 },
3110 matches,
3111 loaderData: {},
3112 errors: {
3113 [boundaryMatch.route.id]: result.error
3114 },
3115 loaderHeaders: {}
3116 };
3117 } else {
3118 return {
3119 actionData: {
3120 [actionMatch.route.id]: result.data
3121 },
3122 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {},
3123 matches,
3124 loaderData: {},
3125 errors: null,
3126 statusCode: result.statusCode || 200,
3127 loaderHeaders: {}
3128 };
3129 }
3130 }
3131 let loaderRequest = new Request(request.url, {
3132 headers: request.headers,
3133 redirect: request.redirect,
3134 signal: request.signal
3135 });
3136 if (isErrorResult(result)) {
3137 let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
3138 let handlerContext2 = await loadRouteData(
3139 loaderRequest,
3140 matches,
3141 requestContext,
3142 dataStrategy,
3143 skipLoaderErrorBubbling,
3144 null,
3145 filterMatchesToLoad,
3146 [boundaryMatch.route.id, result]
3147 );
3148 return {
3149 ...handlerContext2,
3150 statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
3151 actionData: null,
3152 actionHeaders: {
3153 ...result.headers ? { [actionMatch.route.id]: result.headers } : {}
3154 }
3155 };
3156 }
3157 let handlerContext = await loadRouteData(
3158 loaderRequest,
3159 matches,
3160 requestContext,
3161 dataStrategy,
3162 skipLoaderErrorBubbling,
3163 null,
3164 filterMatchesToLoad
3165 );
3166 return {
3167 ...handlerContext,
3168 actionData: {
3169 [actionMatch.route.id]: result.data
3170 },
3171 // action status codes take precedence over loader status codes
3172 ...result.statusCode ? { statusCode: result.statusCode } : {},
3173 actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {}
3174 };
3175 }
3176 async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, pendingActionResult) {
3177 let isRouteRequest = routeMatch != null;
3178 if (isRouteRequest && !routeMatch?.route.loader && !routeMatch?.route.lazy) {
3179 throw getInternalRouterError(400, {
3180 method: request.method,
3181 pathname: new URL(request.url).pathname,
3182 routeId: routeMatch?.route.id
3183 });
3184 }
3185 let dsMatches;
3186 if (routeMatch) {
3187 dsMatches = getTargetedDataStrategyMatches(
3188 mapRouteProperties2,
3189 manifest,
3190 request,
3191 matches,
3192 routeMatch,
3193 [],
3194 requestContext
3195 );
3196 } else {
3197 let maxIdx = pendingActionResult && isErrorResult(pendingActionResult[1]) ? (
3198 // Up to but not including the boundary
3199 matches.findIndex((m) => m.route.id === pendingActionResult[0]) - 1
3200 ) : void 0;
3201 dsMatches = matches.map((match, index) => {
3202 if (maxIdx != null && index > maxIdx) {
3203 return getDataStrategyMatch(
3204 mapRouteProperties2,
3205 manifest,
3206 request,
3207 match,
3208 [],
3209 requestContext,
3210 false
3211 );
3212 }
3213 return getDataStrategyMatch(
3214 mapRouteProperties2,
3215 manifest,
3216 request,
3217 match,
3218 [],
3219 requestContext,
3220 (match.route.loader || match.route.lazy) != null && (!filterMatchesToLoad || filterMatchesToLoad(match))
3221 );
3222 });
3223 }
3224 if (!dataStrategy && !dsMatches.some((m) => m.shouldLoad)) {
3225 return {
3226 matches,
3227 loaderData: {},
3228 errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? {
3229 [pendingActionResult[0]]: pendingActionResult[1].error
3230 } : null,
3231 statusCode: 200,
3232 loaderHeaders: {}
3233 };
3234 }
3235 let results = await callDataStrategy(
3236 request,
3237 dsMatches,
3238 isRouteRequest,
3239 requestContext,
3240 dataStrategy
3241 );
3242 if (request.signal.aborted) {
3243 throwStaticHandlerAbortedError(request, isRouteRequest);
3244 }
3245 let handlerContext = processRouteLoaderData(
3246 matches,
3247 results,
3248 pendingActionResult,
3249 true,
3250 skipLoaderErrorBubbling
3251 );
3252 return {
3253 ...handlerContext,
3254 matches
3255 };
3256 }
3257 async function callDataStrategy(request, matches, isRouteRequest, requestContext, dataStrategy) {
3258 let results = await callDataStrategyImpl(
3259 dataStrategy || defaultDataStrategy,
3260 request,
3261 matches,
3262 null,
3263 requestContext,
3264 true
3265 );
3266 let dataResults = {};
3267 await Promise.all(
3268 matches.map(async (match) => {
3269 if (!(match.route.id in results)) {
3270 return;
3271 }
3272 let result = results[match.route.id];
3273 if (isRedirectDataStrategyResult(result)) {
3274 let response = result.result;
3275 throw normalizeRelativeRoutingRedirectResponse(
3276 response,
3277 request,
3278 match.route.id,
3279 matches,
3280 basename
3281 );
3282 }
3283 if (isResponse(result.result) && isRouteRequest) {
3284 throw result;
3285 }
3286 dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);
3287 })
3288 );
3289 return dataResults;
3290 }
3291 return {
3292 dataRoutes,
3293 query,
3294 queryRoute
3295 };
3296}
3297function getStaticContextFromError(routes, handlerContext, error, boundaryId) {
3298 let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id;
3299 return {
3300 ...handlerContext,
3301 statusCode: isRouteErrorResponse(error) ? error.status : 500,
3302 errors: {
3303 [errorBoundaryId]: error
3304 }
3305 };
3306}
3307function throwStaticHandlerAbortedError(request, isRouteRequest) {
3308 if (request.signal.reason !== void 0) {
3309 throw request.signal.reason;
3310 }
3311 let method = isRouteRequest ? "queryRoute" : "query";
3312 throw new Error(
3313 `${method}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
3314 );
3315}
3316function isSubmissionNavigation(opts) {
3317 return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== void 0);
3318}
3319function normalizeTo(location, matches, basename, to, fromRouteId, relative) {
3320 let contextualMatches;
3321 let activeRouteMatch;
3322 if (fromRouteId) {
3323 contextualMatches = [];
3324 for (let match of matches) {
3325 contextualMatches.push(match);
3326 if (match.route.id === fromRouteId) {
3327 activeRouteMatch = match;
3328 break;
3329 }
3330 }
3331 } else {
3332 contextualMatches = matches;
3333 activeRouteMatch = matches[matches.length - 1];
3334 }
3335 let path = resolveTo(
3336 to ? to : ".",
3337 getResolveToMatches(contextualMatches),
3338 stripBasename(location.pathname, basename) || location.pathname,
3339 relative === "path"
3340 );
3341 if (to == null) {
3342 path.search = location.search;
3343 path.hash = location.hash;
3344 }
3345 if ((to == null || to === "" || to === ".") && activeRouteMatch) {
3346 let nakedIndex = hasNakedIndexQuery(path.search);
3347 if (activeRouteMatch.route.index && !nakedIndex) {
3348 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
3349 } else if (!activeRouteMatch.route.index && nakedIndex) {
3350 let params = new URLSearchParams(path.search);
3351 let indexValues = params.getAll("index");
3352 params.delete("index");
3353 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
3354 let qs = params.toString();
3355 path.search = qs ? `?${qs}` : "";
3356 }
3357 }
3358 if (basename !== "/") {
3359 path.pathname = prependBasename({ basename, pathname: path.pathname });
3360 }
3361 return createPath(path);
3362}
3363function normalizeNavigateOptions(isFetcher, path, opts) {
3364 if (!opts || !isSubmissionNavigation(opts)) {
3365 return { path };
3366 }
3367 if (opts.formMethod && !isValidMethod(opts.formMethod)) {
3368 return {
3369 path,
3370 error: getInternalRouterError(405, { method: opts.formMethod })
3371 };
3372 }
3373 let getInvalidBodyError = () => ({
3374 path,
3375 error: getInternalRouterError(400, { type: "invalid-body" })
3376 });
3377 let rawFormMethod = opts.formMethod || "get";
3378 let formMethod = rawFormMethod.toUpperCase();
3379 let formAction = stripHashFromPath(path);
3380 if (opts.body !== void 0) {
3381 if (opts.formEncType === "text/plain") {
3382 if (!isMutationMethod(formMethod)) {
3383 return getInvalidBodyError();
3384 }
3385 let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ? (
3386 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
3387 Array.from(opts.body.entries()).reduce(
3388 (acc, [name, value]) => `${acc}${name}=${value}
3389`,
3390 ""
3391 )
3392 ) : String(opts.body);
3393 return {
3394 path,
3395 submission: {
3396 formMethod,
3397 formAction,
3398 formEncType: opts.formEncType,
3399 formData: void 0,
3400 json: void 0,
3401 text
3402 }
3403 };
3404 } else if (opts.formEncType === "application/json") {
3405 if (!isMutationMethod(formMethod)) {
3406 return getInvalidBodyError();
3407 }
3408 try {
3409 let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body;
3410 return {
3411 path,
3412 submission: {
3413 formMethod,
3414 formAction,
3415 formEncType: opts.formEncType,
3416 formData: void 0,
3417 json,
3418 text: void 0
3419 }
3420 };
3421 } catch (e) {
3422 return getInvalidBodyError();
3423 }
3424 }
3425 }
3426 invariant(
3427 typeof FormData === "function",
3428 "FormData is not available in this environment"
3429 );
3430 let searchParams;
3431 let formData;
3432 if (opts.formData) {
3433 searchParams = convertFormDataToSearchParams(opts.formData);
3434 formData = opts.formData;
3435 } else if (opts.body instanceof FormData) {
3436 searchParams = convertFormDataToSearchParams(opts.body);
3437 formData = opts.body;
3438 } else if (opts.body instanceof URLSearchParams) {
3439 searchParams = opts.body;
3440 formData = convertSearchParamsToFormData(searchParams);
3441 } else if (opts.body == null) {
3442 searchParams = new URLSearchParams();
3443 formData = new FormData();
3444 } else {
3445 try {
3446 searchParams = new URLSearchParams(opts.body);
3447 formData = convertSearchParamsToFormData(searchParams);
3448 } catch (e) {
3449 return getInvalidBodyError();
3450 }
3451 }
3452 let submission = {
3453 formMethod,
3454 formAction,
3455 formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
3456 formData,
3457 json: void 0,
3458 text: void 0
3459 };
3460 if (isMutationMethod(submission.formMethod)) {
3461 return { path, submission };
3462 }
3463 let parsedPath = parsePath(path);
3464 if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
3465 searchParams.append("index", "");
3466 }
3467 parsedPath.search = `?${searchParams}`;
3468 return { path: createPath(parsedPath), submission };
3469}
3470function getMatchesToLoad(request, scopedContext, mapRouteProperties2, manifest, history, state, matches, submission, location, lazyRoutePropertiesToSkip, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, hasPatchRoutesOnNavigation, pendingActionResult) {
3471 let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0;
3472 let currentUrl = history.createURL(state.location);
3473 let nextUrl = history.createURL(location);
3474 let maxIdx;
3475 if (initialHydration && state.errors) {
3476 let boundaryId = Object.keys(state.errors)[0];
3477 maxIdx = matches.findIndex((m) => m.route.id === boundaryId);
3478 } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
3479 let boundaryId = pendingActionResult[0];
3480 maxIdx = matches.findIndex((m) => m.route.id === boundaryId) - 1;
3481 }
3482 let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0;
3483 let shouldSkipRevalidation = actionStatus && actionStatus >= 400;
3484 let baseShouldRevalidateArgs = {
3485 currentUrl,
3486 currentParams: state.matches[0]?.params || {},
3487 nextUrl,
3488 nextParams: matches[0].params,
3489 ...submission,
3490 actionResult,
3491 actionStatus
3492 };
3493 let dsMatches = matches.map((match, index) => {
3494 let { route } = match;
3495 let forceShouldLoad = null;
3496 if (maxIdx != null && index > maxIdx) {
3497 forceShouldLoad = false;
3498 } else if (route.lazy) {
3499 forceShouldLoad = true;
3500 } else if (route.loader == null) {
3501 forceShouldLoad = false;
3502 } else if (initialHydration) {
3503 forceShouldLoad = shouldLoadRouteOnHydration(
3504 route,
3505 state.loaderData,
3506 state.errors
3507 );
3508 } else if (isNewLoader(state.loaderData, state.matches[index], match)) {
3509 forceShouldLoad = true;
3510 }
3511 if (forceShouldLoad !== null) {
3512 return getDataStrategyMatch(
3513 mapRouteProperties2,
3514 manifest,
3515 request,
3516 match,
3517 lazyRoutePropertiesToSkip,
3518 scopedContext,
3519 forceShouldLoad
3520 );
3521 }
3522 let defaultShouldRevalidate = shouldSkipRevalidation ? false : (
3523 // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
3524 isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
3525 currentUrl.search !== nextUrl.search || isNewRouteInstance(state.matches[index], match)
3526 );
3527 let shouldRevalidateArgs = {
3528 ...baseShouldRevalidateArgs,
3529 defaultShouldRevalidate
3530 };
3531 let shouldLoad = shouldRevalidateLoader(match, shouldRevalidateArgs);
3532 return getDataStrategyMatch(
3533 mapRouteProperties2,
3534 manifest,
3535 request,
3536 match,
3537 lazyRoutePropertiesToSkip,
3538 scopedContext,
3539 shouldLoad,
3540 shouldRevalidateArgs
3541 );
3542 });
3543 let revalidatingFetchers = [];
3544 fetchLoadMatches.forEach((f, key) => {
3545 if (initialHydration || !matches.some((m) => m.route.id === f.routeId) || fetchersQueuedForDeletion.has(key)) {
3546 return;
3547 }
3548 let fetcher = state.fetchers.get(key);
3549 let isMidInitialLoad = fetcher && fetcher.state !== "idle" && fetcher.data === void 0;
3550 let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
3551 if (!fetcherMatches) {
3552 if (hasPatchRoutesOnNavigation && isMidInitialLoad) {
3553 return;
3554 }
3555 revalidatingFetchers.push({
3556 key,
3557 routeId: f.routeId,
3558 path: f.path,
3559 matches: null,
3560 match: null,
3561 request: null,
3562 controller: null
3563 });
3564 return;
3565 }
3566 if (fetchRedirectIds.has(key)) {
3567 return;
3568 }
3569 let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
3570 let fetchController = new AbortController();
3571 let fetchRequest = createClientSideRequest(
3572 history,
3573 f.path,
3574 fetchController.signal
3575 );
3576 let fetcherDsMatches = null;
3577 if (cancelledFetcherLoads.has(key)) {
3578 cancelledFetcherLoads.delete(key);
3579 fetcherDsMatches = getTargetedDataStrategyMatches(
3580 mapRouteProperties2,
3581 manifest,
3582 fetchRequest,
3583 fetcherMatches,
3584 fetcherMatch,
3585 lazyRoutePropertiesToSkip,
3586 scopedContext
3587 );
3588 } else if (isMidInitialLoad) {
3589 if (isRevalidationRequired) {
3590 fetcherDsMatches = getTargetedDataStrategyMatches(
3591 mapRouteProperties2,
3592 manifest,
3593 fetchRequest,
3594 fetcherMatches,
3595 fetcherMatch,
3596 lazyRoutePropertiesToSkip,
3597 scopedContext
3598 );
3599 }
3600 } else {
3601 let shouldRevalidateArgs = {
3602 ...baseShouldRevalidateArgs,
3603 defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired
3604 };
3605 if (shouldRevalidateLoader(fetcherMatch, shouldRevalidateArgs)) {
3606 fetcherDsMatches = getTargetedDataStrategyMatches(
3607 mapRouteProperties2,
3608 manifest,
3609 fetchRequest,
3610 fetcherMatches,
3611 fetcherMatch,
3612 lazyRoutePropertiesToSkip,
3613 scopedContext,
3614 shouldRevalidateArgs
3615 );
3616 }
3617 }
3618 if (fetcherDsMatches) {
3619 revalidatingFetchers.push({
3620 key,
3621 routeId: f.routeId,
3622 path: f.path,
3623 matches: fetcherDsMatches,
3624 match: fetcherMatch,
3625 request: fetchRequest,
3626 controller: fetchController
3627 });
3628 }
3629 });
3630 return { dsMatches, revalidatingFetchers };
3631}
3632function shouldLoadRouteOnHydration(route, loaderData, errors) {
3633 if (route.lazy) {
3634 return true;
3635 }
3636 if (!route.loader) {
3637 return false;
3638 }
3639 let hasData = loaderData != null && route.id in loaderData;
3640 let hasError = errors != null && errors[route.id] !== void 0;
3641 if (!hasData && hasError) {
3642 return false;
3643 }
3644 if (typeof route.loader === "function" && route.loader.hydrate === true) {
3645 return true;
3646 }
3647 return !hasData && !hasError;
3648}
3649function isNewLoader(currentLoaderData, currentMatch, match) {
3650 let isNew = (
3651 // [a] -> [a, b]
3652 !currentMatch || // [a, b] -> [a, c]
3653 match.route.id !== currentMatch.route.id
3654 );
3655 let isMissingData = !currentLoaderData.hasOwnProperty(match.route.id);
3656 return isNew || isMissingData;
3657}
3658function isNewRouteInstance(currentMatch, match) {
3659 let currentPath = currentMatch.route.path;
3660 return (
3661 // param change for this match, /users/123 -> /users/456
3662 currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
3663 // e.g. /files/images/avatar.jpg -> files/finances.xls
3664 currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
3665 );
3666}
3667function shouldRevalidateLoader(loaderMatch, arg) {
3668 if (loaderMatch.route.shouldRevalidate) {
3669 let routeChoice = loaderMatch.route.shouldRevalidate(arg);
3670 if (typeof routeChoice === "boolean") {
3671 return routeChoice;
3672 }
3673 }
3674 return arg.defaultShouldRevalidate;
3675}
3676function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties2, allowElementMutations) {
3677 let childrenToPatch;
3678 if (routeId) {
3679 let route = manifest[routeId];
3680 invariant(
3681 route,
3682 `No route found to patch children into: routeId = ${routeId}`
3683 );
3684 if (!route.children) {
3685 route.children = [];
3686 }
3687 childrenToPatch = route.children;
3688 } else {
3689 childrenToPatch = routesToUse;
3690 }
3691 let uniqueChildren = [];
3692 let existingChildren = [];
3693 children.forEach((newRoute) => {
3694 let existingRoute = childrenToPatch.find(
3695 (existingRoute2) => isSameRoute(newRoute, existingRoute2)
3696 );
3697 if (existingRoute) {
3698 existingChildren.push({ existingRoute, newRoute });
3699 } else {
3700 uniqueChildren.push(newRoute);
3701 }
3702 });
3703 if (uniqueChildren.length > 0) {
3704 let newRoutes = convertRoutesToDataRoutes(
3705 uniqueChildren,
3706 mapRouteProperties2,
3707 [routeId || "_", "patch", String(childrenToPatch?.length || "0")],
3708 manifest
3709 );
3710 childrenToPatch.push(...newRoutes);
3711 }
3712 if (allowElementMutations && existingChildren.length > 0) {
3713 for (let i = 0; i < existingChildren.length; i++) {
3714 let { existingRoute, newRoute } = existingChildren[i];
3715 let existingRouteTyped = existingRoute;
3716 let [newRouteTyped] = convertRoutesToDataRoutes(
3717 [newRoute],
3718 mapRouteProperties2,
3719 [],
3720 // Doesn't matter for mutated routes since they already have an id
3721 {},
3722 // Don't touch the manifest here since we're updating in place
3723 true
3724 );
3725 Object.assign(existingRouteTyped, {
3726 element: newRouteTyped.element ? newRouteTyped.element : existingRouteTyped.element,
3727 errorElement: newRouteTyped.errorElement ? newRouteTyped.errorElement : existingRouteTyped.errorElement,
3728 hydrateFallbackElement: newRouteTyped.hydrateFallbackElement ? newRouteTyped.hydrateFallbackElement : existingRouteTyped.hydrateFallbackElement
3729 });
3730 }
3731 }
3732}
3733function isSameRoute(newRoute, existingRoute) {
3734 if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) {
3735 return true;
3736 }
3737 if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) {
3738 return false;
3739 }
3740 if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) {
3741 return true;
3742 }
3743 return newRoute.children.every(
3744 (aChild, i) => existingRoute.children?.some((bChild) => isSameRoute(aChild, bChild))
3745 );
3746}
3747var lazyRoutePropertyCache = /* @__PURE__ */ new WeakMap();
3748var loadLazyRouteProperty = ({
3749 key,
3750 route,
3751 manifest,
3752 mapRouteProperties: mapRouteProperties2
3753}) => {
3754 let routeToUpdate = manifest[route.id];
3755 invariant(routeToUpdate, "No route found in manifest");
3756 if (!routeToUpdate.lazy || typeof routeToUpdate.lazy !== "object") {
3757 return;
3758 }
3759 let lazyFn = routeToUpdate.lazy[key];
3760 if (!lazyFn) {
3761 return;
3762 }
3763 let cache = lazyRoutePropertyCache.get(routeToUpdate);
3764 if (!cache) {
3765 cache = {};
3766 lazyRoutePropertyCache.set(routeToUpdate, cache);
3767 }
3768 let cachedPromise = cache[key];
3769 if (cachedPromise) {
3770 return cachedPromise;
3771 }
3772 let propertyPromise = (async () => {
3773 let isUnsupported = isUnsupportedLazyRouteObjectKey(key);
3774 let staticRouteValue = routeToUpdate[key];
3775 let isStaticallyDefined = staticRouteValue !== void 0 && key !== "hasErrorBoundary";
3776 if (isUnsupported) {
3777 warning(
3778 !isUnsupported,
3779 "Route property " + key + " is not a supported lazy route property. This property will be ignored."
3780 );
3781 cache[key] = Promise.resolve();
3782 } else if (isStaticallyDefined) {
3783 warning(
3784 false,
3785 `Route "${routeToUpdate.id}" has a static property "${key}" defined. The lazy property will be ignored.`
3786 );
3787 } else {
3788 let value = await lazyFn();
3789 if (value != null) {
3790 Object.assign(routeToUpdate, { [key]: value });
3791 Object.assign(routeToUpdate, mapRouteProperties2(routeToUpdate));
3792 }
3793 }
3794 if (typeof routeToUpdate.lazy === "object") {
3795 routeToUpdate.lazy[key] = void 0;
3796 if (Object.values(routeToUpdate.lazy).every((value) => value === void 0)) {
3797 routeToUpdate.lazy = void 0;
3798 }
3799 }
3800 })();
3801 cache[key] = propertyPromise;
3802 return propertyPromise;
3803};
3804var lazyRouteFunctionCache = /* @__PURE__ */ new WeakMap();
3805function loadLazyRoute(route, type, manifest, mapRouteProperties2, lazyRoutePropertiesToSkip) {
3806 let routeToUpdate = manifest[route.id];
3807 invariant(routeToUpdate, "No route found in manifest");
3808 if (!route.lazy) {
3809 return {
3810 lazyRoutePromise: void 0,
3811 lazyHandlerPromise: void 0
3812 };
3813 }
3814 if (typeof route.lazy === "function") {
3815 let cachedPromise = lazyRouteFunctionCache.get(routeToUpdate);
3816 if (cachedPromise) {
3817 return {
3818 lazyRoutePromise: cachedPromise,
3819 lazyHandlerPromise: cachedPromise
3820 };
3821 }
3822 let lazyRoutePromise2 = (async () => {
3823 invariant(
3824 typeof route.lazy === "function",
3825 "No lazy route function found"
3826 );
3827 let lazyRoute = await route.lazy();
3828 let routeUpdates = {};
3829 for (let lazyRouteProperty in lazyRoute) {
3830 let lazyValue = lazyRoute[lazyRouteProperty];
3831 if (lazyValue === void 0) {
3832 continue;
3833 }
3834 let isUnsupported = isUnsupportedLazyRouteFunctionKey(lazyRouteProperty);
3835 let staticRouteValue = routeToUpdate[lazyRouteProperty];
3836 let isStaticallyDefined = staticRouteValue !== void 0 && // This property isn't static since it should always be updated based
3837 // on the route updates
3838 lazyRouteProperty !== "hasErrorBoundary";
3839 if (isUnsupported) {
3840 warning(
3841 !isUnsupported,
3842 "Route property " + lazyRouteProperty + " is not a supported property to be returned from a lazy route function. This property will be ignored."
3843 );
3844 } else if (isStaticallyDefined) {
3845 warning(
3846 !isStaticallyDefined,
3847 `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.`
3848 );
3849 } else {
3850 routeUpdates[lazyRouteProperty] = lazyValue;
3851 }
3852 }
3853 Object.assign(routeToUpdate, routeUpdates);
3854 Object.assign(routeToUpdate, {
3855 // To keep things framework agnostic, we use the provided `mapRouteProperties`
3856 // function to set the framework-aware properties (`element`/`hasErrorBoundary`)
3857 // since the logic will differ between frameworks.
3858 ...mapRouteProperties2(routeToUpdate),
3859 lazy: void 0
3860 });
3861 })();
3862 lazyRouteFunctionCache.set(routeToUpdate, lazyRoutePromise2);
3863 lazyRoutePromise2.catch(() => {
3864 });
3865 return {
3866 lazyRoutePromise: lazyRoutePromise2,
3867 lazyHandlerPromise: lazyRoutePromise2
3868 };
3869 }
3870 let lazyKeys = Object.keys(route.lazy);
3871 let lazyPropertyPromises = [];
3872 let lazyHandlerPromise = void 0;
3873 for (let key of lazyKeys) {
3874 if (lazyRoutePropertiesToSkip && lazyRoutePropertiesToSkip.includes(key)) {
3875 continue;
3876 }
3877 let promise = loadLazyRouteProperty({
3878 key,
3879 route,
3880 manifest,
3881 mapRouteProperties: mapRouteProperties2
3882 });
3883 if (promise) {
3884 lazyPropertyPromises.push(promise);
3885 if (key === type) {
3886 lazyHandlerPromise = promise;
3887 }
3888 }
3889 }
3890 let lazyRoutePromise = lazyPropertyPromises.length > 0 ? Promise.all(lazyPropertyPromises).then(() => {
3891 }) : void 0;
3892 lazyRoutePromise?.catch(() => {
3893 });
3894 lazyHandlerPromise?.catch(() => {
3895 });
3896 return {
3897 lazyRoutePromise,
3898 lazyHandlerPromise
3899 };
3900}
3901function isNonNullable(value) {
3902 return value !== void 0;
3903}
3904function loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties2) {
3905 let promises = matches.map(({ route }) => {
3906 if (typeof route.lazy !== "object" || !route.lazy.unstable_middleware) {
3907 return void 0;
3908 }
3909 return loadLazyRouteProperty({
3910 key: "unstable_middleware",
3911 route,
3912 manifest,
3913 mapRouteProperties: mapRouteProperties2
3914 });
3915 }).filter(isNonNullable);
3916 return promises.length > 0 ? Promise.all(promises) : void 0;
3917}
3918async function defaultDataStrategy(args) {
3919 let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
3920 let keyedResults = {};
3921 let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
3922 results.forEach((result, i) => {
3923 keyedResults[matchesToLoad[i].route.id] = result;
3924 });
3925 return keyedResults;
3926}
3927async function defaultDataStrategyWithMiddleware(args) {
3928 if (!args.matches.some((m) => m.route.unstable_middleware)) {
3929 return defaultDataStrategy(args);
3930 }
3931 return runMiddlewarePipeline(
3932 args,
3933 false,
3934 () => defaultDataStrategy(args),
3935 (error, routeId) => ({ [routeId]: { type: "error", result: error } })
3936 );
3937}
3938async function runMiddlewarePipeline(args, propagateResult, handler, errorHandler) {
3939 let { matches, request, params, context } = args;
3940 let middlewareState = {
3941 handlerResult: void 0
3942 };
3943 try {
3944 let tuples = matches.flatMap(
3945 (m) => m.route.unstable_middleware ? m.route.unstable_middleware.map((fn) => [m.route.id, fn]) : []
3946 );
3947 let result = await callRouteMiddleware(
3948 { request, params, context },
3949 tuples,
3950 propagateResult,
3951 middlewareState,
3952 handler
3953 );
3954 return propagateResult ? result : middlewareState.handlerResult;
3955 } catch (e) {
3956 if (!middlewareState.middlewareError) {
3957 throw e;
3958 }
3959 let result = await errorHandler(
3960 middlewareState.middlewareError.error,
3961 middlewareState.middlewareError.routeId
3962 );
3963 if (propagateResult || !middlewareState.handlerResult) {
3964 return result;
3965 }
3966 return Object.assign(middlewareState.handlerResult, result);
3967 }
3968}
3969async function callRouteMiddleware(args, middlewares, propagateResult, middlewareState, handler, idx = 0) {
3970 let { request } = args;
3971 if (request.signal.aborted) {
3972 if (request.signal.reason) {
3973 throw request.signal.reason;
3974 }
3975 throw new Error(
3976 `Request aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
3977 );
3978 }
3979 let tuple = middlewares[idx];
3980 if (!tuple) {
3981 middlewareState.handlerResult = await handler();
3982 return middlewareState.handlerResult;
3983 }
3984 let [routeId, middleware] = tuple;
3985 let nextCalled = false;
3986 let nextResult = void 0;
3987 let next = async () => {
3988 if (nextCalled) {
3989 throw new Error("You may only call `next()` once per middleware");
3990 }
3991 nextCalled = true;
3992 let result = await callRouteMiddleware(
3993 args,
3994 middlewares,
3995 propagateResult,
3996 middlewareState,
3997 handler,
3998 idx + 1
3999 );
4000 if (propagateResult) {
4001 nextResult = result;
4002 return nextResult;
4003 }
4004 };
4005 try {
4006 let result = await middleware(
4007 {
4008 request: args.request,
4009 params: args.params,
4010 context: args.context
4011 },
4012 next
4013 );
4014 if (nextCalled) {
4015 if (result === void 0) {
4016 return nextResult;
4017 } else {
4018 return result;
4019 }
4020 } else {
4021 return next();
4022 }
4023 } catch (error) {
4024 if (!middlewareState.middlewareError) {
4025 middlewareState.middlewareError = { routeId, error };
4026 } else if (middlewareState.middlewareError.error !== error) {
4027 middlewareState.middlewareError = { routeId, error };
4028 }
4029 throw error;
4030 }
4031}
4032function getDataStrategyMatchLazyPromises(mapRouteProperties2, manifest, request, match, lazyRoutePropertiesToSkip) {
4033 let lazyMiddlewarePromise = loadLazyRouteProperty({
4034 key: "unstable_middleware",
4035 route: match.route,
4036 manifest,
4037 mapRouteProperties: mapRouteProperties2
4038 });
4039 let lazyRoutePromises = loadLazyRoute(
4040 match.route,
4041 isMutationMethod(request.method) ? "action" : "loader",
4042 manifest,
4043 mapRouteProperties2,
4044 lazyRoutePropertiesToSkip
4045 );
4046 return {
4047 middleware: lazyMiddlewarePromise,
4048 route: lazyRoutePromises.lazyRoutePromise,
4049 handler: lazyRoutePromises.lazyHandlerPromise
4050 };
4051}
4052function getDataStrategyMatch(mapRouteProperties2, manifest, request, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, unstable_shouldRevalidateArgs = null) {
4053 let isUsingNewApi = false;
4054 let _lazyPromises = getDataStrategyMatchLazyPromises(
4055 mapRouteProperties2,
4056 manifest,
4057 request,
4058 match,
4059 lazyRoutePropertiesToSkip
4060 );
4061 return {
4062 ...match,
4063 _lazyPromises,
4064 shouldLoad,
4065 unstable_shouldRevalidateArgs,
4066 unstable_shouldCallHandler(defaultShouldRevalidate) {
4067 isUsingNewApi = true;
4068 if (!unstable_shouldRevalidateArgs) {
4069 return shouldLoad;
4070 }
4071 if (typeof defaultShouldRevalidate === "boolean") {
4072 return shouldRevalidateLoader(match, {
4073 ...unstable_shouldRevalidateArgs,
4074 defaultShouldRevalidate
4075 });
4076 }
4077 return shouldRevalidateLoader(match, unstable_shouldRevalidateArgs);
4078 },
4079 resolve(handlerOverride) {
4080 if (isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (match.route.lazy || match.route.loader)) {
4081 return callLoaderOrAction({
4082 request,
4083 match,
4084 lazyHandlerPromise: _lazyPromises?.handler,
4085 lazyRoutePromise: _lazyPromises?.route,
4086 handlerOverride,
4087 scopedContext
4088 });
4089 }
4090 return Promise.resolve({ type: "data" /* data */, result: void 0 });
4091 }
4092 };
4093}
4094function getTargetedDataStrategyMatches(mapRouteProperties2, manifest, request, matches, targetMatch, lazyRoutePropertiesToSkip, scopedContext, shouldRevalidateArgs = null) {
4095 return matches.map((match) => {
4096 if (match.route.id !== targetMatch.route.id) {
4097 return {
4098 ...match,
4099 shouldLoad: false,
4100 unstable_shouldRevalidateArgs: shouldRevalidateArgs,
4101 unstable_shouldCallHandler: () => false,
4102 _lazyPromises: getDataStrategyMatchLazyPromises(
4103 mapRouteProperties2,
4104 manifest,
4105 request,
4106 match,
4107 lazyRoutePropertiesToSkip
4108 ),
4109 resolve: () => Promise.resolve({ type: "data", result: void 0 })
4110 };
4111 }
4112 return getDataStrategyMatch(
4113 mapRouteProperties2,
4114 manifest,
4115 request,
4116 match,
4117 lazyRoutePropertiesToSkip,
4118 scopedContext,
4119 true,
4120 shouldRevalidateArgs
4121 );
4122 });
4123}
4124async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherKey, scopedContext, isStaticHandler) {
4125 if (matches.some((m) => m._lazyPromises?.middleware)) {
4126 await Promise.all(matches.map((m) => m._lazyPromises?.middleware));
4127 }
4128 let dataStrategyArgs = {
4129 request,
4130 params: matches[0].params,
4131 context: scopedContext,
4132 matches
4133 };
4134 let unstable_runClientMiddleware = isStaticHandler ? () => {
4135 throw new Error(
4136 "You cannot call `unstable_runClientMiddleware()` from a static handler `dataStrategy`. Middleware is run outside of `dataStrategy` during SSR in order to bubble up the Response. You can enable middleware via the `respond` API in `query`/`queryRoute`"
4137 );
4138 } : (cb) => {
4139 let typedDataStrategyArgs = dataStrategyArgs;
4140 return runMiddlewarePipeline(
4141 typedDataStrategyArgs,
4142 false,
4143 () => cb({
4144 ...typedDataStrategyArgs,
4145 fetcherKey,
4146 unstable_runClientMiddleware: () => {
4147 throw new Error(
4148 "Cannot call `unstable_runClientMiddleware()` from within an `unstable_runClientMiddleware` handler"
4149 );
4150 }
4151 }),
4152 (error, routeId) => ({
4153 [routeId]: { type: "error", result: error }
4154 })
4155 );
4156 };
4157 let results = await dataStrategyImpl({
4158 ...dataStrategyArgs,
4159 fetcherKey,
4160 unstable_runClientMiddleware
4161 });
4162 try {
4163 await Promise.all(
4164 matches.flatMap((m) => [
4165 m._lazyPromises?.handler,
4166 m._lazyPromises?.route
4167 ])
4168 );
4169 } catch (e) {
4170 }
4171 return results;
4172}
4173async function callLoaderOrAction({
4174 request,
4175 match,
4176 lazyHandlerPromise,
4177 lazyRoutePromise,
4178 handlerOverride,
4179 scopedContext
4180}) {
4181 let result;
4182 let onReject;
4183 let isAction = isMutationMethod(request.method);
4184 let type = isAction ? "action" : "loader";
4185 let runHandler = (handler) => {
4186 let reject;
4187 let abortPromise = new Promise((_, r) => reject = r);
4188 onReject = () => reject();
4189 request.signal.addEventListener("abort", onReject);
4190 let actualHandler = (ctx) => {
4191 if (typeof handler !== "function") {
4192 return Promise.reject(
4193 new Error(
4194 `You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]`
4195 )
4196 );
4197 }
4198 return handler(
4199 {
4200 request,
4201 params: match.params,
4202 context: scopedContext
4203 },
4204 ...ctx !== void 0 ? [ctx] : []
4205 );
4206 };
4207 let handlerPromise = (async () => {
4208 try {
4209 let val = await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler());
4210 return { type: "data", result: val };
4211 } catch (e) {
4212 return { type: "error", result: e };
4213 }
4214 })();
4215 return Promise.race([handlerPromise, abortPromise]);
4216 };
4217 try {
4218 let handler = isAction ? match.route.action : match.route.loader;
4219 if (lazyHandlerPromise || lazyRoutePromise) {
4220 if (handler) {
4221 let handlerError;
4222 let [value] = await Promise.all([
4223 // If the handler throws, don't let it immediately bubble out,
4224 // since we need to let the lazy() execution finish so we know if this
4225 // route has a boundary that can handle the error
4226 runHandler(handler).catch((e) => {
4227 handlerError = e;
4228 }),
4229 // Ensure all lazy route promises are resolved before continuing
4230 lazyHandlerPromise,
4231 lazyRoutePromise
4232 ]);
4233 if (handlerError !== void 0) {
4234 throw handlerError;
4235 }
4236 result = value;
4237 } else {
4238 await lazyHandlerPromise;
4239 let handler2 = isAction ? match.route.action : match.route.loader;
4240 if (handler2) {
4241 [result] = await Promise.all([runHandler(handler2), lazyRoutePromise]);
4242 } else if (type === "action") {
4243 let url = new URL(request.url);
4244 let pathname = url.pathname + url.search;
4245 throw getInternalRouterError(405, {
4246 method: request.method,
4247 pathname,
4248 routeId: match.route.id
4249 });
4250 } else {
4251 return { type: "data" /* data */, result: void 0 };
4252 }
4253 }
4254 } else if (!handler) {
4255 let url = new URL(request.url);
4256 let pathname = url.pathname + url.search;
4257 throw getInternalRouterError(404, {
4258 pathname
4259 });
4260 } else {
4261 result = await runHandler(handler);
4262 }
4263 } catch (e) {
4264 return { type: "error" /* error */, result: e };
4265 } finally {
4266 if (onReject) {
4267 request.signal.removeEventListener("abort", onReject);
4268 }
4269 }
4270 return result;
4271}
4272async function convertDataStrategyResultToDataResult(dataStrategyResult) {
4273 let { result, type } = dataStrategyResult;
4274 if (isResponse(result)) {
4275 let data2;
4276 try {
4277 let contentType = result.headers.get("Content-Type");
4278 if (contentType && /\bapplication\/json\b/.test(contentType)) {
4279 if (result.body == null) {
4280 data2 = null;
4281 } else {
4282 data2 = await result.json();
4283 }
4284 } else {
4285 data2 = await result.text();
4286 }
4287 } catch (e) {
4288 return { type: "error" /* error */, error: e };
4289 }
4290 if (type === "error" /* error */) {
4291 return {
4292 type: "error" /* error */,
4293 error: new ErrorResponseImpl(result.status, result.statusText, data2),
4294 statusCode: result.status,
4295 headers: result.headers
4296 };
4297 }
4298 return {
4299 type: "data" /* data */,
4300 data: data2,
4301 statusCode: result.status,
4302 headers: result.headers
4303 };
4304 }
4305 if (type === "error" /* error */) {
4306 if (isDataWithResponseInit(result)) {
4307 if (result.data instanceof Error) {
4308 return {
4309 type: "error" /* error */,
4310 error: result.data,
4311 statusCode: result.init?.status,
4312 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
4313 };
4314 }
4315 return {
4316 type: "error" /* error */,
4317 error: new ErrorResponseImpl(
4318 result.init?.status || 500,
4319 void 0,
4320 result.data
4321 ),
4322 statusCode: isRouteErrorResponse(result) ? result.status : void 0,
4323 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
4324 };
4325 }
4326 return {
4327 type: "error" /* error */,
4328 error: result,
4329 statusCode: isRouteErrorResponse(result) ? result.status : void 0
4330 };
4331 }
4332 if (isDataWithResponseInit(result)) {
4333 return {
4334 type: "data" /* data */,
4335 data: result.data,
4336 statusCode: result.init?.status,
4337 headers: result.init?.headers ? new Headers(result.init.headers) : void 0
4338 };
4339 }
4340 return { type: "data" /* data */, data: result };
4341}
4342function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) {
4343 let location = response.headers.get("Location");
4344 invariant(
4345 location,
4346 "Redirects returned/thrown from loaders/actions must have a Location header"
4347 );
4348 if (!isAbsoluteUrl(location)) {
4349 let trimmedMatches = matches.slice(
4350 0,
4351 matches.findIndex((m) => m.route.id === routeId) + 1
4352 );
4353 location = normalizeTo(
4354 new URL(request.url),
4355 trimmedMatches,
4356 basename,
4357 location
4358 );
4359 response.headers.set("Location", location);
4360 }
4361 return response;
4362}
4363function normalizeRedirectLocation(location, currentUrl, basename) {
4364 if (isAbsoluteUrl(location)) {
4365 let normalizedLocation = location;
4366 let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);
4367 let isSameBasename = stripBasename(url.pathname, basename) != null;
4368 if (url.origin === currentUrl.origin && isSameBasename) {
4369 return url.pathname + url.search + url.hash;
4370 }
4371 }
4372 return location;
4373}
4374function createClientSideRequest(history, location, signal, submission) {
4375 let url = history.createURL(stripHashFromPath(location)).toString();
4376 let init = { signal };
4377 if (submission && isMutationMethod(submission.formMethod)) {
4378 let { formMethod, formEncType } = submission;
4379 init.method = formMethod.toUpperCase();
4380 if (formEncType === "application/json") {
4381 init.headers = new Headers({ "Content-Type": formEncType });
4382 init.body = JSON.stringify(submission.json);
4383 } else if (formEncType === "text/plain") {
4384 init.body = submission.text;
4385 } else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) {
4386 init.body = convertFormDataToSearchParams(submission.formData);
4387 } else {
4388 init.body = submission.formData;
4389 }
4390 }
4391 return new Request(url, init);
4392}
4393function convertFormDataToSearchParams(formData) {
4394 let searchParams = new URLSearchParams();
4395 for (let [key, value] of formData.entries()) {
4396 searchParams.append(key, typeof value === "string" ? value : value.name);
4397 }
4398 return searchParams;
4399}
4400function convertSearchParamsToFormData(searchParams) {
4401 let formData = new FormData();
4402 for (let [key, value] of searchParams.entries()) {
4403 formData.append(key, value);
4404 }
4405 return formData;
4406}
4407function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) {
4408 let loaderData = {};
4409 let errors = null;
4410 let statusCode;
4411 let foundError = false;
4412 let loaderHeaders = {};
4413 let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0;
4414 matches.forEach((match) => {
4415 if (!(match.route.id in results)) {
4416 return;
4417 }
4418 let id = match.route.id;
4419 let result = results[id];
4420 invariant(
4421 !isRedirectResult(result),
4422 "Cannot handle redirect results in processLoaderData"
4423 );
4424 if (isErrorResult(result)) {
4425 let error = result.error;
4426 if (pendingError !== void 0) {
4427 error = pendingError;
4428 pendingError = void 0;
4429 }
4430 errors = errors || {};
4431 if (skipLoaderErrorBubbling) {
4432 errors[id] = error;
4433 } else {
4434 let boundaryMatch = findNearestBoundary(matches, id);
4435 if (errors[boundaryMatch.route.id] == null) {
4436 errors[boundaryMatch.route.id] = error;
4437 }
4438 }
4439 if (!isStaticHandler) {
4440 loaderData[id] = ResetLoaderDataSymbol;
4441 }
4442 if (!foundError) {
4443 foundError = true;
4444 statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
4445 }
4446 if (result.headers) {
4447 loaderHeaders[id] = result.headers;
4448 }
4449 } else {
4450 loaderData[id] = result.data;
4451 if (result.statusCode && result.statusCode !== 200 && !foundError) {
4452 statusCode = result.statusCode;
4453 }
4454 if (result.headers) {
4455 loaderHeaders[id] = result.headers;
4456 }
4457 }
4458 });
4459 if (pendingError !== void 0 && pendingActionResult) {
4460 errors = { [pendingActionResult[0]]: pendingError };
4461 if (pendingActionResult[2]) {
4462 loaderData[pendingActionResult[2]] = void 0;
4463 }
4464 }
4465 return {
4466 loaderData,
4467 errors,
4468 statusCode: statusCode || 200,
4469 loaderHeaders
4470 };
4471}
4472function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) {
4473 let { loaderData, errors } = processRouteLoaderData(
4474 matches,
4475 results,
4476 pendingActionResult
4477 );
4478 revalidatingFetchers.filter((f) => !f.matches || f.matches.some((m) => m.shouldLoad)).forEach((rf) => {
4479 let { key, match, controller } = rf;
4480 let result = fetcherResults[key];
4481 invariant(result, "Did not find corresponding fetcher result");
4482 if (controller && controller.signal.aborted) {
4483 return;
4484 } else if (isErrorResult(result)) {
4485 let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);
4486 if (!(errors && errors[boundaryMatch.route.id])) {
4487 errors = {
4488 ...errors,
4489 [boundaryMatch.route.id]: result.error
4490 };
4491 }
4492 state.fetchers.delete(key);
4493 } else if (isRedirectResult(result)) {
4494 invariant(false, "Unhandled fetcher revalidation redirect");
4495 } else {
4496 let doneFetcher = getDoneFetcher(result.data);
4497 state.fetchers.set(key, doneFetcher);
4498 }
4499 });
4500 return { loaderData, errors };
4501}
4502function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
4503 let mergedLoaderData = Object.entries(newLoaderData).filter(([, v]) => v !== ResetLoaderDataSymbol).reduce((merged, [k, v]) => {
4504 merged[k] = v;
4505 return merged;
4506 }, {});
4507 for (let match of matches) {
4508 let id = match.route.id;
4509 if (!newLoaderData.hasOwnProperty(id) && loaderData.hasOwnProperty(id) && match.route.loader) {
4510 mergedLoaderData[id] = loaderData[id];
4511 }
4512 if (errors && errors.hasOwnProperty(id)) {
4513 break;
4514 }
4515 }
4516 return mergedLoaderData;
4517}
4518function getActionDataForCommit(pendingActionResult) {
4519 if (!pendingActionResult) {
4520 return {};
4521 }
4522 return isErrorResult(pendingActionResult[1]) ? {
4523 // Clear out prior actionData on errors
4524 actionData: {}
4525 } : {
4526 actionData: {
4527 [pendingActionResult[0]]: pendingActionResult[1].data
4528 }
4529 };
4530}
4531function findNearestBoundary(matches, routeId) {
4532 let eligibleMatches = routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches];
4533 return eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0];
4534}
4535function getShortCircuitMatches(routes) {
4536 let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || {
4537 id: `__shim-error-route__`
4538 };
4539 return {
4540 matches: [
4541 {
4542 params: {},
4543 pathname: "",
4544 pathnameBase: "",
4545 route
4546 }
4547 ],
4548 route
4549 };
4550}
4551function getInternalRouterError(status, {
4552 pathname,
4553 routeId,
4554 method,
4555 type,
4556 message
4557} = {}) {
4558 let statusText = "Unknown Server Error";
4559 let errorMessage = "Unknown @remix-run/router error";
4560 if (status === 400) {
4561 statusText = "Bad Request";
4562 if (method && pathname && routeId) {
4563 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.`;
4564 } else if (type === "invalid-body") {
4565 errorMessage = "Unable to encode submission body";
4566 }
4567 } else if (status === 403) {
4568 statusText = "Forbidden";
4569 errorMessage = `Route "${routeId}" does not match URL "${pathname}"`;
4570 } else if (status === 404) {
4571 statusText = "Not Found";
4572 errorMessage = `No route matches URL "${pathname}"`;
4573 } else if (status === 405) {
4574 statusText = "Method Not Allowed";
4575 if (method && pathname && routeId) {
4576 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.`;
4577 } else if (method) {
4578 errorMessage = `Invalid request method "${method.toUpperCase()}"`;
4579 }
4580 }
4581 return new ErrorResponseImpl(
4582 status || 500,
4583 statusText,
4584 new Error(errorMessage),
4585 true
4586 );
4587}
4588function findRedirect(results) {
4589 let entries = Object.entries(results);
4590 for (let i = entries.length - 1; i >= 0; i--) {
4591 let [key, result] = entries[i];
4592 if (isRedirectResult(result)) {
4593 return { key, result };
4594 }
4595 }
4596}
4597function stripHashFromPath(path) {
4598 let parsedPath = typeof path === "string" ? parsePath(path) : path;
4599 return createPath({ ...parsedPath, hash: "" });
4600}
4601function isHashChangeOnly(a, b) {
4602 if (a.pathname !== b.pathname || a.search !== b.search) {
4603 return false;
4604 }
4605 if (a.hash === "") {
4606 return b.hash !== "";
4607 } else if (a.hash === b.hash) {
4608 return true;
4609 } else if (b.hash !== "") {
4610 return true;
4611 }
4612 return false;
4613}
4614function isDataStrategyResult(result) {
4615 return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" /* data */ || result.type === "error" /* error */);
4616}
4617function isRedirectDataStrategyResult(result) {
4618 return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
4619}
4620function isErrorResult(result) {
4621 return result.type === "error" /* error */;
4622}
4623function isRedirectResult(result) {
4624 return (result && result.type) === "redirect" /* redirect */;
4625}
4626function isDataWithResponseInit(value) {
4627 return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit";
4628}
4629function isResponse(value) {
4630 return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
4631}
4632function isRedirectStatusCode(statusCode) {
4633 return redirectStatusCodes.has(statusCode);
4634}
4635function isRedirectResponse(result) {
4636 return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location");
4637}
4638function isValidMethod(method) {
4639 return validRequestMethods.has(method.toUpperCase());
4640}
4641function isMutationMethod(method) {
4642 return validMutationMethods.has(method.toUpperCase());
4643}
4644function hasNakedIndexQuery(search) {
4645 return new URLSearchParams(search).getAll("index").some((v) => v === "");
4646}
4647function getTargetMatch(matches, location) {
4648 let search = typeof location === "string" ? parsePath(location).search : location.search;
4649 if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
4650 return matches[matches.length - 1];
4651 }
4652 let pathMatches = getPathContributingMatches(matches);
4653 return pathMatches[pathMatches.length - 1];
4654}
4655function getSubmissionFromNavigation(navigation) {
4656 let { formMethod, formAction, formEncType, text, formData, json } = navigation;
4657 if (!formMethod || !formAction || !formEncType) {
4658 return;
4659 }
4660 if (text != null) {
4661 return {
4662 formMethod,
4663 formAction,
4664 formEncType,
4665 formData: void 0,
4666 json: void 0,
4667 text
4668 };
4669 } else if (formData != null) {
4670 return {
4671 formMethod,
4672 formAction,
4673 formEncType,
4674 formData,
4675 json: void 0,
4676 text: void 0
4677 };
4678 } else if (json !== void 0) {
4679 return {
4680 formMethod,
4681 formAction,
4682 formEncType,
4683 formData: void 0,
4684 json,
4685 text: void 0
4686 };
4687 }
4688}
4689function getLoadingNavigation(location, submission) {
4690 if (submission) {
4691 let navigation = {
4692 state: "loading",
4693 location,
4694 formMethod: submission.formMethod,
4695 formAction: submission.formAction,
4696 formEncType: submission.formEncType,
4697 formData: submission.formData,
4698 json: submission.json,
4699 text: submission.text
4700 };
4701 return navigation;
4702 } else {
4703 let navigation = {
4704 state: "loading",
4705 location,
4706 formMethod: void 0,
4707 formAction: void 0,
4708 formEncType: void 0,
4709 formData: void 0,
4710 json: void 0,
4711 text: void 0
4712 };
4713 return navigation;
4714 }
4715}
4716function getSubmittingNavigation(location, submission) {
4717 let navigation = {
4718 state: "submitting",
4719 location,
4720 formMethod: submission.formMethod,
4721 formAction: submission.formAction,
4722 formEncType: submission.formEncType,
4723 formData: submission.formData,
4724 json: submission.json,
4725 text: submission.text
4726 };
4727 return navigation;
4728}
4729function getLoadingFetcher(submission, data2) {
4730 if (submission) {
4731 let fetcher = {
4732 state: "loading",
4733 formMethod: submission.formMethod,
4734 formAction: submission.formAction,
4735 formEncType: submission.formEncType,
4736 formData: submission.formData,
4737 json: submission.json,
4738 text: submission.text,
4739 data: data2
4740 };
4741 return fetcher;
4742 } else {
4743 let fetcher = {
4744 state: "loading",
4745 formMethod: void 0,
4746 formAction: void 0,
4747 formEncType: void 0,
4748 formData: void 0,
4749 json: void 0,
4750 text: void 0,
4751 data: data2
4752 };
4753 return fetcher;
4754 }
4755}
4756function getSubmittingFetcher(submission, existingFetcher) {
4757 let fetcher = {
4758 state: "submitting",
4759 formMethod: submission.formMethod,
4760 formAction: submission.formAction,
4761 formEncType: submission.formEncType,
4762 formData: submission.formData,
4763 json: submission.json,
4764 text: submission.text,
4765 data: existingFetcher ? existingFetcher.data : void 0
4766 };
4767 return fetcher;
4768}
4769function getDoneFetcher(data2) {
4770 let fetcher = {
4771 state: "idle",
4772 formMethod: void 0,
4773 formAction: void 0,
4774 formEncType: void 0,
4775 formData: void 0,
4776 json: void 0,
4777 text: void 0,
4778 data: data2
4779 };
4780 return fetcher;
4781}
4782function restoreAppliedTransitions(_window, transitions) {
4783 try {
4784 let sessionPositions = _window.sessionStorage.getItem(
4785 TRANSITIONS_STORAGE_KEY
4786 );
4787 if (sessionPositions) {
4788 let json = JSON.parse(sessionPositions);
4789 for (let [k, v] of Object.entries(json || {})) {
4790 if (v && Array.isArray(v)) {
4791 transitions.set(k, new Set(v || []));
4792 }
4793 }
4794 }
4795 } catch (e) {
4796 }
4797}
4798function persistAppliedTransitions(_window, transitions) {
4799 if (transitions.size > 0) {
4800 let json = {};
4801 for (let [k, v] of transitions) {
4802 json[k] = [...v];
4803 }
4804 try {
4805 _window.sessionStorage.setItem(
4806 TRANSITIONS_STORAGE_KEY,
4807 JSON.stringify(json)
4808 );
4809 } catch (error) {
4810 warning(
4811 false,
4812 `Failed to save applied view transitions in sessionStorage (${error}).`
4813 );
4814 }
4815 }
4816}
4817function createDeferred() {
4818 let resolve;
4819 let reject;
4820 let promise = new Promise((res, rej) => {
4821 resolve = async (val) => {
4822 res(val);
4823 try {
4824 await promise;
4825 } catch (e) {
4826 }
4827 };
4828 reject = async (error) => {
4829 rej(error);
4830 try {
4831 await promise;
4832 } catch (e) {
4833 }
4834 };
4835 });
4836 return {
4837 promise,
4838 //@ts-ignore
4839 resolve,
4840 //@ts-ignore
4841 reject
4842 };
4843}
4844
4845// lib/context.ts
4846import * as React from "react";
4847var DataRouterContext = React.createContext(null);
4848DataRouterContext.displayName = "DataRouter";
4849var DataRouterStateContext = React.createContext(null);
4850DataRouterStateContext.displayName = "DataRouterState";
4851var RSCRouterContext = React.createContext(false);
4852function useIsRSCRouterContext() {
4853 return React.useContext(RSCRouterContext);
4854}
4855var ViewTransitionContext = React.createContext({
4856 isTransitioning: false
4857});
4858ViewTransitionContext.displayName = "ViewTransition";
4859var FetchersContext = React.createContext(
4860 /* @__PURE__ */ new Map()
4861);
4862FetchersContext.displayName = "Fetchers";
4863var AwaitContext = React.createContext(null);
4864AwaitContext.displayName = "Await";
4865var NavigationContext = React.createContext(
4866 null
4867);
4868NavigationContext.displayName = "Navigation";
4869var LocationContext = React.createContext(
4870 null
4871);
4872LocationContext.displayName = "Location";
4873var RouteContext = React.createContext({
4874 outlet: null,
4875 matches: [],
4876 isDataRoute: false
4877});
4878RouteContext.displayName = "Route";
4879var RouteErrorContext = React.createContext(null);
4880RouteErrorContext.displayName = "RouteError";
4881var ENABLE_DEV_WARNINGS = true;
4882
4883// lib/hooks.tsx
4884import * as React2 from "react";
4885function useHref(to, { relative } = {}) {
4886 invariant(
4887 useInRouterContext(),
4888 // TODO: This error is probably because they somehow have 2 versions of the
4889 // router loaded. We can help them understand how to avoid that.
4890 `useHref() may be used only in the context of a <Router> component.`
4891 );
4892 let { basename, navigator } = React2.useContext(NavigationContext);
4893 let { hash, pathname, search } = useResolvedPath(to, { relative });
4894 let joinedPathname = pathname;
4895 if (basename !== "/") {
4896 joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
4897 }
4898 return navigator.createHref({ pathname: joinedPathname, search, hash });
4899}
4900function useInRouterContext() {
4901 return React2.useContext(LocationContext) != null;
4902}
4903function useLocation() {
4904 invariant(
4905 useInRouterContext(),
4906 // TODO: This error is probably because they somehow have 2 versions of the
4907 // router loaded. We can help them understand how to avoid that.
4908 `useLocation() may be used only in the context of a <Router> component.`
4909 );
4910 return React2.useContext(LocationContext).location;
4911}
4912function useNavigationType() {
4913 return React2.useContext(LocationContext).navigationType;
4914}
4915function useMatch(pattern) {
4916 invariant(
4917 useInRouterContext(),
4918 // TODO: This error is probably because they somehow have 2 versions of the
4919 // router loaded. We can help them understand how to avoid that.
4920 `useMatch() may be used only in the context of a <Router> component.`
4921 );
4922 let { pathname } = useLocation();
4923 return React2.useMemo(
4924 () => matchPath(pattern, decodePath(pathname)),
4925 [pathname, pattern]
4926 );
4927}
4928var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`;
4929function useIsomorphicLayoutEffect(cb) {
4930 let isStatic = React2.useContext(NavigationContext).static;
4931 if (!isStatic) {
4932 React2.useLayoutEffect(cb);
4933 }
4934}
4935function useNavigate() {
4936 let { isDataRoute } = React2.useContext(RouteContext);
4937 return isDataRoute ? useNavigateStable() : useNavigateUnstable();
4938}
4939function useNavigateUnstable() {
4940 invariant(
4941 useInRouterContext(),
4942 // TODO: This error is probably because they somehow have 2 versions of the
4943 // router loaded. We can help them understand how to avoid that.
4944 `useNavigate() may be used only in the context of a <Router> component.`
4945 );
4946 let dataRouterContext = React2.useContext(DataRouterContext);
4947 let { basename, navigator } = React2.useContext(NavigationContext);
4948 let { matches } = React2.useContext(RouteContext);
4949 let { pathname: locationPathname } = useLocation();
4950 let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
4951 let activeRef = React2.useRef(false);
4952 useIsomorphicLayoutEffect(() => {
4953 activeRef.current = true;
4954 });
4955 let navigate = React2.useCallback(
4956 (to, options = {}) => {
4957 warning(activeRef.current, navigateEffectWarning);
4958 if (!activeRef.current) return;
4959 if (typeof to === "number") {
4960 navigator.go(to);
4961 return;
4962 }
4963 let path = resolveTo(
4964 to,
4965 JSON.parse(routePathnamesJson),
4966 locationPathname,
4967 options.relative === "path"
4968 );
4969 if (dataRouterContext == null && basename !== "/") {
4970 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
4971 }
4972 (!!options.replace ? navigator.replace : navigator.push)(
4973 path,
4974 options.state,
4975 options
4976 );
4977 },
4978 [
4979 basename,
4980 navigator,
4981 routePathnamesJson,
4982 locationPathname,
4983 dataRouterContext
4984 ]
4985 );
4986 return navigate;
4987}
4988var OutletContext = React2.createContext(null);
4989function useOutletContext() {
4990 return React2.useContext(OutletContext);
4991}
4992function useOutlet(context) {
4993 let outlet = React2.useContext(RouteContext).outlet;
4994 if (outlet) {
4995 return /* @__PURE__ */ React2.createElement(OutletContext.Provider, { value: context }, outlet);
4996 }
4997 return outlet;
4998}
4999function useParams() {
5000 let { matches } = React2.useContext(RouteContext);
5001 let routeMatch = matches[matches.length - 1];
5002 return routeMatch ? routeMatch.params : {};
5003}
5004function useResolvedPath(to, { relative } = {}) {
5005 let { matches } = React2.useContext(RouteContext);
5006 let { pathname: locationPathname } = useLocation();
5007 let routePathnamesJson = JSON.stringify(getResolveToMatches(matches));
5008 return React2.useMemo(
5009 () => resolveTo(
5010 to,
5011 JSON.parse(routePathnamesJson),
5012 locationPathname,
5013 relative === "path"
5014 ),
5015 [to, routePathnamesJson, locationPathname, relative]
5016 );
5017}
5018function useRoutes(routes, locationArg) {
5019 return useRoutesImpl(routes, locationArg);
5020}
5021function useRoutesImpl(routes, locationArg, dataRouterState, future) {
5022 invariant(
5023 useInRouterContext(),
5024 // TODO: This error is probably because they somehow have 2 versions of the
5025 // router loaded. We can help them understand how to avoid that.
5026 `useRoutes() may be used only in the context of a <Router> component.`
5027 );
5028 let { navigator } = React2.useContext(NavigationContext);
5029 let { matches: parentMatches } = React2.useContext(RouteContext);
5030 let routeMatch = parentMatches[parentMatches.length - 1];
5031 let parentParams = routeMatch ? routeMatch.params : {};
5032 let parentPathname = routeMatch ? routeMatch.pathname : "/";
5033 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
5034 let parentRoute = routeMatch && routeMatch.route;
5035 if (ENABLE_DEV_WARNINGS) {
5036 let parentPath = parentRoute && parentRoute.path || "";
5037 warningOnce(
5038 parentPathname,
5039 !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"),
5040 `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.
5041
5042Please change the parent <Route path="${parentPath}"> to <Route path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`
5043 );
5044 }
5045 let locationFromContext = useLocation();
5046 let location;
5047 if (locationArg) {
5048 let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
5049 invariant(
5050 parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase),
5051 `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.`
5052 );
5053 location = parsedLocationArg;
5054 } else {
5055 location = locationFromContext;
5056 }
5057 let pathname = location.pathname || "/";
5058 let remainingPathname = pathname;
5059 if (parentPathnameBase !== "/") {
5060 let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
5061 let segments = pathname.replace(/^\//, "").split("/");
5062 remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
5063 }
5064 let matches = matchRoutes(routes, { pathname: remainingPathname });
5065 if (ENABLE_DEV_WARNINGS) {
5066 warning(
5067 parentRoute || matches != null,
5068 `No routes matched location "${location.pathname}${location.search}${location.hash}" `
5069 );
5070 warning(
5071 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,
5072 `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.`
5073 );
5074 }
5075 let renderedMatches = _renderMatches(
5076 matches && matches.map(
5077 (match) => Object.assign({}, match, {
5078 params: Object.assign({}, parentParams, match.params),
5079 pathname: joinPaths([
5080 parentPathnameBase,
5081 // Re-encode pathnames that were decoded inside matchRoutes
5082 navigator.encodeLocation ? navigator.encodeLocation(match.pathname).pathname : match.pathname
5083 ]),
5084 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([
5085 parentPathnameBase,
5086 // Re-encode pathnames that were decoded inside matchRoutes
5087 navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase).pathname : match.pathnameBase
5088 ])
5089 })
5090 ),
5091 parentMatches,
5092 dataRouterState,
5093 future
5094 );
5095 if (locationArg && renderedMatches) {
5096 return /* @__PURE__ */ React2.createElement(
5097 LocationContext.Provider,
5098 {
5099 value: {
5100 location: {
5101 pathname: "/",
5102 search: "",
5103 hash: "",
5104 state: null,
5105 key: "default",
5106 ...location
5107 },
5108 navigationType: "POP" /* Pop */
5109 }
5110 },
5111 renderedMatches
5112 );
5113 }
5114 return renderedMatches;
5115}
5116function DefaultErrorComponent() {
5117 let error = useRouteError();
5118 let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
5119 let stack = error instanceof Error ? error.stack : null;
5120 let lightgrey = "rgba(200,200,200, 0.5)";
5121 let preStyles = { padding: "0.5rem", backgroundColor: lightgrey };
5122 let codeStyles = { padding: "2px 4px", backgroundColor: lightgrey };
5123 let devInfo = null;
5124 if (ENABLE_DEV_WARNINGS) {
5125 console.error(
5126 "Error handled by React Router default ErrorBoundary:",
5127 error
5128 );
5129 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."));
5130 }
5131 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);
5132}
5133var defaultErrorElement = /* @__PURE__ */ React2.createElement(DefaultErrorComponent, null);
5134var RenderErrorBoundary = class extends React2.Component {
5135 constructor(props) {
5136 super(props);
5137 this.state = {
5138 location: props.location,
5139 revalidation: props.revalidation,
5140 error: props.error
5141 };
5142 }
5143 static getDerivedStateFromError(error) {
5144 return { error };
5145 }
5146 static getDerivedStateFromProps(props, state) {
5147 if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
5148 return {
5149 error: props.error,
5150 location: props.location,
5151 revalidation: props.revalidation
5152 };
5153 }
5154 return {
5155 error: props.error !== void 0 ? props.error : state.error,
5156 location: state.location,
5157 revalidation: props.revalidation || state.revalidation
5158 };
5159 }
5160 componentDidCatch(error, errorInfo) {
5161 console.error(
5162 "React Router caught the following error during render",
5163 error,
5164 errorInfo
5165 );
5166 }
5167 render() {
5168 return this.state.error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement(
5169 RouteErrorContext.Provider,
5170 {
5171 value: this.state.error,
5172 children: this.props.component
5173 }
5174 )) : this.props.children;
5175 }
5176};
5177function RenderedRoute({ routeContext, match, children }) {
5178 let dataRouterContext = React2.useContext(DataRouterContext);
5179 if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
5180 dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
5181 }
5182 return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children);
5183}
5184function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) {
5185 if (matches == null) {
5186 if (!dataRouterState) {
5187 return null;
5188 }
5189 if (dataRouterState.errors) {
5190 matches = dataRouterState.matches;
5191 } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) {
5192 matches = dataRouterState.matches;
5193 } else {
5194 return null;
5195 }
5196 }
5197 let renderedMatches = matches;
5198 let errors = dataRouterState?.errors;
5199 if (errors != null) {
5200 let errorIndex = renderedMatches.findIndex(
5201 (m) => m.route.id && errors?.[m.route.id] !== void 0
5202 );
5203 invariant(
5204 errorIndex >= 0,
5205 `Could not find a matching route for errors on route IDs: ${Object.keys(
5206 errors
5207 ).join(",")}`
5208 );
5209 renderedMatches = renderedMatches.slice(
5210 0,
5211 Math.min(renderedMatches.length, errorIndex + 1)
5212 );
5213 }
5214 let renderFallback = false;
5215 let fallbackIndex = -1;
5216 if (dataRouterState) {
5217 for (let i = 0; i < renderedMatches.length; i++) {
5218 let match = renderedMatches[i];
5219 if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
5220 fallbackIndex = i;
5221 }
5222 if (match.route.id) {
5223 let { loaderData, errors: errors2 } = dataRouterState;
5224 let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0);
5225 if (match.route.lazy || needsToRunLoader) {
5226 renderFallback = true;
5227 if (fallbackIndex >= 0) {
5228 renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
5229 } else {
5230 renderedMatches = [renderedMatches[0]];
5231 }
5232 break;
5233 }
5234 }
5235 }
5236 }
5237 return renderedMatches.reduceRight(
5238 (outlet, match, index) => {
5239 let error;
5240 let shouldRenderHydrateFallback = false;
5241 let errorElement = null;
5242 let hydrateFallbackElement = null;
5243 if (dataRouterState) {
5244 error = errors && match.route.id ? errors[match.route.id] : void 0;
5245 errorElement = match.route.errorElement || defaultErrorElement;
5246 if (renderFallback) {
5247 if (fallbackIndex < 0 && index === 0) {
5248 warningOnce(
5249 "route-fallback",
5250 false,
5251 "No `HydrateFallback` element provided to render during initial hydration"
5252 );
5253 shouldRenderHydrateFallback = true;
5254 hydrateFallbackElement = null;
5255 } else if (fallbackIndex === index) {
5256 shouldRenderHydrateFallback = true;
5257 hydrateFallbackElement = match.route.hydrateFallbackElement || null;
5258 }
5259 }
5260 }
5261 let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1));
5262 let getChildren = () => {
5263 let children;
5264 if (error) {
5265 children = errorElement;
5266 } else if (shouldRenderHydrateFallback) {
5267 children = hydrateFallbackElement;
5268 } else if (match.route.Component) {
5269 children = /* @__PURE__ */ React2.createElement(match.route.Component, null);
5270 } else if (match.route.element) {
5271 children = match.route.element;
5272 } else {
5273 children = outlet;
5274 }
5275 return /* @__PURE__ */ React2.createElement(
5276 RenderedRoute,
5277 {
5278 match,
5279 routeContext: {
5280 outlet,
5281 matches: matches2,
5282 isDataRoute: dataRouterState != null
5283 },
5284 children
5285 }
5286 );
5287 };
5288 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React2.createElement(
5289 RenderErrorBoundary,
5290 {
5291 location: dataRouterState.location,
5292 revalidation: dataRouterState.revalidation,
5293 component: errorElement,
5294 error,
5295 children: getChildren(),
5296 routeContext: { outlet: null, matches: matches2, isDataRoute: true }
5297 }
5298 ) : getChildren();
5299 },
5300 null
5301 );
5302}
5303function getDataRouterConsoleError(hookName) {
5304 return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
5305}
5306function useDataRouterContext(hookName) {
5307 let ctx = React2.useContext(DataRouterContext);
5308 invariant(ctx, getDataRouterConsoleError(hookName));
5309 return ctx;
5310}
5311function useDataRouterState(hookName) {
5312 let state = React2.useContext(DataRouterStateContext);
5313 invariant(state, getDataRouterConsoleError(hookName));
5314 return state;
5315}
5316function useRouteContext(hookName) {
5317 let route = React2.useContext(RouteContext);
5318 invariant(route, getDataRouterConsoleError(hookName));
5319 return route;
5320}
5321function useCurrentRouteId(hookName) {
5322 let route = useRouteContext(hookName);
5323 let thisRoute = route.matches[route.matches.length - 1];
5324 invariant(
5325 thisRoute.route.id,
5326 `${hookName} can only be used on routes that contain a unique "id"`
5327 );
5328 return thisRoute.route.id;
5329}
5330function useRouteId() {
5331 return useCurrentRouteId("useRouteId" /* UseRouteId */);
5332}
5333function useNavigation() {
5334 let state = useDataRouterState("useNavigation" /* UseNavigation */);
5335 return state.navigation;
5336}
5337function useRevalidator() {
5338 let dataRouterContext = useDataRouterContext("useRevalidator" /* UseRevalidator */);
5339 let state = useDataRouterState("useRevalidator" /* UseRevalidator */);
5340 let revalidate = React2.useCallback(async () => {
5341 await dataRouterContext.router.revalidate();
5342 }, [dataRouterContext.router]);
5343 return React2.useMemo(
5344 () => ({ revalidate, state: state.revalidation }),
5345 [revalidate, state.revalidation]
5346 );
5347}
5348function useMatches() {
5349 let { matches, loaderData } = useDataRouterState(
5350 "useMatches" /* UseMatches */
5351 );
5352 return React2.useMemo(
5353 () => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)),
5354 [matches, loaderData]
5355 );
5356}
5357function useLoaderData() {
5358 let state = useDataRouterState("useLoaderData" /* UseLoaderData */);
5359 let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */);
5360 return state.loaderData[routeId];
5361}
5362function useRouteLoaderData(routeId) {
5363 let state = useDataRouterState("useRouteLoaderData" /* UseRouteLoaderData */);
5364 return state.loaderData[routeId];
5365}
5366function useActionData() {
5367 let state = useDataRouterState("useActionData" /* UseActionData */);
5368 let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */);
5369 return state.actionData ? state.actionData[routeId] : void 0;
5370}
5371function useRouteError() {
5372 let error = React2.useContext(RouteErrorContext);
5373 let state = useDataRouterState("useRouteError" /* UseRouteError */);
5374 let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */);
5375 if (error !== void 0) {
5376 return error;
5377 }
5378 return state.errors?.[routeId];
5379}
5380function useAsyncValue() {
5381 let value = React2.useContext(AwaitContext);
5382 return value?._data;
5383}
5384function useAsyncError() {
5385 let value = React2.useContext(AwaitContext);
5386 return value?._error;
5387}
5388var blockerId = 0;
5389function useBlocker(shouldBlock) {
5390 let { router, basename } = useDataRouterContext("useBlocker" /* UseBlocker */);
5391 let state = useDataRouterState("useBlocker" /* UseBlocker */);
5392 let [blockerKey, setBlockerKey] = React2.useState("");
5393 let blockerFunction = React2.useCallback(
5394 (arg) => {
5395 if (typeof shouldBlock !== "function") {
5396 return !!shouldBlock;
5397 }
5398 if (basename === "/") {
5399 return shouldBlock(arg);
5400 }
5401 let { currentLocation, nextLocation, historyAction } = arg;
5402 return shouldBlock({
5403 currentLocation: {
5404 ...currentLocation,
5405 pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
5406 },
5407 nextLocation: {
5408 ...nextLocation,
5409 pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
5410 },
5411 historyAction
5412 });
5413 },
5414 [basename, shouldBlock]
5415 );
5416 React2.useEffect(() => {
5417 let key = String(++blockerId);
5418 setBlockerKey(key);
5419 return () => router.deleteBlocker(key);
5420 }, [router]);
5421 React2.useEffect(() => {
5422 if (blockerKey !== "") {
5423 router.getBlocker(blockerKey, blockerFunction);
5424 }
5425 }, [router, blockerKey, blockerFunction]);
5426 return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER;
5427}
5428function useNavigateStable() {
5429 let { router } = useDataRouterContext("useNavigate" /* UseNavigateStable */);
5430 let id = useCurrentRouteId("useNavigate" /* UseNavigateStable */);
5431 let activeRef = React2.useRef(false);
5432 useIsomorphicLayoutEffect(() => {
5433 activeRef.current = true;
5434 });
5435 let navigate = React2.useCallback(
5436 async (to, options = {}) => {
5437 warning(activeRef.current, navigateEffectWarning);
5438 if (!activeRef.current) return;
5439 if (typeof to === "number") {
5440 router.navigate(to);
5441 } else {
5442 await router.navigate(to, { fromRouteId: id, ...options });
5443 }
5444 },
5445 [router, id]
5446 );
5447 return navigate;
5448}
5449var alreadyWarned = {};
5450function warningOnce(key, cond, message) {
5451 if (!cond && !alreadyWarned[key]) {
5452 alreadyWarned[key] = true;
5453 warning(false, message);
5454 }
5455}
5456
5457// lib/components.tsx
5458import * as React3 from "react";
5459
5460// lib/server-runtime/warnings.ts
5461var alreadyWarned2 = {};
5462function warnOnce(condition, message) {
5463 if (!condition && !alreadyWarned2[message]) {
5464 alreadyWarned2[message] = true;
5465 console.warn(message);
5466 }
5467}
5468
5469// lib/components.tsx
5470function mapRouteProperties(route) {
5471 let updates = {
5472 // Note: this check also occurs in createRoutesFromChildren so update
5473 // there if you change this -- please and thank you!
5474 hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null
5475 };
5476 if (route.Component) {
5477 if (ENABLE_DEV_WARNINGS) {
5478 if (route.element) {
5479 warning(
5480 false,
5481 "You should not include both `Component` and `element` on your route - `Component` will be used."
5482 );
5483 }
5484 }
5485 Object.assign(updates, {
5486 element: React3.createElement(route.Component),
5487 Component: void 0
5488 });
5489 }
5490 if (route.HydrateFallback) {
5491 if (ENABLE_DEV_WARNINGS) {
5492 if (route.hydrateFallbackElement) {
5493 warning(
5494 false,
5495 "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used."
5496 );
5497 }
5498 }
5499 Object.assign(updates, {
5500 hydrateFallbackElement: React3.createElement(route.HydrateFallback),
5501 HydrateFallback: void 0
5502 });
5503 }
5504 if (route.ErrorBoundary) {
5505 if (ENABLE_DEV_WARNINGS) {
5506 if (route.errorElement) {
5507 warning(
5508 false,
5509 "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used."
5510 );
5511 }
5512 }
5513 Object.assign(updates, {
5514 errorElement: React3.createElement(route.ErrorBoundary),
5515 ErrorBoundary: void 0
5516 });
5517 }
5518 return updates;
5519}
5520var hydrationRouteProperties = [
5521 "HydrateFallback",
5522 "hydrateFallbackElement"
5523];
5524function createMemoryRouter(routes, opts) {
5525 return createRouter({
5526 basename: opts?.basename,
5527 unstable_getContext: opts?.unstable_getContext,
5528 future: opts?.future,
5529 history: createMemoryHistory({
5530 initialEntries: opts?.initialEntries,
5531 initialIndex: opts?.initialIndex
5532 }),
5533 hydrationData: opts?.hydrationData,
5534 routes,
5535 hydrationRouteProperties,
5536 mapRouteProperties,
5537 dataStrategy: opts?.dataStrategy,
5538 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation
5539 }).initialize();
5540}
5541var Deferred = class {
5542 constructor() {
5543 this.status = "pending";
5544 this.promise = new Promise((resolve, reject) => {
5545 this.resolve = (value) => {
5546 if (this.status === "pending") {
5547 this.status = "resolved";
5548 resolve(value);
5549 }
5550 };
5551 this.reject = (reason) => {
5552 if (this.status === "pending") {
5553 this.status = "rejected";
5554 reject(reason);
5555 }
5556 };
5557 });
5558 }
5559};
5560function RouterProvider({
5561 router,
5562 flushSync: reactDomFlushSyncImpl
5563}) {
5564 let [state, setStateImpl] = React3.useState(router.state);
5565 let [pendingState, setPendingState] = React3.useState();
5566 let [vtContext, setVtContext] = React3.useState({
5567 isTransitioning: false
5568 });
5569 let [renderDfd, setRenderDfd] = React3.useState();
5570 let [transition, setTransition] = React3.useState();
5571 let [interruption, setInterruption] = React3.useState();
5572 let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
5573 let setState = React3.useCallback(
5574 (newState, { deletedFetchers, flushSync, viewTransitionOpts }) => {
5575 newState.fetchers.forEach((fetcher, key) => {
5576 if (fetcher.data !== void 0) {
5577 fetcherData.current.set(key, fetcher.data);
5578 }
5579 });
5580 deletedFetchers.forEach((key) => fetcherData.current.delete(key));
5581 warnOnce(
5582 flushSync === false || reactDomFlushSyncImpl != null,
5583 '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.'
5584 );
5585 let isViewTransitionAvailable = router.window != null && router.window.document != null && typeof router.window.document.startViewTransition === "function";
5586 warnOnce(
5587 viewTransitionOpts == null || isViewTransitionAvailable,
5588 "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."
5589 );
5590 if (!viewTransitionOpts || !isViewTransitionAvailable) {
5591 if (reactDomFlushSyncImpl && flushSync) {
5592 reactDomFlushSyncImpl(() => setStateImpl(newState));
5593 } else {
5594 React3.startTransition(() => setStateImpl(newState));
5595 }
5596 return;
5597 }
5598 if (reactDomFlushSyncImpl && flushSync) {
5599 reactDomFlushSyncImpl(() => {
5600 if (transition) {
5601 renderDfd && renderDfd.resolve();
5602 transition.skipTransition();
5603 }
5604 setVtContext({
5605 isTransitioning: true,
5606 flushSync: true,
5607 currentLocation: viewTransitionOpts.currentLocation,
5608 nextLocation: viewTransitionOpts.nextLocation
5609 });
5610 });
5611 let t = router.window.document.startViewTransition(() => {
5612 reactDomFlushSyncImpl(() => setStateImpl(newState));
5613 });
5614 t.finished.finally(() => {
5615 reactDomFlushSyncImpl(() => {
5616 setRenderDfd(void 0);
5617 setTransition(void 0);
5618 setPendingState(void 0);
5619 setVtContext({ isTransitioning: false });
5620 });
5621 });
5622 reactDomFlushSyncImpl(() => setTransition(t));
5623 return;
5624 }
5625 if (transition) {
5626 renderDfd && renderDfd.resolve();
5627 transition.skipTransition();
5628 setInterruption({
5629 state: newState,
5630 currentLocation: viewTransitionOpts.currentLocation,
5631 nextLocation: viewTransitionOpts.nextLocation
5632 });
5633 } else {
5634 setPendingState(newState);
5635 setVtContext({
5636 isTransitioning: true,
5637 flushSync: false,
5638 currentLocation: viewTransitionOpts.currentLocation,
5639 nextLocation: viewTransitionOpts.nextLocation
5640 });
5641 }
5642 },
5643 [router.window, reactDomFlushSyncImpl, transition, renderDfd]
5644 );
5645 React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
5646 React3.useEffect(() => {
5647 if (vtContext.isTransitioning && !vtContext.flushSync) {
5648 setRenderDfd(new Deferred());
5649 }
5650 }, [vtContext]);
5651 React3.useEffect(() => {
5652 if (renderDfd && pendingState && router.window) {
5653 let newState = pendingState;
5654 let renderPromise = renderDfd.promise;
5655 let transition2 = router.window.document.startViewTransition(async () => {
5656 React3.startTransition(() => setStateImpl(newState));
5657 await renderPromise;
5658 });
5659 transition2.finished.finally(() => {
5660 setRenderDfd(void 0);
5661 setTransition(void 0);
5662 setPendingState(void 0);
5663 setVtContext({ isTransitioning: false });
5664 });
5665 setTransition(transition2);
5666 }
5667 }, [pendingState, renderDfd, router.window]);
5668 React3.useEffect(() => {
5669 if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
5670 renderDfd.resolve();
5671 }
5672 }, [renderDfd, transition, state.location, pendingState]);
5673 React3.useEffect(() => {
5674 if (!vtContext.isTransitioning && interruption) {
5675 setPendingState(interruption.state);
5676 setVtContext({
5677 isTransitioning: true,
5678 flushSync: false,
5679 currentLocation: interruption.currentLocation,
5680 nextLocation: interruption.nextLocation
5681 });
5682 setInterruption(void 0);
5683 }
5684 }, [vtContext.isTransitioning, interruption]);
5685 let navigator = React3.useMemo(() => {
5686 return {
5687 createHref: router.createHref,
5688 encodeLocation: router.encodeLocation,
5689 go: (n) => router.navigate(n),
5690 push: (to, state2, opts) => router.navigate(to, {
5691 state: state2,
5692 preventScrollReset: opts?.preventScrollReset
5693 }),
5694 replace: (to, state2, opts) => router.navigate(to, {
5695 replace: true,
5696 state: state2,
5697 preventScrollReset: opts?.preventScrollReset
5698 })
5699 };
5700 }, [router]);
5701 let basename = router.basename || "/";
5702 let dataRouterContext = React3.useMemo(
5703 () => ({
5704 router,
5705 navigator,
5706 static: false,
5707 basename
5708 }),
5709 [router, navigator, basename]
5710 );
5711 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(
5712 Router,
5713 {
5714 basename,
5715 location: state.location,
5716 navigationType: state.historyAction,
5717 navigator
5718 },
5719 /* @__PURE__ */ React3.createElement(
5720 MemoizedDataRoutes,
5721 {
5722 routes: router.routes,
5723 future: router.future,
5724 state
5725 }
5726 )
5727 ))))), null);
5728}
5729var MemoizedDataRoutes = React3.memo(DataRoutes);
5730function DataRoutes({
5731 routes,
5732 future,
5733 state
5734}) {
5735 return useRoutesImpl(routes, void 0, state, future);
5736}
5737function MemoryRouter({
5738 basename,
5739 children,
5740 initialEntries,
5741 initialIndex
5742}) {
5743 let historyRef = React3.useRef();
5744 if (historyRef.current == null) {
5745 historyRef.current = createMemoryHistory({
5746 initialEntries,
5747 initialIndex,
5748 v5Compat: true
5749 });
5750 }
5751 let history = historyRef.current;
5752 let [state, setStateImpl] = React3.useState({
5753 action: history.action,
5754 location: history.location
5755 });
5756 let setState = React3.useCallback(
5757 (newState) => {
5758 React3.startTransition(() => setStateImpl(newState));
5759 },
5760 [setStateImpl]
5761 );
5762 React3.useLayoutEffect(() => history.listen(setState), [history, setState]);
5763 return /* @__PURE__ */ React3.createElement(
5764 Router,
5765 {
5766 basename,
5767 children,
5768 location: state.location,
5769 navigationType: state.action,
5770 navigator: history
5771 }
5772 );
5773}
5774function Navigate({
5775 to,
5776 replace: replace2,
5777 state,
5778 relative
5779}) {
5780 invariant(
5781 useInRouterContext(),
5782 // TODO: This error is probably because they somehow have 2 versions of
5783 // the router loaded. We can help them understand how to avoid that.
5784 `<Navigate> may be used only in the context of a <Router> component.`
5785 );
5786 let { static: isStatic } = React3.useContext(NavigationContext);
5787 warning(
5788 !isStatic,
5789 `<Navigate> must not be used on the initial render in a <StaticRouter>. This is a no-op, but you should modify your code so the <Navigate> is only ever rendered in response to some user interaction or state change.`
5790 );
5791 let { matches } = React3.useContext(RouteContext);
5792 let { pathname: locationPathname } = useLocation();
5793 let navigate = useNavigate();
5794 let path = resolveTo(
5795 to,
5796 getResolveToMatches(matches),
5797 locationPathname,
5798 relative === "path"
5799 );
5800 let jsonPath = JSON.stringify(path);
5801 React3.useEffect(() => {
5802 navigate(JSON.parse(jsonPath), { replace: replace2, state, relative });
5803 }, [navigate, jsonPath, relative, replace2, state]);
5804 return null;
5805}
5806function Outlet(props) {
5807 return useOutlet(props.context);
5808}
5809function Route(props) {
5810 invariant(
5811 false,
5812 `A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.`
5813 );
5814}
5815function Router({
5816 basename: basenameProp = "/",
5817 children = null,
5818 location: locationProp,
5819 navigationType = "POP" /* Pop */,
5820 navigator,
5821 static: staticProp = false
5822}) {
5823 invariant(
5824 !useInRouterContext(),
5825 `You cannot render a <Router> inside another <Router>. You should never have more than one in your app.`
5826 );
5827 let basename = basenameProp.replace(/^\/*/, "/");
5828 let navigationContext = React3.useMemo(
5829 () => ({
5830 basename,
5831 navigator,
5832 static: staticProp,
5833 future: {}
5834 }),
5835 [basename, navigator, staticProp]
5836 );
5837 if (typeof locationProp === "string") {
5838 locationProp = parsePath(locationProp);
5839 }
5840 let {
5841 pathname = "/",
5842 search = "",
5843 hash = "",
5844 state = null,
5845 key = "default"
5846 } = locationProp;
5847 let locationContext = React3.useMemo(() => {
5848 let trailingPathname = stripBasename(pathname, basename);
5849 if (trailingPathname == null) {
5850 return null;
5851 }
5852 return {
5853 location: {
5854 pathname: trailingPathname,
5855 search,
5856 hash,
5857 state,
5858 key
5859 },
5860 navigationType
5861 };
5862 }, [basename, pathname, search, hash, state, key, navigationType]);
5863 warning(
5864 locationContext != null,
5865 `<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.`
5866 );
5867 if (locationContext == null) {
5868 return null;
5869 }
5870 return /* @__PURE__ */ React3.createElement(NavigationContext.Provider, { value: navigationContext }, /* @__PURE__ */ React3.createElement(LocationContext.Provider, { children, value: locationContext }));
5871}
5872function Routes({
5873 children,
5874 location
5875}) {
5876 return useRoutes(createRoutesFromChildren(children), location);
5877}
5878function Await({
5879 children,
5880 errorElement,
5881 resolve
5882}) {
5883 return /* @__PURE__ */ React3.createElement(AwaitErrorBoundary, { resolve, errorElement }, /* @__PURE__ */ React3.createElement(ResolveAwait, null, children));
5884}
5885var AwaitErrorBoundary = class extends React3.Component {
5886 constructor(props) {
5887 super(props);
5888 this.state = { error: null };
5889 }
5890 static getDerivedStateFromError(error) {
5891 return { error };
5892 }
5893 componentDidCatch(error, errorInfo) {
5894 console.error(
5895 "<Await> caught the following error during render",
5896 error,
5897 errorInfo
5898 );
5899 }
5900 render() {
5901 let { children, errorElement, resolve } = this.props;
5902 let promise = null;
5903 let status = 0 /* pending */;
5904 if (!(resolve instanceof Promise)) {
5905 status = 1 /* success */;
5906 promise = Promise.resolve();
5907 Object.defineProperty(promise, "_tracked", { get: () => true });
5908 Object.defineProperty(promise, "_data", { get: () => resolve });
5909 } else if (this.state.error) {
5910 status = 2 /* error */;
5911 let renderError = this.state.error;
5912 promise = Promise.reject().catch(() => {
5913 });
5914 Object.defineProperty(promise, "_tracked", { get: () => true });
5915 Object.defineProperty(promise, "_error", { get: () => renderError });
5916 } else if (resolve._tracked) {
5917 promise = resolve;
5918 status = "_error" in promise ? 2 /* error */ : "_data" in promise ? 1 /* success */ : 0 /* pending */;
5919 } else {
5920 status = 0 /* pending */;
5921 Object.defineProperty(resolve, "_tracked", { get: () => true });
5922 promise = resolve.then(
5923 (data2) => Object.defineProperty(resolve, "_data", { get: () => data2 }),
5924 (error) => Object.defineProperty(resolve, "_error", { get: () => error })
5925 );
5926 }
5927 if (status === 2 /* error */ && !errorElement) {
5928 throw promise._error;
5929 }
5930 if (status === 2 /* error */) {
5931 return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children: errorElement });
5932 }
5933 if (status === 1 /* success */) {
5934 return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children });
5935 }
5936 throw promise;
5937 }
5938};
5939function ResolveAwait({
5940 children
5941}) {
5942 let data2 = useAsyncValue();
5943 let toRender = typeof children === "function" ? children(data2) : children;
5944 return /* @__PURE__ */ React3.createElement(React3.Fragment, null, toRender);
5945}
5946function createRoutesFromChildren(children, parentPath = []) {
5947 let routes = [];
5948 React3.Children.forEach(children, (element, index) => {
5949 if (!React3.isValidElement(element)) {
5950 return;
5951 }
5952 let treePath = [...parentPath, index];
5953 if (element.type === React3.Fragment) {
5954 routes.push.apply(
5955 routes,
5956 createRoutesFromChildren(element.props.children, treePath)
5957 );
5958 return;
5959 }
5960 invariant(
5961 element.type === Route,
5962 `[${typeof element.type === "string" ? element.type : element.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`
5963 );
5964 invariant(
5965 !element.props.index || !element.props.children,
5966 "An index route cannot have child routes."
5967 );
5968 let route = {
5969 id: element.props.id || treePath.join("-"),
5970 caseSensitive: element.props.caseSensitive,
5971 element: element.props.element,
5972 Component: element.props.Component,
5973 index: element.props.index,
5974 path: element.props.path,
5975 loader: element.props.loader,
5976 action: element.props.action,
5977 hydrateFallbackElement: element.props.hydrateFallbackElement,
5978 HydrateFallback: element.props.HydrateFallback,
5979 errorElement: element.props.errorElement,
5980 ErrorBoundary: element.props.ErrorBoundary,
5981 hasErrorBoundary: element.props.hasErrorBoundary === true || element.props.ErrorBoundary != null || element.props.errorElement != null,
5982 shouldRevalidate: element.props.shouldRevalidate,
5983 handle: element.props.handle,
5984 lazy: element.props.lazy
5985 };
5986 if (element.props.children) {
5987 route.children = createRoutesFromChildren(
5988 element.props.children,
5989 treePath
5990 );
5991 }
5992 routes.push(route);
5993 });
5994 return routes;
5995}
5996var createRoutesFromElements = createRoutesFromChildren;
5997function renderMatches(matches) {
5998 return _renderMatches(matches);
5999}
6000function useRouteComponentProps() {
6001 return {
6002 params: useParams(),
6003 loaderData: useLoaderData(),
6004 actionData: useActionData(),
6005 matches: useMatches()
6006 };
6007}
6008function WithComponentProps({
6009 children
6010}) {
6011 const props = useRouteComponentProps();
6012 return React3.cloneElement(children, props);
6013}
6014function withComponentProps(Component4) {
6015 return function WithComponentProps2() {
6016 const props = useRouteComponentProps();
6017 return React3.createElement(Component4, props);
6018 };
6019}
6020function useHydrateFallbackProps() {
6021 return {
6022 params: useParams(),
6023 loaderData: useLoaderData(),
6024 actionData: useActionData()
6025 };
6026}
6027function WithHydrateFallbackProps({
6028 children
6029}) {
6030 const props = useHydrateFallbackProps();
6031 return React3.cloneElement(children, props);
6032}
6033function withHydrateFallbackProps(HydrateFallback) {
6034 return function WithHydrateFallbackProps2() {
6035 const props = useHydrateFallbackProps();
6036 return React3.createElement(HydrateFallback, props);
6037 };
6038}
6039function useErrorBoundaryProps() {
6040 return {
6041 params: useParams(),
6042 loaderData: useLoaderData(),
6043 actionData: useActionData(),
6044 error: useRouteError()
6045 };
6046}
6047function WithErrorBoundaryProps({
6048 children
6049}) {
6050 const props = useErrorBoundaryProps();
6051 return React3.cloneElement(children, props);
6052}
6053function withErrorBoundaryProps(ErrorBoundary) {
6054 return function WithErrorBoundaryProps2() {
6055 const props = useErrorBoundaryProps();
6056 return React3.createElement(ErrorBoundary, props);
6057 };
6058}
6059
6060// lib/dom/dom.ts
6061var defaultMethod = "get";
6062var defaultEncType = "application/x-www-form-urlencoded";
6063function isHtmlElement(object) {
6064 return object != null && typeof object.tagName === "string";
6065}
6066function isButtonElement(object) {
6067 return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
6068}
6069function isFormElement(object) {
6070 return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
6071}
6072function isInputElement(object) {
6073 return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
6074}
6075function isModifiedEvent(event) {
6076 return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
6077}
6078function shouldProcessLinkClick(event, target) {
6079 return event.button === 0 && // Ignore everything but left clicks
6080 (!target || target === "_self") && // Let browser handle "target=_blank" etc.
6081 !isModifiedEvent(event);
6082}
6083function createSearchParams(init = "") {
6084 return new URLSearchParams(
6085 typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key) => {
6086 let value = init[key];
6087 return memo2.concat(
6088 Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]
6089 );
6090 }, [])
6091 );
6092}
6093function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
6094 let searchParams = createSearchParams(locationSearch);
6095 if (defaultSearchParams) {
6096 defaultSearchParams.forEach((_, key) => {
6097 if (!searchParams.has(key)) {
6098 defaultSearchParams.getAll(key).forEach((value) => {
6099 searchParams.append(key, value);
6100 });
6101 }
6102 });
6103 }
6104 return searchParams;
6105}
6106var _formDataSupportsSubmitter = null;
6107function isFormDataSubmitterSupported() {
6108 if (_formDataSupportsSubmitter === null) {
6109 try {
6110 new FormData(
6111 document.createElement("form"),
6112 // @ts-expect-error if FormData supports the submitter parameter, this will throw
6113 0
6114 );
6115 _formDataSupportsSubmitter = false;
6116 } catch (e) {
6117 _formDataSupportsSubmitter = true;
6118 }
6119 }
6120 return _formDataSupportsSubmitter;
6121}
6122var supportedFormEncTypes = /* @__PURE__ */ new Set([
6123 "application/x-www-form-urlencoded",
6124 "multipart/form-data",
6125 "text/plain"
6126]);
6127function getFormEncType(encType) {
6128 if (encType != null && !supportedFormEncTypes.has(encType)) {
6129 warning(
6130 false,
6131 `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`
6132 );
6133 return null;
6134 }
6135 return encType;
6136}
6137function getFormSubmissionInfo(target, basename) {
6138 let method;
6139 let action;
6140 let encType;
6141 let formData;
6142 let body;
6143 if (isFormElement(target)) {
6144 let attr = target.getAttribute("action");
6145 action = attr ? stripBasename(attr, basename) : null;
6146 method = target.getAttribute("method") || defaultMethod;
6147 encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
6148 formData = new FormData(target);
6149 } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
6150 let form = target.form;
6151 if (form == null) {
6152 throw new Error(
6153 `Cannot submit a <button> or <input type="submit"> without a <form>`
6154 );
6155 }
6156 let attr = target.getAttribute("formaction") || form.getAttribute("action");
6157 action = attr ? stripBasename(attr, basename) : null;
6158 method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
6159 encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
6160 formData = new FormData(form, target);
6161 if (!isFormDataSubmitterSupported()) {
6162 let { name, type, value } = target;
6163 if (type === "image") {
6164 let prefix = name ? `${name}.` : "";
6165 formData.append(`${prefix}x`, "0");
6166 formData.append(`${prefix}y`, "0");
6167 } else if (name) {
6168 formData.append(name, value);
6169 }
6170 }
6171 } else if (isHtmlElement(target)) {
6172 throw new Error(
6173 `Cannot submit element that is not <form>, <button>, or <input type="submit|image">`
6174 );
6175 } else {
6176 method = defaultMethod;
6177 action = null;
6178 encType = defaultEncType;
6179 body = target;
6180 }
6181 if (formData && encType === "text/plain") {
6182 body = formData;
6183 formData = void 0;
6184 }
6185 return { action, method: method.toLowerCase(), encType, formData, body };
6186}
6187
6188// lib/dom/ssr/single-fetch.tsx
6189import * as React4 from "react";
6190
6191// vendor/turbo-stream-v2/utils.ts
6192var HOLE = -1;
6193var NAN = -2;
6194var NEGATIVE_INFINITY = -3;
6195var NEGATIVE_ZERO = -4;
6196var NULL = -5;
6197var POSITIVE_INFINITY = -6;
6198var UNDEFINED = -7;
6199var TYPE_BIGINT = "B";
6200var TYPE_DATE = "D";
6201var TYPE_ERROR = "E";
6202var TYPE_MAP = "M";
6203var TYPE_NULL_OBJECT = "N";
6204var TYPE_PROMISE = "P";
6205var TYPE_REGEXP = "R";
6206var TYPE_SET = "S";
6207var TYPE_SYMBOL = "Y";
6208var TYPE_URL = "U";
6209var TYPE_PREVIOUS_RESOLVED = "Z";
6210var Deferred2 = class {
6211 constructor() {
6212 this.promise = new Promise((resolve, reject) => {
6213 this.resolve = resolve;
6214 this.reject = reject;
6215 });
6216 }
6217};
6218function createLineSplittingTransform() {
6219 const decoder = new TextDecoder();
6220 let leftover = "";
6221 return new TransformStream({
6222 transform(chunk, controller) {
6223 const str = decoder.decode(chunk, { stream: true });
6224 const parts = (leftover + str).split("\n");
6225 leftover = parts.pop() || "";
6226 for (const part of parts) {
6227 controller.enqueue(part);
6228 }
6229 },
6230 flush(controller) {
6231 if (leftover) {
6232 controller.enqueue(leftover);
6233 }
6234 }
6235 });
6236}
6237
6238// vendor/turbo-stream-v2/flatten.ts
6239function flatten(input) {
6240 const { indices } = this;
6241 const existing = indices.get(input);
6242 if (existing) return [existing];
6243 if (input === void 0) return UNDEFINED;
6244 if (input === null) return NULL;
6245 if (Number.isNaN(input)) return NAN;
6246 if (input === Number.POSITIVE_INFINITY) return POSITIVE_INFINITY;
6247 if (input === Number.NEGATIVE_INFINITY) return NEGATIVE_INFINITY;
6248 if (input === 0 && 1 / input < 0) return NEGATIVE_ZERO;
6249 const index = this.index++;
6250 indices.set(input, index);
6251 stringify.call(this, input, index);
6252 return index;
6253}
6254function stringify(input, index) {
6255 const { deferred, plugins, postPlugins } = this;
6256 const str = this.stringified;
6257 const stack = [[input, index]];
6258 while (stack.length > 0) {
6259 const [input2, index2] = stack.pop();
6260 const partsForObj = (obj) => Object.keys(obj).map((k) => `"_${flatten.call(this, k)}":${flatten.call(this, obj[k])}`).join(",");
6261 let error = null;
6262 switch (typeof input2) {
6263 case "boolean":
6264 case "number":
6265 case "string":
6266 str[index2] = JSON.stringify(input2);
6267 break;
6268 case "bigint":
6269 str[index2] = `["${TYPE_BIGINT}","${input2}"]`;
6270 break;
6271 case "symbol": {
6272 const keyFor = Symbol.keyFor(input2);
6273 if (!keyFor) {
6274 error = new Error(
6275 "Cannot encode symbol unless created with Symbol.for()"
6276 );
6277 } else {
6278 str[index2] = `["${TYPE_SYMBOL}",${JSON.stringify(keyFor)}]`;
6279 }
6280 break;
6281 }
6282 case "object": {
6283 if (!input2) {
6284 str[index2] = `${NULL}`;
6285 break;
6286 }
6287 const isArray = Array.isArray(input2);
6288 let pluginHandled = false;
6289 if (!isArray && plugins) {
6290 for (const plugin of plugins) {
6291 const pluginResult = plugin(input2);
6292 if (Array.isArray(pluginResult)) {
6293 pluginHandled = true;
6294 const [pluginIdentifier, ...rest] = pluginResult;
6295 str[index2] = `[${JSON.stringify(pluginIdentifier)}`;
6296 if (rest.length > 0) {
6297 str[index2] += `,${rest.map((v) => flatten.call(this, v)).join(",")}`;
6298 }
6299 str[index2] += "]";
6300 break;
6301 }
6302 }
6303 }
6304 if (!pluginHandled) {
6305 let result = isArray ? "[" : "{";
6306 if (isArray) {
6307 for (let i = 0; i < input2.length; i++)
6308 result += (i ? "," : "") + (i in input2 ? flatten.call(this, input2[i]) : HOLE);
6309 str[index2] = `${result}]`;
6310 } else if (input2 instanceof Date) {
6311 const dateTime = input2.getTime();
6312 str[index2] = `["${TYPE_DATE}",${Number.isNaN(dateTime) ? JSON.stringify("invalid") : dateTime}]`;
6313 } else if (input2 instanceof URL) {
6314 str[index2] = `["${TYPE_URL}",${JSON.stringify(input2.href)}]`;
6315 } else if (input2 instanceof RegExp) {
6316 str[index2] = `["${TYPE_REGEXP}",${JSON.stringify(
6317 input2.source
6318 )},${JSON.stringify(input2.flags)}]`;
6319 } else if (input2 instanceof Set) {
6320 if (input2.size > 0) {
6321 str[index2] = `["${TYPE_SET}",${[...input2].map((val) => flatten.call(this, val)).join(",")}]`;
6322 } else {
6323 str[index2] = `["${TYPE_SET}"]`;
6324 }
6325 } else if (input2 instanceof Map) {
6326 if (input2.size > 0) {
6327 str[index2] = `["${TYPE_MAP}",${[...input2].flatMap(([k, v]) => [
6328 flatten.call(this, k),
6329 flatten.call(this, v)
6330 ]).join(",")}]`;
6331 } else {
6332 str[index2] = `["${TYPE_MAP}"]`;
6333 }
6334 } else if (input2 instanceof Promise) {
6335 str[index2] = `["${TYPE_PROMISE}",${index2}]`;
6336 deferred[index2] = input2;
6337 } else if (input2 instanceof Error) {
6338 str[index2] = `["${TYPE_ERROR}",${JSON.stringify(input2.message)}`;
6339 if (input2.name !== "Error") {
6340 str[index2] += `,${JSON.stringify(input2.name)}`;
6341 }
6342 str[index2] += "]";
6343 } else if (Object.getPrototypeOf(input2) === null) {
6344 str[index2] = `["${TYPE_NULL_OBJECT}",{${partsForObj(input2)}}]`;
6345 } else if (isPlainObject(input2)) {
6346 str[index2] = `{${partsForObj(input2)}}`;
6347 } else {
6348 error = new Error("Cannot encode object with prototype");
6349 }
6350 }
6351 break;
6352 }
6353 default: {
6354 const isArray = Array.isArray(input2);
6355 let pluginHandled = false;
6356 if (!isArray && plugins) {
6357 for (const plugin of plugins) {
6358 const pluginResult = plugin(input2);
6359 if (Array.isArray(pluginResult)) {
6360 pluginHandled = true;
6361 const [pluginIdentifier, ...rest] = pluginResult;
6362 str[index2] = `[${JSON.stringify(pluginIdentifier)}`;
6363 if (rest.length > 0) {
6364 str[index2] += `,${rest.map((v) => flatten.call(this, v)).join(",")}`;
6365 }
6366 str[index2] += "]";
6367 break;
6368 }
6369 }
6370 }
6371 if (!pluginHandled) {
6372 error = new Error("Cannot encode function or unexpected type");
6373 }
6374 }
6375 }
6376 if (error) {
6377 let pluginHandled = false;
6378 if (postPlugins) {
6379 for (const plugin of postPlugins) {
6380 const pluginResult = plugin(input2);
6381 if (Array.isArray(pluginResult)) {
6382 pluginHandled = true;
6383 const [pluginIdentifier, ...rest] = pluginResult;
6384 str[index2] = `[${JSON.stringify(pluginIdentifier)}`;
6385 if (rest.length > 0) {
6386 str[index2] += `,${rest.map((v) => flatten.call(this, v)).join(",")}`;
6387 }
6388 str[index2] += "]";
6389 break;
6390 }
6391 }
6392 }
6393 if (!pluginHandled) {
6394 throw error;
6395 }
6396 }
6397 }
6398}
6399var objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
6400function isPlainObject(thing) {
6401 const proto = Object.getPrototypeOf(thing);
6402 return proto === Object.prototype || proto === null || Object.getOwnPropertyNames(proto).sort().join("\0") === objectProtoNames;
6403}
6404
6405// vendor/turbo-stream-v2/unflatten.ts
6406var globalObj = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : void 0;
6407function unflatten(parsed) {
6408 const { hydrated, values } = this;
6409 if (typeof parsed === "number") return hydrate.call(this, parsed);
6410 if (!Array.isArray(parsed) || !parsed.length) throw new SyntaxError();
6411 const startIndex = values.length;
6412 for (const value of parsed) {
6413 values.push(value);
6414 }
6415 hydrated.length = values.length;
6416 return hydrate.call(this, startIndex);
6417}
6418function hydrate(index) {
6419 const { hydrated, values, deferred, plugins } = this;
6420 let result;
6421 const stack = [
6422 [
6423 index,
6424 (v) => {
6425 result = v;
6426 }
6427 ]
6428 ];
6429 let postRun = [];
6430 while (stack.length > 0) {
6431 const [index2, set] = stack.pop();
6432 switch (index2) {
6433 case UNDEFINED:
6434 set(void 0);
6435 continue;
6436 case NULL:
6437 set(null);
6438 continue;
6439 case NAN:
6440 set(NaN);
6441 continue;
6442 case POSITIVE_INFINITY:
6443 set(Infinity);
6444 continue;
6445 case NEGATIVE_INFINITY:
6446 set(-Infinity);
6447 continue;
6448 case NEGATIVE_ZERO:
6449 set(-0);
6450 continue;
6451 }
6452 if (hydrated[index2]) {
6453 set(hydrated[index2]);
6454 continue;
6455 }
6456 const value = values[index2];
6457 if (!value || typeof value !== "object") {
6458 hydrated[index2] = value;
6459 set(value);
6460 continue;
6461 }
6462 if (Array.isArray(value)) {
6463 if (typeof value[0] === "string") {
6464 const [type, b, c] = value;
6465 switch (type) {
6466 case TYPE_DATE:
6467 set(hydrated[index2] = new Date(b));
6468 continue;
6469 case TYPE_URL:
6470 set(hydrated[index2] = new URL(b));
6471 continue;
6472 case TYPE_BIGINT:
6473 set(hydrated[index2] = BigInt(b));
6474 continue;
6475 case TYPE_REGEXP:
6476 set(hydrated[index2] = new RegExp(b, c));
6477 continue;
6478 case TYPE_SYMBOL:
6479 set(hydrated[index2] = Symbol.for(b));
6480 continue;
6481 case TYPE_SET:
6482 const newSet = /* @__PURE__ */ new Set();
6483 hydrated[index2] = newSet;
6484 for (let i = value.length - 1; i > 0; i--)
6485 stack.push([
6486 value[i],
6487 (v) => {
6488 newSet.add(v);
6489 }
6490 ]);
6491 set(newSet);
6492 continue;
6493 case TYPE_MAP:
6494 const map = /* @__PURE__ */ new Map();
6495 hydrated[index2] = map;
6496 for (let i = value.length - 2; i > 0; i -= 2) {
6497 const r = [];
6498 stack.push([
6499 value[i + 1],
6500 (v) => {
6501 r[1] = v;
6502 }
6503 ]);
6504 stack.push([
6505 value[i],
6506 (k) => {
6507 r[0] = k;
6508 }
6509 ]);
6510 postRun.push(() => {
6511 map.set(r[0], r[1]);
6512 });
6513 }
6514 set(map);
6515 continue;
6516 case TYPE_NULL_OBJECT:
6517 const obj = /* @__PURE__ */ Object.create(null);
6518 hydrated[index2] = obj;
6519 for (const key of Object.keys(b).reverse()) {
6520 const r = [];
6521 stack.push([
6522 b[key],
6523 (v) => {
6524 r[1] = v;
6525 }
6526 ]);
6527 stack.push([
6528 Number(key.slice(1)),
6529 (k) => {
6530 r[0] = k;
6531 }
6532 ]);
6533 postRun.push(() => {
6534 obj[r[0]] = r[1];
6535 });
6536 }
6537 set(obj);
6538 continue;
6539 case TYPE_PROMISE:
6540 if (hydrated[b]) {
6541 set(hydrated[index2] = hydrated[b]);
6542 } else {
6543 const d = new Deferred2();
6544 deferred[b] = d;
6545 set(hydrated[index2] = d.promise);
6546 }
6547 continue;
6548 case TYPE_ERROR:
6549 const [, message, errorType] = value;
6550 let error = errorType && globalObj && globalObj[errorType] ? new globalObj[errorType](message) : new Error(message);
6551 hydrated[index2] = error;
6552 set(error);
6553 continue;
6554 case TYPE_PREVIOUS_RESOLVED:
6555 set(hydrated[index2] = hydrated[b]);
6556 continue;
6557 default:
6558 if (Array.isArray(plugins)) {
6559 const r = [];
6560 const vals = value.slice(1);
6561 for (let i = 0; i < vals.length; i++) {
6562 const v = vals[i];
6563 stack.push([
6564 v,
6565 (v2) => {
6566 r[i] = v2;
6567 }
6568 ]);
6569 }
6570 postRun.push(() => {
6571 for (const plugin of plugins) {
6572 const result2 = plugin(value[0], ...r);
6573 if (result2) {
6574 set(hydrated[index2] = result2.value);
6575 return;
6576 }
6577 }
6578 throw new SyntaxError();
6579 });
6580 continue;
6581 }
6582 throw new SyntaxError();
6583 }
6584 } else {
6585 const array = [];
6586 hydrated[index2] = array;
6587 for (let i = 0; i < value.length; i++) {
6588 const n = value[i];
6589 if (n !== HOLE) {
6590 stack.push([
6591 n,
6592 (v) => {
6593 array[i] = v;
6594 }
6595 ]);
6596 }
6597 }
6598 set(array);
6599 continue;
6600 }
6601 } else {
6602 const object = {};
6603 hydrated[index2] = object;
6604 for (const key of Object.keys(value).reverse()) {
6605 const r = [];
6606 stack.push([
6607 value[key],
6608 (v) => {
6609 r[1] = v;
6610 }
6611 ]);
6612 stack.push([
6613 Number(key.slice(1)),
6614 (k) => {
6615 r[0] = k;
6616 }
6617 ]);
6618 postRun.push(() => {
6619 object[r[0]] = r[1];
6620 });
6621 }
6622 set(object);
6623 continue;
6624 }
6625 }
6626 while (postRun.length > 0) {
6627 postRun.pop()();
6628 }
6629 return result;
6630}
6631
6632// vendor/turbo-stream-v2/turbo-stream.ts
6633async function decode(readable, options) {
6634 const { plugins } = options ?? {};
6635 const done = new Deferred2();
6636 const reader = readable.pipeThrough(createLineSplittingTransform()).getReader();
6637 const decoder = {
6638 values: [],
6639 hydrated: [],
6640 deferred: {},
6641 plugins
6642 };
6643 const decoded = await decodeInitial.call(decoder, reader);
6644 let donePromise = done.promise;
6645 if (decoded.done) {
6646 done.resolve();
6647 } else {
6648 donePromise = decodeDeferred.call(decoder, reader).then(done.resolve).catch((reason) => {
6649 for (const deferred of Object.values(decoder.deferred)) {
6650 deferred.reject(reason);
6651 }
6652 done.reject(reason);
6653 });
6654 }
6655 return {
6656 done: donePromise.then(() => reader.closed),
6657 value: decoded.value
6658 };
6659}
6660async function decodeInitial(reader) {
6661 const read = await reader.read();
6662 if (!read.value) {
6663 throw new SyntaxError();
6664 }
6665 let line;
6666 try {
6667 line = JSON.parse(read.value);
6668 } catch (reason) {
6669 throw new SyntaxError();
6670 }
6671 return {
6672 done: read.done,
6673 value: unflatten.call(this, line)
6674 };
6675}
6676async function decodeDeferred(reader) {
6677 let read = await reader.read();
6678 while (!read.done) {
6679 if (!read.value) continue;
6680 const line = read.value;
6681 switch (line[0]) {
6682 case TYPE_PROMISE: {
6683 const colonIndex = line.indexOf(":");
6684 const deferredId = Number(line.slice(1, colonIndex));
6685 const deferred = this.deferred[deferredId];
6686 if (!deferred) {
6687 throw new Error(`Deferred ID ${deferredId} not found in stream`);
6688 }
6689 const lineData = line.slice(colonIndex + 1);
6690 let jsonLine;
6691 try {
6692 jsonLine = JSON.parse(lineData);
6693 } catch (reason) {
6694 throw new SyntaxError();
6695 }
6696 const value = unflatten.call(this, jsonLine);
6697 deferred.resolve(value);
6698 break;
6699 }
6700 case TYPE_ERROR: {
6701 const colonIndex = line.indexOf(":");
6702 const deferredId = Number(line.slice(1, colonIndex));
6703 const deferred = this.deferred[deferredId];
6704 if (!deferred) {
6705 throw new Error(`Deferred ID ${deferredId} not found in stream`);
6706 }
6707 const lineData = line.slice(colonIndex + 1);
6708 let jsonLine;
6709 try {
6710 jsonLine = JSON.parse(lineData);
6711 } catch (reason) {
6712 throw new SyntaxError();
6713 }
6714 const value = unflatten.call(this, jsonLine);
6715 deferred.reject(value);
6716 break;
6717 }
6718 default:
6719 throw new SyntaxError();
6720 }
6721 read = await reader.read();
6722 }
6723}
6724function encode(input, options) {
6725 const { plugins, postPlugins, signal } = options ?? {};
6726 const encoder = {
6727 deferred: {},
6728 index: 0,
6729 indices: /* @__PURE__ */ new Map(),
6730 stringified: [],
6731 plugins,
6732 postPlugins,
6733 signal
6734 };
6735 const textEncoder = new TextEncoder();
6736 let lastSentIndex = 0;
6737 const readable = new ReadableStream({
6738 async start(controller) {
6739 const id = flatten.call(encoder, input);
6740 if (Array.isArray(id)) {
6741 throw new Error("This should never happen");
6742 }
6743 if (id < 0) {
6744 controller.enqueue(textEncoder.encode(`${id}
6745`));
6746 } else {
6747 controller.enqueue(
6748 textEncoder.encode(`[${encoder.stringified.join(",")}]
6749`)
6750 );
6751 lastSentIndex = encoder.stringified.length - 1;
6752 }
6753 const seenPromises = /* @__PURE__ */ new WeakSet();
6754 if (Object.keys(encoder.deferred).length) {
6755 let raceDone;
6756 const racePromise = new Promise((resolve, reject) => {
6757 raceDone = resolve;
6758 if (signal) {
6759 const rejectPromise = () => reject(signal.reason || new Error("Signal was aborted."));
6760 if (signal.aborted) {
6761 rejectPromise();
6762 } else {
6763 signal.addEventListener("abort", (event) => {
6764 rejectPromise();
6765 });
6766 }
6767 }
6768 });
6769 while (Object.keys(encoder.deferred).length > 0) {
6770 for (const [deferredId, deferred] of Object.entries(
6771 encoder.deferred
6772 )) {
6773 if (seenPromises.has(deferred)) continue;
6774 seenPromises.add(
6775 // biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
6776 encoder.deferred[Number(deferredId)] = Promise.race([
6777 racePromise,
6778 deferred
6779 ]).then(
6780 (resolved) => {
6781 const id2 = flatten.call(encoder, resolved);
6782 if (Array.isArray(id2)) {
6783 controller.enqueue(
6784 textEncoder.encode(
6785 `${TYPE_PROMISE}${deferredId}:[["${TYPE_PREVIOUS_RESOLVED}",${id2[0]}]]
6786`
6787 )
6788 );
6789 encoder.index++;
6790 lastSentIndex++;
6791 } else if (id2 < 0) {
6792 controller.enqueue(
6793 textEncoder.encode(
6794 `${TYPE_PROMISE}${deferredId}:${id2}
6795`
6796 )
6797 );
6798 } else {
6799 const values = encoder.stringified.slice(lastSentIndex + 1).join(",");
6800 controller.enqueue(
6801 textEncoder.encode(
6802 `${TYPE_PROMISE}${deferredId}:[${values}]
6803`
6804 )
6805 );
6806 lastSentIndex = encoder.stringified.length - 1;
6807 }
6808 },
6809 (reason) => {
6810 if (!reason || typeof reason !== "object" || !(reason instanceof Error)) {
6811 reason = new Error("An unknown error occurred");
6812 }
6813 const id2 = flatten.call(encoder, reason);
6814 if (Array.isArray(id2)) {
6815 controller.enqueue(
6816 textEncoder.encode(
6817 `${TYPE_ERROR}${deferredId}:[["${TYPE_PREVIOUS_RESOLVED}",${id2[0]}]]
6818`
6819 )
6820 );
6821 encoder.index++;
6822 lastSentIndex++;
6823 } else if (id2 < 0) {
6824 controller.enqueue(
6825 textEncoder.encode(
6826 `${TYPE_ERROR}${deferredId}:${id2}
6827`
6828 )
6829 );
6830 } else {
6831 const values = encoder.stringified.slice(lastSentIndex + 1).join(",");
6832 controller.enqueue(
6833 textEncoder.encode(
6834 `${TYPE_ERROR}${deferredId}:[${values}]
6835`
6836 )
6837 );
6838 lastSentIndex = encoder.stringified.length - 1;
6839 }
6840 }
6841 ).finally(() => {
6842 delete encoder.deferred[Number(deferredId)];
6843 })
6844 );
6845 }
6846 await Promise.race(Object.values(encoder.deferred));
6847 }
6848 raceDone();
6849 }
6850 await Promise.all(Object.values(encoder.deferred));
6851 controller.close();
6852 }
6853 });
6854 return readable;
6855}
6856
6857// lib/dom/ssr/data.ts
6858async function createRequestInit(request) {
6859 let init = { signal: request.signal };
6860 if (request.method !== "GET") {
6861 init.method = request.method;
6862 let contentType = request.headers.get("Content-Type");
6863 if (contentType && /\bapplication\/json\b/.test(contentType)) {
6864 init.headers = { "Content-Type": contentType };
6865 init.body = JSON.stringify(await request.json());
6866 } else if (contentType && /\btext\/plain\b/.test(contentType)) {
6867 init.headers = { "Content-Type": contentType };
6868 init.body = await request.text();
6869 } else if (contentType && /\bapplication\/x-www-form-urlencoded\b/.test(contentType)) {
6870 init.body = new URLSearchParams(await request.text());
6871 } else {
6872 init.body = await request.formData();
6873 }
6874 }
6875 return init;
6876}
6877
6878// lib/dom/ssr/markup.ts
6879var ESCAPE_LOOKUP = {
6880 "&": "\\u0026",
6881 ">": "\\u003e",
6882 "<": "\\u003c",
6883 "\u2028": "\\u2028",
6884 "\u2029": "\\u2029"
6885};
6886var ESCAPE_REGEX = /[&><\u2028\u2029]/g;
6887function escapeHtml(html) {
6888 return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
6889}
6890function createHtml(html) {
6891 return { __html: html };
6892}
6893
6894// lib/dom/ssr/invariant.ts
6895function invariant2(value, message) {
6896 if (value === false || value === null || typeof value === "undefined") {
6897 throw new Error(message);
6898 }
6899}
6900
6901// lib/dom/ssr/single-fetch.tsx
6902var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
6903var SingleFetchNoResultError = class extends Error {
6904};
6905var SINGLE_FETCH_REDIRECT_STATUS = 202;
6906var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205]);
6907function StreamTransfer({
6908 context,
6909 identifier,
6910 reader,
6911 textDecoder,
6912 nonce
6913}) {
6914 if (!context.renderMeta || !context.renderMeta.didRenderScripts) {
6915 return null;
6916 }
6917 if (!context.renderMeta.streamCache) {
6918 context.renderMeta.streamCache = {};
6919 }
6920 let { streamCache } = context.renderMeta;
6921 let promise = streamCache[identifier];
6922 if (!promise) {
6923 promise = streamCache[identifier] = reader.read().then((result) => {
6924 streamCache[identifier].result = {
6925 done: result.done,
6926 value: textDecoder.decode(result.value, { stream: true })
6927 };
6928 }).catch((e) => {
6929 streamCache[identifier].error = e;
6930 });
6931 }
6932 if (promise.error) {
6933 throw promise.error;
6934 }
6935 if (promise.result === void 0) {
6936 throw promise;
6937 }
6938 let { done, value } = promise.result;
6939 let scriptTag = value ? /* @__PURE__ */ React4.createElement(
6940 "script",
6941 {
6942 nonce,
6943 dangerouslySetInnerHTML: {
6944 __html: `window.__reactRouterContext.streamController.enqueue(${escapeHtml(
6945 JSON.stringify(value)
6946 )});`
6947 }
6948 }
6949 ) : null;
6950 if (done) {
6951 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(
6952 "script",
6953 {
6954 nonce,
6955 dangerouslySetInnerHTML: {
6956 __html: `window.__reactRouterContext.streamController.close();`
6957 }
6958 }
6959 ));
6960 } else {
6961 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(React4.Suspense, null, /* @__PURE__ */ React4.createElement(
6962 StreamTransfer,
6963 {
6964 context,
6965 identifier: identifier + 1,
6966 reader,
6967 textDecoder,
6968 nonce
6969 }
6970 )));
6971 }
6972}
6973function getTurboStreamSingleFetchDataStrategy(getRouter, manifest, routeModules, ssr, basename) {
6974 let dataStrategy = getSingleFetchDataStrategyImpl(
6975 getRouter,
6976 (match) => {
6977 let manifestRoute = manifest.routes[match.route.id];
6978 invariant2(manifestRoute, "Route not found in manifest");
6979 let routeModule = routeModules[match.route.id];
6980 return {
6981 hasLoader: manifestRoute.hasLoader,
6982 hasClientLoader: manifestRoute.hasClientLoader,
6983 hasShouldRevalidate: Boolean(routeModule?.shouldRevalidate)
6984 };
6985 },
6986 fetchAndDecodeViaTurboStream,
6987 ssr,
6988 basename
6989 );
6990 return async (args) => args.unstable_runClientMiddleware(dataStrategy);
6991}
6992function getSingleFetchDataStrategyImpl(getRouter, getRouteInfo, fetchAndDecode, ssr, basename, shouldAllowOptOut = () => true) {
6993 return async (args) => {
6994 let { request, matches, fetcherKey } = args;
6995 let router = getRouter();
6996 if (request.method !== "GET") {
6997 return singleFetchActionStrategy(args, fetchAndDecode, basename);
6998 }
6999 let foundRevalidatingServerLoader = matches.some((m) => {
7000 let { hasLoader, hasClientLoader } = getRouteInfo(m);
7001 return m.unstable_shouldCallHandler() && hasLoader && !hasClientLoader;
7002 });
7003 if (!ssr && !foundRevalidatingServerLoader) {
7004 return nonSsrStrategy(args, getRouteInfo, fetchAndDecode, basename);
7005 }
7006 if (fetcherKey) {
7007 return singleFetchLoaderFetcherStrategy(args, fetchAndDecode, basename);
7008 }
7009 return singleFetchLoaderNavigationStrategy(
7010 args,
7011 router,
7012 getRouteInfo,
7013 fetchAndDecode,
7014 ssr,
7015 basename,
7016 shouldAllowOptOut
7017 );
7018 };
7019}
7020async function singleFetchActionStrategy(args, fetchAndDecode, basename) {
7021 let actionMatch = args.matches.find((m) => m.unstable_shouldCallHandler());
7022 invariant2(actionMatch, "No action match found");
7023 let actionStatus = void 0;
7024 let result = await actionMatch.resolve(async (handler) => {
7025 let result2 = await handler(async () => {
7026 let { data: data2, status } = await fetchAndDecode(args, basename, [
7027 actionMatch.route.id
7028 ]);
7029 actionStatus = status;
7030 return unwrapSingleFetchResult(data2, actionMatch.route.id);
7031 });
7032 return result2;
7033 });
7034 if (isResponse(result.result) || isRouteErrorResponse(result.result) || isDataWithResponseInit(result.result)) {
7035 return { [actionMatch.route.id]: result };
7036 }
7037 return {
7038 [actionMatch.route.id]: {
7039 type: result.type,
7040 result: data(result.result, actionStatus)
7041 }
7042 };
7043}
7044async function nonSsrStrategy(args, getRouteInfo, fetchAndDecode, basename) {
7045 let matchesToLoad = args.matches.filter(
7046 (m) => m.unstable_shouldCallHandler()
7047 );
7048 let results = {};
7049 await Promise.all(
7050 matchesToLoad.map(
7051 (m) => m.resolve(async (handler) => {
7052 try {
7053 let { hasClientLoader } = getRouteInfo(m);
7054 let routeId = m.route.id;
7055 let result = hasClientLoader ? await handler(async () => {
7056 let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
7057 return unwrapSingleFetchResult(data2, routeId);
7058 }) : await handler();
7059 results[m.route.id] = { type: "data", result };
7060 } catch (e) {
7061 results[m.route.id] = { type: "error", result: e };
7062 }
7063 })
7064 )
7065 );
7066 return results;
7067}
7068async function singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, basename, shouldAllowOptOut = () => true) {
7069 let routesParams = /* @__PURE__ */ new Set();
7070 let foundOptOutRoute = false;
7071 let routeDfds = args.matches.map(() => createDeferred2());
7072 let singleFetchDfd = createDeferred2();
7073 let results = {};
7074 let resolvePromise = Promise.all(
7075 args.matches.map(
7076 async (m, i) => m.resolve(async (handler) => {
7077 routeDfds[i].resolve();
7078 let routeId = m.route.id;
7079 let { hasLoader, hasClientLoader, hasShouldRevalidate } = getRouteInfo(m);
7080 let defaultShouldRevalidate = !m.unstable_shouldRevalidateArgs || m.unstable_shouldRevalidateArgs.actionStatus == null || m.unstable_shouldRevalidateArgs.actionStatus < 400;
7081 let shouldCall = m.unstable_shouldCallHandler(defaultShouldRevalidate);
7082 if (!shouldCall) {
7083 foundOptOutRoute || (foundOptOutRoute = m.unstable_shouldRevalidateArgs != null && // This is a revalidation,
7084 hasLoader && // for a route with a server loader,
7085 hasShouldRevalidate === true);
7086 return;
7087 }
7088 if (shouldAllowOptOut(m) && hasClientLoader) {
7089 if (hasLoader) {
7090 foundOptOutRoute = true;
7091 }
7092 try {
7093 let result = await handler(async () => {
7094 let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
7095 return unwrapSingleFetchResult(data2, routeId);
7096 });
7097 results[routeId] = { type: "data", result };
7098 } catch (e) {
7099 results[routeId] = { type: "error", result: e };
7100 }
7101 return;
7102 }
7103 if (hasLoader) {
7104 routesParams.add(routeId);
7105 }
7106 try {
7107 let result = await handler(async () => {
7108 let data2 = await singleFetchDfd.promise;
7109 return unwrapSingleFetchResult(data2, routeId);
7110 });
7111 results[routeId] = { type: "data", result };
7112 } catch (e) {
7113 results[routeId] = { type: "error", result: e };
7114 }
7115 })
7116 )
7117 );
7118 await Promise.all(routeDfds.map((d) => d.promise));
7119 let isInitialLoad = !router.state.initialized && router.state.navigation.state === "idle";
7120 if ((isInitialLoad || routesParams.size === 0) && !window.__reactRouterHdrActive) {
7121 singleFetchDfd.resolve({ routes: {} });
7122 } else {
7123 let targetRoutes = ssr && foundOptOutRoute && routesParams.size > 0 ? [...routesParams.keys()] : void 0;
7124 try {
7125 let data2 = await fetchAndDecode(args, basename, targetRoutes);
7126 singleFetchDfd.resolve(data2.data);
7127 } catch (e) {
7128 singleFetchDfd.reject(e);
7129 }
7130 }
7131 await resolvePromise;
7132 await bubbleMiddlewareErrors(
7133 singleFetchDfd.promise,
7134 args.matches,
7135 routesParams,
7136 results
7137 );
7138 return results;
7139}
7140async function bubbleMiddlewareErrors(singleFetchPromise, matches, routesParams, results) {
7141 try {
7142 let middlewareError;
7143 let fetchedData = await singleFetchPromise;
7144 if ("routes" in fetchedData) {
7145 for (let match of matches) {
7146 if (match.route.id in fetchedData.routes) {
7147 let routeResult = fetchedData.routes[match.route.id];
7148 if ("error" in routeResult) {
7149 middlewareError = routeResult.error;
7150 break;
7151 }
7152 }
7153 }
7154 }
7155 if (middlewareError !== void 0) {
7156 Array.from(routesParams.values()).forEach((routeId) => {
7157 if (results[routeId].result instanceof SingleFetchNoResultError) {
7158 results[routeId].result = middlewareError;
7159 }
7160 });
7161 }
7162 } catch (e) {
7163 }
7164}
7165async function singleFetchLoaderFetcherStrategy(args, fetchAndDecode, basename) {
7166 let fetcherMatch = args.matches.find((m) => m.unstable_shouldCallHandler());
7167 invariant2(fetcherMatch, "No fetcher match found");
7168 let routeId = fetcherMatch.route.id;
7169 let result = await fetcherMatch.resolve(
7170 async (handler) => handler(async () => {
7171 let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
7172 return unwrapSingleFetchResult(data2, routeId);
7173 })
7174 );
7175 return { [fetcherMatch.route.id]: result };
7176}
7177function stripIndexParam(url) {
7178 let indexValues = url.searchParams.getAll("index");
7179 url.searchParams.delete("index");
7180 let indexValuesToKeep = [];
7181 for (let indexValue of indexValues) {
7182 if (indexValue) {
7183 indexValuesToKeep.push(indexValue);
7184 }
7185 }
7186 for (let toKeep of indexValuesToKeep) {
7187 url.searchParams.append("index", toKeep);
7188 }
7189 return url;
7190}
7191function singleFetchUrl(reqUrl, basename, extension) {
7192 let url = typeof reqUrl === "string" ? new URL(
7193 reqUrl,
7194 // This can be called during the SSR flow via PrefetchPageLinksImpl so
7195 // don't assume window is available
7196 typeof window === "undefined" ? "server://singlefetch/" : window.location.origin
7197 ) : reqUrl;
7198 if (url.pathname === "/") {
7199 url.pathname = `_root.${extension}`;
7200 } else if (basename && stripBasename(url.pathname, basename) === "/") {
7201 url.pathname = `${basename.replace(/\/$/, "")}/_root.${extension}`;
7202 } else {
7203 url.pathname = `${url.pathname.replace(/\/$/, "")}.${extension}`;
7204 }
7205 return url;
7206}
7207async function fetchAndDecodeViaTurboStream(args, basename, targetRoutes) {
7208 let { request } = args;
7209 let url = singleFetchUrl(request.url, basename, "data");
7210 if (request.method === "GET") {
7211 url = stripIndexParam(url);
7212 if (targetRoutes) {
7213 url.searchParams.set("_routes", targetRoutes.join(","));
7214 }
7215 }
7216 let res = await fetch(url, await createRequestInit(request));
7217 if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
7218 throw new ErrorResponseImpl(404, "Not Found", true);
7219 }
7220 if (res.status === 204 && res.headers.has("X-Remix-Redirect")) {
7221 return {
7222 status: SINGLE_FETCH_REDIRECT_STATUS,
7223 data: {
7224 redirect: {
7225 redirect: res.headers.get("X-Remix-Redirect"),
7226 status: Number(res.headers.get("X-Remix-Status") || "302"),
7227 revalidate: res.headers.get("X-Remix-Revalidate") === "true",
7228 reload: res.headers.get("X-Remix-Reload-Document") === "true",
7229 replace: res.headers.get("X-Remix-Replace") === "true"
7230 }
7231 }
7232 };
7233 }
7234 if (NO_BODY_STATUS_CODES.has(res.status)) {
7235 let routes = {};
7236 if (targetRoutes && request.method !== "GET") {
7237 routes[targetRoutes[0]] = { data: void 0 };
7238 }
7239 return {
7240 status: res.status,
7241 data: { routes }
7242 };
7243 }
7244 invariant2(res.body, "No response body to decode");
7245 try {
7246 let decoded = await decodeViaTurboStream(res.body, window);
7247 let data2;
7248 if (request.method === "GET") {
7249 let typed = decoded.value;
7250 if (SingleFetchRedirectSymbol in typed) {
7251 data2 = { redirect: typed[SingleFetchRedirectSymbol] };
7252 } else {
7253 data2 = { routes: typed };
7254 }
7255 } else {
7256 let typed = decoded.value;
7257 let routeId = targetRoutes?.[0];
7258 invariant2(routeId, "No routeId found for single fetch call decoding");
7259 if ("redirect" in typed) {
7260 data2 = { redirect: typed };
7261 } else {
7262 data2 = { routes: { [routeId]: typed } };
7263 }
7264 }
7265 return { status: res.status, data: data2 };
7266 } catch (e) {
7267 throw new Error("Unable to decode turbo-stream response");
7268 }
7269}
7270function decodeViaTurboStream(body, global) {
7271 return decode(body, {
7272 plugins: [
7273 (type, ...rest) => {
7274 if (type === "SanitizedError") {
7275 let [name, message, stack] = rest;
7276 let Constructor = Error;
7277 if (name && name in global && typeof global[name] === "function") {
7278 Constructor = global[name];
7279 }
7280 let error = new Constructor(message);
7281 error.stack = stack;
7282 return { value: error };
7283 }
7284 if (type === "ErrorResponse") {
7285 let [data2, status, statusText] = rest;
7286 return {
7287 value: new ErrorResponseImpl(status, statusText, data2)
7288 };
7289 }
7290 if (type === "SingleFetchRedirect") {
7291 return { value: { [SingleFetchRedirectSymbol]: rest[0] } };
7292 }
7293 if (type === "SingleFetchClassInstance") {
7294 return { value: rest[0] };
7295 }
7296 if (type === "SingleFetchFallback") {
7297 return { value: void 0 };
7298 }
7299 }
7300 ]
7301 });
7302}
7303function unwrapSingleFetchResult(result, routeId) {
7304 if ("redirect" in result) {
7305 let {
7306 redirect: location,
7307 revalidate,
7308 reload,
7309 replace: replace2,
7310 status
7311 } = result.redirect;
7312 throw redirect(location, {
7313 status,
7314 headers: {
7315 // Three R's of redirecting (lol Veep)
7316 ...revalidate ? { "X-Remix-Revalidate": "yes" } : null,
7317 ...reload ? { "X-Remix-Reload-Document": "yes" } : null,
7318 ...replace2 ? { "X-Remix-Replace": "yes" } : null
7319 }
7320 });
7321 }
7322 let routeResult = result.routes[routeId];
7323 if (routeResult == null) {
7324 throw new SingleFetchNoResultError(
7325 `No result found for routeId "${routeId}"`
7326 );
7327 } else if ("error" in routeResult) {
7328 throw routeResult.error;
7329 } else if ("data" in routeResult) {
7330 return routeResult.data;
7331 } else {
7332 throw new Error(`Invalid response found for routeId "${routeId}"`);
7333 }
7334}
7335function createDeferred2() {
7336 let resolve;
7337 let reject;
7338 let promise = new Promise((res, rej) => {
7339 resolve = async (val) => {
7340 res(val);
7341 try {
7342 await promise;
7343 } catch (e) {
7344 }
7345 };
7346 reject = async (error) => {
7347 rej(error);
7348 try {
7349 await promise;
7350 } catch (e) {
7351 }
7352 };
7353 });
7354 return {
7355 promise,
7356 //@ts-ignore
7357 resolve,
7358 //@ts-ignore
7359 reject
7360 };
7361}
7362
7363// lib/dom/ssr/errorBoundaries.tsx
7364import * as React9 from "react";
7365
7366// lib/dom/ssr/components.tsx
7367import * as React8 from "react";
7368
7369// lib/dom/ssr/routeModules.ts
7370async function loadRouteModule(route, routeModulesCache) {
7371 if (route.id in routeModulesCache) {
7372 return routeModulesCache[route.id];
7373 }
7374 try {
7375 let routeModule = await import(
7376 /* @vite-ignore */
7377 /* webpackIgnore: true */
7378 route.module
7379 );
7380 routeModulesCache[route.id] = routeModule;
7381 return routeModule;
7382 } catch (error) {
7383 console.error(
7384 `Error loading route module \`${route.module}\`, reloading page...`
7385 );
7386 console.error(error);
7387 if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
7388 import.meta.hot) {
7389 throw error;
7390 }
7391 window.location.reload();
7392 return new Promise(() => {
7393 });
7394 }
7395}
7396
7397// lib/dom/ssr/links.ts
7398function getKeyedLinksForMatches(matches, routeModules, manifest) {
7399 let descriptors = matches.map((match) => {
7400 let module = routeModules[match.route.id];
7401 let route = manifest.routes[match.route.id];
7402 return [
7403 route && route.css ? route.css.map((href) => ({ rel: "stylesheet", href })) : [],
7404 module?.links?.() || []
7405 ];
7406 }).flat(2);
7407 let preloads = getModuleLinkHrefs(matches, manifest);
7408 return dedupeLinkDescriptors(descriptors, preloads);
7409}
7410function getRouteCssDescriptors(route) {
7411 if (!route.css) return [];
7412 return route.css.map((href) => ({ rel: "stylesheet", href }));
7413}
7414async function prefetchRouteCss(route) {
7415 if (!route.css) return;
7416 let descriptors = getRouteCssDescriptors(route);
7417 await Promise.all(descriptors.map(prefetchStyleLink));
7418}
7419async function prefetchStyleLinks(route, routeModule) {
7420 if (!route.css && !routeModule.links || !isPreloadSupported()) return;
7421 let descriptors = [];
7422 if (route.css) {
7423 descriptors.push(...getRouteCssDescriptors(route));
7424 }
7425 if (routeModule.links) {
7426 descriptors.push(...routeModule.links());
7427 }
7428 if (descriptors.length === 0) return;
7429 let styleLinks = [];
7430 for (let descriptor of descriptors) {
7431 if (!isPageLinkDescriptor(descriptor) && descriptor.rel === "stylesheet") {
7432 styleLinks.push({
7433 ...descriptor,
7434 rel: "preload",
7435 as: "style"
7436 });
7437 }
7438 }
7439 await Promise.all(styleLinks.map(prefetchStyleLink));
7440}
7441async function prefetchStyleLink(descriptor) {
7442 return new Promise((resolve) => {
7443 if (descriptor.media && !window.matchMedia(descriptor.media).matches || document.querySelector(
7444 `link[rel="stylesheet"][href="${descriptor.href}"]`
7445 )) {
7446 return resolve();
7447 }
7448 let link = document.createElement("link");
7449 Object.assign(link, descriptor);
7450 function removeLink() {
7451 if (document.head.contains(link)) {
7452 document.head.removeChild(link);
7453 }
7454 }
7455 link.onload = () => {
7456 removeLink();
7457 resolve();
7458 };
7459 link.onerror = () => {
7460 removeLink();
7461 resolve();
7462 };
7463 document.head.appendChild(link);
7464 });
7465}
7466function isPageLinkDescriptor(object) {
7467 return object != null && typeof object.page === "string";
7468}
7469function isHtmlLinkDescriptor(object) {
7470 if (object == null) {
7471 return false;
7472 }
7473 if (object.href == null) {
7474 return object.rel === "preload" && typeof object.imageSrcSet === "string" && typeof object.imageSizes === "string";
7475 }
7476 return typeof object.rel === "string" && typeof object.href === "string";
7477}
7478async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
7479 let links = await Promise.all(
7480 matches.map(async (match) => {
7481 let route = manifest.routes[match.route.id];
7482 if (route) {
7483 let mod = await loadRouteModule(route, routeModules);
7484 return mod.links ? mod.links() : [];
7485 }
7486 return [];
7487 })
7488 );
7489 return dedupeLinkDescriptors(
7490 links.flat(1).filter(isHtmlLinkDescriptor).filter((link) => link.rel === "stylesheet" || link.rel === "preload").map(
7491 (link) => link.rel === "stylesheet" ? { ...link, rel: "prefetch", as: "style" } : { ...link, rel: "prefetch" }
7492 )
7493 );
7494}
7495function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
7496 let isNew = (match, index) => {
7497 if (!currentMatches[index]) return true;
7498 return match.route.id !== currentMatches[index].route.id;
7499 };
7500 let matchPathChanged = (match, index) => {
7501 return (
7502 // param change, /users/123 -> /users/456
7503 currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path
7504 // e.g. /files/images/avatar.jpg -> files/finances.xls
7505 currentMatches[index].route.path?.endsWith("*") && currentMatches[index].params["*"] !== match.params["*"]
7506 );
7507 };
7508 if (mode === "assets") {
7509 return nextMatches.filter(
7510 (match, index) => isNew(match, index) || matchPathChanged(match, index)
7511 );
7512 }
7513 if (mode === "data") {
7514 return nextMatches.filter((match, index) => {
7515 let manifestRoute = manifest.routes[match.route.id];
7516 if (!manifestRoute || !manifestRoute.hasLoader) {
7517 return false;
7518 }
7519 if (isNew(match, index) || matchPathChanged(match, index)) {
7520 return true;
7521 }
7522 if (match.route.shouldRevalidate) {
7523 let routeChoice = match.route.shouldRevalidate({
7524 currentUrl: new URL(
7525 location.pathname + location.search + location.hash,
7526 window.origin
7527 ),
7528 currentParams: currentMatches[0]?.params || {},
7529 nextUrl: new URL(page, window.origin),
7530 nextParams: match.params,
7531 defaultShouldRevalidate: true
7532 });
7533 if (typeof routeChoice === "boolean") {
7534 return routeChoice;
7535 }
7536 }
7537 return true;
7538 });
7539 }
7540 return [];
7541}
7542function getModuleLinkHrefs(matches, manifest, { includeHydrateFallback } = {}) {
7543 return dedupeHrefs(
7544 matches.map((match) => {
7545 let route = manifest.routes[match.route.id];
7546 if (!route) return [];
7547 let hrefs = [route.module];
7548 if (route.clientActionModule) {
7549 hrefs = hrefs.concat(route.clientActionModule);
7550 }
7551 if (route.clientLoaderModule) {
7552 hrefs = hrefs.concat(route.clientLoaderModule);
7553 }
7554 if (includeHydrateFallback && route.hydrateFallbackModule) {
7555 hrefs = hrefs.concat(route.hydrateFallbackModule);
7556 }
7557 if (route.imports) {
7558 hrefs = hrefs.concat(route.imports);
7559 }
7560 return hrefs;
7561 }).flat(1)
7562 );
7563}
7564function dedupeHrefs(hrefs) {
7565 return [...new Set(hrefs)];
7566}
7567function sortKeys(obj) {
7568 let sorted = {};
7569 let keys = Object.keys(obj).sort();
7570 for (let key of keys) {
7571 sorted[key] = obj[key];
7572 }
7573 return sorted;
7574}
7575function dedupeLinkDescriptors(descriptors, preloads) {
7576 let set = /* @__PURE__ */ new Set();
7577 let preloadsSet = new Set(preloads);
7578 return descriptors.reduce((deduped, descriptor) => {
7579 let alreadyModulePreload = preloads && !isPageLinkDescriptor(descriptor) && descriptor.as === "script" && descriptor.href && preloadsSet.has(descriptor.href);
7580 if (alreadyModulePreload) {
7581 return deduped;
7582 }
7583 let key = JSON.stringify(sortKeys(descriptor));
7584 if (!set.has(key)) {
7585 set.add(key);
7586 deduped.push({ key, link: descriptor });
7587 }
7588 return deduped;
7589 }, []);
7590}
7591var _isPreloadSupported;
7592function isPreloadSupported() {
7593 if (_isPreloadSupported !== void 0) {
7594 return _isPreloadSupported;
7595 }
7596 let el = document.createElement("link");
7597 _isPreloadSupported = el.relList.supports("preload");
7598 el = null;
7599 return _isPreloadSupported;
7600}
7601
7602// lib/dom/ssr/fog-of-war.ts
7603import * as React7 from "react";
7604
7605// lib/dom/ssr/routes.tsx
7606import * as React6 from "react";
7607
7608// lib/dom/ssr/fallback.tsx
7609import * as React5 from "react";
7610function RemixRootDefaultHydrateFallback() {
7611 return /* @__PURE__ */ React5.createElement(BoundaryShell, { title: "Loading...", renderScripts: true }, ENABLE_DEV_WARNINGS ? /* @__PURE__ */ React5.createElement(
7612 "script",
7613 {
7614 dangerouslySetInnerHTML: {
7615 __html: `
7616 console.log(
7617 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this " +
7618 "when your app is loading JS modules and/or running \`clientLoader\` " +
7619 "functions. Check out https://reactrouter.com/start/framework/route-module#hydratefallback " +
7620 "for more information."
7621 );
7622 `
7623 }
7624 }
7625 ) : null);
7626}
7627
7628// lib/dom/ssr/routes.tsx
7629function groupRoutesByParentId(manifest) {
7630 let routes = {};
7631 Object.values(manifest).forEach((route) => {
7632 if (route) {
7633 let parentId = route.parentId || "";
7634 if (!routes[parentId]) {
7635 routes[parentId] = [];
7636 }
7637 routes[parentId].push(route);
7638 }
7639 });
7640 return routes;
7641}
7642function getRouteComponents(route, routeModule, isSpaMode) {
7643 let Component4 = getRouteModuleComponent(routeModule);
7644 let HydrateFallback = routeModule.HydrateFallback && (!isSpaMode || route.id === "root") ? routeModule.HydrateFallback : route.id === "root" ? RemixRootDefaultHydrateFallback : void 0;
7645 let ErrorBoundary = routeModule.ErrorBoundary ? routeModule.ErrorBoundary : route.id === "root" ? () => /* @__PURE__ */ React6.createElement(RemixRootDefaultErrorBoundary, { error: useRouteError() }) : void 0;
7646 if (route.id === "root" && routeModule.Layout) {
7647 return {
7648 ...Component4 ? {
7649 element: /* @__PURE__ */ React6.createElement(routeModule.Layout, null, /* @__PURE__ */ React6.createElement(Component4, null))
7650 } : { Component: Component4 },
7651 ...ErrorBoundary ? {
7652 errorElement: /* @__PURE__ */ React6.createElement(routeModule.Layout, null, /* @__PURE__ */ React6.createElement(ErrorBoundary, null))
7653 } : { ErrorBoundary },
7654 ...HydrateFallback ? {
7655 hydrateFallbackElement: /* @__PURE__ */ React6.createElement(routeModule.Layout, null, /* @__PURE__ */ React6.createElement(HydrateFallback, null))
7656 } : { HydrateFallback }
7657 };
7658 }
7659 return { Component: Component4, ErrorBoundary, HydrateFallback };
7660}
7661function createServerRoutes(manifest, routeModules, future, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), spaModeLazyPromise = Promise.resolve({ Component: () => null })) {
7662 return (routesByParentId[parentId] || []).map((route) => {
7663 let routeModule = routeModules[route.id];
7664 invariant2(
7665 routeModule,
7666 "No `routeModule` available to create server routes"
7667 );
7668 let dataRoute = {
7669 ...getRouteComponents(route, routeModule, isSpaMode),
7670 caseSensitive: route.caseSensitive,
7671 id: route.id,
7672 index: route.index,
7673 path: route.path,
7674 handle: routeModule.handle,
7675 // For SPA Mode, all routes are lazy except root. However we tell the
7676 // router root is also lazy here too since we don't need a full
7677 // implementation - we just need a `lazy` prop to tell the RR rendering
7678 // where to stop which is always at the root route in SPA mode
7679 lazy: isSpaMode ? () => spaModeLazyPromise : void 0,
7680 // For partial hydration rendering, we need to indicate when the route
7681 // has a loader/clientLoader, but it won't ever be called during the static
7682 // render, so just give it a no-op function so we can render down to the
7683 // proper fallback
7684 loader: route.hasLoader || route.hasClientLoader ? () => null : void 0
7685 // We don't need middleware/action/shouldRevalidate on these routes since
7686 // they're for a static render
7687 };
7688 let children = createServerRoutes(
7689 manifest,
7690 routeModules,
7691 future,
7692 isSpaMode,
7693 route.id,
7694 routesByParentId,
7695 spaModeLazyPromise
7696 );
7697 if (children.length > 0) dataRoute.children = children;
7698 return dataRoute;
7699 });
7700}
7701function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState, ssr, isSpaMode) {
7702 return createClientRoutes(
7703 manifest,
7704 routeModulesCache,
7705 initialState,
7706 ssr,
7707 isSpaMode,
7708 "",
7709 groupRoutesByParentId(manifest),
7710 needsRevalidation
7711 );
7712}
7713function preventInvalidServerHandlerCall(type, route) {
7714 if (type === "loader" && !route.hasLoader || type === "action" && !route.hasAction) {
7715 let fn = type === "action" ? "serverAction()" : "serverLoader()";
7716 let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
7717 console.error(msg);
7718 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
7719 }
7720}
7721function noActionDefinedError(type, routeId) {
7722 let article = type === "clientAction" ? "a" : "an";
7723 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`;
7724 console.error(msg);
7725 throw new ErrorResponseImpl(405, "Method Not Allowed", new Error(msg), true);
7726}
7727function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
7728 return (routesByParentId[parentId] || []).map((route) => {
7729 let routeModule = routeModulesCache[route.id];
7730 function fetchServerHandler(singleFetch) {
7731 invariant2(
7732 typeof singleFetch === "function",
7733 "No single fetch function available for route handler"
7734 );
7735 return singleFetch();
7736 }
7737 function fetchServerLoader(singleFetch) {
7738 if (!route.hasLoader) return Promise.resolve(null);
7739 return fetchServerHandler(singleFetch);
7740 }
7741 function fetchServerAction(singleFetch) {
7742 if (!route.hasAction) {
7743 throw noActionDefinedError("action", route.id);
7744 }
7745 return fetchServerHandler(singleFetch);
7746 }
7747 function prefetchModule(modulePath) {
7748 import(
7749 /* @vite-ignore */
7750 /* webpackIgnore: true */
7751 modulePath
7752 );
7753 }
7754 function prefetchRouteModuleChunks(route2) {
7755 if (route2.clientActionModule) {
7756 prefetchModule(route2.clientActionModule);
7757 }
7758 if (route2.clientLoaderModule) {
7759 prefetchModule(route2.clientLoaderModule);
7760 }
7761 }
7762 async function prefetchStylesAndCallHandler(handler) {
7763 let cachedModule = routeModulesCache[route.id];
7764 let linkPrefetchPromise = cachedModule ? prefetchStyleLinks(route, cachedModule) : Promise.resolve();
7765 try {
7766 return handler();
7767 } finally {
7768 await linkPrefetchPromise;
7769 }
7770 }
7771 let dataRoute = {
7772 id: route.id,
7773 index: route.index,
7774 path: route.path
7775 };
7776 if (routeModule) {
7777 Object.assign(dataRoute, {
7778 ...dataRoute,
7779 ...getRouteComponents(route, routeModule, isSpaMode),
7780 unstable_middleware: routeModule.unstable_clientMiddleware,
7781 handle: routeModule.handle,
7782 shouldRevalidate: getShouldRevalidateFunction(
7783 dataRoute.path,
7784 routeModule,
7785 route,
7786 ssr,
7787 needsRevalidation
7788 )
7789 });
7790 let hasInitialData = initialState && initialState.loaderData && route.id in initialState.loaderData;
7791 let initialData = hasInitialData ? initialState?.loaderData?.[route.id] : void 0;
7792 let hasInitialError = initialState && initialState.errors && route.id in initialState.errors;
7793 let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
7794 let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
7795 dataRoute.loader = async ({ request, params, context }, singleFetch) => {
7796 try {
7797 let result = await prefetchStylesAndCallHandler(async () => {
7798 invariant2(
7799 routeModule,
7800 "No `routeModule` available for critical-route loader"
7801 );
7802 if (!routeModule.clientLoader) {
7803 return fetchServerLoader(singleFetch);
7804 }
7805 return routeModule.clientLoader({
7806 request,
7807 params,
7808 context,
7809 async serverLoader() {
7810 preventInvalidServerHandlerCall("loader", route);
7811 if (isHydrationRequest) {
7812 if (hasInitialData) {
7813 return initialData;
7814 }
7815 if (hasInitialError) {
7816 throw initialError;
7817 }
7818 }
7819 return fetchServerLoader(singleFetch);
7820 }
7821 });
7822 });
7823 return result;
7824 } finally {
7825 isHydrationRequest = false;
7826 }
7827 };
7828 dataRoute.loader.hydrate = shouldHydrateRouteLoader(
7829 route.id,
7830 routeModule.clientLoader,
7831 route.hasLoader,
7832 isSpaMode
7833 );
7834 dataRoute.action = ({ request, params, context }, singleFetch) => {
7835 return prefetchStylesAndCallHandler(async () => {
7836 invariant2(
7837 routeModule,
7838 "No `routeModule` available for critical-route action"
7839 );
7840 if (!routeModule.clientAction) {
7841 if (isSpaMode) {
7842 throw noActionDefinedError("clientAction", route.id);
7843 }
7844 return fetchServerAction(singleFetch);
7845 }
7846 return routeModule.clientAction({
7847 request,
7848 params,
7849 context,
7850 async serverAction() {
7851 preventInvalidServerHandlerCall("action", route);
7852 return fetchServerAction(singleFetch);
7853 }
7854 });
7855 });
7856 };
7857 } else {
7858 if (!route.hasClientLoader) {
7859 dataRoute.loader = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
7860 return fetchServerLoader(singleFetch);
7861 });
7862 }
7863 if (!route.hasClientAction) {
7864 dataRoute.action = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
7865 if (isSpaMode) {
7866 throw noActionDefinedError("clientAction", route.id);
7867 }
7868 return fetchServerAction(singleFetch);
7869 });
7870 }
7871 let lazyRoutePromise;
7872 async function getLazyRoute() {
7873 if (lazyRoutePromise) {
7874 return await lazyRoutePromise;
7875 }
7876 lazyRoutePromise = (async () => {
7877 if (route.clientLoaderModule || route.clientActionModule) {
7878 await new Promise((resolve) => setTimeout(resolve, 0));
7879 }
7880 let routeModulePromise = loadRouteModuleWithBlockingLinks(
7881 route,
7882 routeModulesCache
7883 );
7884 prefetchRouteModuleChunks(route);
7885 return await routeModulePromise;
7886 })();
7887 return await lazyRoutePromise;
7888 }
7889 dataRoute.lazy = {
7890 loader: route.hasClientLoader ? async () => {
7891 let { clientLoader } = route.clientLoaderModule ? await import(
7892 /* @vite-ignore */
7893 /* webpackIgnore: true */
7894 route.clientLoaderModule
7895 ) : await getLazyRoute();
7896 invariant2(clientLoader, "No `clientLoader` export found");
7897 return (args, singleFetch) => clientLoader({
7898 ...args,
7899 async serverLoader() {
7900 preventInvalidServerHandlerCall("loader", route);
7901 return fetchServerLoader(singleFetch);
7902 }
7903 });
7904 } : void 0,
7905 action: route.hasClientAction ? async () => {
7906 let clientActionPromise = route.clientActionModule ? import(
7907 /* @vite-ignore */
7908 /* webpackIgnore: true */
7909 route.clientActionModule
7910 ) : getLazyRoute();
7911 prefetchRouteModuleChunks(route);
7912 let { clientAction } = await clientActionPromise;
7913 invariant2(clientAction, "No `clientAction` export found");
7914 return (args, singleFetch) => clientAction({
7915 ...args,
7916 async serverAction() {
7917 preventInvalidServerHandlerCall("action", route);
7918 return fetchServerAction(singleFetch);
7919 }
7920 });
7921 } : void 0,
7922 unstable_middleware: route.hasClientMiddleware ? async () => {
7923 let { unstable_clientMiddleware } = route.clientMiddlewareModule ? await import(
7924 /* @vite-ignore */
7925 /* webpackIgnore: true */
7926 route.clientMiddlewareModule
7927 ) : await getLazyRoute();
7928 invariant2(
7929 unstable_clientMiddleware,
7930 "No `unstable_clientMiddleware` export found"
7931 );
7932 return unstable_clientMiddleware;
7933 } : void 0,
7934 shouldRevalidate: async () => {
7935 let lazyRoute = await getLazyRoute();
7936 return getShouldRevalidateFunction(
7937 dataRoute.path,
7938 lazyRoute,
7939 route,
7940 ssr,
7941 needsRevalidation
7942 );
7943 },
7944 handle: async () => (await getLazyRoute()).handle,
7945 // No need to wrap these in layout since the root route is never
7946 // loaded via route.lazy()
7947 Component: async () => (await getLazyRoute()).Component,
7948 ErrorBoundary: route.hasErrorBoundary ? async () => (await getLazyRoute()).ErrorBoundary : void 0
7949 };
7950 }
7951 let children = createClientRoutes(
7952 manifest,
7953 routeModulesCache,
7954 initialState,
7955 ssr,
7956 isSpaMode,
7957 route.id,
7958 routesByParentId,
7959 needsRevalidation
7960 );
7961 if (children.length > 0) dataRoute.children = children;
7962 return dataRoute;
7963 });
7964}
7965function getShouldRevalidateFunction(path, route, manifestRoute, ssr, needsRevalidation) {
7966 if (needsRevalidation) {
7967 return wrapShouldRevalidateForHdr(
7968 manifestRoute.id,
7969 route.shouldRevalidate,
7970 needsRevalidation
7971 );
7972 }
7973 if (!ssr && manifestRoute.hasLoader && !manifestRoute.hasClientLoader) {
7974 let myParams = path ? compilePath(path)[1].map((p) => p.paramName) : [];
7975 const didParamsChange = (opts) => myParams.some((p) => opts.currentParams[p] !== opts.nextParams[p]);
7976 if (route.shouldRevalidate) {
7977 let fn = route.shouldRevalidate;
7978 return (opts) => fn({
7979 ...opts,
7980 defaultShouldRevalidate: didParamsChange(opts)
7981 });
7982 } else {
7983 return (opts) => didParamsChange(opts);
7984 }
7985 }
7986 if (ssr && route.shouldRevalidate) {
7987 let fn = route.shouldRevalidate;
7988 return (opts) => fn({ ...opts, defaultShouldRevalidate: true });
7989 }
7990 return route.shouldRevalidate;
7991}
7992function wrapShouldRevalidateForHdr(routeId, routeShouldRevalidate, needsRevalidation) {
7993 let handledRevalidation = false;
7994 return (arg) => {
7995 if (!handledRevalidation) {
7996 handledRevalidation = true;
7997 return needsRevalidation.has(routeId);
7998 }
7999 return routeShouldRevalidate ? routeShouldRevalidate(arg) : arg.defaultShouldRevalidate;
8000 };
8001}
8002async function loadRouteModuleWithBlockingLinks(route, routeModules) {
8003 let routeModulePromise = loadRouteModule(route, routeModules);
8004 let prefetchRouteCssPromise = prefetchRouteCss(route);
8005 let routeModule = await routeModulePromise;
8006 await Promise.all([
8007 prefetchRouteCssPromise,
8008 prefetchStyleLinks(route, routeModule)
8009 ]);
8010 return {
8011 Component: getRouteModuleComponent(routeModule),
8012 ErrorBoundary: routeModule.ErrorBoundary,
8013 unstable_clientMiddleware: routeModule.unstable_clientMiddleware,
8014 clientAction: routeModule.clientAction,
8015 clientLoader: routeModule.clientLoader,
8016 handle: routeModule.handle,
8017 links: routeModule.links,
8018 meta: routeModule.meta,
8019 shouldRevalidate: routeModule.shouldRevalidate
8020 };
8021}
8022function getRouteModuleComponent(routeModule) {
8023 if (routeModule.default == null) return void 0;
8024 let isEmptyObject = typeof routeModule.default === "object" && Object.keys(routeModule.default).length === 0;
8025 if (!isEmptyObject) {
8026 return routeModule.default;
8027 }
8028}
8029function shouldHydrateRouteLoader(routeId, clientLoader, hasLoader, isSpaMode) {
8030 return isSpaMode && routeId !== "root" || clientLoader != null && (clientLoader.hydrate === true || hasLoader !== true);
8031}
8032
8033// lib/dom/ssr/fog-of-war.ts
8034var nextPaths = /* @__PURE__ */ new Set();
8035var discoveredPathsMaxSize = 1e3;
8036var discoveredPaths = /* @__PURE__ */ new Set();
8037var URL_LIMIT = 7680;
8038function isFogOfWarEnabled(routeDiscovery, ssr) {
8039 return routeDiscovery.mode === "lazy" && ssr === true;
8040}
8041function getPartialManifest({ sri, ...manifest }, router) {
8042 let routeIds = new Set(router.state.matches.map((m) => m.route.id));
8043 let segments = router.state.location.pathname.split("/").filter(Boolean);
8044 let paths = ["/"];
8045 segments.pop();
8046 while (segments.length > 0) {
8047 paths.push(`/${segments.join("/")}`);
8048 segments.pop();
8049 }
8050 paths.forEach((path) => {
8051 let matches = matchRoutes(router.routes, path, router.basename);
8052 if (matches) {
8053 matches.forEach((m) => routeIds.add(m.route.id));
8054 }
8055 });
8056 let initialRoutes = [...routeIds].reduce(
8057 (acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }),
8058 {}
8059 );
8060 return {
8061 ...manifest,
8062 routes: initialRoutes,
8063 sri: sri ? true : void 0
8064 };
8065}
8066function getPatchRoutesOnNavigationFunction(manifest, routeModules, ssr, routeDiscovery, isSpaMode, basename) {
8067 if (!isFogOfWarEnabled(routeDiscovery, ssr)) {
8068 return void 0;
8069 }
8070 return async ({ path, patch, signal, fetcherKey }) => {
8071 if (discoveredPaths.has(path)) {
8072 return;
8073 }
8074 await fetchAndApplyManifestPatches(
8075 [path],
8076 fetcherKey ? window.location.href : path,
8077 manifest,
8078 routeModules,
8079 ssr,
8080 isSpaMode,
8081 basename,
8082 routeDiscovery.manifestPath,
8083 patch,
8084 signal
8085 );
8086 };
8087}
8088function useFogOFWarDiscovery(router, manifest, routeModules, ssr, routeDiscovery, isSpaMode) {
8089 React7.useEffect(() => {
8090 if (!isFogOfWarEnabled(routeDiscovery, ssr) || // @ts-expect-error - TS doesn't know about this yet
8091 window.navigator?.connection?.saveData === true) {
8092 return;
8093 }
8094 function registerElement(el) {
8095 let path = el.tagName === "FORM" ? el.getAttribute("action") : el.getAttribute("href");
8096 if (!path) {
8097 return;
8098 }
8099 let pathname = el.tagName === "A" ? el.pathname : new URL(path, window.location.origin).pathname;
8100 if (!discoveredPaths.has(pathname)) {
8101 nextPaths.add(pathname);
8102 }
8103 }
8104 async function fetchPatches() {
8105 document.querySelectorAll("a[data-discover], form[data-discover]").forEach(registerElement);
8106 let lazyPaths = Array.from(nextPaths.keys()).filter((path) => {
8107 if (discoveredPaths.has(path)) {
8108 nextPaths.delete(path);
8109 return false;
8110 }
8111 return true;
8112 });
8113 if (lazyPaths.length === 0) {
8114 return;
8115 }
8116 try {
8117 await fetchAndApplyManifestPatches(
8118 lazyPaths,
8119 null,
8120 manifest,
8121 routeModules,
8122 ssr,
8123 isSpaMode,
8124 router.basename,
8125 routeDiscovery.manifestPath,
8126 router.patchRoutes
8127 );
8128 } catch (e) {
8129 console.error("Failed to fetch manifest patches", e);
8130 }
8131 }
8132 let debouncedFetchPatches = debounce(fetchPatches, 100);
8133 fetchPatches();
8134 let observer = new MutationObserver(() => debouncedFetchPatches());
8135 observer.observe(document.documentElement, {
8136 subtree: true,
8137 childList: true,
8138 attributes: true,
8139 attributeFilter: ["data-discover", "href", "action"]
8140 });
8141 return () => observer.disconnect();
8142 }, [ssr, isSpaMode, manifest, routeModules, router, routeDiscovery]);
8143}
8144function getManifestPath(_manifestPath, basename) {
8145 let manifestPath = _manifestPath || "/__manifest";
8146 if (basename == null) {
8147 return manifestPath;
8148 }
8149 return `${basename}${manifestPath}`.replace(/\/+/g, "/");
8150}
8151var MANIFEST_VERSION_STORAGE_KEY = "react-router-manifest-version";
8152async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, manifestPath, patchRoutes, signal) {
8153 let url = new URL(
8154 getManifestPath(manifestPath, basename),
8155 window.location.origin
8156 );
8157 paths.sort().forEach((path) => url.searchParams.append("p", path));
8158 url.searchParams.set("version", manifest.version);
8159 if (url.toString().length > URL_LIMIT) {
8160 nextPaths.clear();
8161 return;
8162 }
8163 let serverPatches;
8164 try {
8165 let res = await fetch(url, { signal });
8166 if (!res.ok) {
8167 throw new Error(`${res.status} ${res.statusText}`);
8168 } else if (res.status === 204 && res.headers.has("X-Remix-Reload-Document")) {
8169 if (!errorReloadPath) {
8170 console.warn(
8171 "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."
8172 );
8173 return;
8174 }
8175 if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === manifest.version) {
8176 console.error(
8177 "Unable to discover routes due to manifest version mismatch."
8178 );
8179 return;
8180 }
8181 sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, manifest.version);
8182 window.location.href = errorReloadPath;
8183 console.warn("Detected manifest version mismatch, reloading...");
8184 await new Promise(() => {
8185 });
8186 } else if (res.status >= 400) {
8187 throw new Error(await res.text());
8188 }
8189 sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
8190 serverPatches = await res.json();
8191 } catch (e) {
8192 if (signal?.aborted) return;
8193 throw e;
8194 }
8195 let knownRoutes = new Set(Object.keys(manifest.routes));
8196 let patches = Object.values(serverPatches).reduce((acc, route) => {
8197 if (route && !knownRoutes.has(route.id)) {
8198 acc[route.id] = route;
8199 }
8200 return acc;
8201 }, {});
8202 Object.assign(manifest.routes, patches);
8203 paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
8204 let parentIds = /* @__PURE__ */ new Set();
8205 Object.values(patches).forEach((patch) => {
8206 if (patch && (!patch.parentId || !patches[patch.parentId])) {
8207 parentIds.add(patch.parentId);
8208 }
8209 });
8210 parentIds.forEach(
8211 (parentId) => patchRoutes(
8212 parentId || null,
8213 createClientRoutes(patches, routeModules, null, ssr, isSpaMode, parentId)
8214 )
8215 );
8216}
8217function addToFifoQueue(path, queue) {
8218 if (queue.size >= discoveredPathsMaxSize) {
8219 let first = queue.values().next().value;
8220 queue.delete(first);
8221 }
8222 queue.add(path);
8223}
8224function debounce(callback, wait) {
8225 let timeoutId;
8226 return (...args) => {
8227 window.clearTimeout(timeoutId);
8228 timeoutId = window.setTimeout(() => callback(...args), wait);
8229 };
8230}
8231
8232// lib/dom/ssr/components.tsx
8233function useDataRouterContext2() {
8234 let context = React8.useContext(DataRouterContext);
8235 invariant2(
8236 context,
8237 "You must render this element inside a <DataRouterContext.Provider> element"
8238 );
8239 return context;
8240}
8241function useDataRouterStateContext() {
8242 let context = React8.useContext(DataRouterStateContext);
8243 invariant2(
8244 context,
8245 "You must render this element inside a <DataRouterStateContext.Provider> element"
8246 );
8247 return context;
8248}
8249var FrameworkContext = React8.createContext(void 0);
8250FrameworkContext.displayName = "FrameworkContext";
8251function useFrameworkContext() {
8252 let context = React8.useContext(FrameworkContext);
8253 invariant2(
8254 context,
8255 "You must render this element inside a <HydratedRouter> element"
8256 );
8257 return context;
8258}
8259function usePrefetchBehavior(prefetch, theirElementProps) {
8260 let frameworkContext = React8.useContext(FrameworkContext);
8261 let [maybePrefetch, setMaybePrefetch] = React8.useState(false);
8262 let [shouldPrefetch, setShouldPrefetch] = React8.useState(false);
8263 let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
8264 let ref = React8.useRef(null);
8265 React8.useEffect(() => {
8266 if (prefetch === "render") {
8267 setShouldPrefetch(true);
8268 }
8269 if (prefetch === "viewport") {
8270 let callback = (entries) => {
8271 entries.forEach((entry) => {
8272 setShouldPrefetch(entry.isIntersecting);
8273 });
8274 };
8275 let observer = new IntersectionObserver(callback, { threshold: 0.5 });
8276 if (ref.current) observer.observe(ref.current);
8277 return () => {
8278 observer.disconnect();
8279 };
8280 }
8281 }, [prefetch]);
8282 React8.useEffect(() => {
8283 if (maybePrefetch) {
8284 let id = setTimeout(() => {
8285 setShouldPrefetch(true);
8286 }, 100);
8287 return () => {
8288 clearTimeout(id);
8289 };
8290 }
8291 }, [maybePrefetch]);
8292 let setIntent = () => {
8293 setMaybePrefetch(true);
8294 };
8295 let cancelIntent = () => {
8296 setMaybePrefetch(false);
8297 setShouldPrefetch(false);
8298 };
8299 if (!frameworkContext) {
8300 return [false, ref, {}];
8301 }
8302 if (prefetch !== "intent") {
8303 return [shouldPrefetch, ref, {}];
8304 }
8305 return [
8306 shouldPrefetch,
8307 ref,
8308 {
8309 onFocus: composeEventHandlers(onFocus, setIntent),
8310 onBlur: composeEventHandlers(onBlur, cancelIntent),
8311 onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
8312 onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
8313 onTouchStart: composeEventHandlers(onTouchStart, setIntent)
8314 }
8315 ];
8316}
8317function composeEventHandlers(theirHandler, ourHandler) {
8318 return (event) => {
8319 theirHandler && theirHandler(event);
8320 if (!event.defaultPrevented) {
8321 ourHandler(event);
8322 }
8323 };
8324}
8325function getActiveMatches(matches, errors, isSpaMode) {
8326 if (isSpaMode && !isHydrated) {
8327 return [matches[0]];
8328 }
8329 if (errors) {
8330 let errorIdx = matches.findIndex((m) => errors[m.route.id] !== void 0);
8331 return matches.slice(0, errorIdx + 1);
8332 }
8333 return matches;
8334}
8335var CRITICAL_CSS_DATA_ATTRIBUTE = "data-react-router-critical-css";
8336function Links() {
8337 let { isSpaMode, manifest, routeModules, criticalCss } = useFrameworkContext();
8338 let { errors, matches: routerMatches } = useDataRouterStateContext();
8339 let matches = getActiveMatches(routerMatches, errors, isSpaMode);
8340 let keyedLinks = React8.useMemo(
8341 () => getKeyedLinksForMatches(matches, routeModules, manifest),
8342 [matches, routeModules, manifest]
8343 );
8344 return /* @__PURE__ */ React8.createElement(React8.Fragment, null, typeof criticalCss === "string" ? /* @__PURE__ */ React8.createElement(
8345 "style",
8346 {
8347 ...{ [CRITICAL_CSS_DATA_ATTRIBUTE]: "" },
8348 dangerouslySetInnerHTML: { __html: criticalCss }
8349 }
8350 ) : null, typeof criticalCss === "object" ? /* @__PURE__ */ React8.createElement(
8351 "link",
8352 {
8353 ...{ [CRITICAL_CSS_DATA_ATTRIBUTE]: "" },
8354 rel: "stylesheet",
8355 href: criticalCss.href
8356 }
8357 ) : null, keyedLinks.map(
8358 ({ key, link }) => isPageLinkDescriptor(link) ? /* @__PURE__ */ React8.createElement(PrefetchPageLinks, { key, ...link }) : /* @__PURE__ */ React8.createElement("link", { key, ...link })
8359 ));
8360}
8361function PrefetchPageLinks({ page, ...linkProps }) {
8362 let { router } = useDataRouterContext2();
8363 let matches = React8.useMemo(
8364 () => matchRoutes(router.routes, page, router.basename),
8365 [router.routes, page, router.basename]
8366 );
8367 if (!matches) {
8368 return null;
8369 }
8370 return /* @__PURE__ */ React8.createElement(PrefetchPageLinksImpl, { page, matches, ...linkProps });
8371}
8372function useKeyedPrefetchLinks(matches) {
8373 let { manifest, routeModules } = useFrameworkContext();
8374 let [keyedPrefetchLinks, setKeyedPrefetchLinks] = React8.useState([]);
8375 React8.useEffect(() => {
8376 let interrupted = false;
8377 void getKeyedPrefetchLinks(matches, manifest, routeModules).then(
8378 (links) => {
8379 if (!interrupted) {
8380 setKeyedPrefetchLinks(links);
8381 }
8382 }
8383 );
8384 return () => {
8385 interrupted = true;
8386 };
8387 }, [matches, manifest, routeModules]);
8388 return keyedPrefetchLinks;
8389}
8390function PrefetchPageLinksImpl({
8391 page,
8392 matches: nextMatches,
8393 ...linkProps
8394}) {
8395 let location = useLocation();
8396 let { manifest, routeModules } = useFrameworkContext();
8397 let { basename } = useDataRouterContext2();
8398 let { loaderData, matches } = useDataRouterStateContext();
8399 let newMatchesForData = React8.useMemo(
8400 () => getNewMatchesForLinks(
8401 page,
8402 nextMatches,
8403 matches,
8404 manifest,
8405 location,
8406 "data"
8407 ),
8408 [page, nextMatches, matches, manifest, location]
8409 );
8410 let newMatchesForAssets = React8.useMemo(
8411 () => getNewMatchesForLinks(
8412 page,
8413 nextMatches,
8414 matches,
8415 manifest,
8416 location,
8417 "assets"
8418 ),
8419 [page, nextMatches, matches, manifest, location]
8420 );
8421 let dataHrefs = React8.useMemo(() => {
8422 if (page === location.pathname + location.search + location.hash) {
8423 return [];
8424 }
8425 let routesParams = /* @__PURE__ */ new Set();
8426 let foundOptOutRoute = false;
8427 nextMatches.forEach((m) => {
8428 let manifestRoute = manifest.routes[m.route.id];
8429 if (!manifestRoute || !manifestRoute.hasLoader) {
8430 return;
8431 }
8432 if (!newMatchesForData.some((m2) => m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) {
8433 foundOptOutRoute = true;
8434 } else if (manifestRoute.hasClientLoader) {
8435 foundOptOutRoute = true;
8436 } else {
8437 routesParams.add(m.route.id);
8438 }
8439 });
8440 if (routesParams.size === 0) {
8441 return [];
8442 }
8443 let url = singleFetchUrl(page, basename, "data");
8444 if (foundOptOutRoute && routesParams.size > 0) {
8445 url.searchParams.set(
8446 "_routes",
8447 nextMatches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
8448 );
8449 }
8450 return [url.pathname + url.search];
8451 }, [
8452 basename,
8453 loaderData,
8454 location,
8455 manifest,
8456 newMatchesForData,
8457 nextMatches,
8458 page,
8459 routeModules
8460 ]);
8461 let moduleHrefs = React8.useMemo(
8462 () => getModuleLinkHrefs(newMatchesForAssets, manifest),
8463 [newMatchesForAssets, manifest]
8464 );
8465 let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
8466 return /* @__PURE__ */ React8.createElement(React8.Fragment, null, dataHrefs.map((href) => /* @__PURE__ */ React8.createElement("link", { key: href, rel: "prefetch", as: "fetch", href, ...linkProps })), moduleHrefs.map((href) => /* @__PURE__ */ React8.createElement("link", { key: href, rel: "modulepreload", href, ...linkProps })), keyedPrefetchLinks.map(({ key, link }) => (
8467 // these don't spread `linkProps` because they are full link descriptors
8468 // already with their own props
8469 /* @__PURE__ */ React8.createElement("link", { key, ...link })
8470 )));
8471}
8472function Meta() {
8473 let { isSpaMode, routeModules } = useFrameworkContext();
8474 let {
8475 errors,
8476 matches: routerMatches,
8477 loaderData
8478 } = useDataRouterStateContext();
8479 let location = useLocation();
8480 let _matches = getActiveMatches(routerMatches, errors, isSpaMode);
8481 let error = null;
8482 if (errors) {
8483 error = errors[_matches[_matches.length - 1].route.id];
8484 }
8485 let meta = [];
8486 let leafMeta = null;
8487 let matches = [];
8488 for (let i = 0; i < _matches.length; i++) {
8489 let _match = _matches[i];
8490 let routeId = _match.route.id;
8491 let data2 = loaderData[routeId];
8492 let params = _match.params;
8493 let routeModule = routeModules[routeId];
8494 let routeMeta = [];
8495 let match = {
8496 id: routeId,
8497 data: data2,
8498 meta: [],
8499 params: _match.params,
8500 pathname: _match.pathname,
8501 handle: _match.route.handle,
8502 error
8503 };
8504 matches[i] = match;
8505 if (routeModule?.meta) {
8506 routeMeta = typeof routeModule.meta === "function" ? routeModule.meta({
8507 data: data2,
8508 params,
8509 location,
8510 matches,
8511 error
8512 }) : Array.isArray(routeModule.meta) ? [...routeModule.meta] : routeModule.meta;
8513 } else if (leafMeta) {
8514 routeMeta = [...leafMeta];
8515 }
8516 routeMeta = routeMeta || [];
8517 if (!Array.isArray(routeMeta)) {
8518 throw new Error(
8519 "The route at " + _match.route.path + " returns an invalid value. All route meta functions must return an array of meta objects.\n\nTo reference the meta function API, see https://remix.run/route/meta"
8520 );
8521 }
8522 match.meta = routeMeta;
8523 matches[i] = match;
8524 meta = [...routeMeta];
8525 leafMeta = meta;
8526 }
8527 return /* @__PURE__ */ React8.createElement(React8.Fragment, null, meta.flat().map((metaProps) => {
8528 if (!metaProps) {
8529 return null;
8530 }
8531 if ("tagName" in metaProps) {
8532 let { tagName, ...rest } = metaProps;
8533 if (!isValidMetaTag(tagName)) {
8534 console.warn(
8535 `A meta object uses an invalid tagName: ${tagName}. Expected either 'link' or 'meta'`
8536 );
8537 return null;
8538 }
8539 let Comp = tagName;
8540 return /* @__PURE__ */ React8.createElement(Comp, { key: JSON.stringify(rest), ...rest });
8541 }
8542 if ("title" in metaProps) {
8543 return /* @__PURE__ */ React8.createElement("title", { key: "title" }, String(metaProps.title));
8544 }
8545 if ("charset" in metaProps) {
8546 metaProps.charSet ?? (metaProps.charSet = metaProps.charset);
8547 delete metaProps.charset;
8548 }
8549 if ("charSet" in metaProps && metaProps.charSet != null) {
8550 return typeof metaProps.charSet === "string" ? /* @__PURE__ */ React8.createElement("meta", { key: "charSet", charSet: metaProps.charSet }) : null;
8551 }
8552 if ("script:ld+json" in metaProps) {
8553 try {
8554 let json = JSON.stringify(metaProps["script:ld+json"]);
8555 return /* @__PURE__ */ React8.createElement(
8556 "script",
8557 {
8558 key: `script:ld+json:${json}`,
8559 type: "application/ld+json",
8560 dangerouslySetInnerHTML: { __html: json }
8561 }
8562 );
8563 } catch (err) {
8564 return null;
8565 }
8566 }
8567 return /* @__PURE__ */ React8.createElement("meta", { key: JSON.stringify(metaProps), ...metaProps });
8568 }));
8569}
8570function isValidMetaTag(tagName) {
8571 return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
8572}
8573var isHydrated = false;
8574function Scripts(scriptProps) {
8575 let {
8576 manifest,
8577 serverHandoffString,
8578 isSpaMode,
8579 renderMeta,
8580 routeDiscovery,
8581 ssr
8582 } = useFrameworkContext();
8583 let { router, static: isStatic, staticContext } = useDataRouterContext2();
8584 let { matches: routerMatches } = useDataRouterStateContext();
8585 let isRSCRouterContext = useIsRSCRouterContext();
8586 let enableFogOfWar = isFogOfWarEnabled(routeDiscovery, ssr);
8587 if (renderMeta) {
8588 renderMeta.didRenderScripts = true;
8589 }
8590 let matches = getActiveMatches(routerMatches, null, isSpaMode);
8591 React8.useEffect(() => {
8592 isHydrated = true;
8593 }, []);
8594 let initialScripts = React8.useMemo(() => {
8595 if (isRSCRouterContext) {
8596 return null;
8597 }
8598 let streamScript = "window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());";
8599 let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};${streamScript}` : " ";
8600 let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
8601${matches.map((match, routeIndex) => {
8602 let routeVarName = `route${routeIndex}`;
8603 let manifestEntry = manifest.routes[match.route.id];
8604 invariant2(manifestEntry, `Route ${match.route.id} not found in manifest`);
8605 let {
8606 clientActionModule,
8607 clientLoaderModule,
8608 clientMiddlewareModule,
8609 hydrateFallbackModule,
8610 module
8611 } = manifestEntry;
8612 let chunks = [
8613 ...clientActionModule ? [
8614 {
8615 module: clientActionModule,
8616 varName: `${routeVarName}_clientAction`
8617 }
8618 ] : [],
8619 ...clientLoaderModule ? [
8620 {
8621 module: clientLoaderModule,
8622 varName: `${routeVarName}_clientLoader`
8623 }
8624 ] : [],
8625 ...clientMiddlewareModule ? [
8626 {
8627 module: clientMiddlewareModule,
8628 varName: `${routeVarName}_clientMiddleware`
8629 }
8630 ] : [],
8631 ...hydrateFallbackModule ? [
8632 {
8633 module: hydrateFallbackModule,
8634 varName: `${routeVarName}_HydrateFallback`
8635 }
8636 ] : [],
8637 { module, varName: `${routeVarName}_main` }
8638 ];
8639 if (chunks.length === 1) {
8640 return `import * as ${routeVarName} from ${JSON.stringify(module)};`;
8641 }
8642 let chunkImportsSnippet = chunks.map((chunk) => `import * as ${chunk.varName} from "${chunk.module}";`).join("\n");
8643 let mergedChunksSnippet = `const ${routeVarName} = {${chunks.map((chunk) => `...${chunk.varName}`).join(",")}};`;
8644 return [chunkImportsSnippet, mergedChunksSnippet].join("\n");
8645 }).join("\n")}
8646 ${enableFogOfWar ? (
8647 // Inline a minimal manifest with the SSR matches
8648 `window.__reactRouterManifest = ${JSON.stringify(
8649 getPartialManifest(manifest, router),
8650 null,
8651 2
8652 )};`
8653 ) : ""}
8654 window.__reactRouterRouteModules = {${matches.map((match, index) => `${JSON.stringify(match.route.id)}:route${index}`).join(",")}};
8655
8656import(${JSON.stringify(manifest.entry.module)});`;
8657 return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
8658 "script",
8659 {
8660 ...scriptProps,
8661 suppressHydrationWarning: true,
8662 dangerouslySetInnerHTML: createHtml(contextScript),
8663 type: void 0
8664 }
8665 ), /* @__PURE__ */ React8.createElement(
8666 "script",
8667 {
8668 ...scriptProps,
8669 suppressHydrationWarning: true,
8670 dangerouslySetInnerHTML: createHtml(routeModulesScript),
8671 type: "module",
8672 async: true
8673 }
8674 ));
8675 }, []);
8676 let preloads = isHydrated || isRSCRouterContext ? [] : dedupe(
8677 manifest.entry.imports.concat(
8678 getModuleLinkHrefs(matches, manifest, {
8679 includeHydrateFallback: true
8680 })
8681 )
8682 );
8683 let sri = typeof manifest.sri === "object" ? manifest.sri : {};
8684 warnOnce(
8685 !isRSCRouterContext,
8686 "The <Scripts /> element is a no-op when using RSC and can be safely removed."
8687 );
8688 return isHydrated || isRSCRouterContext ? null : /* @__PURE__ */ React8.createElement(React8.Fragment, null, typeof manifest.sri === "object" ? /* @__PURE__ */ React8.createElement(
8689 "script",
8690 {
8691 "rr-importmap": "",
8692 type: "importmap",
8693 suppressHydrationWarning: true,
8694 dangerouslySetInnerHTML: {
8695 __html: JSON.stringify({
8696 integrity: sri
8697 })
8698 }
8699 }
8700 ) : null, !enableFogOfWar ? /* @__PURE__ */ React8.createElement(
8701 "link",
8702 {
8703 rel: "modulepreload",
8704 href: manifest.url,
8705 crossOrigin: scriptProps.crossOrigin,
8706 integrity: sri[manifest.url],
8707 suppressHydrationWarning: true
8708 }
8709 ) : null, /* @__PURE__ */ React8.createElement(
8710 "link",
8711 {
8712 rel: "modulepreload",
8713 href: manifest.entry.module,
8714 crossOrigin: scriptProps.crossOrigin,
8715 integrity: sri[manifest.entry.module],
8716 suppressHydrationWarning: true
8717 }
8718 ), preloads.map((path) => /* @__PURE__ */ React8.createElement(
8719 "link",
8720 {
8721 key: path,
8722 rel: "modulepreload",
8723 href: path,
8724 crossOrigin: scriptProps.crossOrigin,
8725 integrity: sri[path],
8726 suppressHydrationWarning: true
8727 }
8728 )), initialScripts);
8729}
8730function dedupe(array) {
8731 return [...new Set(array)];
8732}
8733function mergeRefs(...refs) {
8734 return (value) => {
8735 refs.forEach((ref) => {
8736 if (typeof ref === "function") {
8737 ref(value);
8738 } else if (ref != null) {
8739 ref.current = value;
8740 }
8741 });
8742 };
8743}
8744
8745// lib/dom/ssr/errorBoundaries.tsx
8746var RemixErrorBoundary = class extends React9.Component {
8747 constructor(props) {
8748 super(props);
8749 this.state = { error: props.error || null, location: props.location };
8750 }
8751 static getDerivedStateFromError(error) {
8752 return { error };
8753 }
8754 static getDerivedStateFromProps(props, state) {
8755 if (state.location !== props.location) {
8756 return { error: props.error || null, location: props.location };
8757 }
8758 return { error: props.error || state.error, location: state.location };
8759 }
8760 render() {
8761 if (this.state.error) {
8762 return /* @__PURE__ */ React9.createElement(
8763 RemixRootDefaultErrorBoundary,
8764 {
8765 error: this.state.error,
8766 isOutsideRemixApp: true
8767 }
8768 );
8769 } else {
8770 return this.props.children;
8771 }
8772 }
8773};
8774function RemixRootDefaultErrorBoundary({
8775 error,
8776 isOutsideRemixApp
8777}) {
8778 console.error(error);
8779 let heyDeveloper = /* @__PURE__ */ React9.createElement(
8780 "script",
8781 {
8782 dangerouslySetInnerHTML: {
8783 __html: `
8784 console.log(
8785 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this when your app throws errors. Check out https://reactrouter.com/how-to/error-boundary for more information."
8786 );
8787 `
8788 }
8789 }
8790 );
8791 if (isRouteErrorResponse(error)) {
8792 return /* @__PURE__ */ React9.createElement(BoundaryShell, { title: "Unhandled Thrown Response!" }, /* @__PURE__ */ React9.createElement("h1", { style: { fontSize: "24px" } }, error.status, " ", error.statusText), ENABLE_DEV_WARNINGS ? heyDeveloper : null);
8793 }
8794 let errorInstance;
8795 if (error instanceof Error) {
8796 errorInstance = error;
8797 } else {
8798 let errorString = error == null ? "Unknown Error" : typeof error === "object" && "toString" in error ? error.toString() : JSON.stringify(error);
8799 errorInstance = new Error(errorString);
8800 }
8801 return /* @__PURE__ */ React9.createElement(
8802 BoundaryShell,
8803 {
8804 title: "Application Error!",
8805 isOutsideRemixApp
8806 },
8807 /* @__PURE__ */ React9.createElement("h1", { style: { fontSize: "24px" } }, "Application Error"),
8808 /* @__PURE__ */ React9.createElement(
8809 "pre",
8810 {
8811 style: {
8812 padding: "2rem",
8813 background: "hsla(10, 50%, 50%, 0.1)",
8814 color: "red",
8815 overflow: "auto"
8816 }
8817 },
8818 errorInstance.stack
8819 ),
8820 heyDeveloper
8821 );
8822}
8823function BoundaryShell({
8824 title,
8825 renderScripts,
8826 isOutsideRemixApp,
8827 children
8828}) {
8829 let { routeModules } = useFrameworkContext();
8830 if (routeModules.root?.Layout && !isOutsideRemixApp) {
8831 return children;
8832 }
8833 return /* @__PURE__ */ React9.createElement("html", { lang: "en" }, /* @__PURE__ */ React9.createElement("head", null, /* @__PURE__ */ React9.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ React9.createElement(
8834 "meta",
8835 {
8836 name: "viewport",
8837 content: "width=device-width,initial-scale=1,viewport-fit=cover"
8838 }
8839 ), /* @__PURE__ */ React9.createElement("title", null, title)), /* @__PURE__ */ React9.createElement("body", null, /* @__PURE__ */ React9.createElement("main", { style: { fontFamily: "system-ui, sans-serif", padding: "2rem" } }, children, renderScripts ? /* @__PURE__ */ React9.createElement(Scripts, null) : null)));
8840}
8841
8842// lib/dom/lib.tsx
8843import * as React10 from "react";
8844var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
8845try {
8846 if (isBrowser) {
8847 window.__reactRouterVersion = // @ts-expect-error
8848 "7.7.1";
8849 }
8850} catch (e) {
8851}
8852function createBrowserRouter(routes, opts) {
8853 return createRouter({
8854 basename: opts?.basename,
8855 unstable_getContext: opts?.unstable_getContext,
8856 future: opts?.future,
8857 history: createBrowserHistory({ window: opts?.window }),
8858 hydrationData: opts?.hydrationData || parseHydrationData(),
8859 routes,
8860 mapRouteProperties,
8861 hydrationRouteProperties,
8862 dataStrategy: opts?.dataStrategy,
8863 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation,
8864 window: opts?.window
8865 }).initialize();
8866}
8867function createHashRouter(routes, opts) {
8868 return createRouter({
8869 basename: opts?.basename,
8870 unstable_getContext: opts?.unstable_getContext,
8871 future: opts?.future,
8872 history: createHashHistory({ window: opts?.window }),
8873 hydrationData: opts?.hydrationData || parseHydrationData(),
8874 routes,
8875 mapRouteProperties,
8876 hydrationRouteProperties,
8877 dataStrategy: opts?.dataStrategy,
8878 patchRoutesOnNavigation: opts?.patchRoutesOnNavigation,
8879 window: opts?.window
8880 }).initialize();
8881}
8882function parseHydrationData() {
8883 let state = window?.__staticRouterHydrationData;
8884 if (state && state.errors) {
8885 state = {
8886 ...state,
8887 errors: deserializeErrors(state.errors)
8888 };
8889 }
8890 return state;
8891}
8892function deserializeErrors(errors) {
8893 if (!errors) return null;
8894 let entries = Object.entries(errors);
8895 let serialized = {};
8896 for (let [key, val] of entries) {
8897 if (val && val.__type === "RouteErrorResponse") {
8898 serialized[key] = new ErrorResponseImpl(
8899 val.status,
8900 val.statusText,
8901 val.data,
8902 val.internal === true
8903 );
8904 } else if (val && val.__type === "Error") {
8905 if (val.__subType) {
8906 let ErrorConstructor = window[val.__subType];
8907 if (typeof ErrorConstructor === "function") {
8908 try {
8909 let error = new ErrorConstructor(val.message);
8910 error.stack = "";
8911 serialized[key] = error;
8912 } catch (e) {
8913 }
8914 }
8915 }
8916 if (serialized[key] == null) {
8917 let error = new Error(val.message);
8918 error.stack = "";
8919 serialized[key] = error;
8920 }
8921 } else {
8922 serialized[key] = val;
8923 }
8924 }
8925 return serialized;
8926}
8927function BrowserRouter({
8928 basename,
8929 children,
8930 window: window2
8931}) {
8932 let historyRef = React10.useRef();
8933 if (historyRef.current == null) {
8934 historyRef.current = createBrowserHistory({ window: window2, v5Compat: true });
8935 }
8936 let history = historyRef.current;
8937 let [state, setStateImpl] = React10.useState({
8938 action: history.action,
8939 location: history.location
8940 });
8941 let setState = React10.useCallback(
8942 (newState) => {
8943 React10.startTransition(() => setStateImpl(newState));
8944 },
8945 [setStateImpl]
8946 );
8947 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
8948 return /* @__PURE__ */ React10.createElement(
8949 Router,
8950 {
8951 basename,
8952 children,
8953 location: state.location,
8954 navigationType: state.action,
8955 navigator: history
8956 }
8957 );
8958}
8959function HashRouter({ basename, children, window: window2 }) {
8960 let historyRef = React10.useRef();
8961 if (historyRef.current == null) {
8962 historyRef.current = createHashHistory({ window: window2, v5Compat: true });
8963 }
8964 let history = historyRef.current;
8965 let [state, setStateImpl] = React10.useState({
8966 action: history.action,
8967 location: history.location
8968 });
8969 let setState = React10.useCallback(
8970 (newState) => {
8971 React10.startTransition(() => setStateImpl(newState));
8972 },
8973 [setStateImpl]
8974 );
8975 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
8976 return /* @__PURE__ */ React10.createElement(
8977 Router,
8978 {
8979 basename,
8980 children,
8981 location: state.location,
8982 navigationType: state.action,
8983 navigator: history
8984 }
8985 );
8986}
8987function HistoryRouter({
8988 basename,
8989 children,
8990 history
8991}) {
8992 let [state, setStateImpl] = React10.useState({
8993 action: history.action,
8994 location: history.location
8995 });
8996 let setState = React10.useCallback(
8997 (newState) => {
8998 React10.startTransition(() => setStateImpl(newState));
8999 },
9000 [setStateImpl]
9001 );
9002 React10.useLayoutEffect(() => history.listen(setState), [history, setState]);
9003 return /* @__PURE__ */ React10.createElement(
9004 Router,
9005 {
9006 basename,
9007 children,
9008 location: state.location,
9009 navigationType: state.action,
9010 navigator: history
9011 }
9012 );
9013}
9014HistoryRouter.displayName = "unstable_HistoryRouter";
9015var ABSOLUTE_URL_REGEX2 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
9016var Link = React10.forwardRef(
9017 function LinkWithRef({
9018 onClick,
9019 discover = "render",
9020 prefetch = "none",
9021 relative,
9022 reloadDocument,
9023 replace: replace2,
9024 state,
9025 target,
9026 to,
9027 preventScrollReset,
9028 viewTransition,
9029 ...rest
9030 }, forwardedRef) {
9031 let { basename } = React10.useContext(NavigationContext);
9032 let isAbsolute = typeof to === "string" && ABSOLUTE_URL_REGEX2.test(to);
9033 let absoluteHref;
9034 let isExternal = false;
9035 if (typeof to === "string" && isAbsolute) {
9036 absoluteHref = to;
9037 if (isBrowser) {
9038 try {
9039 let currentUrl = new URL(window.location.href);
9040 let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
9041 let path = stripBasename(targetUrl.pathname, basename);
9042 if (targetUrl.origin === currentUrl.origin && path != null) {
9043 to = path + targetUrl.search + targetUrl.hash;
9044 } else {
9045 isExternal = true;
9046 }
9047 } catch (e) {
9048 warning(
9049 false,
9050 `<Link to="${to}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`
9051 );
9052 }
9053 }
9054 }
9055 let href = useHref(to, { relative });
9056 let [shouldPrefetch, prefetchRef, prefetchHandlers] = usePrefetchBehavior(
9057 prefetch,
9058 rest
9059 );
9060 let internalOnClick = useLinkClickHandler(to, {
9061 replace: replace2,
9062 state,
9063 target,
9064 preventScrollReset,
9065 relative,
9066 viewTransition
9067 });
9068 function handleClick(event) {
9069 if (onClick) onClick(event);
9070 if (!event.defaultPrevented) {
9071 internalOnClick(event);
9072 }
9073 }
9074 let link = (
9075 // eslint-disable-next-line jsx-a11y/anchor-has-content
9076 /* @__PURE__ */ React10.createElement(
9077 "a",
9078 {
9079 ...rest,
9080 ...prefetchHandlers,
9081 href: absoluteHref || href,
9082 onClick: isExternal || reloadDocument ? onClick : handleClick,
9083 ref: mergeRefs(forwardedRef, prefetchRef),
9084 target,
9085 "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
9086 }
9087 )
9088 );
9089 return shouldPrefetch && !isAbsolute ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, link, /* @__PURE__ */ React10.createElement(PrefetchPageLinks, { page: href })) : link;
9090 }
9091);
9092Link.displayName = "Link";
9093var NavLink = React10.forwardRef(
9094 function NavLinkWithRef({
9095 "aria-current": ariaCurrentProp = "page",
9096 caseSensitive = false,
9097 className: classNameProp = "",
9098 end = false,
9099 style: styleProp,
9100 to,
9101 viewTransition,
9102 children,
9103 ...rest
9104 }, ref) {
9105 let path = useResolvedPath(to, { relative: rest.relative });
9106 let location = useLocation();
9107 let routerState = React10.useContext(DataRouterStateContext);
9108 let { navigator, basename } = React10.useContext(NavigationContext);
9109 let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
9110 // eslint-disable-next-line react-hooks/rules-of-hooks
9111 useViewTransitionState(path) && viewTransition === true;
9112 let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
9113 let locationPathname = location.pathname;
9114 let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
9115 if (!caseSensitive) {
9116 locationPathname = locationPathname.toLowerCase();
9117 nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
9118 toPathname = toPathname.toLowerCase();
9119 }
9120 if (nextLocationPathname && basename) {
9121 nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
9122 }
9123 const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
9124 let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
9125 let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
9126 let renderProps = {
9127 isActive,
9128 isPending,
9129 isTransitioning
9130 };
9131 let ariaCurrent = isActive ? ariaCurrentProp : void 0;
9132 let className;
9133 if (typeof classNameProp === "function") {
9134 className = classNameProp(renderProps);
9135 } else {
9136 className = [
9137 classNameProp,
9138 isActive ? "active" : null,
9139 isPending ? "pending" : null,
9140 isTransitioning ? "transitioning" : null
9141 ].filter(Boolean).join(" ");
9142 }
9143 let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
9144 return /* @__PURE__ */ React10.createElement(
9145 Link,
9146 {
9147 ...rest,
9148 "aria-current": ariaCurrent,
9149 className,
9150 ref,
9151 style,
9152 to,
9153 viewTransition
9154 },
9155 typeof children === "function" ? children(renderProps) : children
9156 );
9157 }
9158);
9159NavLink.displayName = "NavLink";
9160var Form = React10.forwardRef(
9161 ({
9162 discover = "render",
9163 fetcherKey,
9164 navigate,
9165 reloadDocument,
9166 replace: replace2,
9167 state,
9168 method = defaultMethod,
9169 action,
9170 onSubmit,
9171 relative,
9172 preventScrollReset,
9173 viewTransition,
9174 ...props
9175 }, forwardedRef) => {
9176 let submit = useSubmit();
9177 let formAction = useFormAction(action, { relative });
9178 let formMethod = method.toLowerCase() === "get" ? "get" : "post";
9179 let isAbsolute = typeof action === "string" && ABSOLUTE_URL_REGEX2.test(action);
9180 let submitHandler = (event) => {
9181 onSubmit && onSubmit(event);
9182 if (event.defaultPrevented) return;
9183 event.preventDefault();
9184 let submitter = event.nativeEvent.submitter;
9185 let submitMethod = submitter?.getAttribute("formmethod") || method;
9186 submit(submitter || event.currentTarget, {
9187 fetcherKey,
9188 method: submitMethod,
9189 navigate,
9190 replace: replace2,
9191 state,
9192 relative,
9193 preventScrollReset,
9194 viewTransition
9195 });
9196 };
9197 return /* @__PURE__ */ React10.createElement(
9198 "form",
9199 {
9200 ref: forwardedRef,
9201 method: formMethod,
9202 action: formAction,
9203 onSubmit: reloadDocument ? onSubmit : submitHandler,
9204 ...props,
9205 "data-discover": !isAbsolute && discover === "render" ? "true" : void 0
9206 }
9207 );
9208 }
9209);
9210Form.displayName = "Form";
9211function ScrollRestoration({
9212 getKey,
9213 storageKey,
9214 ...props
9215}) {
9216 let remixContext = React10.useContext(FrameworkContext);
9217 let { basename } = React10.useContext(NavigationContext);
9218 let location = useLocation();
9219 let matches = useMatches();
9220 useScrollRestoration({ getKey, storageKey });
9221 let ssrKey = React10.useMemo(
9222 () => {
9223 if (!remixContext || !getKey) return null;
9224 let userKey = getScrollRestorationKey(
9225 location,
9226 matches,
9227 basename,
9228 getKey
9229 );
9230 return userKey !== location.key ? userKey : null;
9231 },
9232 // Nah, we only need this the first time for the SSR render
9233 // eslint-disable-next-line react-hooks/exhaustive-deps
9234 []
9235 );
9236 if (!remixContext || remixContext.isSpaMode) {
9237 return null;
9238 }
9239 let restoreScroll = ((storageKey2, restoreKey) => {
9240 if (!window.history.state || !window.history.state.key) {
9241 let key = Math.random().toString(32).slice(2);
9242 window.history.replaceState({ key }, "");
9243 }
9244 try {
9245 let positions = JSON.parse(sessionStorage.getItem(storageKey2) || "{}");
9246 let storedY = positions[restoreKey || window.history.state.key];
9247 if (typeof storedY === "number") {
9248 window.scrollTo(0, storedY);
9249 }
9250 } catch (error) {
9251 console.error(error);
9252 sessionStorage.removeItem(storageKey2);
9253 }
9254 }).toString();
9255 return /* @__PURE__ */ React10.createElement(
9256 "script",
9257 {
9258 ...props,
9259 suppressHydrationWarning: true,
9260 dangerouslySetInnerHTML: {
9261 __html: `(${restoreScroll})(${JSON.stringify(
9262 storageKey || SCROLL_RESTORATION_STORAGE_KEY
9263 )}, ${JSON.stringify(ssrKey)})`
9264 }
9265 }
9266 );
9267}
9268ScrollRestoration.displayName = "ScrollRestoration";
9269function getDataRouterConsoleError2(hookName) {
9270 return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`;
9271}
9272function useDataRouterContext3(hookName) {
9273 let ctx = React10.useContext(DataRouterContext);
9274 invariant(ctx, getDataRouterConsoleError2(hookName));
9275 return ctx;
9276}
9277function useDataRouterState2(hookName) {
9278 let state = React10.useContext(DataRouterStateContext);
9279 invariant(state, getDataRouterConsoleError2(hookName));
9280 return state;
9281}
9282function useLinkClickHandler(to, {
9283 target,
9284 replace: replaceProp,
9285 state,
9286 preventScrollReset,
9287 relative,
9288 viewTransition
9289} = {}) {
9290 let navigate = useNavigate();
9291 let location = useLocation();
9292 let path = useResolvedPath(to, { relative });
9293 return React10.useCallback(
9294 (event) => {
9295 if (shouldProcessLinkClick(event, target)) {
9296 event.preventDefault();
9297 let replace2 = replaceProp !== void 0 ? replaceProp : createPath(location) === createPath(path);
9298 navigate(to, {
9299 replace: replace2,
9300 state,
9301 preventScrollReset,
9302 relative,
9303 viewTransition
9304 });
9305 }
9306 },
9307 [
9308 location,
9309 navigate,
9310 path,
9311 replaceProp,
9312 state,
9313 target,
9314 to,
9315 preventScrollReset,
9316 relative,
9317 viewTransition
9318 ]
9319 );
9320}
9321function useSearchParams(defaultInit) {
9322 warning(
9323 typeof URLSearchParams !== "undefined",
9324 `You cannot use the \`useSearchParams\` hook in a browser that does not support the URLSearchParams API. If you need to support Internet Explorer 11, we recommend you load a polyfill such as https://github.com/ungap/url-search-params.`
9325 );
9326 let defaultSearchParamsRef = React10.useRef(createSearchParams(defaultInit));
9327 let hasSetSearchParamsRef = React10.useRef(false);
9328 let location = useLocation();
9329 let searchParams = React10.useMemo(
9330 () => (
9331 // Only merge in the defaults if we haven't yet called setSearchParams.
9332 // Once we call that we want those to take precedence, otherwise you can't
9333 // remove a param with setSearchParams({}) if it has an initial value
9334 getSearchParamsForLocation(
9335 location.search,
9336 hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current
9337 )
9338 ),
9339 [location.search]
9340 );
9341 let navigate = useNavigate();
9342 let setSearchParams = React10.useCallback(
9343 (nextInit, navigateOptions) => {
9344 const newSearchParams = createSearchParams(
9345 typeof nextInit === "function" ? nextInit(new URLSearchParams(searchParams)) : nextInit
9346 );
9347 hasSetSearchParamsRef.current = true;
9348 navigate("?" + newSearchParams, navigateOptions);
9349 },
9350 [navigate, searchParams]
9351 );
9352 return [searchParams, setSearchParams];
9353}
9354var fetcherId = 0;
9355var getUniqueFetcherId = () => `__${String(++fetcherId)}__`;
9356function useSubmit() {
9357 let { router } = useDataRouterContext3("useSubmit" /* UseSubmit */);
9358 let { basename } = React10.useContext(NavigationContext);
9359 let currentRouteId = useRouteId();
9360 return React10.useCallback(
9361 async (target, options = {}) => {
9362 let { action, method, encType, formData, body } = getFormSubmissionInfo(
9363 target,
9364 basename
9365 );
9366 if (options.navigate === false) {
9367 let key = options.fetcherKey || getUniqueFetcherId();
9368 await router.fetch(key, currentRouteId, options.action || action, {
9369 preventScrollReset: options.preventScrollReset,
9370 formData,
9371 body,
9372 formMethod: options.method || method,
9373 formEncType: options.encType || encType,
9374 flushSync: options.flushSync
9375 });
9376 } else {
9377 await router.navigate(options.action || action, {
9378 preventScrollReset: options.preventScrollReset,
9379 formData,
9380 body,
9381 formMethod: options.method || method,
9382 formEncType: options.encType || encType,
9383 replace: options.replace,
9384 state: options.state,
9385 fromRouteId: currentRouteId,
9386 flushSync: options.flushSync,
9387 viewTransition: options.viewTransition
9388 });
9389 }
9390 },
9391 [router, basename, currentRouteId]
9392 );
9393}
9394function useFormAction(action, { relative } = {}) {
9395 let { basename } = React10.useContext(NavigationContext);
9396 let routeContext = React10.useContext(RouteContext);
9397 invariant(routeContext, "useFormAction must be used inside a RouteContext");
9398 let [match] = routeContext.matches.slice(-1);
9399 let path = { ...useResolvedPath(action ? action : ".", { relative }) };
9400 let location = useLocation();
9401 if (action == null) {
9402 path.search = location.search;
9403 let params = new URLSearchParams(path.search);
9404 let indexValues = params.getAll("index");
9405 let hasNakedIndexParam = indexValues.some((v) => v === "");
9406 if (hasNakedIndexParam) {
9407 params.delete("index");
9408 indexValues.filter((v) => v).forEach((v) => params.append("index", v));
9409 let qs = params.toString();
9410 path.search = qs ? `?${qs}` : "";
9411 }
9412 }
9413 if ((!action || action === ".") && match.route.index) {
9414 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
9415 }
9416 if (basename !== "/") {
9417 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
9418 }
9419 return createPath(path);
9420}
9421function useFetcher({
9422 key
9423} = {}) {
9424 let { router } = useDataRouterContext3("useFetcher" /* UseFetcher */);
9425 let state = useDataRouterState2("useFetcher" /* UseFetcher */);
9426 let fetcherData = React10.useContext(FetchersContext);
9427 let route = React10.useContext(RouteContext);
9428 let routeId = route.matches[route.matches.length - 1]?.route.id;
9429 invariant(fetcherData, `useFetcher must be used inside a FetchersContext`);
9430 invariant(route, `useFetcher must be used inside a RouteContext`);
9431 invariant(
9432 routeId != null,
9433 `useFetcher can only be used on routes that contain a unique "id"`
9434 );
9435 let defaultKey = React10.useId();
9436 let [fetcherKey, setFetcherKey] = React10.useState(key || defaultKey);
9437 if (key && key !== fetcherKey) {
9438 setFetcherKey(key);
9439 }
9440 React10.useEffect(() => {
9441 router.getFetcher(fetcherKey);
9442 return () => router.deleteFetcher(fetcherKey);
9443 }, [router, fetcherKey]);
9444 let load = React10.useCallback(
9445 async (href, opts) => {
9446 invariant(routeId, "No routeId available for fetcher.load()");
9447 await router.fetch(fetcherKey, routeId, href, opts);
9448 },
9449 [fetcherKey, routeId, router]
9450 );
9451 let submitImpl = useSubmit();
9452 let submit = React10.useCallback(
9453 async (target, opts) => {
9454 await submitImpl(target, {
9455 ...opts,
9456 navigate: false,
9457 fetcherKey
9458 });
9459 },
9460 [fetcherKey, submitImpl]
9461 );
9462 let FetcherForm = React10.useMemo(() => {
9463 let FetcherForm2 = React10.forwardRef(
9464 (props, ref) => {
9465 return /* @__PURE__ */ React10.createElement(Form, { ...props, navigate: false, fetcherKey, ref });
9466 }
9467 );
9468 FetcherForm2.displayName = "fetcher.Form";
9469 return FetcherForm2;
9470 }, [fetcherKey]);
9471 let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
9472 let data2 = fetcherData.get(fetcherKey);
9473 let fetcherWithComponents = React10.useMemo(
9474 () => ({
9475 Form: FetcherForm,
9476 submit,
9477 load,
9478 ...fetcher,
9479 data: data2
9480 }),
9481 [FetcherForm, submit, load, fetcher, data2]
9482 );
9483 return fetcherWithComponents;
9484}
9485function useFetchers() {
9486 let state = useDataRouterState2("useFetchers" /* UseFetchers */);
9487 return Array.from(state.fetchers.entries()).map(([key, fetcher]) => ({
9488 ...fetcher,
9489 key
9490 }));
9491}
9492var SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
9493var savedScrollPositions = {};
9494function getScrollRestorationKey(location, matches, basename, getKey) {
9495 let key = null;
9496 if (getKey) {
9497 if (basename !== "/") {
9498 key = getKey(
9499 {
9500 ...location,
9501 pathname: stripBasename(location.pathname, basename) || location.pathname
9502 },
9503 matches
9504 );
9505 } else {
9506 key = getKey(location, matches);
9507 }
9508 }
9509 if (key == null) {
9510 key = location.key;
9511 }
9512 return key;
9513}
9514function useScrollRestoration({
9515 getKey,
9516 storageKey
9517} = {}) {
9518 let { router } = useDataRouterContext3("useScrollRestoration" /* UseScrollRestoration */);
9519 let { restoreScrollPosition, preventScrollReset } = useDataRouterState2(
9520 "useScrollRestoration" /* UseScrollRestoration */
9521 );
9522 let { basename } = React10.useContext(NavigationContext);
9523 let location = useLocation();
9524 let matches = useMatches();
9525 let navigation = useNavigation();
9526 React10.useEffect(() => {
9527 window.history.scrollRestoration = "manual";
9528 return () => {
9529 window.history.scrollRestoration = "auto";
9530 };
9531 }, []);
9532 usePageHide(
9533 React10.useCallback(() => {
9534 if (navigation.state === "idle") {
9535 let key = getScrollRestorationKey(location, matches, basename, getKey);
9536 savedScrollPositions[key] = window.scrollY;
9537 }
9538 try {
9539 sessionStorage.setItem(
9540 storageKey || SCROLL_RESTORATION_STORAGE_KEY,
9541 JSON.stringify(savedScrollPositions)
9542 );
9543 } catch (error) {
9544 warning(
9545 false,
9546 `Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (${error}).`
9547 );
9548 }
9549 window.history.scrollRestoration = "auto";
9550 }, [navigation.state, getKey, basename, location, matches, storageKey])
9551 );
9552 if (typeof document !== "undefined") {
9553 React10.useLayoutEffect(() => {
9554 try {
9555 let sessionPositions = sessionStorage.getItem(
9556 storageKey || SCROLL_RESTORATION_STORAGE_KEY
9557 );
9558 if (sessionPositions) {
9559 savedScrollPositions = JSON.parse(sessionPositions);
9560 }
9561 } catch (e) {
9562 }
9563 }, [storageKey]);
9564 React10.useLayoutEffect(() => {
9565 let disableScrollRestoration = router?.enableScrollRestoration(
9566 savedScrollPositions,
9567 () => window.scrollY,
9568 getKey ? (location2, matches2) => getScrollRestorationKey(location2, matches2, basename, getKey) : void 0
9569 );
9570 return () => disableScrollRestoration && disableScrollRestoration();
9571 }, [router, basename, getKey]);
9572 React10.useLayoutEffect(() => {
9573 if (restoreScrollPosition === false) {
9574 return;
9575 }
9576 if (typeof restoreScrollPosition === "number") {
9577 window.scrollTo(0, restoreScrollPosition);
9578 return;
9579 }
9580 try {
9581 if (location.hash) {
9582 let el = document.getElementById(
9583 decodeURIComponent(location.hash.slice(1))
9584 );
9585 if (el) {
9586 el.scrollIntoView();
9587 return;
9588 }
9589 }
9590 } catch {
9591 warning(
9592 false,
9593 `"${location.hash.slice(
9594 1
9595 )}" is not a decodable element ID. The view will not scroll to it.`
9596 );
9597 }
9598 if (preventScrollReset === true) {
9599 return;
9600 }
9601 window.scrollTo(0, 0);
9602 }, [location, restoreScrollPosition, preventScrollReset]);
9603 }
9604}
9605function useBeforeUnload(callback, options) {
9606 let { capture } = options || {};
9607 React10.useEffect(() => {
9608 let opts = capture != null ? { capture } : void 0;
9609 window.addEventListener("beforeunload", callback, opts);
9610 return () => {
9611 window.removeEventListener("beforeunload", callback, opts);
9612 };
9613 }, [callback, capture]);
9614}
9615function usePageHide(callback, options) {
9616 let { capture } = options || {};
9617 React10.useEffect(() => {
9618 let opts = capture != null ? { capture } : void 0;
9619 window.addEventListener("pagehide", callback, opts);
9620 return () => {
9621 window.removeEventListener("pagehide", callback, opts);
9622 };
9623 }, [callback, capture]);
9624}
9625function usePrompt({
9626 when,
9627 message
9628}) {
9629 let blocker = useBlocker(when);
9630 React10.useEffect(() => {
9631 if (blocker.state === "blocked") {
9632 let proceed = window.confirm(message);
9633 if (proceed) {
9634 setTimeout(blocker.proceed, 0);
9635 } else {
9636 blocker.reset();
9637 }
9638 }
9639 }, [blocker, message]);
9640 React10.useEffect(() => {
9641 if (blocker.state === "blocked" && !when) {
9642 blocker.reset();
9643 }
9644 }, [blocker, when]);
9645}
9646function useViewTransitionState(to, { relative } = {}) {
9647 let vtContext = React10.useContext(ViewTransitionContext);
9648 invariant(
9649 vtContext != null,
9650 "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?"
9651 );
9652 let { basename } = useDataRouterContext3(
9653 "useViewTransitionState" /* useViewTransitionState */
9654 );
9655 let path = useResolvedPath(to, { relative });
9656 if (!vtContext.isTransitioning) {
9657 return false;
9658 }
9659 let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
9660 let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
9661 return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
9662}
9663
9664// lib/dom/server.tsx
9665import * as React11 from "react";
9666function StaticRouter({
9667 basename,
9668 children,
9669 location: locationProp = "/"
9670}) {
9671 if (typeof locationProp === "string") {
9672 locationProp = parsePath(locationProp);
9673 }
9674 let action = "POP" /* Pop */;
9675 let location = {
9676 pathname: locationProp.pathname || "/",
9677 search: locationProp.search || "",
9678 hash: locationProp.hash || "",
9679 state: locationProp.state != null ? locationProp.state : null,
9680 key: locationProp.key || "default"
9681 };
9682 let staticNavigator = getStatelessNavigator();
9683 return /* @__PURE__ */ React11.createElement(
9684 Router,
9685 {
9686 basename,
9687 children,
9688 location,
9689 navigationType: action,
9690 navigator: staticNavigator,
9691 static: true
9692 }
9693 );
9694}
9695function StaticRouterProvider({
9696 context,
9697 router,
9698 hydrate: hydrate2 = true,
9699 nonce
9700}) {
9701 invariant(
9702 router && context,
9703 "You must provide `router` and `context` to <StaticRouterProvider>"
9704 );
9705 let dataRouterContext = {
9706 router,
9707 navigator: getStatelessNavigator(),
9708 static: true,
9709 staticContext: context,
9710 basename: context.basename || "/"
9711 };
9712 let fetchersContext = /* @__PURE__ */ new Map();
9713 let hydrateScript = "";
9714 if (hydrate2 !== false) {
9715 let data2 = {
9716 loaderData: context.loaderData,
9717 actionData: context.actionData,
9718 errors: serializeErrors(context.errors)
9719 };
9720 let json = htmlEscape(JSON.stringify(JSON.stringify(data2)));
9721 hydrateScript = `window.__staticRouterHydrationData = JSON.parse(${json});`;
9722 }
9723 let { state } = dataRouterContext.router;
9724 return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React11.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React11.createElement(FetchersContext.Provider, { value: fetchersContext }, /* @__PURE__ */ React11.createElement(ViewTransitionContext.Provider, { value: { isTransitioning: false } }, /* @__PURE__ */ React11.createElement(
9725 Router,
9726 {
9727 basename: dataRouterContext.basename,
9728 location: state.location,
9729 navigationType: state.historyAction,
9730 navigator: dataRouterContext.navigator,
9731 static: dataRouterContext.static
9732 },
9733 /* @__PURE__ */ React11.createElement(
9734 DataRoutes2,
9735 {
9736 routes: router.routes,
9737 future: router.future,
9738 state
9739 }
9740 )
9741 ))))), hydrateScript ? /* @__PURE__ */ React11.createElement(
9742 "script",
9743 {
9744 suppressHydrationWarning: true,
9745 nonce,
9746 dangerouslySetInnerHTML: { __html: hydrateScript }
9747 }
9748 ) : null);
9749}
9750function DataRoutes2({
9751 routes,
9752 future,
9753 state
9754}) {
9755 return useRoutesImpl(routes, void 0, state, future);
9756}
9757function serializeErrors(errors) {
9758 if (!errors) return null;
9759 let entries = Object.entries(errors);
9760 let serialized = {};
9761 for (let [key, val] of entries) {
9762 if (isRouteErrorResponse(val)) {
9763 serialized[key] = { ...val, __type: "RouteErrorResponse" };
9764 } else if (val instanceof Error) {
9765 serialized[key] = {
9766 message: val.message,
9767 __type: "Error",
9768 // If this is a subclass (i.e., ReferenceError), send up the type so we
9769 // can re-create the same type during hydration.
9770 ...val.name !== "Error" ? {
9771 __subType: val.name
9772 } : {}
9773 };
9774 } else {
9775 serialized[key] = val;
9776 }
9777 }
9778 return serialized;
9779}
9780function getStatelessNavigator() {
9781 return {
9782 createHref,
9783 encodeLocation,
9784 push(to) {
9785 throw new Error(
9786 `You cannot use navigator.push() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(to)})\` somewhere in your app.`
9787 );
9788 },
9789 replace(to) {
9790 throw new Error(
9791 `You cannot use navigator.replace() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${JSON.stringify(to)}, { replace: true })\` somewhere in your app.`
9792 );
9793 },
9794 go(delta) {
9795 throw new Error(
9796 `You cannot use navigator.go() on the server because it is a stateless environment. This error was probably triggered when you did a \`navigate(${delta})\` somewhere in your app.`
9797 );
9798 },
9799 back() {
9800 throw new Error(
9801 `You cannot use navigator.back() on the server because it is a stateless environment.`
9802 );
9803 },
9804 forward() {
9805 throw new Error(
9806 `You cannot use navigator.forward() on the server because it is a stateless environment.`
9807 );
9808 }
9809 };
9810}
9811function createStaticHandler2(routes, opts) {
9812 return createStaticHandler(routes, {
9813 ...opts,
9814 mapRouteProperties
9815 });
9816}
9817function createStaticRouter(routes, context, opts = {}) {
9818 let manifest = {};
9819 let dataRoutes = convertRoutesToDataRoutes(
9820 routes,
9821 mapRouteProperties,
9822 void 0,
9823 manifest
9824 );
9825 let matches = context.matches.map((match) => {
9826 let route = manifest[match.route.id] || match.route;
9827 return {
9828 ...match,
9829 route
9830 };
9831 });
9832 let msg = (method) => `You cannot use router.${method}() on the server because it is a stateless environment`;
9833 return {
9834 get basename() {
9835 return context.basename;
9836 },
9837 get future() {
9838 return {
9839 unstable_middleware: false,
9840 ...opts?.future
9841 };
9842 },
9843 get state() {
9844 return {
9845 historyAction: "POP" /* Pop */,
9846 location: context.location,
9847 matches,
9848 loaderData: context.loaderData,
9849 actionData: context.actionData,
9850 errors: context.errors,
9851 initialized: true,
9852 navigation: IDLE_NAVIGATION,
9853 restoreScrollPosition: null,
9854 preventScrollReset: false,
9855 revalidation: "idle",
9856 fetchers: /* @__PURE__ */ new Map(),
9857 blockers: /* @__PURE__ */ new Map()
9858 };
9859 },
9860 get routes() {
9861 return dataRoutes;
9862 },
9863 get window() {
9864 return void 0;
9865 },
9866 initialize() {
9867 throw msg("initialize");
9868 },
9869 subscribe() {
9870 throw msg("subscribe");
9871 },
9872 enableScrollRestoration() {
9873 throw msg("enableScrollRestoration");
9874 },
9875 navigate() {
9876 throw msg("navigate");
9877 },
9878 fetch() {
9879 throw msg("fetch");
9880 },
9881 revalidate() {
9882 throw msg("revalidate");
9883 },
9884 createHref,
9885 encodeLocation,
9886 getFetcher() {
9887 return IDLE_FETCHER;
9888 },
9889 deleteFetcher() {
9890 throw msg("deleteFetcher");
9891 },
9892 dispose() {
9893 throw msg("dispose");
9894 },
9895 getBlocker() {
9896 return IDLE_BLOCKER;
9897 },
9898 deleteBlocker() {
9899 throw msg("deleteBlocker");
9900 },
9901 patchRoutes() {
9902 throw msg("patchRoutes");
9903 },
9904 _internalFetchControllers: /* @__PURE__ */ new Map(),
9905 _internalSetRoutes() {
9906 throw msg("_internalSetRoutes");
9907 },
9908 _internalSetStateDoNotUseOrYouWillBreakYourApp() {
9909 throw msg("_internalSetStateDoNotUseOrYouWillBreakYourApp");
9910 }
9911 };
9912}
9913function createHref(to) {
9914 return typeof to === "string" ? to : createPath(to);
9915}
9916function encodeLocation(to) {
9917 let href = typeof to === "string" ? to : createPath(to);
9918 href = href.replace(/ $/, "%20");
9919 let encoded = ABSOLUTE_URL_REGEX3.test(href) ? new URL(href) : new URL(href, "http://localhost");
9920 return {
9921 pathname: encoded.pathname,
9922 search: encoded.search,
9923 hash: encoded.hash
9924 };
9925}
9926var ABSOLUTE_URL_REGEX3 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
9927var ESCAPE_LOOKUP2 = {
9928 "&": "\\u0026",
9929 ">": "\\u003e",
9930 "<": "\\u003c",
9931 "\u2028": "\\u2028",
9932 "\u2029": "\\u2029"
9933};
9934var ESCAPE_REGEX2 = /[&><\u2028\u2029]/g;
9935function htmlEscape(str) {
9936 return str.replace(ESCAPE_REGEX2, (match) => ESCAPE_LOOKUP2[match]);
9937}
9938
9939export {
9940 Action,
9941 createBrowserHistory,
9942 invariant,
9943 createPath,
9944 parsePath,
9945 unstable_createContext,
9946 unstable_RouterContextProvider,
9947 convertRoutesToDataRoutes,
9948 matchRoutes,
9949 generatePath,
9950 matchPath,
9951 stripBasename,
9952 resolvePath,
9953 data,
9954 redirect,
9955 redirectDocument,
9956 replace,
9957 ErrorResponseImpl,
9958 isRouteErrorResponse,
9959 IDLE_NAVIGATION,
9960 IDLE_FETCHER,
9961 IDLE_BLOCKER,
9962 createRouter,
9963 createStaticHandler,
9964 getStaticContextFromError,
9965 isDataWithResponseInit,
9966 isResponse,
9967 isRedirectStatusCode,
9968 isRedirectResponse,
9969 isMutationMethod,
9970 DataRouterContext,
9971 DataRouterStateContext,
9972 RSCRouterContext,
9973 ViewTransitionContext,
9974 FetchersContext,
9975 NavigationContext,
9976 LocationContext,
9977 RouteContext,
9978 ENABLE_DEV_WARNINGS,
9979 useHref,
9980 useInRouterContext,
9981 useLocation,
9982 useNavigationType,
9983 useMatch,
9984 useNavigate,
9985 useOutletContext,
9986 useOutlet,
9987 useParams,
9988 useResolvedPath,
9989 useRoutes,
9990 useNavigation,
9991 useRevalidator,
9992 useMatches,
9993 useLoaderData,
9994 useRouteLoaderData,
9995 useActionData,
9996 useRouteError,
9997 useAsyncValue,
9998 useAsyncError,
9999 useBlocker,
10000 warnOnce,
10001 mapRouteProperties,
10002 hydrationRouteProperties,
10003 createMemoryRouter,
10004 RouterProvider,
10005 MemoryRouter,
10006 Navigate,
10007 Outlet,
10008 Route,
10009 Router,
10010 Routes,
10011 Await,
10012 createRoutesFromChildren,
10013 createRoutesFromElements,
10014 renderMatches,
10015 WithComponentProps,
10016 withComponentProps,
10017 WithHydrateFallbackProps,
10018 withHydrateFallbackProps,
10019 WithErrorBoundaryProps,
10020 withErrorBoundaryProps,
10021 createSearchParams,
10022 encode,
10023 createRequestInit,
10024 SingleFetchRedirectSymbol,
10025 SINGLE_FETCH_REDIRECT_STATUS,
10026 NO_BODY_STATUS_CODES,
10027 StreamTransfer,
10028 getTurboStreamSingleFetchDataStrategy,
10029 getSingleFetchDataStrategyImpl,
10030 stripIndexParam,
10031 singleFetchUrl,
10032 decodeViaTurboStream,
10033 RemixErrorBoundary,
10034 createServerRoutes,
10035 createClientRoutesWithHMRRevalidationOptOut,
10036 noActionDefinedError,
10037 createClientRoutes,
10038 shouldHydrateRouteLoader,
10039 getPatchRoutesOnNavigationFunction,
10040 useFogOFWarDiscovery,
10041 getManifestPath,
10042 FrameworkContext,
10043 CRITICAL_CSS_DATA_ATTRIBUTE,
10044 Links,
10045 PrefetchPageLinks,
10046 Meta,
10047 Scripts,
10048 createBrowserRouter,
10049 createHashRouter,
10050 BrowserRouter,
10051 HashRouter,
10052 HistoryRouter,
10053 Link,
10054 NavLink,
10055 Form,
10056 ScrollRestoration,
10057 useLinkClickHandler,
10058 useSearchParams,
10059 useSubmit,
10060 useFormAction,
10061 useFetcher,
10062 useFetchers,
10063 useScrollRestoration,
10064 useBeforeUnload,
10065 usePrompt,
10066 useViewTransitionState,
10067 StaticRouter,
10068 StaticRouterProvider,
10069 createStaticHandler2,
10070 createStaticRouter
10071};