UNPKG

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