UNPKG

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