UNPKG

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