UNPKG

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