UNPKG

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