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.
Files changed (176) hide show
  1. package/CHANGELOG.md +46 -2
  2. package/dist/development/dom-export.js +1 -1
  3. package/dist/development/index-react-server-client.js +1 -1
  4. package/dist/development/index-react-server.d.ts +50 -48
  5. package/dist/development/index-react-server.js +96 -43
  6. package/dist/development/index.d.ts +2 -2
  7. package/dist/development/index.js +3 -3
  8. package/dist/development/lib/actions.js +10 -5
  9. package/dist/development/lib/components.js +50 -10
  10. package/dist/development/lib/context.d.ts +14 -5
  11. package/dist/development/lib/context.js +11 -3
  12. package/dist/development/lib/dom/dom.js +2 -2
  13. package/dist/development/lib/dom/lib.js +33 -36
  14. package/dist/development/lib/dom/server.d.ts +6 -1
  15. package/dist/development/lib/dom/server.js +40 -14
  16. package/dist/development/lib/dom/ssr/components.js +16 -24
  17. package/dist/development/lib/dom/ssr/data.js +1 -1
  18. package/dist/development/lib/dom/ssr/entry.d.ts +4 -0
  19. package/dist/development/lib/dom/ssr/errorBoundaries.js +1 -1
  20. package/dist/development/lib/dom/ssr/fallback.js +1 -1
  21. package/dist/development/lib/dom/ssr/fog-of-war.js +34 -12
  22. package/dist/development/lib/dom/ssr/hydration.d.ts +3 -1
  23. package/dist/development/lib/dom/ssr/hydration.js +6 -4
  24. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  25. package/dist/development/lib/dom/ssr/links.js +1 -1
  26. package/dist/development/lib/dom/ssr/markup.js +5 -2
  27. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  28. package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
  29. package/dist/development/lib/dom/ssr/routes.js +1 -1
  30. package/dist/development/lib/dom/ssr/server.js +2 -2
  31. package/dist/development/lib/dom/ssr/single-fetch.js +13 -22
  32. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  33. package/dist/development/lib/dom-export/hydrated-router.js +2 -1
  34. package/dist/development/lib/errors.js +1 -1
  35. package/dist/development/lib/hooks.js +54 -46
  36. package/dist/development/lib/href.js +1 -1
  37. package/dist/development/lib/router/history.js +2 -2
  38. package/dist/development/lib/router/instrumentation.js +1 -1
  39. package/dist/development/lib/router/matcher-route-pattern.d.ts +2 -0
  40. package/dist/development/lib/router/matcher-route-pattern.js +216 -0
  41. package/dist/development/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  42. package/dist/development/lib/router/matcher-route-pattern.preload.js +36 -0
  43. package/dist/development/lib/router/matcher.d.ts +2 -0
  44. package/dist/development/lib/router/matcher.js +29 -0
  45. package/dist/development/lib/router/navigation.js +45 -0
  46. package/dist/development/lib/router/router.d.ts +21 -7
  47. package/dist/development/lib/router/router.js +111 -82
  48. package/dist/development/lib/router/url.js +1 -1
  49. package/dist/development/lib/router/utils.d.ts +6 -1
  50. package/dist/development/lib/router/utils.js +15 -9
  51. package/dist/development/lib/rsc/browser.js +5 -1
  52. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  53. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  54. package/dist/development/lib/rsc/html-stream/server.js +3 -5
  55. package/dist/development/lib/rsc/route-modules.js +1 -1
  56. package/dist/development/lib/rsc/server.rsc.d.ts +7 -0
  57. package/dist/development/lib/rsc/server.ssr.js +26 -22
  58. package/dist/development/lib/server-runtime/cookies.js +2 -2
  59. package/dist/development/lib/server-runtime/crypto.js +2 -2
  60. package/dist/development/lib/server-runtime/data.js +1 -1
  61. package/dist/development/lib/server-runtime/dev.js +2 -2
  62. package/dist/development/lib/server-runtime/entry.js +1 -1
  63. package/dist/development/lib/server-runtime/errors.js +1 -1
  64. package/dist/development/lib/server-runtime/headers.js +1 -1
  65. package/dist/development/lib/server-runtime/invariant.js +1 -1
  66. package/dist/development/lib/server-runtime/mode.js +1 -1
  67. package/dist/development/lib/server-runtime/routeMatching.js +3 -4
  68. package/dist/development/lib/server-runtime/routes.js +1 -1
  69. package/dist/development/lib/server-runtime/server.js +8 -7
  70. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  71. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  72. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  73. package/dist/development/lib/server-runtime/sessions.js +1 -1
  74. package/dist/development/lib/server-runtime/single-fetch.js +2 -2
  75. package/dist/development/lib/server-runtime/urls.js +1 -1
  76. package/dist/development/lib/server-runtime/warnings.js +1 -1
  77. package/dist/development/lib/types/internal.js +1 -1
  78. package/dist/development/route-pattern.d.ts +3 -0
  79. package/dist/development/route-pattern.js +12 -0
  80. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  81. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +4 -4
  82. package/dist/development/vendor/turbo-stream-v2/unflatten.js +1 -1
  83. package/dist/development/vendor/turbo-stream-v2/utils.js +1 -1
  84. package/dist/production/dom-export.js +1 -1
  85. package/dist/production/index-react-server-client.js +1 -1
  86. package/dist/production/index-react-server.d.ts +50 -48
  87. package/dist/production/index-react-server.js +96 -43
  88. package/dist/production/index.d.ts +2 -2
  89. package/dist/production/index.js +3 -3
  90. package/dist/production/lib/actions.js +10 -5
  91. package/dist/production/lib/components.js +50 -10
  92. package/dist/production/lib/context.d.ts +14 -5
  93. package/dist/production/lib/context.js +11 -3
  94. package/dist/production/lib/dom/dom.js +2 -2
  95. package/dist/production/lib/dom/lib.js +33 -36
  96. package/dist/production/lib/dom/server.d.ts +6 -1
  97. package/dist/production/lib/dom/server.js +40 -14
  98. package/dist/production/lib/dom/ssr/components.js +16 -24
  99. package/dist/production/lib/dom/ssr/data.js +1 -1
  100. package/dist/production/lib/dom/ssr/entry.d.ts +4 -0
  101. package/dist/production/lib/dom/ssr/errorBoundaries.js +1 -1
  102. package/dist/production/lib/dom/ssr/fallback.js +1 -1
  103. package/dist/production/lib/dom/ssr/fog-of-war.js +34 -12
  104. package/dist/production/lib/dom/ssr/hydration.d.ts +3 -1
  105. package/dist/production/lib/dom/ssr/hydration.js +6 -4
  106. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  107. package/dist/production/lib/dom/ssr/links.js +1 -1
  108. package/dist/production/lib/dom/ssr/markup.js +5 -2
  109. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  110. package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
  111. package/dist/production/lib/dom/ssr/routes.js +1 -1
  112. package/dist/production/lib/dom/ssr/server.js +2 -2
  113. package/dist/production/lib/dom/ssr/single-fetch.js +13 -22
  114. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  115. package/dist/production/lib/dom-export/hydrated-router.js +2 -1
  116. package/dist/production/lib/errors.js +1 -1
  117. package/dist/production/lib/hooks.js +54 -46
  118. package/dist/production/lib/href.js +1 -1
  119. package/dist/production/lib/router/history.js +2 -2
  120. package/dist/production/lib/router/instrumentation.js +1 -1
  121. package/dist/production/lib/router/matcher-route-pattern.d.ts +2 -0
  122. package/dist/production/lib/router/matcher-route-pattern.js +216 -0
  123. package/dist/production/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  124. package/dist/production/lib/router/matcher-route-pattern.preload.js +36 -0
  125. package/dist/production/lib/router/matcher.d.ts +2 -0
  126. package/dist/production/lib/router/matcher.js +29 -0
  127. package/dist/production/lib/router/navigation.js +45 -0
  128. package/dist/production/lib/router/router.d.ts +21 -7
  129. package/dist/production/lib/router/router.js +111 -82
  130. package/dist/production/lib/router/url.js +1 -1
  131. package/dist/production/lib/router/utils.d.ts +6 -1
  132. package/dist/production/lib/router/utils.js +15 -9
  133. package/dist/production/lib/rsc/browser.js +5 -1
  134. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  135. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  136. package/dist/production/lib/rsc/html-stream/server.js +3 -5
  137. package/dist/production/lib/rsc/route-modules.js +1 -1
  138. package/dist/production/lib/rsc/server.rsc.d.ts +7 -0
  139. package/dist/production/lib/rsc/server.ssr.js +26 -22
  140. package/dist/production/lib/server-runtime/cookies.js +2 -2
  141. package/dist/production/lib/server-runtime/crypto.js +2 -2
  142. package/dist/production/lib/server-runtime/data.js +1 -1
  143. package/dist/production/lib/server-runtime/dev.js +2 -2
  144. package/dist/production/lib/server-runtime/entry.js +1 -1
  145. package/dist/production/lib/server-runtime/errors.js +1 -1
  146. package/dist/production/lib/server-runtime/headers.js +1 -1
  147. package/dist/production/lib/server-runtime/invariant.js +1 -1
  148. package/dist/production/lib/server-runtime/mode.js +1 -1
  149. package/dist/production/lib/server-runtime/routeMatching.js +3 -4
  150. package/dist/production/lib/server-runtime/routes.js +1 -1
  151. package/dist/production/lib/server-runtime/server.js +8 -7
  152. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  153. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  154. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  155. package/dist/production/lib/server-runtime/sessions.js +1 -1
  156. package/dist/production/lib/server-runtime/single-fetch.js +2 -2
  157. package/dist/production/lib/server-runtime/urls.js +1 -1
  158. package/dist/production/lib/server-runtime/warnings.js +1 -1
  159. package/dist/production/lib/types/internal.js +1 -1
  160. package/dist/production/route-pattern.d.ts +3 -0
  161. package/dist/production/route-pattern.js +12 -0
  162. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  163. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +4 -4
  164. package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
  165. package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
  166. package/docs/how-to/fetchers.md +6 -1
  167. package/docs/how-to/middleware.md +3 -1
  168. package/docs/how-to/optimize-revalidation.md +178 -5
  169. package/docs/how-to/react-server-components.md +26 -3
  170. package/docs/how-to/resource-routes.md +3 -0
  171. package/docs/start/data/actions.md +2 -1
  172. package/docs/start/data/route-object.md +21 -6
  173. package/docs/start/framework/actions.md +4 -2
  174. package/docs/start/framework/route-module.md +32 -5
  175. package/docs/upgrading/future.md +68 -0
  176. package/package.json +11 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.0
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
- let { isDataRoute } = React$1.useContext(RouteContext);
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 = dataRouterOpts && dataRouterOpts.state.matches.length ? dataRouterOpts.state.matches.map((m) => Object.assign(m, { route: dataRouterOpts.manifest[m.route.id] || m.route })) : matchRoutes(routes, { pathname: remainingPathname });
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 useRouteContext(hookName) {
812
- let route = React$1.useContext(RouteContext);
813
- invariant(route, getDataRouterConsoleError(hookName));
814
- return route;
816
+ function useDataRouterFetchers(hookName) {
817
+ let fetchers = React$1.useContext(FetchersContext);
818
+ invariant(fetchers, getDataRouterConsoleError(hookName));
819
+ return fetchers;
815
820
  }
816
- function useCurrentRouteId(hookName) {
817
- let route = useRouteContext(hookName);
818
- let thisRoute = route.matches[route.matches.length - 1];
819
- invariant(thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"`);
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
- * Returns the ID for the nearest contextual route
824
- *
825
- * @category Hooks
826
- * @returns The ID of the nearest contextual route
827
- */
828
- function useRouteId() {
829
- return useCurrentRouteId("useRouteId");
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 state = useDataRouterState("useNavigation");
859
+ let { navigation } = useDataRouterNavigation("useNavigation");
855
860
  return React$1.useMemo(() => {
856
- let { matches, historyAction, ...rest } = state.navigation;
861
+ let { matches, historyAction, ...rest } = navigation;
857
862
  return rest;
858
- }, [state.navigation]);
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 state = useDataRouterState("useRevalidator");
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: state.revalidation
904
- }), [revalidate, state.revalidation]);
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, loaderData } = useDataRouterState("useMatches");
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 state = useDataRouterState("useLoaderData");
974
+ let data = useDataRouterData("useLoaderData");
969
975
  let routeId = useCurrentRouteId("useLoaderData");
970
- return state.loaderData[routeId];
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 useDataRouterState("useRouteLoaderData").loaderData[routeId];
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 state = useDataRouterState("useActionData");
1041
- let routeId = useCurrentRouteId("useLoaderData");
1042
- return state.actionData ? state.actionData[routeId] : void 0;
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 state = useDataRouterState("useRouteError");
1072
+ let data = useDataRouterData("useRouteError");
1067
1073
  let routeId = useCurrentRouteId("useRouteError");
1068
1074
  if (error !== void 0) return error;
1069
- return state.errors?.[routeId];
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: state.loaderData[id],
1299
- actionData: state.actionData?.[id]
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, navigation } = useDataRouterState("unstable_useRouterState");
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, useRouteId, useRouteLoaderData, useRouterState, useRoutes, useRoutesImpl };
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.3.0
2
+ * react-router v8.4.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.0
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 (e) {}
196
+ } catch {}
197
197
  }
198
198
  }
199
199
  function createKey() {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.0
2
+ * react-router v8.4.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -0,0 +1,2 @@
1
+
2
+ export { };
@@ -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,2 @@
1
+
2
+ export { };
@@ -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 };