react-router 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/dist/development/dom-export.js +1 -1
- package/dist/development/index-react-server-client.js +1 -1
- package/dist/development/index-react-server.d.ts +109 -19
- package/dist/development/index-react-server.js +176 -45
- package/dist/development/index.js +1 -1
- package/dist/development/lib/actions.js +1 -1
- package/dist/development/lib/components.js +1 -1
- package/dist/development/lib/context.js +1 -1
- package/dist/development/lib/dom/dom.d.ts +24 -24
- package/dist/development/lib/dom/dom.js +25 -25
- package/dist/development/lib/dom/lib.d.ts +2 -1
- package/dist/development/lib/dom/lib.js +5 -4
- package/dist/development/lib/dom/server.js +1 -1
- package/dist/development/lib/dom/ssr/components.js +1 -1
- package/dist/development/lib/dom/ssr/data.js +1 -1
- package/dist/development/lib/dom/ssr/errorBoundaries.js +1 -1
- package/dist/development/lib/dom/ssr/fallback.js +1 -1
- package/dist/development/lib/dom/ssr/fog-of-war.js +26 -21
- package/dist/development/lib/dom/ssr/hydration.js +1 -1
- package/dist/development/lib/dom/ssr/invariant.js +1 -1
- package/dist/development/lib/dom/ssr/links.js +1 -1
- package/dist/development/lib/dom/ssr/markup.js +1 -1
- package/dist/development/lib/dom/ssr/routeModules.js +1 -1
- package/dist/development/lib/dom/ssr/routes-test-stub.d.ts +13 -0
- package/dist/development/lib/dom/ssr/routes-test-stub.js +14 -1
- package/dist/development/lib/dom/ssr/routes.js +1 -1
- package/dist/development/lib/dom/ssr/server.js +1 -1
- package/dist/development/lib/dom/ssr/single-fetch.js +1 -1
- package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/development/lib/dom-export/hydrated-router.js +1 -1
- package/dist/development/lib/errors.js +1 -1
- package/dist/development/lib/hooks.d.ts +33 -6
- package/dist/development/lib/hooks.js +34 -7
- package/dist/development/lib/href.d.ts +24 -8
- package/dist/development/lib/href.js +31 -11
- package/dist/development/lib/router/history.d.ts +6 -0
- package/dist/development/lib/router/history.js +7 -1
- package/dist/development/lib/router/instrumentation.js +1 -1
- package/dist/development/lib/router/router.js +2 -2
- package/dist/development/lib/router/url.js +1 -1
- package/dist/development/lib/router/utils.d.ts +12 -0
- package/dist/development/lib/router/utils.js +61 -5
- package/dist/development/lib/rsc/browser.js +34 -24
- package/dist/development/lib/rsc/errorBoundaries.js +1 -1
- package/dist/development/lib/rsc/html-stream/browser.js +1 -1
- package/dist/development/lib/rsc/html-stream/server.js +29 -10
- package/dist/development/lib/rsc/route-modules.js +1 -1
- package/dist/development/lib/rsc/server.rsc.d.ts +8 -3
- package/dist/development/lib/rsc/server.ssr.d.ts +29 -6
- package/dist/development/lib/rsc/server.ssr.js +27 -12
- package/dist/development/lib/server-runtime/cookies.d.ts +28 -2
- package/dist/development/lib/server-runtime/cookies.js +17 -3
- package/dist/development/lib/server-runtime/crypto.js +1 -1
- package/dist/development/lib/server-runtime/data.js +1 -1
- package/dist/development/lib/server-runtime/dev.js +1 -1
- package/dist/development/lib/server-runtime/entry.js +1 -1
- package/dist/development/lib/server-runtime/errors.js +1 -1
- package/dist/development/lib/server-runtime/headers.js +1 -1
- package/dist/development/lib/server-runtime/invariant.js +1 -1
- package/dist/development/lib/server-runtime/mode.js +1 -1
- package/dist/development/lib/server-runtime/routeMatching.js +1 -1
- package/dist/development/lib/server-runtime/routes.js +1 -1
- package/dist/development/lib/server-runtime/server.d.ts +12 -0
- package/dist/development/lib/server-runtime/server.js +13 -1
- package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/development/lib/server-runtime/sessions/cookieStorage.d.ts +8 -0
- package/dist/development/lib/server-runtime/sessions/cookieStorage.js +9 -1
- package/dist/development/lib/server-runtime/sessions/memoryStorage.d.ts +10 -4
- package/dist/development/lib/server-runtime/sessions/memoryStorage.js +12 -6
- package/dist/development/lib/server-runtime/sessions.d.ts +31 -2
- package/dist/development/lib/server-runtime/sessions.js +20 -3
- package/dist/development/lib/server-runtime/single-fetch.js +1 -1
- package/dist/development/lib/server-runtime/urls.js +1 -1
- package/dist/development/lib/server-runtime/warnings.js +1 -1
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/unflatten.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/utils.js +1 -1
- package/dist/production/dom-export.js +1 -1
- package/dist/production/index-react-server-client.js +1 -1
- package/dist/production/index-react-server.d.ts +109 -19
- package/dist/production/index-react-server.js +176 -45
- package/dist/production/index.js +1 -1
- package/dist/production/lib/actions.js +1 -1
- package/dist/production/lib/components.js +1 -1
- package/dist/production/lib/context.js +1 -1
- package/dist/production/lib/dom/dom.d.ts +24 -24
- package/dist/production/lib/dom/dom.js +25 -25
- package/dist/production/lib/dom/lib.d.ts +2 -1
- package/dist/production/lib/dom/lib.js +5 -4
- package/dist/production/lib/dom/server.js +1 -1
- package/dist/production/lib/dom/ssr/components.js +1 -1
- package/dist/production/lib/dom/ssr/data.js +1 -1
- package/dist/production/lib/dom/ssr/errorBoundaries.js +1 -1
- package/dist/production/lib/dom/ssr/fallback.js +1 -1
- package/dist/production/lib/dom/ssr/fog-of-war.js +26 -21
- package/dist/production/lib/dom/ssr/hydration.js +1 -1
- package/dist/production/lib/dom/ssr/invariant.js +1 -1
- package/dist/production/lib/dom/ssr/links.js +1 -1
- package/dist/production/lib/dom/ssr/markup.js +1 -1
- package/dist/production/lib/dom/ssr/routeModules.js +1 -1
- package/dist/production/lib/dom/ssr/routes-test-stub.d.ts +13 -0
- package/dist/production/lib/dom/ssr/routes-test-stub.js +14 -1
- package/dist/production/lib/dom/ssr/routes.js +1 -1
- package/dist/production/lib/dom/ssr/server.js +1 -1
- package/dist/production/lib/dom/ssr/single-fetch.js +1 -1
- package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/production/lib/dom-export/hydrated-router.js +1 -1
- package/dist/production/lib/errors.js +1 -1
- package/dist/production/lib/hooks.d.ts +33 -6
- package/dist/production/lib/hooks.js +34 -7
- package/dist/production/lib/href.d.ts +24 -8
- package/dist/production/lib/href.js +31 -11
- package/dist/production/lib/router/history.d.ts +6 -0
- package/dist/production/lib/router/history.js +7 -1
- package/dist/production/lib/router/instrumentation.js +1 -1
- package/dist/production/lib/router/router.js +2 -2
- package/dist/production/lib/router/url.js +1 -1
- package/dist/production/lib/router/utils.d.ts +12 -0
- package/dist/production/lib/router/utils.js +61 -5
- package/dist/production/lib/rsc/browser.js +34 -24
- package/dist/production/lib/rsc/errorBoundaries.js +1 -1
- package/dist/production/lib/rsc/html-stream/browser.js +1 -1
- package/dist/production/lib/rsc/html-stream/server.js +29 -10
- package/dist/production/lib/rsc/route-modules.js +1 -1
- package/dist/production/lib/rsc/server.rsc.d.ts +8 -3
- package/dist/production/lib/rsc/server.ssr.d.ts +29 -6
- package/dist/production/lib/rsc/server.ssr.js +27 -12
- package/dist/production/lib/server-runtime/cookies.d.ts +28 -2
- package/dist/production/lib/server-runtime/cookies.js +17 -3
- package/dist/production/lib/server-runtime/crypto.js +1 -1
- package/dist/production/lib/server-runtime/data.js +1 -1
- package/dist/production/lib/server-runtime/dev.js +1 -1
- package/dist/production/lib/server-runtime/entry.js +1 -1
- package/dist/production/lib/server-runtime/errors.js +1 -1
- package/dist/production/lib/server-runtime/headers.js +1 -1
- package/dist/production/lib/server-runtime/invariant.js +1 -1
- package/dist/production/lib/server-runtime/mode.js +1 -1
- package/dist/production/lib/server-runtime/routeMatching.js +1 -1
- package/dist/production/lib/server-runtime/routes.js +1 -1
- package/dist/production/lib/server-runtime/server.d.ts +12 -0
- package/dist/production/lib/server-runtime/server.js +13 -1
- package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/production/lib/server-runtime/sessions/cookieStorage.d.ts +8 -0
- package/dist/production/lib/server-runtime/sessions/cookieStorage.js +9 -1
- package/dist/production/lib/server-runtime/sessions/memoryStorage.d.ts +10 -4
- package/dist/production/lib/server-runtime/sessions/memoryStorage.js +12 -6
- package/dist/production/lib/server-runtime/sessions.d.ts +31 -2
- package/dist/production/lib/server-runtime/sessions.js +20 -3
- package/dist/production/lib/server-runtime/single-fetch.js +1 -1
- package/dist/production/lib/server-runtime/urls.js +1 -1
- package/dist/production/lib/server-runtime/warnings.js +1 -1
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
- package/docs/explanation/hot-module-replacement.md +1 -1
- package/docs/explanation/sessions-and-cookies.md +13 -13
- package/docs/explanation/state-management.md +2 -2
- package/docs/how-to/data-strategy.md +1 -1
- package/docs/how-to/presets.md +2 -2
- package/docs/how-to/react-server-components.md +53 -1
- package/docs/how-to/security.md +8 -1
- package/docs/how-to/server-bundles.md +2 -2
- package/docs/start/data/route-object.md +2 -2
- package/docs/start/data/routing.md +1 -1
- package/docs/start/framework/deploying.md +4 -0
- package/docs/start/framework/pending-ui.md +1 -1
- package/docs/start/framework/route-module.md +8 -8
- package/docs/start/framework/routing.md +1 -1
- package/docs/upgrading/component-routes.md +1 -1
- package/docs/upgrading/future.md +33 -0
- package/docs/upgrading/router-provider.md +5 -5
- package/docs/upgrading/v7.md +39 -22
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.
|
|
2
|
+
* react-router v8.3.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -47,7 +47,10 @@ function createLocation(current, to, state = null, key, mask) {
|
|
|
47
47
|
/**
|
|
48
48
|
* Creates a string URL path from the given pathname, search, and hash components.
|
|
49
49
|
*
|
|
50
|
+
* @public
|
|
50
51
|
* @category Utils
|
|
52
|
+
* @param path The pathname, search, and hash components to combine.
|
|
53
|
+
* @returns The combined URL path.
|
|
51
54
|
*/
|
|
52
55
|
function createPath({ pathname = "/", search = "", hash = "" }) {
|
|
53
56
|
if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
|
|
@@ -57,7 +60,10 @@ function createPath({ pathname = "/", search = "", hash = "" }) {
|
|
|
57
60
|
/**
|
|
58
61
|
* Parses a string URL path into its separate pathname, search, and hash components.
|
|
59
62
|
*
|
|
63
|
+
* @public
|
|
60
64
|
* @category Utils
|
|
65
|
+
* @param path The URL path to parse.
|
|
66
|
+
* @returns The parsed pathname, search, and hash components.
|
|
61
67
|
*/
|
|
62
68
|
function parsePath(path) {
|
|
63
69
|
let parsedPath = {};
|
|
@@ -389,6 +395,8 @@ function rankRouteBranches(branches) {
|
|
|
389
395
|
branches.sort((a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(a.routesMeta.map((meta) => meta.childrenIndex), b.routesMeta.map((meta) => meta.childrenIndex)));
|
|
390
396
|
}
|
|
391
397
|
const paramRe = /^:[\w-]+$/;
|
|
398
|
+
const partialParamRe = /^:[\w-]+/;
|
|
399
|
+
const partialDynamicSegmentValue = 3.5;
|
|
392
400
|
const dynamicSegmentValue = 3;
|
|
393
401
|
const indexRouteValue = 2;
|
|
394
402
|
const emptySegmentValue = 1;
|
|
@@ -400,7 +408,7 @@ function computeScore(path, index) {
|
|
|
400
408
|
let initialScore = segments.length;
|
|
401
409
|
if (segments.some(isSplat)) initialScore += splatPenalty;
|
|
402
410
|
if (index) initialScore += indexRouteValue;
|
|
403
|
-
return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
411
|
+
return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : partialParamRe.test(segment) ? partialDynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
404
412
|
}
|
|
405
413
|
function compareIndexes(a, b) {
|
|
406
414
|
return a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]) ? a[a.length - 1] - b[b.length - 1] : 0;
|
|
@@ -439,6 +447,48 @@ function matchRouteBranch(branch, pathname, allowPartial = false) {
|
|
|
439
447
|
return matches;
|
|
440
448
|
}
|
|
441
449
|
/**
|
|
450
|
+
* Characters that `encodeURIComponent` escapes but that are valid literally in
|
|
451
|
+
* a URL path segment. Per RFC 3986 §3.3, a path segment is made of `pchar`:
|
|
452
|
+
*
|
|
453
|
+
* ```
|
|
454
|
+
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
|
455
|
+
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* `encodeURIComponent` targets query-string values, where `$ & + , ; = : @`
|
|
459
|
+
* are delimiters and must be escaped — but in a path segment they carry no
|
|
460
|
+
* special meaning, and browsers keep them literal in `location.pathname`.
|
|
461
|
+
* (`! ' ( ) *` and the unreserved set are already left alone by
|
|
462
|
+
* `encodeURIComponent`, so they need no restoring.)
|
|
463
|
+
*/
|
|
464
|
+
const PATH_PARAM_OVERESCAPED = {
|
|
465
|
+
"%24": "$",
|
|
466
|
+
"%26": "&",
|
|
467
|
+
"%2B": "+",
|
|
468
|
+
"%2C": ",",
|
|
469
|
+
"%3A": ":",
|
|
470
|
+
"%3B": ";",
|
|
471
|
+
"%3D": "=",
|
|
472
|
+
"%40": "@"
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Encodes a param value for interpolation into a single URL path segment.
|
|
476
|
+
*
|
|
477
|
+
* Escapes characters that would break the path (`/ ? # %`, whitespace,
|
|
478
|
+
* non-ASCII, …) while leaving characters that RFC 3986 permits literally in a
|
|
479
|
+
* path segment untouched. Escaping those would needlessly rewrite URLs — e.g.
|
|
480
|
+
* a semver build param `1.0.0+1` would become `1.0.0%2B1` even though browsers
|
|
481
|
+
* display and match the `+` literally in `location.pathname`.
|
|
482
|
+
*
|
|
483
|
+
* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3))
|
|
484
|
+
*
|
|
485
|
+
* @param value The param value to encode.
|
|
486
|
+
* @returns The encoded value, safe for use as a single path segment.
|
|
487
|
+
*/
|
|
488
|
+
function encodePathParam(value) {
|
|
489
|
+
return encodeURIComponent(value).replace(/%(?:24|26|2B|2C|3A|3B|3D|40)/g, (match) => PATH_PARAM_OVERESCAPED[match]);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
442
492
|
* Performs pattern matching on a URL pathname and returns information about
|
|
443
493
|
* the match.
|
|
444
494
|
*
|
|
@@ -497,7 +547,7 @@ function compilePath(path, caseSensitive = false, end = true) {
|
|
|
497
547
|
return "(?:/([^\\/]*))?";
|
|
498
548
|
}
|
|
499
549
|
return "/([^\\/]+)";
|
|
500
|
-
}).replace(/\/([\w-]+)\?(
|
|
550
|
+
}).replace(/\/([\w-]+)\?(?=\/|$|\()/g, "(?:/$1)?");
|
|
501
551
|
if (path.endsWith("*")) {
|
|
502
552
|
params.push({ paramName: "*" });
|
|
503
553
|
regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
|
|
@@ -2330,6 +2380,8 @@ const Await = (async ({ children, resolve, errorElement }) => {
|
|
|
2330
2380
|
* encoding the {@link unstable_RSCPayload}.
|
|
2331
2381
|
* @param opts.loadServerAction Your `react-server-dom-xyz/server`'s
|
|
2332
2382
|
* `loadServerAction` function, used to load a server action by ID.
|
|
2383
|
+
* @param opts.clientVersion A version derived from the client build output used
|
|
2384
|
+
* to detect stale clients during lazy route discovery.
|
|
2333
2385
|
* @param opts.onError An optional error handler that will be called with any
|
|
2334
2386
|
* errors that occur during the request processing.
|
|
2335
2387
|
* @param opts.request The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
@@ -2343,7 +2395,7 @@ const Await = (async ({ children, resolve, errorElement }) => {
|
|
|
2343
2395
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
2344
2396
|
* data for hydration.
|
|
2345
2397
|
*/
|
|
2346
|
-
async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, routeDiscovery, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse }) {
|
|
2398
|
+
async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, routeDiscovery, loadServerAction, decodeAction, decodeFormState, clientVersion, onError, request, routes, generateResponse }) {
|
|
2347
2399
|
let url = new URL(request.url);
|
|
2348
2400
|
basename = basename || "/";
|
|
2349
2401
|
let normalizedPath = url.pathname;
|
|
@@ -2361,22 +2413,26 @@ async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryRefe
|
|
|
2361
2413
|
});
|
|
2362
2414
|
const temporaryReferences = createTemporaryReferenceSet();
|
|
2363
2415
|
const requestUrl = new URL(request.url);
|
|
2364
|
-
if (isManifestRequest(requestUrl)) return await generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery);
|
|
2416
|
+
if (isManifestRequest(requestUrl)) return await generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion);
|
|
2365
2417
|
let isDataRequest = isReactServerRequest(requestUrl);
|
|
2366
2418
|
let matches = matchRoutes(routes, url.pathname, basename);
|
|
2367
2419
|
if (matches) await Promise.all(matches.map((m) => explodeLazyRoute(m.route)));
|
|
2368
2420
|
const leafMatch = matches?.[matches.length - 1];
|
|
2369
2421
|
if (!isDataRequest && leafMatch && !leafMatch.route.Component && !leafMatch.route.ErrorBoundary) return generateResourceResponse(routerRequest, routes, basename, leafMatch.route.id, requestContext, onError);
|
|
2370
|
-
let response = await generateRenderResponse(routerRequest, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery);
|
|
2422
|
+
let response = await generateRenderResponse(routerRequest, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion);
|
|
2371
2423
|
response.headers.set("X-Remix-Response", "yes");
|
|
2372
2424
|
return response;
|
|
2373
2425
|
}
|
|
2374
|
-
async function generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery) {
|
|
2426
|
+
async function generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion) {
|
|
2375
2427
|
let url = new URL(request.url);
|
|
2376
2428
|
if (url.toString().length > 7680) return new Response(null, {
|
|
2377
2429
|
statusText: "Bad Request",
|
|
2378
2430
|
status: 400
|
|
2379
2431
|
});
|
|
2432
|
+
if (clientVersion !== void 0 && clientVersion !== url.searchParams.get("version")) return new Response(null, {
|
|
2433
|
+
status: 204,
|
|
2434
|
+
headers: { "X-Remix-Reload-Document": "true" }
|
|
2435
|
+
});
|
|
2380
2436
|
if (routeDiscovery?.mode === "initial") {
|
|
2381
2437
|
let payload = {
|
|
2382
2438
|
type: "manifest",
|
|
@@ -2468,7 +2524,7 @@ async function processServerAction(request, basename, decodeReply, loadServerAct
|
|
|
2468
2524
|
try {
|
|
2469
2525
|
let result = await action();
|
|
2470
2526
|
if (isRedirectResponse(result)) result = prependBasenameToRedirectResponse(result, basename);
|
|
2471
|
-
formState = decodeFormState?.(result, formData);
|
|
2527
|
+
formState = await decodeFormState?.(result, formData);
|
|
2472
2528
|
} catch (error) {
|
|
2473
2529
|
if (isRedirectResponse(error)) return prependBasenameToRedirectResponse(error, basename);
|
|
2474
2530
|
if (isResponse(error)) return error;
|
|
@@ -2525,7 +2581,7 @@ async function generateResourceResponse(request, routes, basename, routeId, requ
|
|
|
2525
2581
|
});
|
|
2526
2582
|
}
|
|
2527
2583
|
}
|
|
2528
|
-
async function generateRenderResponse(request, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery) {
|
|
2584
|
+
async function generateRenderResponse(request, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion) {
|
|
2529
2585
|
let statusCode = 200;
|
|
2530
2586
|
let url = new URL(request.url);
|
|
2531
2587
|
let isSubmission = isMutationMethod(request.method);
|
|
@@ -2546,29 +2602,39 @@ async function generateRenderResponse(request, routes, basename, isDataRequest,
|
|
|
2546
2602
|
let formState;
|
|
2547
2603
|
let skipRevalidation = false;
|
|
2548
2604
|
let potentialCSRFAttackError;
|
|
2549
|
-
if (isMutationMethod(request.method))
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2605
|
+
if (isMutationMethod(request.method)) {
|
|
2606
|
+
try {
|
|
2607
|
+
throwIfPotentialCSRFAttack(request, allowedActionOrigins);
|
|
2608
|
+
} catch (error) {
|
|
2609
|
+
onError?.(error);
|
|
2610
|
+
potentialCSRFAttackError = error;
|
|
2611
|
+
request = new Request(request.url, {
|
|
2612
|
+
method: "GET",
|
|
2613
|
+
headers: request.headers,
|
|
2614
|
+
signal: request.signal
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
if (!potentialCSRFAttackError) {
|
|
2618
|
+
ctx.runningAction = true;
|
|
2619
|
+
let result = await processServerAction(request, basename, decodeReply, loadServerAction, decodeAction, decodeFormState, onError, temporaryReferences).finally(() => {
|
|
2620
|
+
ctx.runningAction = false;
|
|
2621
|
+
});
|
|
2622
|
+
if (isResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
2623
|
+
skipRevalidation = result?.skipRevalidation ?? false;
|
|
2624
|
+
actionResult = result?.actionResult;
|
|
2625
|
+
formState = result?.formState;
|
|
2626
|
+
request = result?.revalidationRequest ?? request;
|
|
2627
|
+
if (ctx.redirect) return generateRedirectResponse(ctx.redirect, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, void 0);
|
|
2628
|
+
}
|
|
2563
2629
|
}
|
|
2564
|
-
let staticContext = await query(request, skipRevalidation
|
|
2630
|
+
let staticContext = await query(request, skipRevalidation ? { filterMatchesToLoad: () => false } : void 0);
|
|
2565
2631
|
if (isResponse(staticContext)) return generateRedirectResponse(staticContext, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
2566
2632
|
if (potentialCSRFAttackError) {
|
|
2567
2633
|
staticContext.errors ??= {};
|
|
2568
2634
|
staticContext.errors[staticContext.matches[0].route.id] = potentialCSRFAttackError;
|
|
2569
2635
|
staticContext.statusCode = 400;
|
|
2570
2636
|
}
|
|
2571
|
-
return generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, ctx.redirect?.headers, routeDiscovery);
|
|
2637
|
+
return generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, ctx.redirect?.headers, routeDiscovery, clientVersion);
|
|
2572
2638
|
}
|
|
2573
2639
|
}));
|
|
2574
2640
|
if (isRedirectResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
@@ -2602,7 +2668,7 @@ function generateRedirectResponse(response, actionResult, basename, isDataReques
|
|
|
2602
2668
|
onError: defaultOnError
|
|
2603
2669
|
});
|
|
2604
2670
|
}
|
|
2605
|
-
async function generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, sideEffectRedirectHeaders, routeDiscovery) {
|
|
2671
|
+
async function generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, sideEffectRedirectHeaders, routeDiscovery, clientVersion) {
|
|
2606
2672
|
statusCode = staticContext.statusCode ?? statusCode;
|
|
2607
2673
|
if (staticContext.errors) staticContext.errors = Object.fromEntries(Object.entries(staticContext.errors).map(([key, error]) => [key, isRouteErrorResponse(error) ? Object.fromEntries(Object.entries(error)) : error]));
|
|
2608
2674
|
staticContext.matches.forEach((m) => {
|
|
@@ -2615,6 +2681,7 @@ async function generateStaticContextResponse(routes, basename, generateResponse,
|
|
|
2615
2681
|
const baseRenderPayload = {
|
|
2616
2682
|
type: "render",
|
|
2617
2683
|
basename: staticContext.basename,
|
|
2684
|
+
clientVersion,
|
|
2618
2685
|
routeDiscovery: routeDiscovery ?? { mode: "lazy" },
|
|
2619
2686
|
actionData: staticContext.actionData,
|
|
2620
2687
|
errors: staticContext.errors,
|
|
@@ -2806,15 +2873,34 @@ function canDecodeWithFormData(contentType) {
|
|
|
2806
2873
|
}
|
|
2807
2874
|
//#endregion
|
|
2808
2875
|
//#region lib/href.ts
|
|
2876
|
+
function stringify(p) {
|
|
2877
|
+
return p == null ? "" : typeof p === "string" ? p : String(p);
|
|
2878
|
+
}
|
|
2809
2879
|
/**
|
|
2810
|
-
Returns a resolved URL path for the specified route.
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2880
|
+
* Returns a resolved URL path for the specified route.
|
|
2881
|
+
*
|
|
2882
|
+
* Param values are percent-encoded for use in a path segment: characters that
|
|
2883
|
+
* would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
|
|
2884
|
+
* are escaped, while characters that RFC 3986 allows literally in a path
|
|
2885
|
+
* segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
|
|
2886
|
+
* encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
|
|
2887
|
+
* delimiters and must be escaped. Splat (`*`) values are encoded per segment,
|
|
2888
|
+
* preserving `/` separators.
|
|
2889
|
+
*
|
|
2890
|
+
* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
|
|
2891
|
+
*
|
|
2892
|
+
* @example
|
|
2893
|
+
* const h = href("/:lang?/about", { lang: "en" })
|
|
2894
|
+
* // -> `/en/about`
|
|
2895
|
+
*
|
|
2896
|
+
* <Link to={href("/products/:id", { id: "abc123" })} />
|
|
2897
|
+
*
|
|
2898
|
+
* @public
|
|
2899
|
+
* @category Utils
|
|
2900
|
+
* @mode framework
|
|
2901
|
+
* @param path The route path to resolve
|
|
2902
|
+
* @param args The route params to use when resolving the path
|
|
2903
|
+
* @returns The resolved URL path
|
|
2818
2904
|
*/
|
|
2819
2905
|
function href(path, ...args) {
|
|
2820
2906
|
let params = args[0];
|
|
@@ -2822,11 +2908,11 @@ function href(path, ...args) {
|
|
|
2822
2908
|
const isRequired = questionMark === void 0;
|
|
2823
2909
|
const value = params?.[param];
|
|
2824
2910
|
if (isRequired && value === void 0) throw new Error(`Path '${path}' requires param '${param}' but it was not provided`);
|
|
2825
|
-
return value
|
|
2911
|
+
return value == null ? "" : "/" + encodePathParam(stringify(value));
|
|
2826
2912
|
});
|
|
2827
2913
|
if (path.endsWith("*")) {
|
|
2828
2914
|
const value = params?.["*"];
|
|
2829
|
-
if (value !== void 0) result += "/" + value;
|
|
2915
|
+
if (value !== void 0) result += "/" + stringify(value).split("/").map(encodePathParam).join("/");
|
|
2830
2916
|
}
|
|
2831
2917
|
return result || "/";
|
|
2832
2918
|
}
|
|
@@ -2879,6 +2965,14 @@ function byteStringToUint8Array(byteString) {
|
|
|
2879
2965
|
//#region lib/server-runtime/cookies.ts
|
|
2880
2966
|
/**
|
|
2881
2967
|
* Creates a logical container for managing a browser cookie from the server.
|
|
2968
|
+
*
|
|
2969
|
+
* @public
|
|
2970
|
+
* @category Utils
|
|
2971
|
+
* @mode framework
|
|
2972
|
+
* @mode data
|
|
2973
|
+
* @param name The name of the cookie.
|
|
2974
|
+
* @param cookieOptions Options for parsing and serializing the cookie.
|
|
2975
|
+
* @returns A {@link Cookie} object for parsing and serializing the cookie.
|
|
2882
2976
|
*/
|
|
2883
2977
|
const createCookie = (name, cookieOptions = {}) => {
|
|
2884
2978
|
let { secrets = [], ...options } = {
|
|
@@ -2918,9 +3012,15 @@ const createCookie = (name, cookieOptions = {}) => {
|
|
|
2918
3012
|
};
|
|
2919
3013
|
};
|
|
2920
3014
|
/**
|
|
2921
|
-
* Returns true if
|
|
3015
|
+
* Returns `true` if a value is a React Router {@link Cookie} object.
|
|
2922
3016
|
*
|
|
2923
|
-
* @
|
|
3017
|
+
* @public
|
|
3018
|
+
* @category Utils
|
|
3019
|
+
* @mode framework
|
|
3020
|
+
* @mode data
|
|
3021
|
+
* @param object The value to check.
|
|
3022
|
+
* @returns `true` if the value is a React Router {@link Cookie} object;
|
|
3023
|
+
* otherwise, `false`.
|
|
2924
3024
|
*/
|
|
2925
3025
|
const isCookie = (object) => {
|
|
2926
3026
|
return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function";
|
|
@@ -3010,6 +3110,12 @@ function flash(name) {
|
|
|
3010
3110
|
*
|
|
3011
3111
|
* Note: This function is typically not invoked directly by application code.
|
|
3012
3112
|
* Instead, use a `SessionStorage` object's `getSession` method.
|
|
3113
|
+
*
|
|
3114
|
+
* @category Utils
|
|
3115
|
+
* @param initialData The initial data for the session.
|
|
3116
|
+
* @param id The identifier for the session. Defaults to an empty string for a
|
|
3117
|
+
* new session.
|
|
3118
|
+
* @returns A new {@link Session} object.
|
|
3013
3119
|
*/
|
|
3014
3120
|
const createSession = (initialData = {}, id = "") => {
|
|
3015
3121
|
let map = new Map(Object.entries(initialData));
|
|
@@ -3044,9 +3150,15 @@ const createSession = (initialData = {}, id = "") => {
|
|
|
3044
3150
|
};
|
|
3045
3151
|
};
|
|
3046
3152
|
/**
|
|
3047
|
-
* Returns true if
|
|
3153
|
+
* Returns `true` if a value is a React Router {@link Session} object.
|
|
3048
3154
|
*
|
|
3049
|
-
* @
|
|
3155
|
+
* @public
|
|
3156
|
+
* @category Utils
|
|
3157
|
+
* @mode framework
|
|
3158
|
+
* @mode data
|
|
3159
|
+
* @param object The value to check.
|
|
3160
|
+
* @returns `true` if the value is a React Router {@link Session} object;
|
|
3161
|
+
* otherwise, `false`.
|
|
3050
3162
|
*/
|
|
3051
3163
|
const isSession = (object) => {
|
|
3052
3164
|
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";
|
|
@@ -3056,6 +3168,11 @@ const isSession = (object) => {
|
|
|
3056
3168
|
*
|
|
3057
3169
|
* Note: This is a low-level API that should only be used if none of the
|
|
3058
3170
|
* existing session storage options meet your requirements.
|
|
3171
|
+
*
|
|
3172
|
+
* @category Utils
|
|
3173
|
+
* @param strategy The strategy used to store session identifiers and data.
|
|
3174
|
+
* @returns A {@link SessionStorage} object that persists session data using the
|
|
3175
|
+
* provided strategy.
|
|
3059
3176
|
*/
|
|
3060
3177
|
function createSessionStorage({ cookie: cookieArg, createData, readData, updateData, deleteData }) {
|
|
3061
3178
|
let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
|
|
@@ -3095,6 +3212,14 @@ function warnOnceAboutSigningSessionCookie(cookie) {
|
|
|
3095
3212
|
* needed, and can help to simplify some load-balanced scenarios. However, it
|
|
3096
3213
|
* also has the limitation that serialized session data may not exceed the
|
|
3097
3214
|
* browser's maximum cookie size. Trade-offs!
|
|
3215
|
+
*
|
|
3216
|
+
* @public
|
|
3217
|
+
* @category Utils
|
|
3218
|
+
* @mode framework
|
|
3219
|
+
* @mode data
|
|
3220
|
+
* @param options Options for creating the cookie-backed session storage.
|
|
3221
|
+
* @returns A {@link SessionStorage} object that stores all session data in its
|
|
3222
|
+
* cookie.
|
|
3098
3223
|
*/
|
|
3099
3224
|
function createCookieSessionStorage({ cookie: cookieArg } = {}) {
|
|
3100
3225
|
let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
|
|
@@ -3120,18 +3245,24 @@ function createCookieSessionStorage({ cookie: cookieArg } = {}) {
|
|
|
3120
3245
|
//#endregion
|
|
3121
3246
|
//#region lib/server-runtime/sessions/memoryStorage.ts
|
|
3122
3247
|
/**
|
|
3123
|
-
* Creates and returns a simple in-memory SessionStorage object
|
|
3124
|
-
* for testing and as a reference implementation.
|
|
3248
|
+
* Creates and returns a simple in-memory SessionStorage object.
|
|
3125
3249
|
*
|
|
3126
|
-
*
|
|
3127
|
-
*
|
|
3250
|
+
* Intended for local development and testing. It does not scale beyond a single
|
|
3251
|
+
* process, and all session data is lost when the server process stops/restarts.
|
|
3252
|
+
*
|
|
3253
|
+
* @public
|
|
3254
|
+
* @category Utils
|
|
3255
|
+
* @mode framework
|
|
3256
|
+
* @mode data
|
|
3257
|
+
* @param options Options for creating the in-memory session storage.
|
|
3258
|
+
* @returns A {@link SessionStorage} object that stores session data in memory.
|
|
3128
3259
|
*/
|
|
3129
3260
|
function createMemorySessionStorage({ cookie } = {}) {
|
|
3130
3261
|
let map = /* @__PURE__ */ new Map();
|
|
3131
3262
|
return createSessionStorage({
|
|
3132
3263
|
cookie,
|
|
3133
3264
|
async createData(data, expires) {
|
|
3134
|
-
let id =
|
|
3265
|
+
let id = crypto.randomUUID();
|
|
3135
3266
|
map.set(id, {
|
|
3136
3267
|
data,
|
|
3137
3268
|
expires
|
|
@@ -6,30 +6,30 @@ import { RelativeRoutingType } from "../router/router.js";
|
|
|
6
6
|
type ParamKeyValuePair = [string, string];
|
|
7
7
|
type URLSearchParamsInit = string | ParamKeyValuePair[] | Record<string, string | string[]> | URLSearchParams;
|
|
8
8
|
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
9
|
+
* Creates a URLSearchParams object using the given initializer.
|
|
10
|
+
*
|
|
11
|
+
* This is identical to `new URLSearchParams(init)` except it also supports
|
|
12
|
+
* arrays as values in the object form of the initializer instead of just
|
|
13
|
+
* strings. This is convenient when you need multiple values for a given key,
|
|
14
|
+
* but don't want to use an array initializer.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Instead of:
|
|
18
|
+
* let searchParams = new URLSearchParams([
|
|
19
|
+
* ["sort", "name"],
|
|
20
|
+
* ["sort", "price"],
|
|
21
|
+
* ]);
|
|
22
|
+
*
|
|
23
|
+
* // You can do:
|
|
24
|
+
* let searchParams = createSearchParams({
|
|
25
|
+
* sort: ["name", "price"],
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
* @category Utils
|
|
30
|
+
* @param init The value used to initialize the URL search parameters.
|
|
31
|
+
* @returns A URLSearchParams object containing the initialized search
|
|
32
|
+
* parameters.
|
|
33
33
|
*/
|
|
34
34
|
declare function createSearchParams(init?: URLSearchParamsInit): URLSearchParams;
|
|
35
35
|
type JsonObject = { [Key in string]: JsonValue } & { [Key in string]?: JsonValue | undefined };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.
|
|
2
|
+
* react-router v8.3.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -30,30 +30,30 @@ function shouldProcessLinkClick(event, target) {
|
|
|
30
30
|
return event.button === 0 && (!target || target === "_self") && !isModifiedEvent(event);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
Creates a URLSearchParams object using the given initializer.
|
|
34
|
-
|
|
35
|
-
This is identical to `new URLSearchParams(init)` except it also
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
[
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
33
|
+
* Creates a URLSearchParams object using the given initializer.
|
|
34
|
+
*
|
|
35
|
+
* This is identical to `new URLSearchParams(init)` except it also supports
|
|
36
|
+
* arrays as values in the object form of the initializer instead of just
|
|
37
|
+
* strings. This is convenient when you need multiple values for a given key,
|
|
38
|
+
* but don't want to use an array initializer.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // Instead of:
|
|
42
|
+
* let searchParams = new URLSearchParams([
|
|
43
|
+
* ["sort", "name"],
|
|
44
|
+
* ["sort", "price"],
|
|
45
|
+
* ]);
|
|
46
|
+
*
|
|
47
|
+
* // You can do:
|
|
48
|
+
* let searchParams = createSearchParams({
|
|
49
|
+
* sort: ["name", "price"],
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
* @category Utils
|
|
54
|
+
* @param init The value used to initialize the URL search parameters.
|
|
55
|
+
* @returns A URLSearchParams object containing the initialized search
|
|
56
|
+
* parameters.
|
|
57
57
|
*/
|
|
58
58
|
function createSearchParams(init = "") {
|
|
59
59
|
return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo, key) => {
|
|
@@ -1409,7 +1409,8 @@ declare namespace ScrollRestoration {
|
|
|
1409
1409
|
* for this navigation. To apply specific styles during the transition, see
|
|
1410
1410
|
* {@link useViewTransitionState}. Defaults to `false`.
|
|
1411
1411
|
* @param options.defaultShouldRevalidate Specify the default revalidation
|
|
1412
|
-
* behavior for the navigation.
|
|
1412
|
+
* behavior for the navigation. When not specified, loaders revalidate
|
|
1413
|
+
* according to the router's standard revalidation behavior.
|
|
1413
1414
|
* @param options.mask Masked location to display in the browser instead
|
|
1414
1415
|
* of the router location. Defaults to `undefined`.
|
|
1415
1416
|
* @param options.useTransitions Wraps the navigation in
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.
|
|
2
|
+
* react-router v8.3.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -22,7 +22,7 @@ import * as React$1 from "react";
|
|
|
22
22
|
//#region lib/dom/lib.tsx
|
|
23
23
|
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
24
24
|
try {
|
|
25
|
-
if (isBrowser) window.__reactRouterVersion = "8.
|
|
25
|
+
if (isBrowser) window.__reactRouterVersion = "8.3.0";
|
|
26
26
|
} catch (e) {}
|
|
27
27
|
/**
|
|
28
28
|
* Create a new {@link DataRouter| data router} that manages the application
|
|
@@ -386,7 +386,7 @@ const NavLink = React$1.forwardRef(function NavLinkWithRef({ "aria-current": ari
|
|
|
386
386
|
if (nextLocationPathname && basename) nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
|
|
387
387
|
const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
|
|
388
388
|
let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
|
|
389
|
-
let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(
|
|
389
|
+
let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(endSlashPosition) === "/");
|
|
390
390
|
let renderProps = {
|
|
391
391
|
isActive,
|
|
392
392
|
isPending,
|
|
@@ -609,7 +609,8 @@ function useDataRouterState(hookName) {
|
|
|
609
609
|
* for this navigation. To apply specific styles during the transition, see
|
|
610
610
|
* {@link useViewTransitionState}. Defaults to `false`.
|
|
611
611
|
* @param options.defaultShouldRevalidate Specify the default revalidation
|
|
612
|
-
* behavior for the navigation.
|
|
612
|
+
* behavior for the navigation. When not specified, loaders revalidate
|
|
613
|
+
* according to the router's standard revalidation behavior.
|
|
613
614
|
* @param options.mask Masked location to display in the browser instead
|
|
614
615
|
* of the router location. Defaults to `undefined`.
|
|
615
616
|
* @param options.useTransitions Wraps the navigation in
|