INDIE UNPKG

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