UNPKG

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