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