UNPKG

315 kBJavaScriptView Raw
1/**
2 * react-router v7.0.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: () => createRoutesFromChildren,
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 = true;
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 = true;
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}
5310function renderMatches(matches) {
5311 return _renderMatches(matches);
5312}
5313
5314// lib/dom/lib.tsx
5315var React10 = __toESM(require("react"));
5316
5317// lib/dom/dom.ts
5318var defaultMethod = "get";
5319var defaultEncType = "application/x-www-form-urlencoded";
5320function isHtmlElement(object) {
5321 return object != null && typeof object.tagName === "string";
5322}
5323function isButtonElement(object) {
5324 return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
5325}
5326function isFormElement(object) {
5327 return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
5328}
5329function isInputElement(object) {
5330 return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
5331}
5332function isModifiedEvent(event) {
5333 return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
5334}
5335function shouldProcessLinkClick(event, target) {
5336 return event.button === 0 && // Ignore everything but left clicks
5337 (!target || target === "_self") && // Let browser handle "target=_blank" etc.
5338 !isModifiedEvent(event);
5339}
5340function createSearchParams(init = "") {
5341 return new URLSearchParams(
5342 typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key) => {
5343 let value = init[key];
5344 return memo2.concat(
5345 Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]
5346 );
5347 }, [])
5348 );
5349}
5350function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
5351 let searchParams = createSearchParams(locationSearch);
5352 if (defaultSearchParams) {
5353 defaultSearchParams.forEach((_, key) => {
5354 if (!searchParams.has(key)) {
5355 defaultSearchParams.getAll(key).forEach((value) => {
5356 searchParams.append(key, value);
5357 });
5358 }
5359 });
5360 }
5361 return searchParams;
5362}
5363var _formDataSupportsSubmitter = null;
5364function isFormDataSubmitterSupported() {
5365 if (_formDataSupportsSubmitter === null) {
5366 try {
5367 new FormData(
5368 document.createElement("form"),
5369 // @ts-expect-error if FormData supports the submitter parameter, this will throw
5370 0
5371 );
5372 _formDataSupportsSubmitter = false;
5373 } catch (e) {
5374 _formDataSupportsSubmitter = true;
5375 }
5376 }
5377 return _formDataSupportsSubmitter;
5378}
5379var supportedFormEncTypes = /* @__PURE__ */ new Set([
5380 "application/x-www-form-urlencoded",
5381 "multipart/form-data",
5382 "text/plain"
5383]);
5384function getFormEncType(encType) {
5385 if (encType != null && !supportedFormEncTypes.has(encType)) {
5386 warning(
5387 false,
5388 `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`
5389 );
5390 return null;
5391 }
5392 return encType;
5393}
5394function getFormSubmissionInfo(target, basename) {
5395 let method;
5396 let action;
5397 let encType;
5398 let formData;
5399 let body;
5400 if (isFormElement(target)) {
5401 let attr = target.getAttribute("action");
5402 action = attr ? stripBasename(attr, basename) : null;
5403 method = target.getAttribute("method") || defaultMethod;
5404 encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
5405 formData = new FormData(target);
5406 } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
5407 let form = target.form;
5408 if (form == null) {
5409 throw new Error(
5410 `Cannot submit a <button> or <input type="submit"> without a <form>`
5411 );
5412 }
5413 let attr = target.getAttribute("formaction") || form.getAttribute("action");
5414 action = attr ? stripBasename(attr, basename) : null;
5415 method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
5416 encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
5417 formData = new FormData(form, target);
5418 if (!isFormDataSubmitterSupported()) {
5419 let { name, type, value } = target;
5420 if (type === "image") {
5421 let prefix = name ? `${name}.` : "";
5422 formData.append(`${prefix}x`, "0");
5423 formData.append(`${prefix}y`, "0");
5424 } else if (name) {
5425 formData.append(name, value);
5426 }
5427 }
5428 } else if (isHtmlElement(target)) {
5429 throw new Error(
5430 `Cannot submit element that is not <form>, <button>, or <input type="submit|image">`
5431 );
5432 } else {
5433 method = defaultMethod;
5434 action = null;
5435 encType = defaultEncType;
5436 body = target;
5437 }
5438 if (formData && encType === "text/plain") {
5439 body = formData;
5440 formData = void 0;
5441 }
5442 return { action, method: method.toLowerCase(), encType, formData, body };
5443}
5444
5445// lib/dom/ssr/components.tsx
5446var React9 = __toESM(require("react"));
5447
5448// lib/dom/ssr/invariant.ts
5449function invariant2(value, message) {
5450 if (value === false || value === null || typeof value === "undefined") {
5451 throw new Error(message);
5452 }
5453}
5454
5455// lib/dom/ssr/routeModules.ts
5456async function loadRouteModule(route, routeModulesCache) {
5457 if (route.id in routeModulesCache) {
5458 return routeModulesCache[route.id];
5459 }
5460 try {
5461 let routeModule = await import(
5462 /* @vite-ignore */
5463 /* webpackIgnore: true */
5464 route.module
5465 );
5466 routeModulesCache[route.id] = routeModule;
5467 return routeModule;
5468 } catch (error) {
5469 console.error(
5470 `Error loading route module \`${route.module}\`, reloading page...`
5471 );
5472 console.error(error);
5473 if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
5474 void 0) {
5475 throw error;
5476 }
5477 window.location.reload();
5478 return new Promise(() => {
5479 });
5480 }
5481}
5482
5483// lib/dom/ssr/links.ts
5484function getKeyedLinksForMatches(matches, routeModules, manifest) {
5485 let descriptors = matches.map((match) => {
5486 let module2 = routeModules[match.route.id];
5487 let route = manifest.routes[match.route.id];
5488 return [
5489 route && route.css ? route.css.map((href) => ({ rel: "stylesheet", href })) : [],
5490 module2?.links?.() || []
5491 ];
5492 }).flat(2);
5493 let preloads = getCurrentPageModulePreloadHrefs(matches, manifest);
5494 return dedupeLinkDescriptors(descriptors, preloads);
5495}
5496async function prefetchStyleLinks(route, routeModule) {
5497 if (!route.css && !routeModule.links || !isPreloadSupported()) return;
5498 let descriptors = [];
5499 if (route.css) {
5500 descriptors.push(...route.css.map((href) => ({ rel: "stylesheet", href })));
5501 }
5502 if (routeModule.links) {
5503 descriptors.push(...routeModule.links());
5504 }
5505 if (descriptors.length === 0) return;
5506 let styleLinks = [];
5507 for (let descriptor of descriptors) {
5508 if (!isPageLinkDescriptor(descriptor) && descriptor.rel === "stylesheet") {
5509 styleLinks.push({
5510 ...descriptor,
5511 rel: "preload",
5512 as: "style"
5513 });
5514 }
5515 }
5516 let matchingLinks = styleLinks.filter(
5517 (link) => (!link.media || window.matchMedia(link.media).matches) && !document.querySelector(`link[rel="stylesheet"][href="${link.href}"]`)
5518 );
5519 await Promise.all(matchingLinks.map(prefetchStyleLink));
5520}
5521async function prefetchStyleLink(descriptor) {
5522 return new Promise((resolve) => {
5523 let link = document.createElement("link");
5524 Object.assign(link, descriptor);
5525 function removeLink() {
5526 if (document.head.contains(link)) {
5527 document.head.removeChild(link);
5528 }
5529 }
5530 link.onload = () => {
5531 removeLink();
5532 resolve();
5533 };
5534 link.onerror = () => {
5535 removeLink();
5536 resolve();
5537 };
5538 document.head.appendChild(link);
5539 });
5540}
5541function isPageLinkDescriptor(object) {
5542 return object != null && typeof object.page === "string";
5543}
5544function isHtmlLinkDescriptor(object) {
5545 if (object == null) {
5546 return false;
5547 }
5548 if (object.href == null) {
5549 return object.rel === "preload" && typeof object.imageSrcSet === "string" && typeof object.imageSizes === "string";
5550 }
5551 return typeof object.rel === "string" && typeof object.href === "string";
5552}
5553async function getKeyedPrefetchLinks(matches, manifest, routeModules) {
5554 let links = await Promise.all(
5555 matches.map(async (match) => {
5556 let route = manifest.routes[match.route.id];
5557 if (route) {
5558 let mod = await loadRouteModule(route, routeModules);
5559 return mod.links ? mod.links() : [];
5560 }
5561 return [];
5562 })
5563 );
5564 return dedupeLinkDescriptors(
5565 links.flat(1).filter(isHtmlLinkDescriptor).filter((link) => link.rel === "stylesheet" || link.rel === "preload").map(
5566 (link) => link.rel === "stylesheet" ? { ...link, rel: "prefetch", as: "style" } : { ...link, rel: "prefetch" }
5567 )
5568 );
5569}
5570function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
5571 let isNew = (match, index) => {
5572 if (!currentMatches[index]) return true;
5573 return match.route.id !== currentMatches[index].route.id;
5574 };
5575 let matchPathChanged = (match, index) => {
5576 return (
5577 // param change, /users/123 -> /users/456
5578 currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path
5579 // e.g. /files/images/avatar.jpg -> files/finances.xls
5580 currentMatches[index].route.path?.endsWith("*") && currentMatches[index].params["*"] !== match.params["*"]
5581 );
5582 };
5583 if (mode === "assets") {
5584 return nextMatches.filter(
5585 (match, index) => isNew(match, index) || matchPathChanged(match, index)
5586 );
5587 }
5588 if (mode === "data") {
5589 return nextMatches.filter((match, index) => {
5590 let manifestRoute = manifest.routes[match.route.id];
5591 if (!manifestRoute || !manifestRoute.hasLoader) {
5592 return false;
5593 }
5594 if (isNew(match, index) || matchPathChanged(match, index)) {
5595 return true;
5596 }
5597 if (match.route.shouldRevalidate) {
5598 let routeChoice = match.route.shouldRevalidate({
5599 currentUrl: new URL(
5600 location.pathname + location.search + location.hash,
5601 window.origin
5602 ),
5603 currentParams: currentMatches[0]?.params || {},
5604 nextUrl: new URL(page, window.origin),
5605 nextParams: match.params,
5606 defaultShouldRevalidate: true
5607 });
5608 if (typeof routeChoice === "boolean") {
5609 return routeChoice;
5610 }
5611 }
5612 return true;
5613 });
5614 }
5615 return [];
5616}
5617function getModuleLinkHrefs(matches, manifestPatch) {
5618 return dedupeHrefs(
5619 matches.map((match) => {
5620 let route = manifestPatch.routes[match.route.id];
5621 if (!route) return [];
5622 let hrefs = [route.module];
5623 if (route.imports) {
5624 hrefs = hrefs.concat(route.imports);
5625 }
5626 return hrefs;
5627 }).flat(1)
5628 );
5629}
5630function getCurrentPageModulePreloadHrefs(matches, manifest) {
5631 return dedupeHrefs(
5632 matches.map((match) => {
5633 let route = manifest.routes[match.route.id];
5634 if (!route) return [];
5635 let hrefs = [route.module];
5636 if (route.imports) {
5637 hrefs = hrefs.concat(route.imports);
5638 }
5639 return hrefs;
5640 }).flat(1)
5641 );
5642}
5643function dedupeHrefs(hrefs) {
5644 return [...new Set(hrefs)];
5645}
5646function sortKeys(obj) {
5647 let sorted = {};
5648 let keys = Object.keys(obj).sort();
5649 for (let key of keys) {
5650 sorted[key] = obj[key];
5651 }
5652 return sorted;
5653}
5654function dedupeLinkDescriptors(descriptors, preloads) {
5655 let set = /* @__PURE__ */ new Set();
5656 let preloadsSet = new Set(preloads);
5657 return descriptors.reduce((deduped, descriptor) => {
5658 let alreadyModulePreload = preloads && !isPageLinkDescriptor(descriptor) && descriptor.as === "script" && descriptor.href && preloadsSet.has(descriptor.href);
5659 if (alreadyModulePreload) {
5660 return deduped;
5661 }
5662 let key = JSON.stringify(sortKeys(descriptor));
5663 if (!set.has(key)) {
5664 set.add(key);
5665 deduped.push({ key, link: descriptor });
5666 }
5667 return deduped;
5668 }, []);
5669}
5670var _isPreloadSupported;
5671function isPreloadSupported() {
5672 if (_isPreloadSupported !== void 0) {
5673 return _isPreloadSupported;
5674 }
5675 let el = document.createElement("link");
5676 _isPreloadSupported = el.relList.supports("preload");
5677 el = null;
5678 return _isPreloadSupported;
5679}
5680
5681// lib/dom/ssr/markup.ts
5682var ESCAPE_LOOKUP = {
5683 "&": "\\u0026",
5684 ">": "\\u003e",
5685 "<": "\\u003c",
5686 "\u2028": "\\u2028",
5687 "\u2029": "\\u2029"
5688};
5689var ESCAPE_REGEX = /[&><\u2028\u2029]/g;
5690function escapeHtml(html) {
5691 return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
5692}
5693function createHtml(html) {
5694 return { __html: html };
5695}
5696
5697// lib/dom/ssr/single-fetch.tsx
5698var React4 = __toESM(require("react"));
5699var import_turbo_stream = require("turbo-stream");
5700
5701// lib/dom/ssr/data.ts
5702async function createRequestInit(request) {
5703 let init = { signal: request.signal };
5704 if (request.method !== "GET") {
5705 init.method = request.method;
5706 let contentType = request.headers.get("Content-Type");
5707 if (contentType && /\bapplication\/json\b/.test(contentType)) {
5708 init.headers = { "Content-Type": contentType };
5709 init.body = JSON.stringify(await request.json());
5710 } else if (contentType && /\btext\/plain\b/.test(contentType)) {
5711 init.headers = { "Content-Type": contentType };
5712 init.body = await request.text();
5713 } else if (contentType && /\bapplication\/x-www-form-urlencoded\b/.test(contentType)) {
5714 init.body = new URLSearchParams(await request.text());
5715 } else {
5716 init.body = await request.formData();
5717 }
5718 }
5719 return init;
5720}
5721
5722// lib/dom/ssr/single-fetch.tsx
5723var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
5724function StreamTransfer({
5725 context,
5726 identifier,
5727 reader,
5728 textDecoder,
5729 nonce
5730}) {
5731 if (!context.renderMeta || !context.renderMeta.didRenderScripts) {
5732 return null;
5733 }
5734 if (!context.renderMeta.streamCache) {
5735 context.renderMeta.streamCache = {};
5736 }
5737 let { streamCache } = context.renderMeta;
5738 let promise = streamCache[identifier];
5739 if (!promise) {
5740 promise = streamCache[identifier] = reader.read().then((result) => {
5741 streamCache[identifier].result = {
5742 done: result.done,
5743 value: textDecoder.decode(result.value, { stream: true })
5744 };
5745 }).catch((e) => {
5746 streamCache[identifier].error = e;
5747 });
5748 }
5749 if (promise.error) {
5750 throw promise.error;
5751 }
5752 if (promise.result === void 0) {
5753 throw promise;
5754 }
5755 let { done, value } = promise.result;
5756 let scriptTag = value ? /* @__PURE__ */ React4.createElement(
5757 "script",
5758 {
5759 nonce,
5760 dangerouslySetInnerHTML: {
5761 __html: `window.__reactRouterContext.streamController.enqueue(${escapeHtml(
5762 JSON.stringify(value)
5763 )});`
5764 }
5765 }
5766 ) : null;
5767 if (done) {
5768 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(
5769 "script",
5770 {
5771 nonce,
5772 dangerouslySetInnerHTML: {
5773 __html: `window.__reactRouterContext.streamController.close();`
5774 }
5775 }
5776 ));
5777 } else {
5778 return /* @__PURE__ */ React4.createElement(React4.Fragment, null, scriptTag, /* @__PURE__ */ React4.createElement(React4.Suspense, null, /* @__PURE__ */ React4.createElement(
5779 StreamTransfer,
5780 {
5781 context,
5782 identifier: identifier + 1,
5783 reader,
5784 textDecoder,
5785 nonce
5786 }
5787 )));
5788 }
5789}
5790function getSingleFetchDataStrategy(manifest, routeModules, getRouter) {
5791 return async ({ request, matches, fetcherKey }) => {
5792 if (request.method !== "GET") {
5793 return singleFetchActionStrategy(request, matches);
5794 }
5795 if (fetcherKey) {
5796 return singleFetchLoaderFetcherStrategy(request, matches);
5797 }
5798 return singleFetchLoaderNavigationStrategy(
5799 manifest,
5800 routeModules,
5801 getRouter(),
5802 request,
5803 matches
5804 );
5805 };
5806}
5807async function singleFetchActionStrategy(request, matches) {
5808 let actionMatch = matches.find((m) => m.shouldLoad);
5809 invariant2(actionMatch, "No action match found");
5810 let actionStatus = void 0;
5811 let result = await actionMatch.resolve(async (handler) => {
5812 let result2 = await handler(async () => {
5813 let url = singleFetchUrl(request.url);
5814 let init = await createRequestInit(request);
5815 let { data: data2, status } = await fetchAndDecode(url, init);
5816 actionStatus = status;
5817 return unwrapSingleFetchResult(
5818 data2,
5819 actionMatch.route.id
5820 );
5821 });
5822 return result2;
5823 });
5824 if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
5825 return { [actionMatch.route.id]: result };
5826 }
5827 return {
5828 [actionMatch.route.id]: {
5829 type: result.type,
5830 result: data(result.result, actionStatus)
5831 }
5832 };
5833}
5834async function singleFetchLoaderNavigationStrategy(manifest, routeModules, router, request, matches) {
5835 let routesParams = /* @__PURE__ */ new Set();
5836 let foundOptOutRoute = false;
5837 let routeDfds = matches.map(() => createDeferred2());
5838 let routesLoadedPromise = Promise.all(routeDfds.map((d) => d.promise));
5839 let singleFetchDfd = createDeferred2();
5840 let url = stripIndexParam(singleFetchUrl(request.url));
5841 let init = await createRequestInit(request);
5842 let results = {};
5843 let resolvePromise = Promise.all(
5844 matches.map(
5845 async (m, i) => m.resolve(async (handler) => {
5846 routeDfds[i].resolve();
5847 let manifestRoute = manifest.routes[m.route.id];
5848 if (!m.shouldLoad) {
5849 if (!router.state.initialized) {
5850 return;
5851 }
5852 if (m.route.id in router.state.loaderData && manifestRoute && manifestRoute.hasLoader && routeModules[m.route.id]?.shouldRevalidate) {
5853 foundOptOutRoute = true;
5854 return;
5855 }
5856 }
5857 if (manifestRoute && manifestRoute.hasClientLoader) {
5858 if (manifestRoute.hasLoader) {
5859 foundOptOutRoute = true;
5860 }
5861 try {
5862 let result = await fetchSingleLoader(
5863 handler,
5864 url,
5865 init,
5866 m.route.id
5867 );
5868 results[m.route.id] = { type: "data", result };
5869 } catch (e) {
5870 results[m.route.id] = { type: "error", result: e };
5871 }
5872 return;
5873 }
5874 if (manifestRoute && manifestRoute.hasLoader) {
5875 routesParams.add(m.route.id);
5876 }
5877 try {
5878 let result = await handler(async () => {
5879 let data2 = await singleFetchDfd.promise;
5880 return unwrapSingleFetchResults(data2, m.route.id);
5881 });
5882 results[m.route.id] = {
5883 type: "data",
5884 result
5885 };
5886 } catch (e) {
5887 results[m.route.id] = {
5888 type: "error",
5889 result: e
5890 };
5891 }
5892 })
5893 )
5894 );
5895 await routesLoadedPromise;
5896 if ((!router.state.initialized || routesParams.size === 0) && !window.__reactRouterHdrActive) {
5897 singleFetchDfd.resolve({});
5898 } else {
5899 try {
5900 if (foundOptOutRoute && routesParams.size > 0) {
5901 url.searchParams.set(
5902 "_routes",
5903 matches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
5904 );
5905 }
5906 let data2 = await fetchAndDecode(url, init);
5907 singleFetchDfd.resolve(data2.data);
5908 } catch (e) {
5909 singleFetchDfd.reject(e);
5910 }
5911 }
5912 await resolvePromise;
5913 return results;
5914}
5915async function singleFetchLoaderFetcherStrategy(request, matches) {
5916 let fetcherMatch = matches.find((m) => m.shouldLoad);
5917 invariant2(fetcherMatch, "No fetcher match found");
5918 let result = await fetcherMatch.resolve(async (handler) => {
5919 let url = stripIndexParam(singleFetchUrl(request.url));
5920 let init = await createRequestInit(request);
5921 return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
5922 });
5923 return { [fetcherMatch.route.id]: result };
5924}
5925function fetchSingleLoader(handler, url, init, routeId) {
5926 return handler(async () => {
5927 let singleLoaderUrl = new URL(url);
5928 singleLoaderUrl.searchParams.set("_routes", routeId);
5929 let { data: data2 } = await fetchAndDecode(singleLoaderUrl, init);
5930 return unwrapSingleFetchResults(data2, routeId);
5931 });
5932}
5933function stripIndexParam(url) {
5934 let indexValues = url.searchParams.getAll("index");
5935 url.searchParams.delete("index");
5936 let indexValuesToKeep = [];
5937 for (let indexValue of indexValues) {
5938 if (indexValue) {
5939 indexValuesToKeep.push(indexValue);
5940 }
5941 }
5942 for (let toKeep of indexValuesToKeep) {
5943 url.searchParams.append("index", toKeep);
5944 }
5945 return url;
5946}
5947function singleFetchUrl(reqUrl) {
5948 let url = typeof reqUrl === "string" ? new URL(
5949 reqUrl,
5950 // This can be called during the SSR flow via PrefetchPageLinksImpl so
5951 // don't assume window is available
5952 typeof window === "undefined" ? "server://singlefetch/" : window.location.origin
5953 ) : reqUrl;
5954 if (url.pathname === "/") {
5955 url.pathname = "_root.data";
5956 } else {
5957 url.pathname = `${url.pathname.replace(/\/$/, "")}.data`;
5958 }
5959 return url;
5960}
5961async function fetchAndDecode(url, init) {
5962 let res = await fetch(url, init);
5963 if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
5964 throw new ErrorResponseImpl(404, "Not Found", true);
5965 }
5966 invariant2(res.body, "No response body to decode");
5967 try {
5968 let decoded = await decodeViaTurboStream(res.body, window);
5969 return { status: res.status, data: decoded.value };
5970 } catch (e) {
5971 throw new Error("Unable to decode turbo-stream response");
5972 }
5973}
5974function decodeViaTurboStream(body, global2) {
5975 return (0, import_turbo_stream.decode)(body, {
5976 plugins: [
5977 (type, ...rest) => {
5978 if (type === "SanitizedError") {
5979 let [name, message, stack] = rest;
5980 let Constructor = Error;
5981 if (name && name in global2 && typeof global2[name] === "function") {
5982 Constructor = global2[name];
5983 }
5984 let error = new Constructor(message);
5985 error.stack = stack;
5986 return { value: error };
5987 }
5988 if (type === "ErrorResponse") {
5989 let [data2, status, statusText] = rest;
5990 return {
5991 value: new ErrorResponseImpl(status, statusText, data2)
5992 };
5993 }
5994 if (type === "SingleFetchRedirect") {
5995 return { value: { [SingleFetchRedirectSymbol]: rest[0] } };
5996 }
5997 if (type === "SingleFetchClassInstance") {
5998 return { value: rest[0] };
5999 }
6000 if (type === "SingleFetchFallback") {
6001 return { value: void 0 };
6002 }
6003 }
6004 ]
6005 });
6006}
6007function unwrapSingleFetchResults(results, routeId) {
6008 let redirect2 = results[SingleFetchRedirectSymbol];
6009 if (redirect2) {
6010 return unwrapSingleFetchResult(redirect2, routeId);
6011 }
6012 return results[routeId] !== void 0 ? unwrapSingleFetchResult(results[routeId], routeId) : null;
6013}
6014function unwrapSingleFetchResult(result, routeId) {
6015 if ("error" in result) {
6016 throw result.error;
6017 } else if ("redirect" in result) {
6018 let headers = {};
6019 if (result.revalidate) {
6020 headers["X-Remix-Revalidate"] = "yes";
6021 }
6022 if (result.reload) {
6023 headers["X-Remix-Reload-Document"] = "yes";
6024 }
6025 if (result.replace) {
6026 headers["X-Remix-Replace"] = "yes";
6027 }
6028 return redirect(result.redirect, { status: result.status, headers });
6029 } else if ("data" in result) {
6030 return result.data;
6031 } else {
6032 throw new Error(`No response found for routeId "${routeId}"`);
6033 }
6034}
6035function createDeferred2() {
6036 let resolve;
6037 let reject;
6038 let promise = new Promise((res, rej) => {
6039 resolve = async (val) => {
6040 res(val);
6041 try {
6042 await promise;
6043 } catch (e) {
6044 }
6045 };
6046 reject = async (error) => {
6047 rej(error);
6048 try {
6049 await promise;
6050 } catch (e) {
6051 }
6052 };
6053 });
6054 return {
6055 promise,
6056 //@ts-ignore
6057 resolve,
6058 //@ts-ignore
6059 reject
6060 };
6061}
6062
6063// lib/dom/ssr/fog-of-war.ts
6064var React8 = __toESM(require("react"));
6065
6066// lib/dom/ssr/routes.tsx
6067var React7 = __toESM(require("react"));
6068
6069// lib/dom/ssr/errorBoundaries.tsx
6070var React5 = __toESM(require("react"));
6071var RemixErrorBoundary = class extends React5.Component {
6072 constructor(props) {
6073 super(props);
6074 this.state = { error: props.error || null, location: props.location };
6075 }
6076 static getDerivedStateFromError(error) {
6077 return { error };
6078 }
6079 static getDerivedStateFromProps(props, state) {
6080 if (state.location !== props.location) {
6081 return { error: props.error || null, location: props.location };
6082 }
6083 return { error: props.error || state.error, location: state.location };
6084 }
6085 render() {
6086 if (this.state.error) {
6087 return /* @__PURE__ */ React5.createElement(
6088 RemixRootDefaultErrorBoundary,
6089 {
6090 error: this.state.error,
6091 isOutsideRemixApp: true
6092 }
6093 );
6094 } else {
6095 return this.props.children;
6096 }
6097 }
6098};
6099function RemixRootDefaultErrorBoundary({
6100 error,
6101 isOutsideRemixApp
6102}) {
6103 console.error(error);
6104 let heyDeveloper = /* @__PURE__ */ React5.createElement(
6105 "script",
6106 {
6107 dangerouslySetInnerHTML: {
6108 __html: `
6109 console.log(
6110 "\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."
6111 );
6112 `
6113 }
6114 }
6115 );
6116 if (isRouteErrorResponse(error)) {
6117 return /* @__PURE__ */ React5.createElement(BoundaryShell, { title: "Unhandled Thrown Response!" }, /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, error.status, " ", error.statusText), heyDeveloper);
6118 }
6119 let errorInstance;
6120 if (error instanceof Error) {
6121 errorInstance = error;
6122 } else {
6123 let errorString = error == null ? "Unknown Error" : typeof error === "object" && "toString" in error ? error.toString() : JSON.stringify(error);
6124 errorInstance = new Error(errorString);
6125 }
6126 return /* @__PURE__ */ React5.createElement(
6127 BoundaryShell,
6128 {
6129 title: "Application Error!",
6130 isOutsideRemixApp
6131 },
6132 /* @__PURE__ */ React5.createElement("h1", { style: { fontSize: "24px" } }, "Application Error"),
6133 /* @__PURE__ */ React5.createElement(
6134 "pre",
6135 {
6136 style: {
6137 padding: "2rem",
6138 background: "hsla(10, 50%, 50%, 0.1)",
6139 color: "red",
6140 overflow: "auto"
6141 }
6142 },
6143 errorInstance.stack
6144 ),
6145 heyDeveloper
6146 );
6147}
6148function BoundaryShell({
6149 title,
6150 renderScripts,
6151 isOutsideRemixApp,
6152 children
6153}) {
6154 let { routeModules } = useFrameworkContext();
6155 if (routeModules.root?.Layout && !isOutsideRemixApp) {
6156 return children;
6157 }
6158 return /* @__PURE__ */ React5.createElement("html", { lang: "en" }, /* @__PURE__ */ React5.createElement("head", null, /* @__PURE__ */ React5.createElement("meta", { charSet: "utf-8" }), /* @__PURE__ */ React5.createElement(
6159 "meta",
6160 {
6161 name: "viewport",
6162 content: "width=device-width,initial-scale=1,viewport-fit=cover"
6163 }
6164 ), /* @__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)));
6165}
6166
6167// lib/dom/ssr/fallback.tsx
6168var React6 = __toESM(require("react"));
6169function RemixRootDefaultHydrateFallback() {
6170 return /* @__PURE__ */ React6.createElement(BoundaryShell, { title: "Loading...", renderScripts: true }, /* @__PURE__ */ React6.createElement(
6171 "script",
6172 {
6173 dangerouslySetInnerHTML: {
6174 __html: `
6175 console.log(
6176 "\u{1F4BF} Hey developer \u{1F44B}. You can provide a way better UX than this " +
6177 "when your app is loading JS modules and/or running \`clientLoader\` " +
6178 "functions. Check out https://remix.run/route/hydrate-fallback " +
6179 "for more information."
6180 );
6181 `
6182 }
6183 }
6184 ));
6185}
6186
6187// lib/dom/ssr/routes.tsx
6188function groupRoutesByParentId(manifest) {
6189 let routes = {};
6190 Object.values(manifest).forEach((route) => {
6191 if (route) {
6192 let parentId = route.parentId || "";
6193 if (!routes[parentId]) {
6194 routes[parentId] = [];
6195 }
6196 routes[parentId].push(route);
6197 }
6198 });
6199 return routes;
6200}
6201function getRouteComponents(route, routeModule, isSpaMode) {
6202 let Component4 = getRouteModuleComponent(routeModule);
6203 let HydrateFallback = routeModule.HydrateFallback && (!isSpaMode || route.id === "root") ? routeModule.HydrateFallback : route.id === "root" ? RemixRootDefaultHydrateFallback : void 0;
6204 let ErrorBoundary = routeModule.ErrorBoundary ? routeModule.ErrorBoundary : route.id === "root" ? () => /* @__PURE__ */ React7.createElement(RemixRootDefaultErrorBoundary, { error: useRouteError() }) : void 0;
6205 if (route.id === "root" && routeModule.Layout) {
6206 return {
6207 ...Component4 ? {
6208 element: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(Component4, null))
6209 } : { Component: Component4 },
6210 ...ErrorBoundary ? {
6211 errorElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(ErrorBoundary, null))
6212 } : { ErrorBoundary },
6213 ...HydrateFallback ? {
6214 hydrateFallbackElement: /* @__PURE__ */ React7.createElement(routeModule.Layout, null, /* @__PURE__ */ React7.createElement(HydrateFallback, null))
6215 } : { HydrateFallback }
6216 };
6217 }
6218 return { Component: Component4, ErrorBoundary, HydrateFallback };
6219}
6220function createServerRoutes(manifest, routeModules, future, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), spaModeLazyPromise = Promise.resolve({ Component: () => null })) {
6221 return (routesByParentId[parentId] || []).map((route) => {
6222 let routeModule = routeModules[route.id];
6223 invariant2(
6224 routeModule,
6225 "No `routeModule` available to create server routes"
6226 );
6227 let dataRoute = {
6228 ...getRouteComponents(route, routeModule, isSpaMode),
6229 caseSensitive: route.caseSensitive,
6230 id: route.id,
6231 index: route.index,
6232 path: route.path,
6233 handle: routeModule.handle,
6234 // For SPA Mode, all routes are lazy except root. However we tell the
6235 // router root is also lazy here too since we don't need a full
6236 // implementation - we just need a `lazy` prop to tell the RR rendering
6237 // where to stop which is always at the root route in SPA mode
6238 lazy: isSpaMode ? () => spaModeLazyPromise : void 0,
6239 // For partial hydration rendering, we need to indicate when the route
6240 // has a loader/clientLoader, but it won't ever be called during the static
6241 // render, so just give it a no-op function so we can render down to the
6242 // proper fallback
6243 loader: route.hasLoader || route.hasClientLoader ? () => null : void 0
6244 // We don't need action/shouldRevalidate on these routes since they're
6245 // for a static render
6246 };
6247 let children = createServerRoutes(
6248 manifest,
6249 routeModules,
6250 future,
6251 isSpaMode,
6252 route.id,
6253 routesByParentId,
6254 spaModeLazyPromise
6255 );
6256 if (children.length > 0) dataRoute.children = children;
6257 return dataRoute;
6258 });
6259}
6260function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState, future, isSpaMode) {
6261 return createClientRoutes(
6262 manifest,
6263 routeModulesCache,
6264 initialState,
6265 isSpaMode,
6266 "",
6267 groupRoutesByParentId(manifest),
6268 needsRevalidation
6269 );
6270}
6271function preventInvalidServerHandlerCall(type, route, isSpaMode) {
6272 if (isSpaMode) {
6273 let fn2 = type === "action" ? "serverAction()" : "serverLoader()";
6274 let msg2 = `You cannot call ${fn2} in SPA Mode (routeId: "${route.id}")`;
6275 console.error(msg2);
6276 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg2), true);
6277 }
6278 let fn = type === "action" ? "serverAction()" : "serverLoader()";
6279 let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
6280 if (type === "loader" && !route.hasLoader || type === "action" && !route.hasAction) {
6281 console.error(msg);
6282 throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
6283 }
6284}
6285function noActionDefinedError(type, routeId) {
6286 let article = type === "clientAction" ? "a" : "an";
6287 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`;
6288 console.error(msg);
6289 throw new ErrorResponseImpl(405, "Method Not Allowed", new Error(msg), true);
6290}
6291function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
6292 return (routesByParentId[parentId] || []).map((route) => {
6293 let routeModule = routeModulesCache[route.id];
6294 function fetchServerHandler(singleFetch) {
6295 invariant2(
6296 typeof singleFetch === "function",
6297 "No single fetch function available for route handler"
6298 );
6299 return singleFetch();
6300 }
6301 function fetchServerLoader(singleFetch) {
6302 if (!route.hasLoader) return Promise.resolve(null);
6303 return fetchServerHandler(singleFetch);
6304 }
6305 function fetchServerAction(singleFetch) {
6306 if (!route.hasAction) {
6307 throw noActionDefinedError("action", route.id);
6308 }
6309 return fetchServerHandler(singleFetch);
6310 }
6311 async function prefetchStylesAndCallHandler(handler) {
6312 let cachedModule = routeModulesCache[route.id];
6313 let linkPrefetchPromise = cachedModule ? prefetchStyleLinks(route, cachedModule) : Promise.resolve();
6314 try {
6315 return handler();
6316 } finally {
6317 await linkPrefetchPromise;
6318 }
6319 }
6320 let dataRoute = {
6321 id: route.id,
6322 index: route.index,
6323 path: route.path
6324 };
6325 if (routeModule) {
6326 Object.assign(dataRoute, {
6327 ...dataRoute,
6328 ...getRouteComponents(route, routeModule, isSpaMode),
6329 handle: routeModule.handle,
6330 shouldRevalidate: getShouldRevalidateFunction(
6331 routeModule,
6332 route.id,
6333 needsRevalidation
6334 )
6335 });
6336 let hasInitialData = initialState && initialState.loaderData && route.id in initialState.loaderData;
6337 let initialData = hasInitialData ? initialState?.loaderData?.[route.id] : void 0;
6338 let hasInitialError = initialState && initialState.errors && route.id in initialState.errors;
6339 let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
6340 let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
6341 dataRoute.loader = async ({ request, params }, singleFetch) => {
6342 try {
6343 let result = await prefetchStylesAndCallHandler(async () => {
6344 invariant2(
6345 routeModule,
6346 "No `routeModule` available for critical-route loader"
6347 );
6348 if (!routeModule.clientLoader) {
6349 if (isSpaMode) return null;
6350 return fetchServerLoader(singleFetch);
6351 }
6352 return routeModule.clientLoader({
6353 request,
6354 params,
6355 async serverLoader() {
6356 preventInvalidServerHandlerCall("loader", route, isSpaMode);
6357 if (isHydrationRequest) {
6358 if (hasInitialData) {
6359 return initialData;
6360 }
6361 if (hasInitialError) {
6362 throw initialError;
6363 }
6364 }
6365 return fetchServerLoader(singleFetch);
6366 }
6367 });
6368 });
6369 return result;
6370 } finally {
6371 isHydrationRequest = false;
6372 }
6373 };
6374 dataRoute.loader.hydrate = shouldHydrateRouteLoader(
6375 route,
6376 routeModule,
6377 isSpaMode
6378 );
6379 dataRoute.action = ({ request, params }, singleFetch) => {
6380 return prefetchStylesAndCallHandler(async () => {
6381 invariant2(
6382 routeModule,
6383 "No `routeModule` available for critical-route action"
6384 );
6385 if (!routeModule.clientAction) {
6386 if (isSpaMode) {
6387 throw noActionDefinedError("clientAction", route.id);
6388 }
6389 return fetchServerAction(singleFetch);
6390 }
6391 return routeModule.clientAction({
6392 request,
6393 params,
6394 async serverAction() {
6395 preventInvalidServerHandlerCall("action", route, isSpaMode);
6396 return fetchServerAction(singleFetch);
6397 }
6398 });
6399 });
6400 };
6401 } else {
6402 if (!route.hasClientLoader) {
6403 dataRoute.loader = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
6404 if (isSpaMode) return Promise.resolve(null);
6405 return fetchServerLoader(singleFetch);
6406 });
6407 }
6408 if (!route.hasClientAction) {
6409 dataRoute.action = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
6410 if (isSpaMode) {
6411 throw noActionDefinedError("clientAction", route.id);
6412 }
6413 return fetchServerAction(singleFetch);
6414 });
6415 }
6416 dataRoute.lazy = async () => {
6417 let mod = await loadRouteModuleWithBlockingLinks(
6418 route,
6419 routeModulesCache
6420 );
6421 let lazyRoute = { ...mod };
6422 if (mod.clientLoader) {
6423 let clientLoader = mod.clientLoader;
6424 lazyRoute.loader = (args, singleFetch) => clientLoader({
6425 ...args,
6426 async serverLoader() {
6427 preventInvalidServerHandlerCall("loader", route, isSpaMode);
6428 return fetchServerLoader(singleFetch);
6429 }
6430 });
6431 }
6432 if (mod.clientAction) {
6433 let clientAction = mod.clientAction;
6434 lazyRoute.action = (args, singleFetch) => clientAction({
6435 ...args,
6436 async serverAction() {
6437 preventInvalidServerHandlerCall("action", route, isSpaMode);
6438 return fetchServerAction(singleFetch);
6439 }
6440 });
6441 }
6442 return {
6443 ...lazyRoute.loader ? { loader: lazyRoute.loader } : {},
6444 ...lazyRoute.action ? { action: lazyRoute.action } : {},
6445 hasErrorBoundary: lazyRoute.hasErrorBoundary,
6446 shouldRevalidate: getShouldRevalidateFunction(
6447 lazyRoute,
6448 route.id,
6449 needsRevalidation
6450 ),
6451 handle: lazyRoute.handle,
6452 // No need to wrap these in layout since the root route is never
6453 // loaded via route.lazy()
6454 Component: lazyRoute.Component,
6455 ErrorBoundary: lazyRoute.ErrorBoundary
6456 };
6457 };
6458 }
6459 let children = createClientRoutes(
6460 manifest,
6461 routeModulesCache,
6462 initialState,
6463 isSpaMode,
6464 route.id,
6465 routesByParentId,
6466 needsRevalidation
6467 );
6468 if (children.length > 0) dataRoute.children = children;
6469 return dataRoute;
6470 });
6471}
6472function getShouldRevalidateFunction(route, routeId, needsRevalidation) {
6473 if (needsRevalidation) {
6474 return wrapShouldRevalidateForHdr(
6475 routeId,
6476 route.shouldRevalidate,
6477 needsRevalidation
6478 );
6479 }
6480 if (route.shouldRevalidate) {
6481 let fn = route.shouldRevalidate;
6482 return (opts) => fn({ ...opts, defaultShouldRevalidate: true });
6483 }
6484 return route.shouldRevalidate;
6485}
6486function wrapShouldRevalidateForHdr(routeId, routeShouldRevalidate, needsRevalidation) {
6487 let handledRevalidation = false;
6488 return (arg) => {
6489 if (!handledRevalidation) {
6490 handledRevalidation = true;
6491 return needsRevalidation.has(routeId);
6492 }
6493 return routeShouldRevalidate ? routeShouldRevalidate(arg) : arg.defaultShouldRevalidate;
6494 };
6495}
6496async function loadRouteModuleWithBlockingLinks(route, routeModules) {
6497 let routeModule = await loadRouteModule(route, routeModules);
6498 await prefetchStyleLinks(route, routeModule);
6499 return {
6500 Component: getRouteModuleComponent(routeModule),
6501 ErrorBoundary: routeModule.ErrorBoundary,
6502 clientAction: routeModule.clientAction,
6503 clientLoader: routeModule.clientLoader,
6504 handle: routeModule.handle,
6505 links: routeModule.links,
6506 meta: routeModule.meta,
6507 shouldRevalidate: routeModule.shouldRevalidate
6508 };
6509}
6510function getRouteModuleComponent(routeModule) {
6511 if (routeModule.default == null) return void 0;
6512 let isEmptyObject = typeof routeModule.default === "object" && Object.keys(routeModule.default).length === 0;
6513 if (!isEmptyObject) {
6514 return routeModule.default;
6515 }
6516}
6517function shouldHydrateRouteLoader(route, routeModule, isSpaMode) {
6518 return isSpaMode && route.id !== "root" || routeModule.clientLoader != null && (routeModule.clientLoader.hydrate === true || route.hasLoader !== true);
6519}
6520
6521// lib/dom/ssr/fog-of-war.ts
6522var nextPaths = /* @__PURE__ */ new Set();
6523var discoveredPathsMaxSize = 1e3;
6524var discoveredPaths = /* @__PURE__ */ new Set();
6525var URL_LIMIT = 7680;
6526function isFogOfWarEnabled(isSpaMode) {
6527 return !isSpaMode;
6528}
6529function getPartialManifest(manifest, router) {
6530 let routeIds = new Set(router.state.matches.map((m) => m.route.id));
6531 let segments = router.state.location.pathname.split("/").filter(Boolean);
6532 let paths = ["/"];
6533 segments.pop();
6534 while (segments.length > 0) {
6535 paths.push(`/${segments.join("/")}`);
6536 segments.pop();
6537 }
6538 paths.forEach((path) => {
6539 let matches = matchRoutes(router.routes, path, router.basename);
6540 if (matches) {
6541 matches.forEach((m) => routeIds.add(m.route.id));
6542 }
6543 });
6544 let initialRoutes = [...routeIds].reduce(
6545 (acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }),
6546 {}
6547 );
6548 return {
6549 ...manifest,
6550 routes: initialRoutes
6551 };
6552}
6553function getPatchRoutesOnNavigationFunction(manifest, routeModules, isSpaMode, basename) {
6554 if (!isFogOfWarEnabled(isSpaMode)) {
6555 return void 0;
6556 }
6557 return async ({ path, patch }) => {
6558 if (discoveredPaths.has(path)) {
6559 return;
6560 }
6561 await fetchAndApplyManifestPatches(
6562 [path],
6563 manifest,
6564 routeModules,
6565 isSpaMode,
6566 basename,
6567 patch
6568 );
6569 };
6570}
6571function useFogOFWarDiscovery(router, manifest, routeModules, isSpaMode) {
6572 React8.useEffect(() => {
6573 if (!isFogOfWarEnabled(isSpaMode) || navigator.connection?.saveData === true) {
6574 return;
6575 }
6576 function registerElement(el) {
6577 let path = el.tagName === "FORM" ? el.getAttribute("action") : el.getAttribute("href");
6578 if (!path) {
6579 return;
6580 }
6581 let url = new URL(path, window.location.origin);
6582 if (!discoveredPaths.has(url.pathname)) {
6583 nextPaths.add(url.pathname);
6584 }
6585 }
6586 async function fetchPatches() {
6587 let lazyPaths = Array.from(nextPaths.keys()).filter((path) => {
6588 if (discoveredPaths.has(path)) {
6589 nextPaths.delete(path);
6590 return false;
6591 }
6592 return true;
6593 });
6594 if (lazyPaths.length === 0) {
6595 return;
6596 }
6597 try {
6598 await fetchAndApplyManifestPatches(
6599 lazyPaths,
6600 manifest,
6601 routeModules,
6602 isSpaMode,
6603 router.basename,
6604 router.patchRoutes
6605 );
6606 } catch (e) {
6607 console.error("Failed to fetch manifest patches", e);
6608 }
6609 }
6610 document.body.querySelectorAll("a[data-discover], form[data-discover]").forEach((el) => registerElement(el));
6611 fetchPatches();
6612 let debouncedFetchPatches = debounce(fetchPatches, 100);
6613 function isElement(node) {
6614 return node.nodeType === Node.ELEMENT_NODE;
6615 }
6616 let observer = new MutationObserver((records) => {
6617 let elements = /* @__PURE__ */ new Set();
6618 records.forEach((r) => {
6619 [r.target, ...r.addedNodes].forEach((node) => {
6620 if (!isElement(node)) return;
6621 if (node.tagName === "A" && node.getAttribute("data-discover")) {
6622 elements.add(node);
6623 } else if (node.tagName === "FORM" && node.getAttribute("data-discover")) {
6624 elements.add(node);
6625 }
6626 if (node.tagName !== "A") {
6627 node.querySelectorAll("a[data-discover], form[data-discover]").forEach((el) => elements.add(el));
6628 }
6629 });
6630 });
6631 elements.forEach((el) => registerElement(el));
6632 debouncedFetchPatches();
6633 });
6634 observer.observe(document.documentElement, {
6635 subtree: true,
6636 childList: true,
6637 attributes: true,
6638 attributeFilter: ["data-discover", "href", "action"]
6639 });
6640 return () => observer.disconnect();
6641 }, [isSpaMode, manifest, routeModules, router]);
6642}
6643async function fetchAndApplyManifestPatches(paths, manifest, routeModules, isSpaMode, basename, patchRoutes) {
6644 let manifestPath = `${basename != null ? basename : "/"}/__manifest`.replace(
6645 /\/+/g,
6646 "/"
6647 );
6648 let url = new URL(manifestPath, window.location.origin);
6649 paths.sort().forEach((path) => url.searchParams.append("p", path));
6650 url.searchParams.set("version", manifest.version);
6651 if (url.toString().length > URL_LIMIT) {
6652 nextPaths.clear();
6653 return;
6654 }
6655 let res = await fetch(url);
6656 if (!res.ok) {
6657 throw new Error(`${res.status} ${res.statusText}`);
6658 } else if (res.status >= 400) {
6659 throw new Error(await res.text());
6660 }
6661 let serverPatches = await res.json();
6662 let knownRoutes = new Set(Object.keys(manifest.routes));
6663 let patches = Object.values(serverPatches).reduce((acc, route) => {
6664 if (route && !knownRoutes.has(route.id)) {
6665 acc[route.id] = route;
6666 }
6667 return acc;
6668 }, {});
6669 Object.assign(manifest.routes, patches);
6670 paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
6671 let parentIds = /* @__PURE__ */ new Set();
6672 Object.values(patches).forEach((patch) => {
6673 if (patch && (!patch.parentId || !patches[patch.parentId])) {
6674 parentIds.add(patch.parentId);
6675 }
6676 });
6677 parentIds.forEach(
6678 (parentId) => patchRoutes(
6679 parentId || null,
6680 createClientRoutes(patches, routeModules, null, isSpaMode, parentId)
6681 )
6682 );
6683}
6684function addToFifoQueue(path, queue) {
6685 if (queue.size >= discoveredPathsMaxSize) {
6686 let first = queue.values().next().value;
6687 queue.delete(first);
6688 }
6689 queue.add(path);
6690}
6691function debounce(callback, wait) {
6692 let timeoutId;
6693 return (...args) => {
6694 window.clearTimeout(timeoutId);
6695 timeoutId = window.setTimeout(() => callback(...args), wait);
6696 };
6697}
6698
6699// lib/dom/ssr/components.tsx
6700function useDataRouterContext2() {
6701 let context = React9.useContext(DataRouterContext);
6702 invariant2(
6703 context,
6704 "You must render this element inside a <DataRouterContext.Provider> element"
6705 );
6706 return context;
6707}
6708function useDataRouterStateContext() {
6709 let context = React9.useContext(DataRouterStateContext);
6710 invariant2(
6711 context,
6712 "You must render this element inside a <DataRouterStateContext.Provider> element"
6713 );
6714 return context;
6715}
6716var FrameworkContext = React9.createContext(void 0);
6717FrameworkContext.displayName = "FrameworkContext";
6718function useFrameworkContext() {
6719 let context = React9.useContext(FrameworkContext);
6720 invariant2(
6721 context,
6722 "You must render this element inside a <HydratedRouter> element"
6723 );
6724 return context;
6725}
6726function usePrefetchBehavior(prefetch, theirElementProps) {
6727 let frameworkContext = React9.useContext(FrameworkContext);
6728 let [maybePrefetch, setMaybePrefetch] = React9.useState(false);
6729 let [shouldPrefetch, setShouldPrefetch] = React9.useState(false);
6730 let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
6731 let ref = React9.useRef(null);
6732 React9.useEffect(() => {
6733 if (prefetch === "render") {
6734 setShouldPrefetch(true);
6735 }
6736 if (prefetch === "viewport") {
6737 let callback = (entries) => {
6738 entries.forEach((entry) => {
6739 setShouldPrefetch(entry.isIntersecting);
6740 });
6741 };
6742 let observer = new IntersectionObserver(callback, { threshold: 0.5 });
6743 if (ref.current) observer.observe(ref.current);
6744 return () => {
6745 observer.disconnect();
6746 };
6747 }
6748 }, [prefetch]);
6749 React9.useEffect(() => {
6750 if (maybePrefetch) {
6751 let id = setTimeout(() => {
6752 setShouldPrefetch(true);
6753 }, 100);
6754 return () => {
6755 clearTimeout(id);
6756 };
6757 }
6758 }, [maybePrefetch]);
6759 let setIntent = () => {
6760 setMaybePrefetch(true);
6761 };
6762 let cancelIntent = () => {
6763 setMaybePrefetch(false);
6764 setShouldPrefetch(false);
6765 };
6766 if (!frameworkContext) {
6767 return [false, ref, {}];
6768 }
6769 if (prefetch !== "intent") {
6770 return [shouldPrefetch, ref, {}];
6771 }
6772 return [
6773 shouldPrefetch,
6774 ref,
6775 {
6776 onFocus: composeEventHandlers(onFocus, setIntent),
6777 onBlur: composeEventHandlers(onBlur, cancelIntent),
6778 onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
6779 onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
6780 onTouchStart: composeEventHandlers(onTouchStart, setIntent)
6781 }
6782 ];
6783}
6784function composeEventHandlers(theirHandler, ourHandler) {
6785 return (event) => {
6786 theirHandler && theirHandler(event);
6787 if (!event.defaultPrevented) {
6788 ourHandler(event);
6789 }
6790 };
6791}
6792function getActiveMatches(matches, errors, isSpaMode) {
6793 if (isSpaMode && !isHydrated) {
6794 return [matches[0]];
6795 }
6796 if (errors) {
6797 let errorIdx = matches.findIndex((m) => errors[m.route.id] !== void 0);
6798 return matches.slice(0, errorIdx + 1);
6799 }
6800 return matches;
6801}
6802function Links() {
6803 let { isSpaMode, manifest, routeModules, criticalCss } = useFrameworkContext();
6804 let { errors, matches: routerMatches } = useDataRouterStateContext();
6805 let matches = getActiveMatches(routerMatches, errors, isSpaMode);
6806 let keyedLinks = React9.useMemo(
6807 () => getKeyedLinksForMatches(matches, routeModules, manifest),
6808 [matches, routeModules, manifest]
6809 );
6810 return /* @__PURE__ */ React9.createElement(React9.Fragment, null, criticalCss ? /* @__PURE__ */ React9.createElement("style", { dangerouslySetInnerHTML: { __html: criticalCss } }) : null, keyedLinks.map(
6811 ({ key, link }) => isPageLinkDescriptor(link) ? /* @__PURE__ */ React9.createElement(PrefetchPageLinks, { key, ...link }) : /* @__PURE__ */ React9.createElement("link", { key, ...link })
6812 ));
6813}
6814function PrefetchPageLinks({
6815 page,
6816 ...dataLinkProps
6817}) {
6818 let { router } = useDataRouterContext2();
6819 let matches = React9.useMemo(
6820 () => matchRoutes(router.routes, page, router.basename),
6821 [router.routes, page, router.basename]
6822 );
6823 if (!matches) {
6824 console.warn(`Tried to prefetch ${page} but no routes matched.`);
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.0.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 abortDelay,
8208 nonce
8209}) {
8210 if (typeof url === "string") {
8211 url = new URL(url);
8212 }
8213 let { manifest, routeModules, criticalCss, serverHandoffString } = context;
8214 let routes = createServerRoutes(
8215 manifest.routes,
8216 routeModules,
8217 context.future,
8218 context.isSpaMode
8219 );
8220 context.staticHandlerContext.loaderData = {
8221 ...context.staticHandlerContext.loaderData
8222 };
8223 for (let match of context.staticHandlerContext.matches) {
8224 let routeId = match.route.id;
8225 let route = routeModules[routeId];
8226 let manifestRoute = context.manifest.routes[routeId];
8227 if (route && manifestRoute && shouldHydrateRouteLoader(manifestRoute, route, context.isSpaMode) && (route.HydrateFallback || !manifestRoute.hasLoader)) {
8228 delete context.staticHandlerContext.loaderData[routeId];
8229 }
8230 }
8231 let router = createStaticRouter(routes, context.staticHandlerContext);
8232 return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(
8233 FrameworkContext.Provider,
8234 {
8235 value: {
8236 manifest,
8237 routeModules,
8238 criticalCss,
8239 serverHandoffString,
8240 future: context.future,
8241 isSpaMode: context.isSpaMode,
8242 serializeError: context.serializeError,
8243 abortDelay,
8244 renderMeta: context.renderMeta
8245 }
8246 },
8247 /* @__PURE__ */ React12.createElement(RemixErrorBoundary, { location: router.state.location }, /* @__PURE__ */ React12.createElement(
8248 StaticRouterProvider,
8249 {
8250 router,
8251 context: context.staticHandlerContext,
8252 hydrate: false
8253 }
8254 ))
8255 ), context.serverHandoffStream ? /* @__PURE__ */ React12.createElement(React12.Suspense, null, /* @__PURE__ */ React12.createElement(
8256 StreamTransfer,
8257 {
8258 context,
8259 identifier: 0,
8260 reader: context.serverHandoffStream.getReader(),
8261 textDecoder: new TextDecoder(),
8262 nonce
8263 }
8264 )) : null);
8265}
8266
8267// lib/dom/ssr/routes-test-stub.tsx
8268var React13 = __toESM(require("react"));
8269function createRoutesStub(routes, context = {}) {
8270 return function RoutesTestStub({
8271 initialEntries,
8272 initialIndex,
8273 hydrationData,
8274 future
8275 }) {
8276 let routerRef = React13.useRef();
8277 let remixContextRef = React13.useRef();
8278 if (routerRef.current == null) {
8279 remixContextRef.current = {
8280 future: {},
8281 manifest: {
8282 routes: {},
8283 entry: { imports: [], module: "" },
8284 url: "",
8285 version: ""
8286 },
8287 routeModules: {},
8288 isSpaMode: false
8289 };
8290 let patched = processRoutes(
8291 // @ts-expect-error loader/action context types don't match :/
8292 convertRoutesToDataRoutes(routes, (r) => r),
8293 context,
8294 remixContextRef.current.manifest,
8295 remixContextRef.current.routeModules
8296 );
8297 routerRef.current = createMemoryRouter(patched, {
8298 initialEntries,
8299 initialIndex,
8300 hydrationData
8301 });
8302 }
8303 return /* @__PURE__ */ React13.createElement(FrameworkContext.Provider, { value: remixContextRef.current }, /* @__PURE__ */ React13.createElement(RouterProvider, { router: routerRef.current }));
8304 };
8305}
8306function processRoutes(routes, context, manifest, routeModules, parentId) {
8307 return routes.map((route) => {
8308 if (!route.id) {
8309 throw new Error(
8310 "Expected a route.id in @remix-run/testing processRoutes() function"
8311 );
8312 }
8313 let { loader, action } = route;
8314 let newRoute = {
8315 id: route.id,
8316 path: route.path,
8317 index: route.index,
8318 Component: route.Component,
8319 HydrateFallback: route.HydrateFallback,
8320 ErrorBoundary: route.ErrorBoundary,
8321 action: action ? (args) => action({ ...args, context }) : void 0,
8322 loader: loader ? (args) => loader({ ...args, context }) : void 0,
8323 handle: route.handle,
8324 shouldRevalidate: route.shouldRevalidate
8325 };
8326 let entryRoute = {
8327 id: route.id,
8328 path: route.path,
8329 index: route.index,
8330 parentId,
8331 hasAction: route.action != null,
8332 hasLoader: route.loader != null,
8333 // When testing routes, you should just be stubbing loader/action, not
8334 // trying to re-implement the full loader/clientLoader/SSR/hydration flow.
8335 // That is better tested via E2E tests.
8336 hasClientAction: false,
8337 hasClientLoader: false,
8338 hasErrorBoundary: route.ErrorBoundary != null,
8339 module: "build/stub-path-to-module.js"
8340 // any need for this?
8341 };
8342 manifest.routes[newRoute.id] = entryRoute;
8343 routeModules[route.id] = {
8344 default: route.Component || Outlet,
8345 ErrorBoundary: route.ErrorBoundary || void 0,
8346 handle: route.handle,
8347 links: route.links,
8348 meta: route.meta,
8349 shouldRevalidate: route.shouldRevalidate
8350 };
8351 if (route.children) {
8352 newRoute.children = processRoutes(
8353 route.children,
8354 context,
8355 manifest,
8356 routeModules,
8357 newRoute.id
8358 );
8359 }
8360 return newRoute;
8361 });
8362}
8363
8364// lib/server-runtime/cookies.ts
8365var import_cookie = require("cookie");
8366
8367// lib/server-runtime/crypto.ts
8368var encoder = new TextEncoder();
8369var sign = async (value, secret) => {
8370 let data2 = encoder.encode(value);
8371 let key = await createKey2(secret, ["sign"]);
8372 let signature = await crypto.subtle.sign("HMAC", key, data2);
8373 let hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(
8374 /=+$/,
8375 ""
8376 );
8377 return value + "." + hash;
8378};
8379var unsign = async (cookie, secret) => {
8380 let index = cookie.lastIndexOf(".");
8381 let value = cookie.slice(0, index);
8382 let hash = cookie.slice(index + 1);
8383 let data2 = encoder.encode(value);
8384 let key = await createKey2(secret, ["verify"]);
8385 let signature = byteStringToUint8Array(atob(hash));
8386 let valid = await crypto.subtle.verify("HMAC", key, signature, data2);
8387 return valid ? value : false;
8388};
8389var createKey2 = async (secret, usages) => crypto.subtle.importKey(
8390 "raw",
8391 encoder.encode(secret),
8392 { name: "HMAC", hash: "SHA-256" },
8393 false,
8394 usages
8395);
8396function byteStringToUint8Array(byteString) {
8397 let array = new Uint8Array(byteString.length);
8398 for (let i = 0; i < byteString.length; i++) {
8399 array[i] = byteString.charCodeAt(i);
8400 }
8401 return array;
8402}
8403
8404// lib/server-runtime/cookies.ts
8405var createCookie = (name, cookieOptions = {}) => {
8406 let { secrets = [], ...options } = {
8407 path: "/",
8408 sameSite: "lax",
8409 ...cookieOptions
8410 };
8411 warnOnceAboutExpiresCookie(name, options.expires);
8412 return {
8413 get name() {
8414 return name;
8415 },
8416 get isSigned() {
8417 return secrets.length > 0;
8418 },
8419 get expires() {
8420 return typeof options.maxAge !== "undefined" ? new Date(Date.now() + options.maxAge * 1e3) : options.expires;
8421 },
8422 async parse(cookieHeader, parseOptions) {
8423 if (!cookieHeader) return null;
8424 let cookies = (0, import_cookie.parse)(cookieHeader, { ...options, ...parseOptions });
8425 if (name in cookies) {
8426 let value = cookies[name];
8427 if (typeof value === "string" && value !== "") {
8428 let decoded = await decodeCookieValue(value, secrets);
8429 return decoded;
8430 } else {
8431 return "";
8432 }
8433 } else {
8434 return null;
8435 }
8436 },
8437 async serialize(value, serializeOptions) {
8438 return (0, import_cookie.serialize)(
8439 name,
8440 value === "" ? "" : await encodeCookieValue(value, secrets),
8441 {
8442 ...options,
8443 ...serializeOptions
8444 }
8445 );
8446 }
8447 };
8448};
8449var isCookie = (object) => {
8450 return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function";
8451};
8452async function encodeCookieValue(value, secrets) {
8453 let encoded = encodeData(value);
8454 if (secrets.length > 0) {
8455 encoded = await sign(encoded, secrets[0]);
8456 }
8457 return encoded;
8458}
8459async function decodeCookieValue(value, secrets) {
8460 if (secrets.length > 0) {
8461 for (let secret of secrets) {
8462 let unsignedValue = await unsign(value, secret);
8463 if (unsignedValue !== false) {
8464 return decodeData(unsignedValue);
8465 }
8466 }
8467 return null;
8468 }
8469 return decodeData(value);
8470}
8471function encodeData(value) {
8472 return btoa(myUnescape(encodeURIComponent(JSON.stringify(value))));
8473}
8474function decodeData(value) {
8475 try {
8476 return JSON.parse(decodeURIComponent(myEscape(atob(value))));
8477 } catch (error) {
8478 return {};
8479 }
8480}
8481function myEscape(value) {
8482 let str = value.toString();
8483 let result = "";
8484 let index = 0;
8485 let chr, code;
8486 while (index < str.length) {
8487 chr = str.charAt(index++);
8488 if (/[\w*+\-./@]/.exec(chr)) {
8489 result += chr;
8490 } else {
8491 code = chr.charCodeAt(0);
8492 if (code < 256) {
8493 result += "%" + hex(code, 2);
8494 } else {
8495 result += "%u" + hex(code, 4).toUpperCase();
8496 }
8497 }
8498 }
8499 return result;
8500}
8501function hex(code, length) {
8502 let result = code.toString(16);
8503 while (result.length < length) result = "0" + result;
8504 return result;
8505}
8506function myUnescape(value) {
8507 let str = value.toString();
8508 let result = "";
8509 let index = 0;
8510 let chr, part;
8511 while (index < str.length) {
8512 chr = str.charAt(index++);
8513 if (chr === "%") {
8514 if (str.charAt(index) === "u") {
8515 part = str.slice(index + 1, index + 5);
8516 if (/^[\da-f]{4}$/i.exec(part)) {
8517 result += String.fromCharCode(parseInt(part, 16));
8518 index += 5;
8519 continue;
8520 }
8521 } else {
8522 part = str.slice(index, index + 2);
8523 if (/^[\da-f]{2}$/i.exec(part)) {
8524 result += String.fromCharCode(parseInt(part, 16));
8525 index += 2;
8526 continue;
8527 }
8528 }
8529 }
8530 result += chr;
8531 }
8532 return result;
8533}
8534function warnOnceAboutExpiresCookie(name, expires) {
8535 warnOnce(
8536 !expires,
8537 `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.`
8538 );
8539}
8540
8541// lib/server-runtime/entry.ts
8542function createEntryRouteModules(manifest) {
8543 return Object.keys(manifest).reduce((memo2, routeId) => {
8544 let route = manifest[routeId];
8545 if (route) {
8546 memo2[routeId] = route.module;
8547 }
8548 return memo2;
8549 }, {});
8550}
8551
8552// lib/server-runtime/mode.ts
8553var ServerMode = /* @__PURE__ */ ((ServerMode2) => {
8554 ServerMode2["Development"] = "development";
8555 ServerMode2["Production"] = "production";
8556 ServerMode2["Test"] = "test";
8557 return ServerMode2;
8558})(ServerMode || {});
8559function isServerMode(value) {
8560 return value === "development" /* Development */ || value === "production" /* Production */ || value === "test" /* Test */;
8561}
8562
8563// lib/server-runtime/errors.ts
8564function sanitizeError(error, serverMode) {
8565 if (error instanceof Error && serverMode !== "development" /* Development */) {
8566 let sanitized = new Error("Unexpected Server Error");
8567 sanitized.stack = void 0;
8568 return sanitized;
8569 }
8570 return error;
8571}
8572function sanitizeErrors(errors, serverMode) {
8573 return Object.entries(errors).reduce((acc, [routeId, error]) => {
8574 return Object.assign(acc, { [routeId]: sanitizeError(error, serverMode) });
8575 }, {});
8576}
8577function serializeError(error, serverMode) {
8578 let sanitized = sanitizeError(error, serverMode);
8579 return {
8580 message: sanitized.message,
8581 stack: sanitized.stack
8582 };
8583}
8584function serializeErrors2(errors, serverMode) {
8585 if (!errors) return null;
8586 let entries = Object.entries(errors);
8587 let serialized = {};
8588 for (let [key, val] of entries) {
8589 if (isRouteErrorResponse(val)) {
8590 serialized[key] = { ...val, __type: "RouteErrorResponse" };
8591 } else if (val instanceof Error) {
8592 let sanitized = sanitizeError(val, serverMode);
8593 serialized[key] = {
8594 message: sanitized.message,
8595 stack: sanitized.stack,
8596 __type: "Error",
8597 // If this is a subclass (i.e., ReferenceError), send up the type so we
8598 // can re-create the same type during hydration. This will only apply
8599 // in dev mode since all production errors are sanitized to normal
8600 // Error instances
8601 ...sanitized.name !== "Error" ? {
8602 __subType: sanitized.name
8603 } : {}
8604 };
8605 } else {
8606 serialized[key] = val;
8607 }
8608 }
8609 return serialized;
8610}
8611
8612// lib/server-runtime/routeMatching.ts
8613function matchServerRoutes(routes, pathname, basename) {
8614 let matches = matchRoutes(
8615 routes,
8616 pathname,
8617 basename
8618 );
8619 if (!matches) return null;
8620 return matches.map((match) => ({
8621 params: match.params,
8622 pathname: match.pathname,
8623 route: match.route
8624 }));
8625}
8626
8627// lib/server-runtime/data.ts
8628async function callRouteHandler(handler, args) {
8629 let result = await handler({
8630 request: stripRoutesParam(stripIndexParam2(args.request)),
8631 params: args.params,
8632 context: args.context
8633 });
8634 if (isDataWithResponseInit(result) && result.init && result.init.status && isRedirectStatusCode(result.init.status)) {
8635 throw new Response(null, result.init);
8636 }
8637 return result;
8638}
8639function stripIndexParam2(request) {
8640 let url = new URL(request.url);
8641 let indexValues = url.searchParams.getAll("index");
8642 url.searchParams.delete("index");
8643 let indexValuesToKeep = [];
8644 for (let indexValue of indexValues) {
8645 if (indexValue) {
8646 indexValuesToKeep.push(indexValue);
8647 }
8648 }
8649 for (let toKeep of indexValuesToKeep) {
8650 url.searchParams.append("index", toKeep);
8651 }
8652 let init = {
8653 method: request.method,
8654 body: request.body,
8655 headers: request.headers,
8656 signal: request.signal
8657 };
8658 if (init.body) {
8659 init.duplex = "half";
8660 }
8661 return new Request(url.href, init);
8662}
8663function stripRoutesParam(request) {
8664 let url = new URL(request.url);
8665 url.searchParams.delete("_routes");
8666 let init = {
8667 method: request.method,
8668 body: request.body,
8669 headers: request.headers,
8670 signal: request.signal
8671 };
8672 if (init.body) {
8673 init.duplex = "half";
8674 }
8675 return new Request(url.href, init);
8676}
8677
8678// lib/server-runtime/invariant.ts
8679function invariant3(value, message) {
8680 if (value === false || value === null || typeof value === "undefined") {
8681 console.error(
8682 "The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose"
8683 );
8684 throw new Error(message);
8685 }
8686}
8687
8688// lib/server-runtime/routes.ts
8689function groupRoutesByParentId2(manifest) {
8690 let routes = {};
8691 Object.values(manifest).forEach((route) => {
8692 if (route) {
8693 let parentId = route.parentId || "";
8694 if (!routes[parentId]) {
8695 routes[parentId] = [];
8696 }
8697 routes[parentId].push(route);
8698 }
8699 });
8700 return routes;
8701}
8702function createRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
8703 return (routesByParentId[parentId] || []).map((route) => ({
8704 ...route,
8705 children: createRoutes(manifest, route.id, routesByParentId)
8706 }));
8707}
8708function createStaticHandlerDataRoutes(manifest, future, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
8709 return (routesByParentId[parentId] || []).map((route) => {
8710 let commonRoute = {
8711 // Always include root due to default boundaries
8712 hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
8713 id: route.id,
8714 path: route.path,
8715 // Need to use RR's version in the param typed here to permit the optional
8716 // context even though we know it'll always be provided in remix
8717 loader: route.module.loader ? async (args) => {
8718 if (args.request.headers.has("X-React-Router-Prerender-Data")) {
8719 const preRenderedData = args.request.headers.get(
8720 "X-React-Router-Prerender-Data"
8721 );
8722 let encoded = preRenderedData ? decodeURI(preRenderedData) : preRenderedData;
8723 invariant3(encoded, "Missing prerendered data for route");
8724 let uint8array = new TextEncoder().encode(encoded);
8725 let stream = new ReadableStream({
8726 start(controller) {
8727 controller.enqueue(uint8array);
8728 controller.close();
8729 }
8730 });
8731 let decoded = await decodeViaTurboStream(stream, global);
8732 let data2 = decoded.value;
8733 invariant3(
8734 data2 && route.id in data2,
8735 "Unable to decode prerendered data"
8736 );
8737 let result = data2[route.id];
8738 invariant3("data" in result, "Unable to process prerendered data");
8739 return result.data;
8740 }
8741 let val = await callRouteHandler(route.module.loader, args);
8742 return val;
8743 } : void 0,
8744 action: route.module.action ? (args) => callRouteHandler(route.module.action, args) : void 0,
8745 handle: route.module.handle
8746 };
8747 return route.index ? {
8748 index: true,
8749 ...commonRoute
8750 } : {
8751 caseSensitive: route.caseSensitive,
8752 children: createStaticHandlerDataRoutes(
8753 manifest,
8754 future,
8755 route.id,
8756 routesByParentId
8757 ),
8758 ...commonRoute
8759 };
8760 });
8761}
8762
8763// lib/server-runtime/markup.ts
8764var ESCAPE_LOOKUP3 = {
8765 "&": "\\u0026",
8766 ">": "\\u003e",
8767 "<": "\\u003c",
8768 "\u2028": "\\u2028",
8769 "\u2029": "\\u2029"
8770};
8771var ESCAPE_REGEX3 = /[&><\u2028\u2029]/g;
8772function escapeHtml2(html) {
8773 return html.replace(ESCAPE_REGEX3, (match) => ESCAPE_LOOKUP3[match]);
8774}
8775
8776// lib/server-runtime/serverHandoff.ts
8777function createServerHandoffString(serverHandoff) {
8778 return escapeHtml2(JSON.stringify(serverHandoff));
8779}
8780
8781// lib/server-runtime/dev.ts
8782var globalDevServerHooksKey = "__reactRouterDevServerHooks";
8783function setDevServerHooks(devServerHooks) {
8784 globalThis[globalDevServerHooksKey] = devServerHooks;
8785}
8786function getDevServerHooks() {
8787 return globalThis[globalDevServerHooksKey];
8788}
8789
8790// lib/server-runtime/single-fetch.ts
8791var import_turbo_stream2 = require("turbo-stream");
8792
8793// lib/server-runtime/headers.ts
8794var import_set_cookie_parser = require("set-cookie-parser");
8795function getDocumentHeaders(build, context) {
8796 let boundaryIdx = context.errors ? context.matches.findIndex((m) => context.errors[m.route.id]) : -1;
8797 let matches = boundaryIdx >= 0 ? context.matches.slice(0, boundaryIdx + 1) : context.matches;
8798 let errorHeaders;
8799 if (boundaryIdx >= 0) {
8800 let { actionHeaders, actionData, loaderHeaders, loaderData } = context;
8801 context.matches.slice(boundaryIdx).some((match) => {
8802 let id = match.route.id;
8803 if (actionHeaders[id] && (!actionData || !actionData.hasOwnProperty(id))) {
8804 errorHeaders = actionHeaders[id];
8805 } else if (loaderHeaders[id] && !loaderData.hasOwnProperty(id)) {
8806 errorHeaders = loaderHeaders[id];
8807 }
8808 return errorHeaders != null;
8809 });
8810 }
8811 return matches.reduce((parentHeaders, match, idx) => {
8812 let { id } = match.route;
8813 let route = build.routes[id];
8814 invariant3(route, `Route with id "${id}" not found in build`);
8815 let routeModule = route.module;
8816 let loaderHeaders = context.loaderHeaders[id] || new Headers();
8817 let actionHeaders = context.actionHeaders[id] || new Headers();
8818 let includeErrorHeaders = errorHeaders != null && idx === matches.length - 1;
8819 let includeErrorCookies = includeErrorHeaders && errorHeaders !== loaderHeaders && errorHeaders !== actionHeaders;
8820 if (routeModule.headers == null) {
8821 let headers2 = new Headers(parentHeaders);
8822 if (includeErrorCookies) {
8823 prependCookies(errorHeaders, headers2);
8824 }
8825 prependCookies(actionHeaders, headers2);
8826 prependCookies(loaderHeaders, headers2);
8827 return headers2;
8828 }
8829 let headers = new Headers(
8830 routeModule.headers ? typeof routeModule.headers === "function" ? routeModule.headers({
8831 loaderHeaders,
8832 parentHeaders,
8833 actionHeaders,
8834 errorHeaders: includeErrorHeaders ? errorHeaders : void 0
8835 }) : routeModule.headers : void 0
8836 );
8837 if (includeErrorCookies) {
8838 prependCookies(errorHeaders, headers);
8839 }
8840 prependCookies(actionHeaders, headers);
8841 prependCookies(loaderHeaders, headers);
8842 prependCookies(parentHeaders, headers);
8843 return headers;
8844 }, new Headers());
8845}
8846function prependCookies(parentHeaders, childHeaders) {
8847 let parentSetCookieString = parentHeaders.get("Set-Cookie");
8848 if (parentSetCookieString) {
8849 let cookies = (0, import_set_cookie_parser.splitCookiesString)(parentSetCookieString);
8850 cookies.forEach((cookie) => {
8851 childHeaders.append("Set-Cookie", cookie);
8852 });
8853 }
8854}
8855
8856// lib/server-runtime/single-fetch.ts
8857var SINGLE_FETCH_REDIRECT_STATUS = 202;
8858function getSingleFetchDataStrategy2({
8859 isActionDataRequest,
8860 loadRouteIds
8861} = {}) {
8862 return async ({ request, matches }) => {
8863 if (isActionDataRequest && request.method === "GET") {
8864 return {};
8865 }
8866 let matchesToLoad = loadRouteIds ? matches.filter((m) => loadRouteIds.includes(m.route.id)) : matches;
8867 let results = await Promise.all(
8868 matchesToLoad.map((match) => match.resolve())
8869 );
8870 return results.reduce(
8871 (acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
8872 {}
8873 );
8874 };
8875}
8876async function singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
8877 try {
8878 let handlerRequest = new Request(handlerUrl, {
8879 method: request.method,
8880 body: request.body,
8881 headers: request.headers,
8882 signal: request.signal,
8883 ...request.body ? { duplex: "half" } : void 0
8884 });
8885 let result = await staticHandler.query(handlerRequest, {
8886 requestContext: loadContext,
8887 skipLoaderErrorBubbling: true,
8888 dataStrategy: getSingleFetchDataStrategy2({
8889 isActionDataRequest: true
8890 })
8891 });
8892 if (isResponse(result)) {
8893 return {
8894 result: getSingleFetchRedirect(
8895 result.status,
8896 result.headers,
8897 build.basename
8898 ),
8899 headers: result.headers,
8900 status: SINGLE_FETCH_REDIRECT_STATUS
8901 };
8902 }
8903 let context = result;
8904 let headers = getDocumentHeaders(build, context);
8905 if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
8906 return {
8907 result: getSingleFetchRedirect(
8908 context.statusCode,
8909 headers,
8910 build.basename
8911 ),
8912 headers,
8913 status: SINGLE_FETCH_REDIRECT_STATUS
8914 };
8915 }
8916 if (context.errors) {
8917 Object.values(context.errors).forEach((err) => {
8918 if (!isRouteErrorResponse(err) || err.error) {
8919 handleError(err);
8920 }
8921 });
8922 context.errors = sanitizeErrors(context.errors, serverMode);
8923 }
8924 let singleFetchResult;
8925 if (context.errors) {
8926 singleFetchResult = { error: Object.values(context.errors)[0] };
8927 } else {
8928 singleFetchResult = { data: Object.values(context.actionData || {})[0] };
8929 }
8930 return {
8931 result: singleFetchResult,
8932 headers,
8933 status: context.statusCode
8934 };
8935 } catch (error) {
8936 handleError(error);
8937 return {
8938 result: { error },
8939 headers: new Headers(),
8940 status: 500
8941 };
8942 }
8943}
8944async function singleFetchLoaders(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
8945 try {
8946 let handlerRequest = new Request(handlerUrl, {
8947 headers: request.headers,
8948 signal: request.signal
8949 });
8950 let loadRouteIds = new URL(request.url).searchParams.get("_routes")?.split(",") || void 0;
8951 let result = await staticHandler.query(handlerRequest, {
8952 requestContext: loadContext,
8953 skipLoaderErrorBubbling: true,
8954 dataStrategy: getSingleFetchDataStrategy2({
8955 loadRouteIds
8956 })
8957 });
8958 if (isResponse(result)) {
8959 return {
8960 result: {
8961 [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
8962 result.status,
8963 result.headers,
8964 build.basename
8965 )
8966 },
8967 headers: result.headers,
8968 status: SINGLE_FETCH_REDIRECT_STATUS
8969 };
8970 }
8971 let context = result;
8972 let headers = getDocumentHeaders(build, context);
8973 if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
8974 return {
8975 result: {
8976 [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
8977 context.statusCode,
8978 headers,
8979 build.basename
8980 )
8981 },
8982 headers,
8983 status: SINGLE_FETCH_REDIRECT_STATUS
8984 };
8985 }
8986 if (context.errors) {
8987 Object.values(context.errors).forEach((err) => {
8988 if (!isRouteErrorResponse(err) || err.error) {
8989 handleError(err);
8990 }
8991 });
8992 context.errors = sanitizeErrors(context.errors, serverMode);
8993 }
8994 let results = {};
8995 let loadedMatches = loadRouteIds ? context.matches.filter(
8996 (m) => m.route.loader && loadRouteIds.includes(m.route.id)
8997 ) : context.matches;
8998 loadedMatches.forEach((m) => {
8999 let { id } = m.route;
9000 if (context.errors && context.errors.hasOwnProperty(id)) {
9001 results[id] = { error: context.errors[id] };
9002 } else if (context.loaderData.hasOwnProperty(id)) {
9003 results[id] = { data: context.loaderData[id] };
9004 }
9005 });
9006 return {
9007 result: results,
9008 headers,
9009 status: context.statusCode
9010 };
9011 } catch (error) {
9012 handleError(error);
9013 return {
9014 result: { root: { error } },
9015 headers: new Headers(),
9016 status: 500
9017 };
9018 }
9019}
9020function getSingleFetchRedirect(status, headers, basename) {
9021 let redirect2 = headers.get("Location");
9022 if (basename) {
9023 redirect2 = stripBasename(redirect2, basename) || redirect2;
9024 }
9025 return {
9026 redirect: redirect2,
9027 status,
9028 revalidate: (
9029 // Technically X-Remix-Revalidate isn't needed here - that was an implementation
9030 // detail of ?_data requests as our way to tell the front end to revalidate when
9031 // we didn't have a response body to include that information in.
9032 // With single fetch, we tell the front end via this revalidate boolean field.
9033 // However, we're respecting it for now because it may be something folks have
9034 // used in their own responses
9035 // TODO(v3): Consider removing or making this official public API
9036 headers.has("X-Remix-Revalidate") || headers.has("Set-Cookie")
9037 ),
9038 reload: headers.has("X-Remix-Reload-Document"),
9039 replace: headers.has("X-Remix-Replace")
9040 };
9041}
9042function encodeViaTurboStream(data2, requestSignal, streamTimeout, serverMode) {
9043 let controller = new AbortController();
9044 let timeoutId = setTimeout(
9045 () => controller.abort(new Error("Server Timeout")),
9046 typeof streamTimeout === "number" ? streamTimeout : 4950
9047 );
9048 requestSignal.addEventListener("abort", () => clearTimeout(timeoutId));
9049 return (0, import_turbo_stream2.encode)(data2, {
9050 signal: controller.signal,
9051 plugins: [
9052 (value) => {
9053 if (value instanceof Error) {
9054 let { name, message, stack } = serverMode === "production" /* Production */ ? sanitizeError(value, serverMode) : value;
9055 return ["SanitizedError", name, message, stack];
9056 }
9057 if (value instanceof ErrorResponseImpl) {
9058 let { data: data3, status, statusText } = value;
9059 return ["ErrorResponse", data3, status, statusText];
9060 }
9061 if (value && typeof value === "object" && SingleFetchRedirectSymbol in value) {
9062 return ["SingleFetchRedirect", value[SingleFetchRedirectSymbol]];
9063 }
9064 }
9065 ],
9066 postPlugins: [
9067 (value) => {
9068 if (!value) return;
9069 if (typeof value !== "object") return;
9070 return [
9071 "SingleFetchClassInstance",
9072 Object.fromEntries(Object.entries(value))
9073 ];
9074 },
9075 () => ["SingleFetchFallback"]
9076 ]
9077 });
9078}
9079
9080// lib/server-runtime/server.ts
9081function derive(build, mode) {
9082 let routes = createRoutes(build.routes);
9083 let dataRoutes = createStaticHandlerDataRoutes(build.routes, build.future);
9084 let serverMode = isServerMode(mode) ? mode : "production" /* Production */;
9085 let staticHandler = createStaticHandler(dataRoutes, {
9086 basename: build.basename
9087 });
9088 let errorHandler = build.entry.module.handleError || ((error, { request }) => {
9089 if (serverMode !== "test" /* Test */ && !request.signal.aborted) {
9090 console.error(
9091 // @ts-expect-error This is "private" from users but intended for internal use
9092 isRouteErrorResponse(error) && error.error ? error.error : error
9093 );
9094 }
9095 });
9096 return {
9097 routes,
9098 dataRoutes,
9099 serverMode,
9100 staticHandler,
9101 errorHandler
9102 };
9103}
9104var createRequestHandler = (build, mode) => {
9105 let _build;
9106 let routes;
9107 let serverMode;
9108 let staticHandler;
9109 let errorHandler;
9110 return async function requestHandler(request, loadContext = {}) {
9111 _build = typeof build === "function" ? await build() : build;
9112 if (typeof build === "function") {
9113 let derived = derive(_build, mode);
9114 routes = derived.routes;
9115 serverMode = derived.serverMode;
9116 staticHandler = derived.staticHandler;
9117 errorHandler = derived.errorHandler;
9118 } else if (!routes || !serverMode || !staticHandler || !errorHandler) {
9119 let derived = derive(_build, mode);
9120 routes = derived.routes;
9121 serverMode = derived.serverMode;
9122 staticHandler = derived.staticHandler;
9123 errorHandler = derived.errorHandler;
9124 }
9125 let url = new URL(request.url);
9126 let params = {};
9127 let handleError = (error) => {
9128 if (mode === "development" /* Development */) {
9129 getDevServerHooks()?.processRequestError?.(error);
9130 }
9131 errorHandler(error, {
9132 context: loadContext,
9133 params,
9134 request
9135 });
9136 };
9137 let manifestUrl = `${_build.basename ?? "/"}/__manifest`.replace(
9138 /\/+/g,
9139 "/"
9140 );
9141 if (url.pathname === manifestUrl) {
9142 try {
9143 let res = await handleManifestRequest(_build, routes, url);
9144 return res;
9145 } catch (e) {
9146 handleError(e);
9147 return new Response("Unknown Server Error", { status: 500 });
9148 }
9149 }
9150 let matches = matchServerRoutes(routes, url.pathname, _build.basename);
9151 if (matches && matches.length > 0) {
9152 Object.assign(params, matches[0].params);
9153 }
9154 let response;
9155 if (url.pathname.endsWith(".data")) {
9156 let handlerUrl = new URL(request.url);
9157 handlerUrl.pathname = handlerUrl.pathname.replace(/\.data$/, "").replace(/^\/_root$/, "/");
9158 let singleFetchMatches = matchServerRoutes(
9159 routes,
9160 handlerUrl.pathname,
9161 _build.basename
9162 );
9163 response = await handleSingleFetchRequest(
9164 serverMode,
9165 _build,
9166 staticHandler,
9167 request,
9168 handlerUrl,
9169 loadContext,
9170 handleError
9171 );
9172 if (_build.entry.module.handleDataRequest) {
9173 response = await _build.entry.module.handleDataRequest(response, {
9174 context: loadContext,
9175 params: singleFetchMatches ? singleFetchMatches[0].params : {},
9176 request
9177 });
9178 if (isRedirectResponse(response)) {
9179 let result = getSingleFetchRedirect(
9180 response.status,
9181 response.headers,
9182 _build.basename
9183 );
9184 if (request.method === "GET") {
9185 result = {
9186 [SingleFetchRedirectSymbol]: result
9187 };
9188 }
9189 let headers = new Headers(response.headers);
9190 headers.set("Content-Type", "text/x-script");
9191 return new Response(
9192 encodeViaTurboStream(
9193 result,
9194 request.signal,
9195 _build.entry.module.streamTimeout,
9196 serverMode
9197 ),
9198 {
9199 status: SINGLE_FETCH_REDIRECT_STATUS,
9200 headers
9201 }
9202 );
9203 }
9204 }
9205 } else if (matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
9206 response = await handleResourceRequest(
9207 serverMode,
9208 staticHandler,
9209 matches.slice(-1)[0].route.id,
9210 request,
9211 loadContext,
9212 handleError
9213 );
9214 } else {
9215 let criticalCss = mode === "development" /* Development */ ? await getDevServerHooks()?.getCriticalCss?.(_build, url.pathname) : void 0;
9216 response = await handleDocumentRequest(
9217 serverMode,
9218 _build,
9219 staticHandler,
9220 request,
9221 loadContext,
9222 handleError,
9223 criticalCss
9224 );
9225 }
9226 if (request.method === "HEAD") {
9227 return new Response(null, {
9228 headers: response.headers,
9229 status: response.status,
9230 statusText: response.statusText
9231 });
9232 }
9233 return response;
9234 };
9235};
9236async function handleManifestRequest(build, routes, url) {
9237 let patches = {};
9238 if (url.searchParams.has("p")) {
9239 for (let path of url.searchParams.getAll("p")) {
9240 let matches = matchServerRoutes(routes, path, build.basename);
9241 if (matches) {
9242 for (let match of matches) {
9243 let routeId = match.route.id;
9244 let route = build.assets.routes[routeId];
9245 if (route) {
9246 patches[routeId] = route;
9247 }
9248 }
9249 }
9250 }
9251 return Response.json(patches, {
9252 headers: {
9253 "Cache-Control": "public, max-age=31536000, immutable"
9254 }
9255 });
9256 }
9257 return new Response("Invalid Request", { status: 400 });
9258}
9259async function handleSingleFetchRequest(serverMode, build, staticHandler, request, handlerUrl, loadContext, handleError) {
9260 let { result, headers, status } = request.method !== "GET" ? await singleFetchAction(
9261 build,
9262 serverMode,
9263 staticHandler,
9264 request,
9265 handlerUrl,
9266 loadContext,
9267 handleError
9268 ) : await singleFetchLoaders(
9269 build,
9270 serverMode,
9271 staticHandler,
9272 request,
9273 handlerUrl,
9274 loadContext,
9275 handleError
9276 );
9277 let resultHeaders = new Headers(headers);
9278 resultHeaders.set("X-Remix-Response", "yes");
9279 if (status === 304) {
9280 return new Response(null, { status: 304, headers: resultHeaders });
9281 }
9282 resultHeaders.set("Content-Type", "text/x-script");
9283 return new Response(
9284 encodeViaTurboStream(
9285 result,
9286 request.signal,
9287 build.entry.module.streamTimeout,
9288 serverMode
9289 ),
9290 {
9291 status: status || 200,
9292 headers: resultHeaders
9293 }
9294 );
9295}
9296async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {
9297 let context;
9298 try {
9299 context = await staticHandler.query(request, {
9300 requestContext: loadContext
9301 });
9302 } catch (error) {
9303 handleError(error);
9304 return new Response(null, { status: 500 });
9305 }
9306 if (isResponse(context)) {
9307 return context;
9308 }
9309 let headers = getDocumentHeaders(build, context);
9310 if (context.statusCode === 304) {
9311 return new Response(null, { status: 304, headers });
9312 }
9313 if (context.errors) {
9314 Object.values(context.errors).forEach((err) => {
9315 if (!isRouteErrorResponse(err) || err.error) {
9316 handleError(err);
9317 }
9318 });
9319 context.errors = sanitizeErrors(context.errors, serverMode);
9320 }
9321 let state = {
9322 loaderData: context.loaderData,
9323 actionData: context.actionData,
9324 errors: serializeErrors2(context.errors, serverMode)
9325 };
9326 let entryContext = {
9327 manifest: build.assets,
9328 routeModules: createEntryRouteModules(build.routes),
9329 staticHandlerContext: context,
9330 criticalCss,
9331 serverHandoffString: createServerHandoffString({
9332 basename: build.basename,
9333 criticalCss,
9334 future: build.future,
9335 isSpaMode: build.isSpaMode
9336 }),
9337 serverHandoffStream: encodeViaTurboStream(
9338 state,
9339 request.signal,
9340 build.entry.module.streamTimeout,
9341 serverMode
9342 ),
9343 renderMeta: {},
9344 future: build.future,
9345 isSpaMode: build.isSpaMode,
9346 serializeError: (err) => serializeError(err, serverMode)
9347 };
9348 let handleDocumentRequestFunction = build.entry.module.default;
9349 try {
9350 return await handleDocumentRequestFunction(
9351 request,
9352 context.statusCode,
9353 headers,
9354 entryContext,
9355 loadContext
9356 );
9357 } catch (error) {
9358 handleError(error);
9359 let errorForSecondRender = error;
9360 if (isResponse(error)) {
9361 try {
9362 let data2 = await unwrapResponse(error);
9363 errorForSecondRender = new ErrorResponseImpl(
9364 error.status,
9365 error.statusText,
9366 data2
9367 );
9368 } catch (e) {
9369 }
9370 }
9371 context = getStaticContextFromError(
9372 staticHandler.dataRoutes,
9373 context,
9374 errorForSecondRender
9375 );
9376 if (context.errors) {
9377 context.errors = sanitizeErrors(context.errors, serverMode);
9378 }
9379 let state2 = {
9380 loaderData: context.loaderData,
9381 actionData: context.actionData,
9382 errors: serializeErrors2(context.errors, serverMode)
9383 };
9384 entryContext = {
9385 ...entryContext,
9386 staticHandlerContext: context,
9387 serverHandoffString: createServerHandoffString({
9388 basename: build.basename,
9389 future: build.future,
9390 isSpaMode: build.isSpaMode
9391 }),
9392 serverHandoffStream: encodeViaTurboStream(
9393 state2,
9394 request.signal,
9395 build.entry.module.streamTimeout,
9396 serverMode
9397 ),
9398 renderMeta: {}
9399 };
9400 try {
9401 return await handleDocumentRequestFunction(
9402 request,
9403 context.statusCode,
9404 headers,
9405 entryContext,
9406 loadContext
9407 );
9408 } catch (error2) {
9409 handleError(error2);
9410 return returnLastResortErrorResponse(error2, serverMode);
9411 }
9412 }
9413}
9414async function handleResourceRequest(serverMode, staticHandler, routeId, request, loadContext, handleError) {
9415 try {
9416 let response = await staticHandler.queryRoute(request, {
9417 routeId,
9418 requestContext: loadContext
9419 });
9420 invariant3(
9421 isResponse(response),
9422 "Expected a Response to be returned from resource route handler"
9423 );
9424 return response;
9425 } catch (error) {
9426 if (isResponse(error)) {
9427 error.headers.set("X-Remix-Catch", "yes");
9428 return error;
9429 }
9430 if (isRouteErrorResponse(error)) {
9431 if (error) {
9432 handleError(error);
9433 }
9434 return errorResponseToJson(error, serverMode);
9435 }
9436 handleError(error);
9437 return returnLastResortErrorResponse(error, serverMode);
9438 }
9439}
9440function errorResponseToJson(errorResponse, serverMode) {
9441 return Response.json(
9442 serializeError(
9443 // @ts-expect-error This is "private" from users but intended for internal use
9444 errorResponse.error || new Error("Unexpected Server Error"),
9445 serverMode
9446 ),
9447 {
9448 status: errorResponse.status,
9449 statusText: errorResponse.statusText,
9450 headers: {
9451 "X-Remix-Error": "yes"
9452 }
9453 }
9454 );
9455}
9456function returnLastResortErrorResponse(error, serverMode) {
9457 let message = "Unexpected Server Error";
9458 if (serverMode !== "production" /* Production */) {
9459 message += `
9460
9461${String(error)}`;
9462 }
9463 return new Response(message, {
9464 status: 500,
9465 headers: {
9466 "Content-Type": "text/plain"
9467 }
9468 });
9469}
9470function unwrapResponse(response) {
9471 let contentType = response.headers.get("Content-Type");
9472 return contentType && /\bapplication\/json\b/.test(contentType) ? response.body == null ? null : response.json() : response.text();
9473}
9474
9475// lib/server-runtime/sessions.ts
9476function flash(name) {
9477 return `__flash_${name}__`;
9478}
9479var createSession = (initialData = {}, id = "") => {
9480 let map = new Map(Object.entries(initialData));
9481 return {
9482 get id() {
9483 return id;
9484 },
9485 get data() {
9486 return Object.fromEntries(map);
9487 },
9488 has(name) {
9489 return map.has(name) || map.has(flash(name));
9490 },
9491 get(name) {
9492 if (map.has(name)) return map.get(name);
9493 let flashName = flash(name);
9494 if (map.has(flashName)) {
9495 let value = map.get(flashName);
9496 map.delete(flashName);
9497 return value;
9498 }
9499 return void 0;
9500 },
9501 set(name, value) {
9502 map.set(name, value);
9503 },
9504 flash(name, value) {
9505 map.set(flash(name), value);
9506 },
9507 unset(name) {
9508 map.delete(name);
9509 }
9510 };
9511};
9512var isSession = (object) => {
9513 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";
9514};
9515function createSessionStorage({
9516 cookie: cookieArg,
9517 createData,
9518 readData,
9519 updateData,
9520 deleteData
9521}) {
9522 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
9523 warnOnceAboutSigningSessionCookie(cookie);
9524 return {
9525 async getSession(cookieHeader, options) {
9526 let id = cookieHeader && await cookie.parse(cookieHeader, options);
9527 let data2 = id && await readData(id);
9528 return createSession(data2 || {}, id || "");
9529 },
9530 async commitSession(session, options) {
9531 let { id, data: data2 } = session;
9532 let expires = options?.maxAge != null ? new Date(Date.now() + options.maxAge * 1e3) : options?.expires != null ? options.expires : cookie.expires;
9533 if (id) {
9534 await updateData(id, data2, expires);
9535 } else {
9536 id = await createData(data2, expires);
9537 }
9538 return cookie.serialize(id, options);
9539 },
9540 async destroySession(session, options) {
9541 await deleteData(session.id);
9542 return cookie.serialize("", {
9543 ...options,
9544 maxAge: void 0,
9545 expires: /* @__PURE__ */ new Date(0)
9546 });
9547 }
9548 };
9549}
9550function warnOnceAboutSigningSessionCookie(cookie) {
9551 warnOnce(
9552 cookie.isSigned,
9553 `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.`
9554 );
9555}
9556
9557// lib/server-runtime/sessions/cookieStorage.ts
9558function createCookieSessionStorage({ cookie: cookieArg } = {}) {
9559 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
9560 warnOnceAboutSigningSessionCookie(cookie);
9561 return {
9562 async getSession(cookieHeader, options) {
9563 return createSession(
9564 cookieHeader && await cookie.parse(cookieHeader, options) || {}
9565 );
9566 },
9567 async commitSession(session, options) {
9568 let serializedCookie = await cookie.serialize(session.data, options);
9569 if (serializedCookie.length > 4096) {
9570 throw new Error(
9571 "Cookie length will exceed browser maximum. Length: " + serializedCookie.length
9572 );
9573 }
9574 return serializedCookie;
9575 },
9576 async destroySession(_session, options) {
9577 return cookie.serialize("", {
9578 ...options,
9579 maxAge: void 0,
9580 expires: /* @__PURE__ */ new Date(0)
9581 });
9582 }
9583 };
9584}
9585
9586// lib/server-runtime/sessions/memoryStorage.ts
9587function createMemorySessionStorage({ cookie } = {}) {
9588 let map = /* @__PURE__ */ new Map();
9589 return createSessionStorage({
9590 cookie,
9591 async createData(data2, expires) {
9592 let id = Math.random().toString(36).substring(2, 10);
9593 map.set(id, { data: data2, expires });
9594 return id;
9595 },
9596 async readData(id) {
9597 if (map.has(id)) {
9598 let { data: data2, expires } = map.get(id);
9599 if (!expires || expires > /* @__PURE__ */ new Date()) {
9600 return data2;
9601 }
9602 if (expires) map.delete(id);
9603 }
9604 return null;
9605 },
9606 async updateData(id, data2, expires) {
9607 map.set(id, { data: data2, expires });
9608 },
9609 async deleteData(id) {
9610 map.delete(id);
9611 }
9612 });
9613}
9614
9615// lib/dom/ssr/errors.ts
9616function deserializeErrors2(errors) {
9617 if (!errors) return null;
9618 let entries = Object.entries(errors);
9619 let serialized = {};
9620 for (let [key, val] of entries) {
9621 if (val && val.__type === "RouteErrorResponse") {
9622 serialized[key] = new ErrorResponseImpl(
9623 val.status,
9624 val.statusText,
9625 val.data,
9626 val.internal === true
9627 );
9628 } else if (val && val.__type === "Error") {
9629 if (val.__subType) {
9630 let ErrorConstructor = window[val.__subType];
9631 if (typeof ErrorConstructor === "function") {
9632 try {
9633 let error = new ErrorConstructor(val.message);
9634 error.stack = val.stack;
9635 serialized[key] = error;
9636 } catch (e) {
9637 }
9638 }
9639 }
9640 if (serialized[key] == null) {
9641 let error = new Error(val.message);
9642 error.stack = val.stack;
9643 serialized[key] = error;
9644 }
9645 } else {
9646 serialized[key] = val;
9647 }
9648 }
9649 return serialized;
9650}
9651// Annotate the CommonJS export names for ESM import in node:
96520 && (module.exports = {
9653 Await,
9654 BrowserRouter,
9655 Form,
9656 HashRouter,
9657 IDLE_BLOCKER,
9658 IDLE_FETCHER,
9659 IDLE_NAVIGATION,
9660 Link,
9661 Links,
9662 MemoryRouter,
9663 Meta,
9664 NavLink,
9665 Navigate,
9666 NavigationType,
9667 Outlet,
9668 PrefetchPageLinks,
9669 Route,
9670 Router,
9671 RouterProvider,
9672 Routes,
9673 Scripts,
9674 ScrollRestoration,
9675 ServerRouter,
9676 StaticRouter,
9677 StaticRouterProvider,
9678 UNSAFE_DataRouterContext,
9679 UNSAFE_DataRouterStateContext,
9680 UNSAFE_ErrorResponseImpl,
9681 UNSAFE_FetchersContext,
9682 UNSAFE_FrameworkContext,
9683 UNSAFE_LocationContext,
9684 UNSAFE_NavigationContext,
9685 UNSAFE_RemixErrorBoundary,
9686 UNSAFE_RouteContext,
9687 UNSAFE_ServerMode,
9688 UNSAFE_SingleFetchRedirectSymbol,
9689 UNSAFE_ViewTransitionContext,
9690 UNSAFE_createBrowserHistory,
9691 UNSAFE_createClientRoutes,
9692 UNSAFE_createClientRoutesWithHMRRevalidationOptOut,
9693 UNSAFE_createRouter,
9694 UNSAFE_decodeViaTurboStream,
9695 UNSAFE_deserializeErrors,
9696 UNSAFE_getPatchRoutesOnNavigationFunction,
9697 UNSAFE_getSingleFetchDataStrategy,
9698 UNSAFE_invariant,
9699 UNSAFE_mapRouteProperties,
9700 UNSAFE_shouldHydrateRouteLoader,
9701 UNSAFE_useFogOFWarDiscovery,
9702 UNSAFE_useScrollRestoration,
9703 createBrowserRouter,
9704 createCookie,
9705 createCookieSessionStorage,
9706 createHashRouter,
9707 createMemoryRouter,
9708 createMemorySessionStorage,
9709 createPath,
9710 createRequestHandler,
9711 createRoutesFromChildren,
9712 createRoutesFromElements,
9713 createRoutesStub,
9714 createSearchParams,
9715 createSession,
9716 createSessionStorage,
9717 createStaticHandler,
9718 createStaticRouter,
9719 data,
9720 generatePath,
9721 isCookie,
9722 isRouteErrorResponse,
9723 isSession,
9724 matchPath,
9725 matchRoutes,
9726 parsePath,
9727 redirect,
9728 redirectDocument,
9729 renderMatches,
9730 replace,
9731 resolvePath,
9732 unstable_HistoryRouter,
9733 unstable_setDevServerHooks,
9734 unstable_usePrompt,
9735 useActionData,
9736 useAsyncError,
9737 useAsyncValue,
9738 useBeforeUnload,
9739 useBlocker,
9740 useFetcher,
9741 useFetchers,
9742 useFormAction,
9743 useHref,
9744 useInRouterContext,
9745 useLinkClickHandler,
9746 useLoaderData,
9747 useLocation,
9748 useMatch,
9749 useMatches,
9750 useNavigate,
9751 useNavigation,
9752 useNavigationType,
9753 useOutlet,
9754 useOutletContext,
9755 useParams,
9756 useResolvedPath,
9757 useRevalidator,
9758 useRouteError,
9759 useRouteLoaderData,
9760 useRoutes,
9761 useSearchParams,
9762 useSubmit,
9763 useViewTransitionState
9764});