react-router 8.3.0 → 8.3.1
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 +13 -2
- 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 +8 -0
- package/dist/development/index-react-server.js +22 -13
- package/dist/development/index.js +1 -1
- package/dist/development/lib/actions.js +10 -5
- package/dist/development/lib/components.js +6 -3
- package/dist/development/lib/context.d.ts +1 -0
- package/dist/development/lib/context.js +1 -1
- package/dist/development/lib/dom/dom.js +2 -2
- package/dist/development/lib/dom/lib.js +20 -5
- package/dist/development/lib/dom/server.js +1 -1
- package/dist/development/lib/dom/ssr/components.js +2 -2
- 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 +2 -1
- 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.js +1 -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 +5 -5
- 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.js +6 -3
- package/dist/development/lib/href.js +1 -1
- package/dist/development/lib/router/history.js +2 -2
- package/dist/development/lib/router/instrumentation.js +1 -1
- package/dist/development/lib/router/navigation.js +45 -0
- package/dist/development/lib/router/router.d.ts +8 -0
- package/dist/development/lib/router/router.js +31 -17
- package/dist/development/lib/router/url.js +1 -1
- package/dist/development/lib/router/utils.js +10 -6
- package/dist/development/lib/rsc/browser.js +4 -1
- 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 +2 -2
- package/dist/development/lib/rsc/route-modules.js +1 -1
- package/dist/development/lib/rsc/server.ssr.js +2 -2
- package/dist/development/lib/server-runtime/cookies.js +2 -2
- package/dist/development/lib/server-runtime/crypto.js +2 -2
- package/dist/development/lib/server-runtime/data.js +1 -1
- package/dist/development/lib/server-runtime/dev.js +2 -2
- 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.js +2 -2
- package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
- package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
- package/dist/development/lib/server-runtime/sessions.js +1 -1
- package/dist/development/lib/server-runtime/single-fetch.js +2 -2
- 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 +4 -4
- 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 +8 -0
- package/dist/production/index-react-server.js +22 -13
- package/dist/production/index.js +1 -1
- package/dist/production/lib/actions.js +10 -5
- package/dist/production/lib/components.js +6 -3
- package/dist/production/lib/context.d.ts +1 -0
- package/dist/production/lib/context.js +1 -1
- package/dist/production/lib/dom/dom.js +2 -2
- package/dist/production/lib/dom/lib.js +20 -5
- package/dist/production/lib/dom/server.js +1 -1
- package/dist/production/lib/dom/ssr/components.js +2 -2
- 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 +2 -1
- 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.js +1 -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 +5 -5
- 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.js +6 -3
- package/dist/production/lib/href.js +1 -1
- package/dist/production/lib/router/history.js +2 -2
- package/dist/production/lib/router/instrumentation.js +1 -1
- package/dist/production/lib/router/navigation.js +45 -0
- package/dist/production/lib/router/router.d.ts +8 -0
- package/dist/production/lib/router/router.js +31 -17
- package/dist/production/lib/router/url.js +1 -1
- package/dist/production/lib/router/utils.js +10 -6
- package/dist/production/lib/rsc/browser.js +4 -1
- 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 +2 -2
- package/dist/production/lib/rsc/route-modules.js +1 -1
- package/dist/production/lib/rsc/server.ssr.js +2 -2
- package/dist/production/lib/server-runtime/cookies.js +2 -2
- package/dist/production/lib/server-runtime/crypto.js +2 -2
- package/dist/production/lib/server-runtime/data.js +1 -1
- package/dist/production/lib/server-runtime/dev.js +2 -2
- 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.js +2 -2
- package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
- package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
- package/dist/production/lib/server-runtime/sessions.js +1 -1
- package/dist/production/lib/server-runtime/single-fetch.js +2 -2
- 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 +4 -4
- package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# `react-router`
|
|
2
2
|
|
|
3
|
+
## v8.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix `Expected fetcher: <key>` error thrown on navigation when a fetcher is aborted during its post-action revalidation ([#15365](https://github.com/remix-run/react-router/pull/15365))
|
|
8
|
+
- Fix lazy route discovery caching a path as discovered when the triggering navigation was aborted after the manifest response settled but before the route tree was patched, which permanently (for the session) shadowed the real route behind a catch-all or produced 404s on every subsequent visit ([#15399](https://github.com/remix-run/react-router/pull/15399))
|
|
9
|
+
- Improve route matching performance for long paths ([#15417](https://github.com/remix-run/react-router/pull/15417))
|
|
10
|
+
- Improve validation of action request origins ([#15419](https://github.com/remix-run/react-router/pull/15419))
|
|
11
|
+
- Fix `<ScrollRestoration>` leaving `history.scrollRestoration` set to `"auto"` after a bfcache restore, which let the browser restore scroll on subsequent history traversals before the destination route had rendered ([#15397](https://github.com/remix-run/react-router/pull/15397))
|
|
12
|
+
- Properly respect the `relative` option in `useSubmit`/`fetcher.submit` when resolivng the `action` path ([#15400](https://github.com/remix-run/react-router/pull/15400))
|
|
13
|
+
- Add additional URL validation on client side navigations/redirects ([#15445](https://github.com/remix-run/react-router/pull/15445))
|
|
14
|
+
|
|
3
15
|
## v8.3.0
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -17,7 +29,7 @@
|
|
|
17
29
|
|
|
18
30
|
### Unstable Changes
|
|
19
31
|
|
|
20
|
-
⚠️
|
|
32
|
+
⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
|
|
21
33
|
|
|
22
34
|
- Detect stale RSC clients during lazy route discovery and reload the destination document ([#15318](https://github.com/remix-run/react-router/pull/15318))
|
|
23
35
|
|
|
@@ -35,7 +47,6 @@
|
|
|
35
47
|
```
|
|
36
48
|
|
|
37
49
|
- Add CSP nonce support to RSC document rendering ([#15320](https://github.com/remix-run/react-router/pull/15320))
|
|
38
|
-
|
|
39
50
|
- Add `nonce` options to `unstable_routeRSCServerRequest` and `unstable_RSCStaticRouter`
|
|
40
51
|
- Forward the nonce to the HTML renderer and apply it to injected RSC payload scripts and nonce-aware framework components
|
|
41
52
|
|
|
@@ -1231,6 +1231,14 @@ interface Router$1 {
|
|
|
1231
1231
|
* @param location
|
|
1232
1232
|
*/
|
|
1233
1233
|
createHref(location: Location | URL): string;
|
|
1234
|
+
/**
|
|
1235
|
+
* @private
|
|
1236
|
+
* PRIVATE - DO NOT USE
|
|
1237
|
+
*
|
|
1238
|
+
* Utility function to create a URL for the given location
|
|
1239
|
+
* @param location
|
|
1240
|
+
*/
|
|
1241
|
+
createURL?(to: To): URL;
|
|
1234
1242
|
/**
|
|
1235
1243
|
* @private
|
|
1236
1244
|
* PRIVATE - DO NOT USE
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -24,7 +24,7 @@ function warning(cond, message) {
|
|
|
24
24
|
if (typeof console !== "undefined") console.warn(message);
|
|
25
25
|
try {
|
|
26
26
|
throw new Error(message);
|
|
27
|
-
} catch
|
|
27
|
+
} catch {}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
function createKey$1() {
|
|
@@ -515,13 +515,13 @@ function matchPathImpl(pattern, pathname, matcher, compiledParams) {
|
|
|
515
515
|
let match = pathname.match(matcher);
|
|
516
516
|
if (!match) return null;
|
|
517
517
|
let matchedPathname = match[0];
|
|
518
|
-
let pathnameBase = matchedPathname
|
|
518
|
+
let pathnameBase = removeTrailingSlash(matchedPathname, 1);
|
|
519
519
|
let captureGroups = match.slice(1);
|
|
520
520
|
return {
|
|
521
521
|
params: compiledParams.reduce((memo, { paramName, isOptional }, index) => {
|
|
522
522
|
if (paramName === "*") {
|
|
523
523
|
let splatValue = captureGroups[index] || "";
|
|
524
|
-
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length)
|
|
524
|
+
pathnameBase = removeTrailingSlash(matchedPathname.slice(0, matchedPathname.length - splatValue.length), 1);
|
|
525
525
|
}
|
|
526
526
|
const value = captureGroups[index];
|
|
527
527
|
if (isOptional && !value) memo[paramName] = void 0;
|
|
@@ -590,7 +590,7 @@ function resolvePath(to, fromPathname = "/") {
|
|
|
590
590
|
let pathname;
|
|
591
591
|
if (toPathname) {
|
|
592
592
|
toPathname = removeDoubleSlashes(toPathname);
|
|
593
|
-
if (toPathname.startsWith("/")) pathname = resolvePathname(toPathname.substring(1), "/");
|
|
593
|
+
if (toPathname.startsWith("/") || toPathname.startsWith("\\")) pathname = resolvePathname(toPathname.substring(1), "/");
|
|
594
594
|
else pathname = resolvePathname(toPathname, fromPathname);
|
|
595
595
|
} else pathname = fromPathname;
|
|
596
596
|
return {
|
|
@@ -651,7 +651,11 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = fal
|
|
|
651
651
|
}
|
|
652
652
|
const removeDoubleSlashes = (path) => path.replace(/[\\/]{2,}/g, "/");
|
|
653
653
|
const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
|
|
654
|
-
|
|
654
|
+
function removeTrailingSlash(path, minLength = 0) {
|
|
655
|
+
let end = path.length;
|
|
656
|
+
while (end > minLength && path.charCodeAt(end - 1) === 47) end--;
|
|
657
|
+
return end === path.length ? path : path.slice(0, end);
|
|
658
|
+
}
|
|
655
659
|
const normalizePathname = (pathname) => removeTrailingSlash(pathname).replace(/^\/*/, "/");
|
|
656
660
|
const normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
|
657
661
|
const normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
|
@@ -1816,7 +1820,7 @@ async function callDataStrategyImpl(dataStrategyImpl, request, path, matches, fe
|
|
|
1816
1820
|
});
|
|
1817
1821
|
try {
|
|
1818
1822
|
await Promise.all(matches.flatMap((m) => [m._lazyPromises?.handler, m._lazyPromises?.route]));
|
|
1819
|
-
} catch
|
|
1823
|
+
} catch {}
|
|
1820
1824
|
return results;
|
|
1821
1825
|
}
|
|
1822
1826
|
async function callLoaderOrAction({ request, path, pattern, match, lazyHandlerPromise, lazyRoutePromise, handlerOverride, scopedContext }) {
|
|
@@ -2217,14 +2221,19 @@ function getPathsWithAncestors(paths) {
|
|
|
2217
2221
|
function throwIfPotentialCSRFAttack(request, allowedActionOrigins) {
|
|
2218
2222
|
let originHeader = request.headers.get("origin");
|
|
2219
2223
|
let originDomain = null;
|
|
2224
|
+
let originUrl = null;
|
|
2220
2225
|
try {
|
|
2221
|
-
|
|
2226
|
+
if (typeof originHeader === "string" && originHeader !== "null") {
|
|
2227
|
+
originUrl = new URL(originHeader);
|
|
2228
|
+
originDomain = originUrl.host;
|
|
2229
|
+
} else originDomain = originHeader;
|
|
2222
2230
|
} catch {
|
|
2223
2231
|
throw new Error(`\`origin\` header is not a valid URL. Aborting the action.`);
|
|
2224
2232
|
}
|
|
2225
|
-
let
|
|
2226
|
-
|
|
2227
|
-
|
|
2233
|
+
let requestUrl = new URL(request.url);
|
|
2234
|
+
let originMatchesRequest = originUrl ? originUrl.origin === requestUrl.origin : originDomain === requestUrl.host;
|
|
2235
|
+
if (originDomain && !originMatchesRequest) {
|
|
2236
|
+
if (!isAllowedOrigin(originDomain, allowedActionOrigins)) throw new Error("The `request.url` origin does not match `origin` header from a forwarded action request. Aborting the action.");
|
|
2228
2237
|
}
|
|
2229
2238
|
}
|
|
2230
2239
|
function matchWildcardDomain(domain, pattern) {
|
|
@@ -2948,7 +2957,7 @@ const unsign = async (cookie, secret) => {
|
|
|
2948
2957
|
try {
|
|
2949
2958
|
let signature = byteStringToUint8Array(atob(hash));
|
|
2950
2959
|
return await crypto.subtle.verify("HMAC", key, signature, data) ? value : false;
|
|
2951
|
-
} catch
|
|
2960
|
+
} catch {
|
|
2952
2961
|
return false;
|
|
2953
2962
|
}
|
|
2954
2963
|
};
|
|
@@ -3046,7 +3055,7 @@ function encodeData(value) {
|
|
|
3046
3055
|
function decodeData(value) {
|
|
3047
3056
|
try {
|
|
3048
3057
|
return JSON.parse(decodeURIComponent(myEscape(atob(value))));
|
|
3049
|
-
} catch
|
|
3058
|
+
} catch {
|
|
3050
3059
|
return {};
|
|
3051
3060
|
}
|
|
3052
3061
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -12,14 +12,19 @@
|
|
|
12
12
|
function throwIfPotentialCSRFAttack(request, allowedActionOrigins) {
|
|
13
13
|
let originHeader = request.headers.get("origin");
|
|
14
14
|
let originDomain = null;
|
|
15
|
+
let originUrl = null;
|
|
15
16
|
try {
|
|
16
|
-
|
|
17
|
+
if (typeof originHeader === "string" && originHeader !== "null") {
|
|
18
|
+
originUrl = new URL(originHeader);
|
|
19
|
+
originDomain = originUrl.host;
|
|
20
|
+
} else originDomain = originHeader;
|
|
17
21
|
} catch {
|
|
18
22
|
throw new Error(`\`origin\` header is not a valid URL. Aborting the action.`);
|
|
19
23
|
}
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
let requestUrl = new URL(request.url);
|
|
25
|
+
let originMatchesRequest = originUrl ? originUrl.origin === requestUrl.origin : originDomain === requestUrl.host;
|
|
26
|
+
if (originDomain && !originMatchesRequest) {
|
|
27
|
+
if (!isAllowedOrigin(originDomain, allowedActionOrigins)) throw new Error("The `request.url` origin does not match `origin` header from a forwarded action request. Aborting the action.");
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
function matchWildcardDomain(domain, pattern) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { createMemoryHistory, invariant, parsePath, warning } from "./router/history.js";
|
|
11
|
+
import { createMemoryHistory, createPath, invariant, parsePath, warning } from "./router/history.js";
|
|
12
12
|
import { defaultMapRouteProperties, getResolveToMatches, getRoutePattern, resolveTo, stripBasename } from "./router/utils.js";
|
|
13
|
+
import { getNavigatorCurrentUrl, validateNavigationTarget } from "./router/navigation.js";
|
|
13
14
|
import { createRouter } from "./router/router.js";
|
|
14
15
|
import { AwaitContext, DataRouterContext, DataRouterStateContext, FetchersContext, LocationContext, NavigationContext, RouteContext, ViewTransitionContext, useIsRSCRouterContext } from "./context.js";
|
|
15
16
|
import { _renderMatches, useActionData, useAsyncValue, useInRouterContext, useLoaderData, useLocation, useMatches, useNavigate, useOutlet, useParams, useRouteError, useRoutes, useRoutesImpl } from "./hooks.js";
|
|
@@ -256,6 +257,7 @@ function RouterProvider({ router, flushSync: reactDomFlushSyncImpl, onError, use
|
|
|
256
257
|
let navigator = React$1.useMemo(() => {
|
|
257
258
|
return {
|
|
258
259
|
createHref: router.createHref,
|
|
260
|
+
createURL: router.createURL,
|
|
259
261
|
encodeLocation: router.encodeLocation,
|
|
260
262
|
go: (n) => router.navigate(n),
|
|
261
263
|
push: (to, state, opts) => router.navigate(to, {
|
|
@@ -379,12 +381,13 @@ function MemoryRouter({ basename, children, initialEntries, initialIndex, useTra
|
|
|
379
381
|
*/
|
|
380
382
|
function Navigate({ to, replace, state, relative }) {
|
|
381
383
|
invariant(useInRouterContext(), `<Navigate> may be used only in the context of a <Router> component.`);
|
|
382
|
-
let { static: isStatic } = React$1.useContext(NavigationContext);
|
|
384
|
+
let { static: isStatic, navigator } = React$1.useContext(NavigationContext);
|
|
383
385
|
warning(!isStatic, "<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.");
|
|
384
386
|
let { matches } = React$1.useContext(RouteContext);
|
|
385
387
|
let { pathname: locationPathname } = useLocation();
|
|
386
388
|
let navigate = useNavigate();
|
|
387
389
|
let path = resolveTo(to, getResolveToMatches(matches), locationPathname, relative === "path");
|
|
390
|
+
validateNavigationTarget(typeof to === "string" ? to : createPath(to), navigator.createHref(path), getNavigatorCurrentUrl(navigator), "reject");
|
|
388
391
|
let jsonPath = JSON.stringify(path);
|
|
389
392
|
React$1.useEffect(() => {
|
|
390
393
|
navigate(JSON.parse(jsonPath), {
|
|
@@ -55,6 +55,7 @@ interface NavigateOptions {
|
|
|
55
55
|
*/
|
|
56
56
|
interface Navigator {
|
|
57
57
|
createHref: History["createHref"];
|
|
58
|
+
createURL?: History["createURL"];
|
|
58
59
|
encodeLocation?: History["encodeLocation"];
|
|
59
60
|
go: History["go"];
|
|
60
61
|
push(to: To, state?: any, opts?: NavigateOptions): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -75,7 +75,7 @@ function isFormDataSubmitterSupported() {
|
|
|
75
75
|
if (_formDataSupportsSubmitter === null) try {
|
|
76
76
|
new FormData(document.createElement("form"), 0);
|
|
77
77
|
_formDataSupportsSubmitter = false;
|
|
78
|
-
} catch
|
|
78
|
+
} catch {
|
|
79
79
|
_formDataSupportsSubmitter = true;
|
|
80
80
|
}
|
|
81
81
|
return _formDataSupportsSubmitter;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -22,8 +22,8 @@ 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
|
|
26
|
-
} catch
|
|
25
|
+
if (isBrowser) window.__reactRouterVersion = "8";
|
|
26
|
+
} catch {}
|
|
27
27
|
/**
|
|
28
28
|
* Create a new {@link DataRouter| data router} that manages the application
|
|
29
29
|
* path via [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)
|
|
@@ -123,7 +123,7 @@ function deserializeErrors(errors) {
|
|
|
123
123
|
let error = new ErrorConstructor(val.message);
|
|
124
124
|
error.stack = "";
|
|
125
125
|
serialized[key] = error;
|
|
126
|
-
} catch
|
|
126
|
+
} catch {}
|
|
127
127
|
}
|
|
128
128
|
if (serialized[key] == null) {
|
|
129
129
|
let error = new Error(val.message);
|
|
@@ -796,6 +796,7 @@ function useSubmit() {
|
|
|
796
796
|
if (options.navigate === false) await routerFetch(options.fetcherKey || getUniqueFetcherId(), currentRouteId, options.action || action, {
|
|
797
797
|
defaultShouldRevalidate: options.defaultShouldRevalidate,
|
|
798
798
|
preventScrollReset: options.preventScrollReset,
|
|
799
|
+
relative: options.relative,
|
|
799
800
|
formData,
|
|
800
801
|
body,
|
|
801
802
|
formMethod: options.method || method,
|
|
@@ -805,6 +806,7 @@ function useSubmit() {
|
|
|
805
806
|
else await routerNavigate(options.action || action, {
|
|
806
807
|
defaultShouldRevalidate: options.defaultShouldRevalidate,
|
|
807
808
|
preventScrollReset: options.preventScrollReset,
|
|
809
|
+
relative: options.relative,
|
|
808
810
|
formData,
|
|
809
811
|
body,
|
|
810
812
|
formMethod: options.method || method,
|
|
@@ -1087,6 +1089,9 @@ function useScrollRestoration({ getKey, storageKey } = {}) {
|
|
|
1087
1089
|
window.history.scrollRestoration = "auto";
|
|
1088
1090
|
};
|
|
1089
1091
|
}, []);
|
|
1092
|
+
usePageShow(React$1.useCallback((event) => {
|
|
1093
|
+
if (event.persisted) window.history.scrollRestoration = "manual";
|
|
1094
|
+
}, []));
|
|
1090
1095
|
usePageHide(React$1.useCallback(() => {
|
|
1091
1096
|
if (navigation.state === "idle") {
|
|
1092
1097
|
let key = getScrollRestorationKey(location, matches, basename, getKey);
|
|
@@ -1111,7 +1116,7 @@ function useScrollRestoration({ getKey, storageKey } = {}) {
|
|
|
1111
1116
|
try {
|
|
1112
1117
|
let sessionPositions = sessionStorage.getItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY);
|
|
1113
1118
|
if (sessionPositions) savedScrollPositions = JSON.parse(sessionPositions);
|
|
1114
|
-
} catch
|
|
1119
|
+
} catch {}
|
|
1115
1120
|
}, [storageKey]);
|
|
1116
1121
|
React$1.useLayoutEffect(() => {
|
|
1117
1122
|
let disableScrollRestoration = router?.enableScrollRestoration(savedScrollPositions, () => window.scrollY, getKey ? (location, matches) => getScrollRestorationKey(location, matches, basename, getKey) : void 0);
|
|
@@ -1179,6 +1184,16 @@ function usePageHide(callback, options) {
|
|
|
1179
1184
|
};
|
|
1180
1185
|
}, [callback, capture]);
|
|
1181
1186
|
}
|
|
1187
|
+
function usePageShow(callback, options) {
|
|
1188
|
+
let { capture } = options || {};
|
|
1189
|
+
React$1.useEffect(() => {
|
|
1190
|
+
let opts = capture != null ? { capture } : void 0;
|
|
1191
|
+
window.addEventListener("pageshow", callback, opts);
|
|
1192
|
+
return () => {
|
|
1193
|
+
window.removeEventListener("pageshow", callback, opts);
|
|
1194
|
+
};
|
|
1195
|
+
}, [callback, capture]);
|
|
1196
|
+
}
|
|
1182
1197
|
/**
|
|
1183
1198
|
* Wrapper around {@link useBlocker} to show a [`window.confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm)
|
|
1184
1199
|
* prompt to users instead of building a custom UI with {@link useBlocker}.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -425,7 +425,7 @@ function Meta() {
|
|
|
425
425
|
type: "application/ld+json",
|
|
426
426
|
dangerouslySetInnerHTML: { __html: escapeHtml(json) }
|
|
427
427
|
});
|
|
428
|
-
} catch
|
|
428
|
+
} catch {
|
|
429
429
|
return null;
|
|
430
430
|
}
|
|
431
431
|
return /* @__PURE__ */ React$1.createElement("meta", {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -154,6 +154,7 @@ async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, ro
|
|
|
154
154
|
if (signal?.aborted) return;
|
|
155
155
|
throw e;
|
|
156
156
|
}
|
|
157
|
+
if (signal?.aborted) return;
|
|
157
158
|
let knownRoutes = new Set(Object.keys(manifest.routes));
|
|
158
159
|
let patches = Object.values(serverPatches).reduce((acc, route) => {
|
|
159
160
|
if (route && !knownRoutes.has(route.id)) acc[route.id] = route;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -205,7 +205,7 @@ async function bubbleMiddlewareErrors(singleFetchPromise, matches, routesParams,
|
|
|
205
205
|
if (middlewareError !== void 0) Array.from(routesParams.values()).forEach((routeId) => {
|
|
206
206
|
if (results[routeId].result instanceof SingleFetchNoResultError) results[routeId].result = middlewareError;
|
|
207
207
|
});
|
|
208
|
-
} catch
|
|
208
|
+
} catch {}
|
|
209
209
|
}
|
|
210
210
|
async function singleFetchLoaderFetcherStrategy(args, fetchAndDecode) {
|
|
211
211
|
let fetcherMatch = args.matches.find((m) => m.shouldCallHandler());
|
|
@@ -277,7 +277,7 @@ async function fetchAndDecodeViaTurboStream(args, targetRoutes) {
|
|
|
277
277
|
status: res.status,
|
|
278
278
|
data
|
|
279
279
|
};
|
|
280
|
-
} catch
|
|
280
|
+
} catch {
|
|
281
281
|
throw new Error("Unable to decode turbo-stream response");
|
|
282
282
|
}
|
|
283
283
|
}
|
|
@@ -326,13 +326,13 @@ function createDeferred() {
|
|
|
326
326
|
res(val);
|
|
327
327
|
try {
|
|
328
328
|
await promise;
|
|
329
|
-
} catch
|
|
329
|
+
} catch {}
|
|
330
330
|
};
|
|
331
331
|
reject = async (error) => {
|
|
332
332
|
rej(error);
|
|
333
333
|
try {
|
|
334
334
|
await promise;
|
|
335
|
-
} catch
|
|
335
|
+
} catch {}
|
|
336
336
|
};
|
|
337
337
|
});
|
|
338
338
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { invariant, parsePath, warning } from "./router/history.js";
|
|
11
|
+
import { createPath, invariant, parsePath, warning } from "./router/history.js";
|
|
12
12
|
import { convertRouteMatchToUiMatch, decodePath, getResolveToMatches, getRoutePattern, isBrowser, isRouteErrorResponse, joinPaths, matchPath, matchRoutes, parseToInfo, resolveTo, stripBasename } from "./router/utils.js";
|
|
13
|
+
import { getNavigatorCurrentUrl, validateNavigationTarget } from "./router/navigation.js";
|
|
13
14
|
import { IDLE_BLOCKER, hasInvalidProtocol } from "./router/router.js";
|
|
14
15
|
import { AwaitContext, DataRouterContext, DataRouterStateContext, LocationContext, NavigationContext, RSCRouterContext, RouteContext, RouteErrorContext } from "./context.js";
|
|
15
16
|
import { decodeRedirectErrorDigest, decodeRouteErrorResponseDigest } from "./errors.js";
|
|
@@ -291,6 +292,7 @@ function useNavigateUnstable() {
|
|
|
291
292
|
}
|
|
292
293
|
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
|
|
293
294
|
if (dataRouterContext == null && basename !== "/") path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
|
|
295
|
+
validateNavigationTarget(typeof to === "string" ? to : createPath(to), navigator.createHref(path), getNavigatorCurrentUrl(navigator), "reject");
|
|
294
296
|
(!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
|
|
295
297
|
}, [
|
|
296
298
|
basename,
|
|
@@ -687,7 +689,7 @@ var RenderErrorBoundary = class extends React$1.Component {
|
|
|
687
689
|
};
|
|
688
690
|
const errorRedirectHandledMap = /* @__PURE__ */ new WeakMap();
|
|
689
691
|
function RSCErrorHandler({ children, error }) {
|
|
690
|
-
let { basename } = React$1.useContext(NavigationContext);
|
|
692
|
+
let { basename, navigator } = React$1.useContext(NavigationContext);
|
|
691
693
|
if (typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
|
|
692
694
|
let redirect = decodeRedirectErrorDigest(error.digest);
|
|
693
695
|
if (redirect) {
|
|
@@ -695,6 +697,7 @@ function RSCErrorHandler({ children, error }) {
|
|
|
695
697
|
if (existingRedirect) throw existingRedirect;
|
|
696
698
|
let parsed = parseToInfo(redirect.location, basename);
|
|
697
699
|
let target = parsed.absoluteURL || parsed.to;
|
|
700
|
+
validateNavigationTarget(redirect.location, target, getNavigatorCurrentUrl(navigator), "allow-explicit");
|
|
698
701
|
if (hasInvalidProtocol(target)) throw new Error("Invalid redirect location");
|
|
699
702
|
if (isBrowser && !errorRedirectHandledMap.get(error)) if (parsed.isExternal || redirect.reloadDocument) window.location.href = target;
|
|
700
703
|
else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.3.
|
|
2
|
+
* react-router v8.3.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -193,7 +193,7 @@ function warning(cond, message) {
|
|
|
193
193
|
if (typeof console !== "undefined") console.warn(message);
|
|
194
194
|
try {
|
|
195
195
|
throw new Error(message);
|
|
196
|
-
} catch
|
|
196
|
+
} catch {}
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
function createKey() {
|