UNPKG

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