UNPKG

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