react-router 8.3.0 → 8.4.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 +46 -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 +50 -48
- package/dist/development/index-react-server.js +96 -43
- package/dist/development/index.d.ts +2 -2
- package/dist/development/index.js +3 -3
- package/dist/development/lib/actions.js +10 -5
- package/dist/development/lib/components.js +50 -10
- package/dist/development/lib/context.d.ts +14 -5
- package/dist/development/lib/context.js +11 -3
- package/dist/development/lib/dom/dom.js +2 -2
- package/dist/development/lib/dom/lib.js +33 -36
- package/dist/development/lib/dom/server.d.ts +6 -1
- package/dist/development/lib/dom/server.js +40 -14
- package/dist/development/lib/dom/ssr/components.js +16 -24
- package/dist/development/lib/dom/ssr/data.js +1 -1
- package/dist/development/lib/dom/ssr/entry.d.ts +4 -0
- 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 +34 -12
- package/dist/development/lib/dom/ssr/hydration.d.ts +3 -1
- package/dist/development/lib/dom/ssr/hydration.js +6 -4
- 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 +5 -2
- 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 +2 -2
- package/dist/development/lib/dom/ssr/single-fetch.js +13 -22
- package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/development/lib/dom-export/hydrated-router.js +2 -1
- package/dist/development/lib/errors.js +1 -1
- package/dist/development/lib/hooks.js +54 -46
- 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/matcher-route-pattern.d.ts +2 -0
- package/dist/development/lib/router/matcher-route-pattern.js +216 -0
- package/dist/development/lib/router/matcher-route-pattern.preload.d.ts +20 -0
- package/dist/development/lib/router/matcher-route-pattern.preload.js +36 -0
- package/dist/development/lib/router/matcher.d.ts +2 -0
- package/dist/development/lib/router/matcher.js +29 -0
- package/dist/development/lib/router/navigation.js +45 -0
- package/dist/development/lib/router/router.d.ts +21 -7
- package/dist/development/lib/router/router.js +111 -82
- package/dist/development/lib/router/url.js +1 -1
- package/dist/development/lib/router/utils.d.ts +6 -1
- package/dist/development/lib/router/utils.js +15 -9
- package/dist/development/lib/rsc/browser.js +5 -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 +3 -5
- package/dist/development/lib/rsc/route-modules.js +1 -1
- package/dist/development/lib/rsc/server.rsc.d.ts +7 -0
- package/dist/development/lib/rsc/server.ssr.js +26 -22
- 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 +3 -4
- package/dist/development/lib/server-runtime/routes.js +1 -1
- package/dist/development/lib/server-runtime/server.js +8 -7
- 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/route-pattern.d.ts +3 -0
- package/dist/development/route-pattern.js +12 -0
- 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 +50 -48
- package/dist/production/index-react-server.js +96 -43
- package/dist/production/index.d.ts +2 -2
- package/dist/production/index.js +3 -3
- package/dist/production/lib/actions.js +10 -5
- package/dist/production/lib/components.js +50 -10
- package/dist/production/lib/context.d.ts +14 -5
- package/dist/production/lib/context.js +11 -3
- package/dist/production/lib/dom/dom.js +2 -2
- package/dist/production/lib/dom/lib.js +33 -36
- package/dist/production/lib/dom/server.d.ts +6 -1
- package/dist/production/lib/dom/server.js +40 -14
- package/dist/production/lib/dom/ssr/components.js +16 -24
- package/dist/production/lib/dom/ssr/data.js +1 -1
- package/dist/production/lib/dom/ssr/entry.d.ts +4 -0
- 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 +34 -12
- package/dist/production/lib/dom/ssr/hydration.d.ts +3 -1
- package/dist/production/lib/dom/ssr/hydration.js +6 -4
- 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 +5 -2
- 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 +2 -2
- package/dist/production/lib/dom/ssr/single-fetch.js +13 -22
- package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/production/lib/dom-export/hydrated-router.js +2 -1
- package/dist/production/lib/errors.js +1 -1
- package/dist/production/lib/hooks.js +54 -46
- 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/matcher-route-pattern.d.ts +2 -0
- package/dist/production/lib/router/matcher-route-pattern.js +216 -0
- package/dist/production/lib/router/matcher-route-pattern.preload.d.ts +20 -0
- package/dist/production/lib/router/matcher-route-pattern.preload.js +36 -0
- package/dist/production/lib/router/matcher.d.ts +2 -0
- package/dist/production/lib/router/matcher.js +29 -0
- package/dist/production/lib/router/navigation.js +45 -0
- package/dist/production/lib/router/router.d.ts +21 -7
- package/dist/production/lib/router/router.js +111 -82
- package/dist/production/lib/router/url.js +1 -1
- package/dist/production/lib/router/utils.d.ts +6 -1
- package/dist/production/lib/router/utils.js +15 -9
- package/dist/production/lib/rsc/browser.js +5 -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 +3 -5
- package/dist/production/lib/rsc/route-modules.js +1 -1
- package/dist/production/lib/rsc/server.rsc.d.ts +7 -0
- package/dist/production/lib/rsc/server.ssr.js +26 -22
- 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 +3 -4
- package/dist/production/lib/server-runtime/routes.js +1 -1
- package/dist/production/lib/server-runtime/server.js +8 -7
- 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/route-pattern.d.ts +3 -0
- package/dist/production/route-pattern.js +12 -0
- 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/docs/how-to/fetchers.md +6 -1
- package/docs/how-to/middleware.md +3 -1
- package/docs/how-to/optimize-revalidation.md +178 -5
- package/docs/how-to/react-server-components.md +26 -3
- package/docs/how-to/resource-routes.md +3 -0
- package/docs/start/data/actions.md +2 -1
- package/docs/start/data/route-object.md +21 -6
- package/docs/start/framework/actions.md +4 -2
- package/docs/start/framework/route-module.md +32 -5
- package/docs/upgrading/future.md +68 -0
- package/package.json +11 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.
|
|
2
|
+
* react-router v8.4.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,10 +8,11 @@
|
|
|
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
|
-
import { AwaitContext, DataRouterContext, DataRouterStateContext, LocationContext, NavigationContext, RSCRouterContext, RouteContext, RouteErrorContext } from "./context.js";
|
|
15
|
+
import { AwaitContext, DataRouterContext, DataRouterDataContext, DataRouterNavigationContext, DataRouterStateContext, FetchersContext, IsDataRouteContext, LocationContext, NavigationContext, RSCRouterContext, RouteContext, RouteErrorContext, RouteIdContext } from "./context.js";
|
|
15
16
|
import { decodeRedirectErrorDigest, decodeRouteErrorResponseDigest } from "./errors.js";
|
|
16
17
|
import * as React$1 from "react";
|
|
17
18
|
//#region lib/hooks.tsx
|
|
@@ -268,8 +269,7 @@ const navigateEffectWarning = "You should call navigate() in a React.useEffect()
|
|
|
268
269
|
* @returns A navigate function for programmatic navigation
|
|
269
270
|
*/
|
|
270
271
|
function useNavigate() {
|
|
271
|
-
|
|
272
|
-
return isDataRoute ? useNavigateStable() : useNavigateUnstable();
|
|
272
|
+
return React$1.useContext(IsDataRouteContext) ? useNavigateStable() : useNavigateUnstable();
|
|
273
273
|
}
|
|
274
274
|
function useNavigateUnstable() {
|
|
275
275
|
invariant(useInRouterContext(), `useNavigate() may be used only in the context of a <Router> component.`);
|
|
@@ -291,6 +291,7 @@ function useNavigateUnstable() {
|
|
|
291
291
|
}
|
|
292
292
|
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
|
|
293
293
|
if (dataRouterContext == null && basename !== "/") path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
|
|
294
|
+
validateNavigationTarget(typeof to === "string" ? to : createPath(to), navigator.createHref(path), getNavigatorCurrentUrl(navigator), "reject");
|
|
294
295
|
(!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
|
|
295
296
|
}, [
|
|
296
297
|
basename,
|
|
@@ -597,7 +598,10 @@ function useRoutesImpl(routes, locationArg, dataRouterOpts) {
|
|
|
597
598
|
let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
|
|
598
599
|
remainingPathname = "/" + pathname.replace(/^\//, "").split("/").slice(parentSegments.length).join("/");
|
|
599
600
|
}
|
|
600
|
-
let matches
|
|
601
|
+
let matches;
|
|
602
|
+
if (dataRouterOpts) if (dataRouterOpts.state.matches.length) matches = dataRouterOpts.state.matches.map((m) => Object.assign(m, { route: dataRouterOpts.manifest[m.route.id] || m.route }));
|
|
603
|
+
else matches = dataRouterOpts.router.match(dataRouterOpts.state.location);
|
|
604
|
+
else matches = matchRoutes(routes, { pathname: remainingPathname });
|
|
601
605
|
let renderedMatches = _renderMatches(matches && matches.map((match) => Object.assign({}, match, {
|
|
602
606
|
params: Object.assign({}, parentParams, match.params),
|
|
603
607
|
pathname: joinPaths([parentPathnameBase, navigator.encodeLocation ? navigator.encodeLocation(match.pathname.replace(/%/g, "%25").replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathname]),
|
|
@@ -662,17 +666,17 @@ var RenderErrorBoundary = class extends React$1.Component {
|
|
|
662
666
|
const decoded = decodeRouteErrorResponseDigest(error.digest);
|
|
663
667
|
if (decoded) error = decoded;
|
|
664
668
|
}
|
|
665
|
-
let result = error !== void 0 ? /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React$1.createElement(RouteErrorContext.Provider, {
|
|
669
|
+
let result = error !== void 0 ? /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React$1.createElement(IsDataRouteContext.Provider, { value: this.props.routeContext.isDataRoute }, /* @__PURE__ */ React$1.createElement(RouteIdContext.Provider, { value: this.props.routeContext.matches[this.props.routeContext.matches.length - 1]?.route.id }, /* @__PURE__ */ React$1.createElement(RouteErrorContext.Provider, {
|
|
666
670
|
value: error,
|
|
667
671
|
children: this.props.component
|
|
668
|
-
})) : this.props.children;
|
|
672
|
+
})))) : this.props.children;
|
|
669
673
|
if (this.context) return /* @__PURE__ */ React$1.createElement(RSCErrorHandler, { error }, result);
|
|
670
674
|
return result;
|
|
671
675
|
}
|
|
672
676
|
};
|
|
673
677
|
const errorRedirectHandledMap = /* @__PURE__ */ new WeakMap();
|
|
674
678
|
function RSCErrorHandler({ children, error }) {
|
|
675
|
-
let { basename } = React$1.useContext(NavigationContext);
|
|
679
|
+
let { basename, navigator } = React$1.useContext(NavigationContext);
|
|
676
680
|
if (typeof error === "object" && error && "digest" in error && typeof error.digest === "string") {
|
|
677
681
|
let redirect = decodeRedirectErrorDigest(error.digest);
|
|
678
682
|
if (redirect) {
|
|
@@ -680,6 +684,7 @@ function RSCErrorHandler({ children, error }) {
|
|
|
680
684
|
if (existingRedirect) throw existingRedirect;
|
|
681
685
|
let parsed = parseToInfo(redirect.location, basename);
|
|
682
686
|
let target = parsed.absoluteURL || parsed.to;
|
|
687
|
+
validateNavigationTarget(redirect.location, target, getNavigatorCurrentUrl(navigator), "allow-explicit");
|
|
683
688
|
if (hasInvalidProtocol(target)) throw new Error("Invalid redirect location");
|
|
684
689
|
if (isBrowser && !errorRedirectHandledMap.get(error)) if (parsed.isExternal || redirect.reloadDocument) window.location.href = target;
|
|
685
690
|
else {
|
|
@@ -698,7 +703,7 @@ function RSCErrorHandler({ children, error }) {
|
|
|
698
703
|
function RenderedRoute({ routeContext, match, children }) {
|
|
699
704
|
let dataRouterContext = React$1.useContext(DataRouterContext);
|
|
700
705
|
if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
|
|
701
|
-
return /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: routeContext }, children);
|
|
706
|
+
return /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: routeContext }, /* @__PURE__ */ React$1.createElement(IsDataRouteContext.Provider, { value: routeContext.isDataRoute }, /* @__PURE__ */ React$1.createElement(RouteIdContext.Provider, { value: match.route.id }, children)));
|
|
702
707
|
}
|
|
703
708
|
function _renderMatches(matches, parentMatches = [], dataRouterOpts) {
|
|
704
709
|
let dataRouterState = dataRouterOpts?.state;
|
|
@@ -808,25 +813,25 @@ function useDataRouterState(hookName) {
|
|
|
808
813
|
invariant(state, getDataRouterConsoleError(hookName));
|
|
809
814
|
return state;
|
|
810
815
|
}
|
|
811
|
-
function
|
|
812
|
-
let
|
|
813
|
-
invariant(
|
|
814
|
-
return
|
|
816
|
+
function useDataRouterFetchers(hookName) {
|
|
817
|
+
let fetchers = React$1.useContext(FetchersContext);
|
|
818
|
+
invariant(fetchers, getDataRouterConsoleError(hookName));
|
|
819
|
+
return fetchers;
|
|
815
820
|
}
|
|
816
|
-
function
|
|
817
|
-
let
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
return thisRoute.route.id;
|
|
821
|
+
function useDataRouterData(hookName) {
|
|
822
|
+
let data = React$1.useContext(DataRouterDataContext);
|
|
823
|
+
invariant(data, getDataRouterConsoleError(hookName));
|
|
824
|
+
return data;
|
|
821
825
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
826
|
+
function useDataRouterNavigation(hookName) {
|
|
827
|
+
let navigation = React$1.useContext(DataRouterNavigationContext);
|
|
828
|
+
invariant(navigation, getDataRouterConsoleError(hookName));
|
|
829
|
+
return navigation;
|
|
830
|
+
}
|
|
831
|
+
function useCurrentRouteId(hookName) {
|
|
832
|
+
let routeId = React$1.useContext(RouteIdContext);
|
|
833
|
+
invariant(routeId, `${hookName} can only be used on routes that contain a unique "id"`);
|
|
834
|
+
return routeId;
|
|
830
835
|
}
|
|
831
836
|
/**
|
|
832
837
|
* Returns the current {@link Navigation}, defaulting to an "idle" navigation
|
|
@@ -851,11 +856,11 @@ function useRouteId() {
|
|
|
851
856
|
* @returns The current {@link Navigation} object
|
|
852
857
|
*/
|
|
853
858
|
function useNavigation() {
|
|
854
|
-
let
|
|
859
|
+
let { navigation } = useDataRouterNavigation("useNavigation");
|
|
855
860
|
return React$1.useMemo(() => {
|
|
856
|
-
let { matches, historyAction, ...rest } =
|
|
861
|
+
let { matches, historyAction, ...rest } = navigation;
|
|
857
862
|
return rest;
|
|
858
|
-
}, [
|
|
863
|
+
}, [navigation]);
|
|
859
864
|
}
|
|
860
865
|
/**
|
|
861
866
|
* Revalidate the data on the page for reasons outside of normal data mutations
|
|
@@ -894,14 +899,14 @@ function useNavigation() {
|
|
|
894
899
|
*/
|
|
895
900
|
function useRevalidator() {
|
|
896
901
|
let dataRouterContext = useDataRouterContext("useRevalidator");
|
|
897
|
-
let
|
|
902
|
+
let { revalidation } = useDataRouterNavigation("useRevalidator");
|
|
898
903
|
let revalidate = React$1.useCallback(async () => {
|
|
899
904
|
await dataRouterContext.router.revalidate();
|
|
900
905
|
}, [dataRouterContext.router]);
|
|
901
906
|
return React$1.useMemo(() => ({
|
|
902
907
|
revalidate,
|
|
903
|
-
state:
|
|
904
|
-
}), [revalidate,
|
|
908
|
+
state: revalidation
|
|
909
|
+
}), [revalidate, revalidation]);
|
|
905
910
|
}
|
|
906
911
|
/**
|
|
907
912
|
* Returns the active route matches, useful for accessing `loaderData` for
|
|
@@ -938,7 +943,8 @@ function useRevalidator() {
|
|
|
938
943
|
* @returns An array of {@link UIMatch | UI matches} for the current route hierarchy
|
|
939
944
|
*/
|
|
940
945
|
function useMatches() {
|
|
941
|
-
let { matches
|
|
946
|
+
let { matches } = useDataRouterState("useMatches");
|
|
947
|
+
let { loaderData } = useDataRouterData("useMatches");
|
|
942
948
|
return React$1.useMemo(() => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
|
|
943
949
|
}
|
|
944
950
|
/**
|
|
@@ -965,9 +971,9 @@ function useMatches() {
|
|
|
965
971
|
* @returns The data returned from the route's [`loader`](../../start/framework/route-module#loader) or [`clientLoader`](../../start/framework/route-module#clientloader) function
|
|
966
972
|
*/
|
|
967
973
|
function useLoaderData() {
|
|
968
|
-
let
|
|
974
|
+
let data = useDataRouterData("useLoaderData");
|
|
969
975
|
let routeId = useCurrentRouteId("useLoaderData");
|
|
970
|
-
return
|
|
976
|
+
return data.loaderData[routeId];
|
|
971
977
|
}
|
|
972
978
|
/**
|
|
973
979
|
* Returns the [`loader`](../../start/framework/route-module#loader) data for a
|
|
@@ -1002,7 +1008,7 @@ function useLoaderData() {
|
|
|
1002
1008
|
* function, or `undefined` if not found
|
|
1003
1009
|
*/
|
|
1004
1010
|
function useRouteLoaderData(routeId) {
|
|
1005
|
-
return
|
|
1011
|
+
return useDataRouterData("useRouteLoaderData").loaderData[routeId];
|
|
1006
1012
|
}
|
|
1007
1013
|
/**
|
|
1008
1014
|
* Returns the [`action`](../../start/framework/route-module#action) data from
|
|
@@ -1037,9 +1043,9 @@ function useRouteLoaderData(routeId) {
|
|
|
1037
1043
|
* has been called
|
|
1038
1044
|
*/
|
|
1039
1045
|
function useActionData() {
|
|
1040
|
-
let
|
|
1041
|
-
let routeId = useCurrentRouteId("
|
|
1042
|
-
return
|
|
1046
|
+
let data = useDataRouterData("useActionData");
|
|
1047
|
+
let routeId = useCurrentRouteId("useActionData");
|
|
1048
|
+
return data.actionData ? data.actionData[routeId] : void 0;
|
|
1043
1049
|
}
|
|
1044
1050
|
/**
|
|
1045
1051
|
* Accesses the error thrown during an
|
|
@@ -1063,10 +1069,10 @@ function useActionData() {
|
|
|
1063
1069
|
*/
|
|
1064
1070
|
function useRouteError() {
|
|
1065
1071
|
let error = React$1.useContext(RouteErrorContext);
|
|
1066
|
-
let
|
|
1072
|
+
let data = useDataRouterData("useRouteError");
|
|
1067
1073
|
let routeId = useCurrentRouteId("useRouteError");
|
|
1068
1074
|
if (error !== void 0) return error;
|
|
1069
|
-
return
|
|
1075
|
+
return data.errors?.[routeId];
|
|
1070
1076
|
}
|
|
1071
1077
|
/**
|
|
1072
1078
|
* Returns the resolved promise value from the closest {@link Await | `<Await>`}.
|
|
@@ -1291,12 +1297,13 @@ function useRoute(...args) {
|
|
|
1291
1297
|
const currentRouteId = useCurrentRouteId("useRoute");
|
|
1292
1298
|
const id = args[0] ?? currentRouteId;
|
|
1293
1299
|
const state = useDataRouterState("useRoute");
|
|
1300
|
+
const data = useDataRouterData("useRoute");
|
|
1294
1301
|
const route = state.matches.find(({ route }) => route.id === id);
|
|
1295
1302
|
if (route === void 0) return void 0;
|
|
1296
1303
|
return {
|
|
1297
1304
|
handle: route.route.handle,
|
|
1298
|
-
loaderData:
|
|
1299
|
-
actionData:
|
|
1305
|
+
loaderData: data.loaderData[id],
|
|
1306
|
+
actionData: data.actionData?.[id]
|
|
1300
1307
|
};
|
|
1301
1308
|
}
|
|
1302
1309
|
function toRouterStateMatch(match) {
|
|
@@ -1350,7 +1357,8 @@ function toRouterStateMatch(match) {
|
|
|
1350
1357
|
* @returns The current router state with `active` and `pending` variants
|
|
1351
1358
|
*/
|
|
1352
1359
|
function useRouterState() {
|
|
1353
|
-
let { location, historyAction: type, matches
|
|
1360
|
+
let { location, historyAction: type, matches } = useDataRouterState("unstable_useRouterState");
|
|
1361
|
+
let { navigation } = useDataRouterNavigation("unstable_useRouterState");
|
|
1354
1362
|
let active = React$1.useMemo(() => ({
|
|
1355
1363
|
type,
|
|
1356
1364
|
location,
|
|
@@ -1397,4 +1405,4 @@ function useRouterState() {
|
|
|
1397
1405
|
}), [active, pending]);
|
|
1398
1406
|
}
|
|
1399
1407
|
//#endregion
|
|
1400
|
-
export { _renderMatches, useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRoute, useRouteError,
|
|
1408
|
+
export { _renderMatches, useActionData, useAsyncError, useAsyncValue, useBlocker, useCurrentRouteId, useDataRouterContext, useDataRouterData, useDataRouterFetchers, useDataRouterState, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRoute, useRouteError, useRouteLoaderData, useRouterState, useRoutes, useRoutesImpl };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.
|
|
2
|
+
* react-router v8.4.0
|
|
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() {
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.4.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { invariant, parsePath, warning } from "./history.js";
|
|
12
|
+
import { decodePath, explodeOptionalSegments, joinPaths, matchPath, normalizePathname, stripBasename } from "./utils.js";
|
|
13
|
+
import { createMultiMatcher } from "@remix-run/route-pattern/match";
|
|
14
|
+
import { descending } from "@remix-run/route-pattern/specificity";
|
|
15
|
+
//#region lib/router/matcher-route-pattern.ts
|
|
16
|
+
var RoutePatternDataRouteMatcher = class {
|
|
17
|
+
#state;
|
|
18
|
+
#basename;
|
|
19
|
+
constructor(basename) {
|
|
20
|
+
this.#basename = basename;
|
|
21
|
+
}
|
|
22
|
+
update(routes) {
|
|
23
|
+
let branches = flattenRoutes(routes);
|
|
24
|
+
let matcher = createMultiMatcher({ ignoreCase: true });
|
|
25
|
+
let partialMatcher = createMultiMatcher({ ignoreCase: true });
|
|
26
|
+
for (let branch of branches) {
|
|
27
|
+
let routePattern = convertReactRouterPathToRoutePattern(branch.path);
|
|
28
|
+
validateRoutePatternSplat(branch.path, routePattern);
|
|
29
|
+
routePattern = addOptionalTrailingSlash(routePattern);
|
|
30
|
+
matcher.add(routePattern, branch);
|
|
31
|
+
if (!branch.routesMeta[branch.routesMeta.length - 1].route.index) partialMatcher.add(routePattern === "/" ? `/*__rr_partial` : `${routePattern}(/*__rr_partial)`, branch);
|
|
32
|
+
}
|
|
33
|
+
this.#state = {
|
|
34
|
+
branches,
|
|
35
|
+
matcher,
|
|
36
|
+
partialMatcher
|
|
37
|
+
};
|
|
38
|
+
return branches;
|
|
39
|
+
}
|
|
40
|
+
match(locationArg, allowPartial = false) {
|
|
41
|
+
let pathname = stripBasename((typeof locationArg === "string" ? parsePath(locationArg) : locationArg).pathname || "/", this.#basename);
|
|
42
|
+
if (pathname == null) return null;
|
|
43
|
+
let decoded = decodePath(pathname);
|
|
44
|
+
let url = new URL("http://reactrouter.local");
|
|
45
|
+
url.pathname = pathname.endsWith("/") ? pathname : `${pathname}/`;
|
|
46
|
+
invariant(this.#state, "Route pattern routes must be initialized before matching.");
|
|
47
|
+
let matches = this.#state.matcher.matchAll(url);
|
|
48
|
+
if (allowPartial) matches.push(...this.#state.partialMatcher.matchAll(url));
|
|
49
|
+
for (let match of prioritizeValidatedMatches(matches)) {
|
|
50
|
+
let routeMatches = convertRoutePatternMatchToRouteMatches(match, decoded, allowPartial);
|
|
51
|
+
if (routeMatches && validateRouteMatchParams(routeMatches)) return routeMatches;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
function validateRoutePatternSplat(routePath, routePattern) {
|
|
57
|
+
invariant(getRoutePatternSplatIndexes(routePattern).length <= 1 && isTerminalRoutePatternSplat(routePattern), `Route path "${routePath}" is not supported with \`future.unstable_routePatternMatching\` because React Router only supports a single splat at the end of a route path.`);
|
|
58
|
+
}
|
|
59
|
+
function getRoutePatternSplatIndexes(routePattern) {
|
|
60
|
+
let splatIndexes = [];
|
|
61
|
+
for (let i = 0; i < routePattern.length; i++) {
|
|
62
|
+
let char = routePattern[i];
|
|
63
|
+
if (char === "\\") {
|
|
64
|
+
i++;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (char === "*") splatIndexes.push(i);
|
|
68
|
+
}
|
|
69
|
+
return splatIndexes;
|
|
70
|
+
}
|
|
71
|
+
function isTerminalRoutePatternSplat(routePattern) {
|
|
72
|
+
for (let i = 0; i < routePattern.length; i++) {
|
|
73
|
+
let char = routePattern[i];
|
|
74
|
+
if (char === "\\") {
|
|
75
|
+
i++;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (char !== "*") continue;
|
|
79
|
+
let suffix = routePattern.slice(i + 1);
|
|
80
|
+
return /^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(suffix) || suffix === "";
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
function addOptionalTrailingSlash(routePattern) {
|
|
85
|
+
return routePattern === "/" ? routePattern : `${routePattern.replace(/\/+$/, "")}(/)`;
|
|
86
|
+
}
|
|
87
|
+
function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
|
|
88
|
+
routes.forEach((route, index) => {
|
|
89
|
+
invariant(route.caseSensitive !== true, "`caseSensitive` routes are not supported with `future.unstable_routePatternMatching`.");
|
|
90
|
+
let meta = {
|
|
91
|
+
relativePath: route.path || "",
|
|
92
|
+
caseSensitive: false,
|
|
93
|
+
childrenIndex: index,
|
|
94
|
+
route
|
|
95
|
+
};
|
|
96
|
+
let absolutePath;
|
|
97
|
+
if (meta.relativePath.startsWith("/")) {
|
|
98
|
+
absolutePath = meta.relativePath;
|
|
99
|
+
let parentPathMatch = explodeOptionalSegments(parentPath).find((path) => meta.relativePath.startsWith(path));
|
|
100
|
+
invariant(parentPathMatch != null, `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`);
|
|
101
|
+
meta.relativePath = meta.relativePath.slice(parentPathMatch.length);
|
|
102
|
+
}
|
|
103
|
+
let routesMeta = parentsMeta.concat(meta);
|
|
104
|
+
let path = absolutePath ?? (meta.relativePath ? joinPaths([parentPath, meta.relativePath]) : parentPath);
|
|
105
|
+
if (route.children && route.children.length > 0) {
|
|
106
|
+
invariant(route.index !== true, `Index routes must not have child routes. Please remove all child routes from route path "${path}".`);
|
|
107
|
+
flattenRoutes(route.children, branches, routesMeta, path);
|
|
108
|
+
if (route.children?.some((child) => child.index)) return;
|
|
109
|
+
}
|
|
110
|
+
if (route.path != null || route.index) branches.push({
|
|
111
|
+
path,
|
|
112
|
+
score: 0,
|
|
113
|
+
routesMeta
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
return branches;
|
|
117
|
+
}
|
|
118
|
+
function convertReactRouterPathToRoutePattern(path) {
|
|
119
|
+
warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`);
|
|
120
|
+
if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) path = path.replace(/\*$/, "/*");
|
|
121
|
+
path = path.replace(/^\/*/, "/");
|
|
122
|
+
if (path === "") return "/";
|
|
123
|
+
let segments = path.split("/");
|
|
124
|
+
let pattern = segments.shift() || "";
|
|
125
|
+
for (let i = 0; i < segments.length;) {
|
|
126
|
+
let optionalRun = [];
|
|
127
|
+
while (i < segments.length && isOptionalRouteSegment(segments[i])) {
|
|
128
|
+
optionalRun.push(convertRouteSegment(segments[i].slice(0, -1)));
|
|
129
|
+
i++;
|
|
130
|
+
}
|
|
131
|
+
if (optionalRun.length > 0) {
|
|
132
|
+
let nested = optionalRun.reduceRight((child, segment) => `/${segment}${child ? `(${child})` : ""}`, "");
|
|
133
|
+
pattern += `(${nested})`;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
pattern += `/${convertRouteSegment(segments[i])}`;
|
|
137
|
+
i++;
|
|
138
|
+
}
|
|
139
|
+
return pattern || "/";
|
|
140
|
+
}
|
|
141
|
+
function isOptionalRouteSegment(segment) {
|
|
142
|
+
return segment.endsWith("?");
|
|
143
|
+
}
|
|
144
|
+
function convertRouteSegment(segment) {
|
|
145
|
+
if (segment === "*") return "*__rr_splat";
|
|
146
|
+
let paramMatch = segment.match(/^:([\w-]+)(\?)?(.*)$/);
|
|
147
|
+
if (paramMatch) {
|
|
148
|
+
let [, paramName, optional, suffix] = paramMatch;
|
|
149
|
+
let converted = `:${paramName}${escapeRoutePatternLiteral(suffix)}`;
|
|
150
|
+
return optional ? `(:${paramName})${escapeRoutePatternLiteral(suffix)}` : converted;
|
|
151
|
+
}
|
|
152
|
+
return escapeRoutePatternLiteral(segment);
|
|
153
|
+
}
|
|
154
|
+
function escapeRoutePatternLiteral(value) {
|
|
155
|
+
return value.replace(/[\\():*]/g, "\\$&");
|
|
156
|
+
}
|
|
157
|
+
function validateRouteMatchParams(matches) {
|
|
158
|
+
return matches.every(({ route, params }) => route.unstable_validateParams == null || Object.keys(route.unstable_validateParams).length === 0 || Object.entries(route.unstable_validateParams).every(([param, re]) => params[param] != null ? new RegExp(re.source, re.flags).test(params[param]) : true));
|
|
159
|
+
}
|
|
160
|
+
function prioritizeValidatedMatches(matches) {
|
|
161
|
+
return matches.sort((a, b) => {
|
|
162
|
+
let specificity = descending(a, b);
|
|
163
|
+
if (specificity !== 0) return specificity;
|
|
164
|
+
return Number(hasParamValidators(b)) - Number(hasParamValidators(a));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function hasParamValidators(match) {
|
|
168
|
+
return match.data.routesMeta.some((meta) => meta.route.unstable_validateParams != null && Object.keys(meta.route.unstable_validateParams).length > 0);
|
|
169
|
+
}
|
|
170
|
+
function convertRoutePatternMatchToRouteMatches(match, pathname, allowPartial) {
|
|
171
|
+
let result = matchRoutePatternBranch(match.data, pathname, allowPartial, 0, "/", {});
|
|
172
|
+
if (result == null) return null;
|
|
173
|
+
for (let routeMatch of result.matches) routeMatch.params = result.params;
|
|
174
|
+
return result.matches;
|
|
175
|
+
}
|
|
176
|
+
function matchRoutePatternBranch(branch, pathname, allowPartial, metaIndex, matchedPathname, matchedParams) {
|
|
177
|
+
let meta = branch.routesMeta[metaIndex];
|
|
178
|
+
let end = metaIndex === branch.routesMeta.length - 1;
|
|
179
|
+
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
|
180
|
+
for (let relativePath of explodeOptionalSegments(meta.relativePath)) {
|
|
181
|
+
let pattern = {
|
|
182
|
+
path: relativePath,
|
|
183
|
+
caseSensitive: false,
|
|
184
|
+
end
|
|
185
|
+
};
|
|
186
|
+
let pathMatch = matchPath(pattern, remainingPathname);
|
|
187
|
+
if (!pathMatch && end && allowPartial && !meta.route.index) pathMatch = matchPath({
|
|
188
|
+
...pattern,
|
|
189
|
+
end: false
|
|
190
|
+
}, remainingPathname);
|
|
191
|
+
if (!pathMatch) continue;
|
|
192
|
+
let params = {
|
|
193
|
+
...matchedParams,
|
|
194
|
+
...pathMatch.params
|
|
195
|
+
};
|
|
196
|
+
let routeMatch = {
|
|
197
|
+
params,
|
|
198
|
+
pathname: joinPaths([matchedPathname, pathMatch.pathname]),
|
|
199
|
+
pathnameBase: normalizePathname(joinPaths([matchedPathname, pathMatch.pathnameBase])),
|
|
200
|
+
route: meta.route
|
|
201
|
+
};
|
|
202
|
+
let nextMatchedPathname = pathMatch.pathnameBase === "/" ? matchedPathname : joinPaths([matchedPathname, pathMatch.pathnameBase]);
|
|
203
|
+
if (end) return {
|
|
204
|
+
matches: [routeMatch],
|
|
205
|
+
params
|
|
206
|
+
};
|
|
207
|
+
let childResult = matchRoutePatternBranch(branch, pathname, allowPartial, metaIndex + 1, nextMatchedPathname, params);
|
|
208
|
+
if (childResult) return {
|
|
209
|
+
matches: [routeMatch, ...childResult.matches],
|
|
210
|
+
params: childResult.params
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
export { RoutePatternDataRouteMatcher };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
//#region lib/router/matcher-route-pattern.preload.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Initialize the route-pattern matcher before creating a Data Router or static
|
|
5
|
+
* handler with `future.unstable_routePatternMatching` enabled. Import from
|
|
6
|
+
* `react-router/route-pattern` and call this once during application startup.
|
|
7
|
+
* Server and browser applications must each preload their own matcher.
|
|
8
|
+
*
|
|
9
|
+
* The matcher is statically imported by this module. Tree-shaking bundlers can
|
|
10
|
+
* remove it from applications that do not use this function. Initialization is
|
|
11
|
+
* synchronous, and repeated calls are safe.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
* @category Data Routers
|
|
15
|
+
* @mode data
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*/
|
|
18
|
+
declare function unstable_preloadRoutePattern(): void;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { unstable_preloadRoutePattern };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.4.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { RoutePatternDataRouteMatcher } from "./matcher-route-pattern.js";
|
|
12
|
+
//#region lib/router/matcher-route-pattern.preload.ts
|
|
13
|
+
let RoutePatternMatcher;
|
|
14
|
+
function getRoutePatternMatcher() {
|
|
15
|
+
return RoutePatternMatcher;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Initialize the route-pattern matcher before creating a Data Router or static
|
|
19
|
+
* handler with `future.unstable_routePatternMatching` enabled. Import from
|
|
20
|
+
* `react-router/route-pattern` and call this once during application startup.
|
|
21
|
+
* Server and browser applications must each preload their own matcher.
|
|
22
|
+
*
|
|
23
|
+
* The matcher is statically imported by this module. Tree-shaking bundlers can
|
|
24
|
+
* remove it from applications that do not use this function. Initialization is
|
|
25
|
+
* synchronous, and repeated calls are safe.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
* @category Data Routers
|
|
29
|
+
* @mode data
|
|
30
|
+
* @returns {void}
|
|
31
|
+
*/
|
|
32
|
+
function unstable_preloadRoutePattern() {
|
|
33
|
+
RoutePatternMatcher = RoutePatternDataRouteMatcher;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { getRoutePatternMatcher, unstable_preloadRoutePattern };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.4.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { flattenAndRankRoutes, matchRoutesImpl } from "./utils.js";
|
|
12
|
+
//#region lib/router/matcher.ts
|
|
13
|
+
var V6RegExMatcher = class {
|
|
14
|
+
#routes = [];
|
|
15
|
+
#branches = [];
|
|
16
|
+
#basename;
|
|
17
|
+
constructor(basename) {
|
|
18
|
+
this.#basename = basename;
|
|
19
|
+
}
|
|
20
|
+
update(routes) {
|
|
21
|
+
this.#routes = routes;
|
|
22
|
+
this.#branches = flattenAndRankRoutes(routes);
|
|
23
|
+
}
|
|
24
|
+
match(locationArg, allowPartial = false) {
|
|
25
|
+
return matchRoutesImpl(this.#routes, locationArg, this.#basename, allowPartial, this.#branches);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { V6RegExMatcher };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.4.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
//#region lib/router/navigation.ts
|
|
12
|
+
const DEFAULT_NAVIGATION_URL = new URL("http://localhost");
|
|
13
|
+
function getNavigatorCurrentUrl(navigator) {
|
|
14
|
+
if (navigator.createURL) return navigator.createURL("/");
|
|
15
|
+
try {
|
|
16
|
+
return new URL(navigator.createHref("/"), DEFAULT_NAVIGATION_URL);
|
|
17
|
+
} catch {
|
|
18
|
+
return DEFAULT_NAVIGATION_URL;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function isSameOrigin(a, b) {
|
|
22
|
+
return a.origin === b.origin && (a.origin !== "null" || a.protocol === b.protocol && a.host === b.host);
|
|
23
|
+
}
|
|
24
|
+
function isExplicitUrl(destination, target) {
|
|
25
|
+
if (destination.startsWith("//")) return true;
|
|
26
|
+
let protocol = target.protocol.toLowerCase();
|
|
27
|
+
if (!destination.toLowerCase().startsWith(protocol)) return false;
|
|
28
|
+
return target.host === "" || destination.slice(protocol.length).startsWith("//");
|
|
29
|
+
}
|
|
30
|
+
function validateNavigationTarget(original, resolved, currentUrl, externalPolicy) {
|
|
31
|
+
let originalUrl = null;
|
|
32
|
+
try {
|
|
33
|
+
originalUrl = original == null ? null : new URL(original, currentUrl);
|
|
34
|
+
} catch {}
|
|
35
|
+
let resolvedUrl = new URL(resolved, currentUrl);
|
|
36
|
+
let originalIsExternal = originalUrl != null && !isSameOrigin(originalUrl, currentUrl);
|
|
37
|
+
let resolvedIsExternal = !isSameOrigin(resolvedUrl, currentUrl);
|
|
38
|
+
if (externalPolicy === "reject") {
|
|
39
|
+
if (originalIsExternal || resolvedIsExternal) throw new Error("External navigation is not allowed");
|
|
40
|
+
} else if (resolvedIsExternal) {
|
|
41
|
+
if (originalUrl == null || !isExplicitUrl(original, originalUrl) || !isSameOrigin(originalUrl, resolvedUrl)) throw new Error("External navigation is not allowed");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { getNavigatorCurrentUrl, validateNavigationTarget };
|