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 = {};
|
|
@@ -380,6 +386,8 @@ function rankRouteBranches(branches) {
|
|
|
380
386
|
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)));
|
|
381
387
|
}
|
|
382
388
|
const paramRe = /^:[\w-]+$/;
|
|
389
|
+
const partialParamRe = /^:[\w-]+/;
|
|
390
|
+
const partialDynamicSegmentValue = 3.5;
|
|
383
391
|
const dynamicSegmentValue = 3;
|
|
384
392
|
const indexRouteValue = 2;
|
|
385
393
|
const emptySegmentValue = 1;
|
|
@@ -391,7 +399,7 @@ function computeScore(path, index) {
|
|
|
391
399
|
let initialScore = segments.length;
|
|
392
400
|
if (segments.some(isSplat)) initialScore += splatPenalty;
|
|
393
401
|
if (index) initialScore += indexRouteValue;
|
|
394
|
-
return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
402
|
+
return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : partialParamRe.test(segment) ? partialDynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
395
403
|
}
|
|
396
404
|
function compareIndexes(a, b) {
|
|
397
405
|
return a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]) ? a[a.length - 1] - b[b.length - 1] : 0;
|
|
@@ -430,6 +438,48 @@ function matchRouteBranch(branch, pathname, allowPartial = false) {
|
|
|
430
438
|
return matches;
|
|
431
439
|
}
|
|
432
440
|
/**
|
|
441
|
+
* Characters that `encodeURIComponent` escapes but that are valid literally in
|
|
442
|
+
* a URL path segment. Per RFC 3986 §3.3, a path segment is made of `pchar`:
|
|
443
|
+
*
|
|
444
|
+
* ```
|
|
445
|
+
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
|
446
|
+
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
|
447
|
+
* ```
|
|
448
|
+
*
|
|
449
|
+
* `encodeURIComponent` targets query-string values, where `$ & + , ; = : @`
|
|
450
|
+
* are delimiters and must be escaped — but in a path segment they carry no
|
|
451
|
+
* special meaning, and browsers keep them literal in `location.pathname`.
|
|
452
|
+
* (`! ' ( ) *` and the unreserved set are already left alone by
|
|
453
|
+
* `encodeURIComponent`, so they need no restoring.)
|
|
454
|
+
*/
|
|
455
|
+
const PATH_PARAM_OVERESCAPED = {
|
|
456
|
+
"%24": "$",
|
|
457
|
+
"%26": "&",
|
|
458
|
+
"%2B": "+",
|
|
459
|
+
"%2C": ",",
|
|
460
|
+
"%3A": ":",
|
|
461
|
+
"%3B": ";",
|
|
462
|
+
"%3D": "=",
|
|
463
|
+
"%40": "@"
|
|
464
|
+
};
|
|
465
|
+
/**
|
|
466
|
+
* Encodes a param value for interpolation into a single URL path segment.
|
|
467
|
+
*
|
|
468
|
+
* Escapes characters that would break the path (`/ ? # %`, whitespace,
|
|
469
|
+
* non-ASCII, …) while leaving characters that RFC 3986 permits literally in a
|
|
470
|
+
* path segment untouched. Escaping those would needlessly rewrite URLs — e.g.
|
|
471
|
+
* a semver build param `1.0.0+1` would become `1.0.0%2B1` even though browsers
|
|
472
|
+
* display and match the `+` literally in `location.pathname`.
|
|
473
|
+
*
|
|
474
|
+
* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3))
|
|
475
|
+
*
|
|
476
|
+
* @param value The param value to encode.
|
|
477
|
+
* @returns The encoded value, safe for use as a single path segment.
|
|
478
|
+
*/
|
|
479
|
+
function encodePathParam(value) {
|
|
480
|
+
return encodeURIComponent(value).replace(/%(?:24|26|2B|2C|3A|3B|3D|40)/g, (match) => PATH_PARAM_OVERESCAPED[match]);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
433
483
|
* Performs pattern matching on a URL pathname and returns information about
|
|
434
484
|
* the match.
|
|
435
485
|
*
|
|
@@ -488,7 +538,7 @@ function compilePath(path, caseSensitive = false, end = true) {
|
|
|
488
538
|
return "(?:/([^\\/]*))?";
|
|
489
539
|
}
|
|
490
540
|
return "/([^\\/]+)";
|
|
491
|
-
}).replace(/\/([\w-]+)\?(
|
|
541
|
+
}).replace(/\/([\w-]+)\?(?=\/|$|\()/g, "(?:/$1)?");
|
|
492
542
|
if (path.endsWith("*")) {
|
|
493
543
|
params.push({ paramName: "*" });
|
|
494
544
|
regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
|
|
@@ -2321,6 +2371,8 @@ const Await = (async ({ children, resolve, errorElement }) => {
|
|
|
2321
2371
|
* encoding the {@link unstable_RSCPayload}.
|
|
2322
2372
|
* @param opts.loadServerAction Your `react-server-dom-xyz/server`'s
|
|
2323
2373
|
* `loadServerAction` function, used to load a server action by ID.
|
|
2374
|
+
* @param opts.clientVersion A version derived from the client build output used
|
|
2375
|
+
* to detect stale clients during lazy route discovery.
|
|
2324
2376
|
* @param opts.onError An optional error handler that will be called with any
|
|
2325
2377
|
* errors that occur during the request processing.
|
|
2326
2378
|
* @param opts.request The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
@@ -2334,7 +2386,7 @@ const Await = (async ({ children, resolve, errorElement }) => {
|
|
|
2334
2386
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
2335
2387
|
* data for hydration.
|
|
2336
2388
|
*/
|
|
2337
|
-
async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, routeDiscovery, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse }) {
|
|
2389
|
+
async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, routeDiscovery, loadServerAction, decodeAction, decodeFormState, clientVersion, onError, request, routes, generateResponse }) {
|
|
2338
2390
|
let url = new URL(request.url);
|
|
2339
2391
|
basename = basename || "/";
|
|
2340
2392
|
let normalizedPath = url.pathname;
|
|
@@ -2352,22 +2404,26 @@ async function matchRSCServerRequest({ allowedActionOrigins, createTemporaryRefe
|
|
|
2352
2404
|
});
|
|
2353
2405
|
const temporaryReferences = createTemporaryReferenceSet();
|
|
2354
2406
|
const requestUrl = new URL(request.url);
|
|
2355
|
-
if (isManifestRequest(requestUrl)) return await generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery);
|
|
2407
|
+
if (isManifestRequest(requestUrl)) return await generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion);
|
|
2356
2408
|
let isDataRequest = isReactServerRequest(requestUrl);
|
|
2357
2409
|
let matches = matchRoutes(routes, url.pathname, basename);
|
|
2358
2410
|
if (matches) await Promise.all(matches.map((m) => explodeLazyRoute(m.route)));
|
|
2359
2411
|
const leafMatch = matches?.[matches.length - 1];
|
|
2360
2412
|
if (!isDataRequest && leafMatch && !leafMatch.route.Component && !leafMatch.route.ErrorBoundary) return generateResourceResponse(routerRequest, routes, basename, leafMatch.route.id, requestContext, onError);
|
|
2361
|
-
let response = await generateRenderResponse(routerRequest, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery);
|
|
2413
|
+
let response = await generateRenderResponse(routerRequest, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion);
|
|
2362
2414
|
response.headers.set("X-Remix-Response", "yes");
|
|
2363
2415
|
return response;
|
|
2364
2416
|
}
|
|
2365
|
-
async function generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery) {
|
|
2417
|
+
async function generateManifestResponse(routes, basename, request, generateResponse, temporaryReferences, routeDiscovery, clientVersion) {
|
|
2366
2418
|
let url = new URL(request.url);
|
|
2367
2419
|
if (url.toString().length > 7680) return new Response(null, {
|
|
2368
2420
|
statusText: "Bad Request",
|
|
2369
2421
|
status: 400
|
|
2370
2422
|
});
|
|
2423
|
+
if (clientVersion !== void 0 && clientVersion !== url.searchParams.get("version")) return new Response(null, {
|
|
2424
|
+
status: 204,
|
|
2425
|
+
headers: { "X-Remix-Reload-Document": "true" }
|
|
2426
|
+
});
|
|
2371
2427
|
if (routeDiscovery?.mode === "initial") {
|
|
2372
2428
|
let payload = {
|
|
2373
2429
|
type: "manifest",
|
|
@@ -2459,7 +2515,7 @@ async function processServerAction(request, basename, decodeReply, loadServerAct
|
|
|
2459
2515
|
try {
|
|
2460
2516
|
let result = await action();
|
|
2461
2517
|
if (isRedirectResponse(result)) result = prependBasenameToRedirectResponse(result, basename);
|
|
2462
|
-
formState = decodeFormState?.(result, formData);
|
|
2518
|
+
formState = await decodeFormState?.(result, formData);
|
|
2463
2519
|
} catch (error) {
|
|
2464
2520
|
if (isRedirectResponse(error)) return prependBasenameToRedirectResponse(error, basename);
|
|
2465
2521
|
if (isResponse(error)) return error;
|
|
@@ -2516,7 +2572,7 @@ async function generateResourceResponse(request, routes, basename, routeId, requ
|
|
|
2516
2572
|
});
|
|
2517
2573
|
}
|
|
2518
2574
|
}
|
|
2519
|
-
async function generateRenderResponse(request, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery) {
|
|
2575
|
+
async function generateRenderResponse(request, routes, basename, isDataRequest, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, generateResponse, temporaryReferences, allowedActionOrigins, routeDiscovery, clientVersion) {
|
|
2520
2576
|
let statusCode = 200;
|
|
2521
2577
|
let url = new URL(request.url);
|
|
2522
2578
|
let isSubmission = isMutationMethod(request.method);
|
|
@@ -2537,29 +2593,39 @@ async function generateRenderResponse(request, routes, basename, isDataRequest,
|
|
|
2537
2593
|
let formState;
|
|
2538
2594
|
let skipRevalidation = false;
|
|
2539
2595
|
let potentialCSRFAttackError;
|
|
2540
|
-
if (isMutationMethod(request.method))
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2596
|
+
if (isMutationMethod(request.method)) {
|
|
2597
|
+
try {
|
|
2598
|
+
throwIfPotentialCSRFAttack(request, allowedActionOrigins);
|
|
2599
|
+
} catch (error) {
|
|
2600
|
+
onError?.(error);
|
|
2601
|
+
potentialCSRFAttackError = error;
|
|
2602
|
+
request = new Request(request.url, {
|
|
2603
|
+
method: "GET",
|
|
2604
|
+
headers: request.headers,
|
|
2605
|
+
signal: request.signal
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
if (!potentialCSRFAttackError) {
|
|
2609
|
+
ctx.runningAction = true;
|
|
2610
|
+
let result = await processServerAction(request, basename, decodeReply, loadServerAction, decodeAction, decodeFormState, onError, temporaryReferences).finally(() => {
|
|
2611
|
+
ctx.runningAction = false;
|
|
2612
|
+
});
|
|
2613
|
+
if (isResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
2614
|
+
skipRevalidation = result?.skipRevalidation ?? false;
|
|
2615
|
+
actionResult = result?.actionResult;
|
|
2616
|
+
formState = result?.formState;
|
|
2617
|
+
request = result?.revalidationRequest ?? request;
|
|
2618
|
+
if (ctx.redirect) return generateRedirectResponse(ctx.redirect, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, void 0);
|
|
2619
|
+
}
|
|
2554
2620
|
}
|
|
2555
|
-
let staticContext = await query(request, skipRevalidation
|
|
2621
|
+
let staticContext = await query(request, skipRevalidation ? { filterMatchesToLoad: () => false } : void 0);
|
|
2556
2622
|
if (isResponse(staticContext)) return generateRedirectResponse(staticContext, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
2557
2623
|
if (potentialCSRFAttackError) {
|
|
2558
2624
|
staticContext.errors ??= {};
|
|
2559
2625
|
staticContext.errors[staticContext.matches[0].route.id] = potentialCSRFAttackError;
|
|
2560
2626
|
staticContext.statusCode = 400;
|
|
2561
2627
|
}
|
|
2562
|
-
return generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, ctx.redirect?.headers, routeDiscovery);
|
|
2628
|
+
return generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, ctx.redirect?.headers, routeDiscovery, clientVersion);
|
|
2563
2629
|
}
|
|
2564
2630
|
}));
|
|
2565
2631
|
if (isRedirectResponse(result)) return generateRedirectResponse(result, actionResult, basename, isDataRequest, generateResponse, temporaryReferences, ctx.redirect?.headers);
|
|
@@ -2593,7 +2659,7 @@ function generateRedirectResponse(response, actionResult, basename, isDataReques
|
|
|
2593
2659
|
onError: defaultOnError
|
|
2594
2660
|
});
|
|
2595
2661
|
}
|
|
2596
|
-
async function generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, sideEffectRedirectHeaders, routeDiscovery) {
|
|
2662
|
+
async function generateStaticContextResponse(routes, basename, generateResponse, statusCode, routeIdsToLoad, isDataRequest, isSubmission, actionResult, formState, staticContext, temporaryReferences, skipRevalidation, sideEffectRedirectHeaders, routeDiscovery, clientVersion) {
|
|
2597
2663
|
statusCode = staticContext.statusCode ?? statusCode;
|
|
2598
2664
|
if (staticContext.errors) staticContext.errors = Object.fromEntries(Object.entries(staticContext.errors).map(([key, error]) => [key, isRouteErrorResponse(error) ? Object.fromEntries(Object.entries(error)) : error]));
|
|
2599
2665
|
staticContext.matches.forEach((m) => {
|
|
@@ -2606,6 +2672,7 @@ async function generateStaticContextResponse(routes, basename, generateResponse,
|
|
|
2606
2672
|
const baseRenderPayload = {
|
|
2607
2673
|
type: "render",
|
|
2608
2674
|
basename: staticContext.basename,
|
|
2675
|
+
clientVersion,
|
|
2609
2676
|
routeDiscovery: routeDiscovery ?? { mode: "lazy" },
|
|
2610
2677
|
actionData: staticContext.actionData,
|
|
2611
2678
|
errors: staticContext.errors,
|
|
@@ -2797,15 +2864,34 @@ function canDecodeWithFormData(contentType) {
|
|
|
2797
2864
|
}
|
|
2798
2865
|
//#endregion
|
|
2799
2866
|
//#region lib/href.ts
|
|
2867
|
+
function stringify(p) {
|
|
2868
|
+
return p == null ? "" : typeof p === "string" ? p : String(p);
|
|
2869
|
+
}
|
|
2800
2870
|
/**
|
|
2801
|
-
Returns a resolved URL path for the specified route.
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2871
|
+
* Returns a resolved URL path for the specified route.
|
|
2872
|
+
*
|
|
2873
|
+
* Param values are percent-encoded for use in a path segment: characters that
|
|
2874
|
+
* would change the URL structure (`/`, `?`, `#`, `%`, whitespace, non-ASCII)
|
|
2875
|
+
* are escaped, while characters that RFC 3986 allows literally in a path
|
|
2876
|
+
* segment (`$ & + , ; = : @`) are kept as-is. Note this differs from query-string
|
|
2877
|
+
* encoding (`encodeURIComponent`/`URLSearchParams`), where those characters are
|
|
2878
|
+
* delimiters and must be escaped. Splat (`*`) values are encoded per segment,
|
|
2879
|
+
* preserving `/` separators.
|
|
2880
|
+
*
|
|
2881
|
+
* See [RFC 3986 §3.3](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3)
|
|
2882
|
+
*
|
|
2883
|
+
* @example
|
|
2884
|
+
* const h = href("/:lang?/about", { lang: "en" })
|
|
2885
|
+
* // -> `/en/about`
|
|
2886
|
+
*
|
|
2887
|
+
* <Link to={href("/products/:id", { id: "abc123" })} />
|
|
2888
|
+
*
|
|
2889
|
+
* @public
|
|
2890
|
+
* @category Utils
|
|
2891
|
+
* @mode framework
|
|
2892
|
+
* @param path The route path to resolve
|
|
2893
|
+
* @param args The route params to use when resolving the path
|
|
2894
|
+
* @returns The resolved URL path
|
|
2809
2895
|
*/
|
|
2810
2896
|
function href(path, ...args) {
|
|
2811
2897
|
let params = args[0];
|
|
@@ -2813,11 +2899,11 @@ function href(path, ...args) {
|
|
|
2813
2899
|
const isRequired = questionMark === void 0;
|
|
2814
2900
|
const value = params?.[param];
|
|
2815
2901
|
if (isRequired && value === void 0) throw new Error(`Path '${path}' requires param '${param}' but it was not provided`);
|
|
2816
|
-
return value
|
|
2902
|
+
return value == null ? "" : "/" + encodePathParam(stringify(value));
|
|
2817
2903
|
});
|
|
2818
2904
|
if (path.endsWith("*")) {
|
|
2819
2905
|
const value = params?.["*"];
|
|
2820
|
-
if (value !== void 0) result += "/" + value;
|
|
2906
|
+
if (value !== void 0) result += "/" + stringify(value).split("/").map(encodePathParam).join("/");
|
|
2821
2907
|
}
|
|
2822
2908
|
return result || "/";
|
|
2823
2909
|
}
|
|
@@ -2870,6 +2956,14 @@ function byteStringToUint8Array(byteString) {
|
|
|
2870
2956
|
//#region lib/server-runtime/cookies.ts
|
|
2871
2957
|
/**
|
|
2872
2958
|
* Creates a logical container for managing a browser cookie from the server.
|
|
2959
|
+
*
|
|
2960
|
+
* @public
|
|
2961
|
+
* @category Utils
|
|
2962
|
+
* @mode framework
|
|
2963
|
+
* @mode data
|
|
2964
|
+
* @param name The name of the cookie.
|
|
2965
|
+
* @param cookieOptions Options for parsing and serializing the cookie.
|
|
2966
|
+
* @returns A {@link Cookie} object for parsing and serializing the cookie.
|
|
2873
2967
|
*/
|
|
2874
2968
|
const createCookie = (name, cookieOptions = {}) => {
|
|
2875
2969
|
let { secrets = [], ...options } = {
|
|
@@ -2909,9 +3003,15 @@ const createCookie = (name, cookieOptions = {}) => {
|
|
|
2909
3003
|
};
|
|
2910
3004
|
};
|
|
2911
3005
|
/**
|
|
2912
|
-
* Returns true if
|
|
3006
|
+
* Returns `true` if a value is a React Router {@link Cookie} object.
|
|
2913
3007
|
*
|
|
2914
|
-
* @
|
|
3008
|
+
* @public
|
|
3009
|
+
* @category Utils
|
|
3010
|
+
* @mode framework
|
|
3011
|
+
* @mode data
|
|
3012
|
+
* @param object The value to check.
|
|
3013
|
+
* @returns `true` if the value is a React Router {@link Cookie} object;
|
|
3014
|
+
* otherwise, `false`.
|
|
2915
3015
|
*/
|
|
2916
3016
|
const isCookie = (object) => {
|
|
2917
3017
|
return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function";
|
|
@@ -3001,6 +3101,12 @@ function flash(name) {
|
|
|
3001
3101
|
*
|
|
3002
3102
|
* Note: This function is typically not invoked directly by application code.
|
|
3003
3103
|
* Instead, use a `SessionStorage` object's `getSession` method.
|
|
3104
|
+
*
|
|
3105
|
+
* @category Utils
|
|
3106
|
+
* @param initialData The initial data for the session.
|
|
3107
|
+
* @param id The identifier for the session. Defaults to an empty string for a
|
|
3108
|
+
* new session.
|
|
3109
|
+
* @returns A new {@link Session} object.
|
|
3004
3110
|
*/
|
|
3005
3111
|
const createSession = (initialData = {}, id = "") => {
|
|
3006
3112
|
let map = new Map(Object.entries(initialData));
|
|
@@ -3035,9 +3141,15 @@ const createSession = (initialData = {}, id = "") => {
|
|
|
3035
3141
|
};
|
|
3036
3142
|
};
|
|
3037
3143
|
/**
|
|
3038
|
-
* Returns true if
|
|
3144
|
+
* Returns `true` if a value is a React Router {@link Session} object.
|
|
3039
3145
|
*
|
|
3040
|
-
* @
|
|
3146
|
+
* @public
|
|
3147
|
+
* @category Utils
|
|
3148
|
+
* @mode framework
|
|
3149
|
+
* @mode data
|
|
3150
|
+
* @param object The value to check.
|
|
3151
|
+
* @returns `true` if the value is a React Router {@link Session} object;
|
|
3152
|
+
* otherwise, `false`.
|
|
3041
3153
|
*/
|
|
3042
3154
|
const isSession = (object) => {
|
|
3043
3155
|
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";
|
|
@@ -3047,6 +3159,11 @@ const isSession = (object) => {
|
|
|
3047
3159
|
*
|
|
3048
3160
|
* Note: This is a low-level API that should only be used if none of the
|
|
3049
3161
|
* existing session storage options meet your requirements.
|
|
3162
|
+
*
|
|
3163
|
+
* @category Utils
|
|
3164
|
+
* @param strategy The strategy used to store session identifiers and data.
|
|
3165
|
+
* @returns A {@link SessionStorage} object that persists session data using the
|
|
3166
|
+
* provided strategy.
|
|
3050
3167
|
*/
|
|
3051
3168
|
function createSessionStorage({ cookie: cookieArg, createData, readData, updateData, deleteData }) {
|
|
3052
3169
|
let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
|
|
@@ -3086,6 +3203,14 @@ function warnOnceAboutSigningSessionCookie(cookie) {
|
|
|
3086
3203
|
* needed, and can help to simplify some load-balanced scenarios. However, it
|
|
3087
3204
|
* also has the limitation that serialized session data may not exceed the
|
|
3088
3205
|
* browser's maximum cookie size. Trade-offs!
|
|
3206
|
+
*
|
|
3207
|
+
* @public
|
|
3208
|
+
* @category Utils
|
|
3209
|
+
* @mode framework
|
|
3210
|
+
* @mode data
|
|
3211
|
+
* @param options Options for creating the cookie-backed session storage.
|
|
3212
|
+
* @returns A {@link SessionStorage} object that stores all session data in its
|
|
3213
|
+
* cookie.
|
|
3089
3214
|
*/
|
|
3090
3215
|
function createCookieSessionStorage({ cookie: cookieArg } = {}) {
|
|
3091
3216
|
let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
|
|
@@ -3111,18 +3236,24 @@ function createCookieSessionStorage({ cookie: cookieArg } = {}) {
|
|
|
3111
3236
|
//#endregion
|
|
3112
3237
|
//#region lib/server-runtime/sessions/memoryStorage.ts
|
|
3113
3238
|
/**
|
|
3114
|
-
* Creates and returns a simple in-memory SessionStorage object
|
|
3115
|
-
* for testing and as a reference implementation.
|
|
3239
|
+
* Creates and returns a simple in-memory SessionStorage object.
|
|
3116
3240
|
*
|
|
3117
|
-
*
|
|
3118
|
-
*
|
|
3241
|
+
* Intended for local development and testing. It does not scale beyond a single
|
|
3242
|
+
* process, and all session data is lost when the server process stops/restarts.
|
|
3243
|
+
*
|
|
3244
|
+
* @public
|
|
3245
|
+
* @category Utils
|
|
3246
|
+
* @mode framework
|
|
3247
|
+
* @mode data
|
|
3248
|
+
* @param options Options for creating the in-memory session storage.
|
|
3249
|
+
* @returns A {@link SessionStorage} object that stores session data in memory.
|
|
3119
3250
|
*/
|
|
3120
3251
|
function createMemorySessionStorage({ cookie } = {}) {
|
|
3121
3252
|
let map = /* @__PURE__ */ new Map();
|
|
3122
3253
|
return createSessionStorage({
|
|
3123
3254
|
cookie,
|
|
3124
3255
|
async createData(data, expires) {
|
|
3125
|
-
let id =
|
|
3256
|
+
let id = crypto.randomUUID();
|
|
3126
3257
|
map.set(id, {
|
|
3127
3258
|
data,
|
|
3128
3259
|
expires
|
package/dist/production/index.js
CHANGED
|
@@ -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
|