react-router 8.3.1 → 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 +33 -0
  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 +42 -48
  5. package/dist/development/index-react-server.js +75 -31
  6. package/dist/development/index.d.ts +2 -2
  7. package/dist/development/index.js +3 -3
  8. package/dist/development/lib/actions.js +1 -1
  9. package/dist/development/lib/components.js +45 -8
  10. package/dist/development/lib/context.d.ts +13 -5
  11. package/dist/development/lib/context.js +11 -3
  12. package/dist/development/lib/dom/dom.js +1 -1
  13. package/dist/development/lib/dom/lib.js +14 -32
  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 +15 -23
  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 +33 -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 +10 -19
  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 +49 -44
  36. package/dist/development/lib/href.js +1 -1
  37. package/dist/development/lib/router/history.js +1 -1
  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 +1 -1
  46. package/dist/development/lib/router/router.d.ts +13 -7
  47. package/dist/development/lib/router/router.js +81 -66
  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 +6 -4
  51. package/dist/development/lib/rsc/browser.js +2 -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 +2 -4
  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 +25 -21
  58. package/dist/development/lib/server-runtime/cookies.js +1 -1
  59. package/dist/development/lib/server-runtime/crypto.js +1 -1
  60. package/dist/development/lib/server-runtime/data.js +1 -1
  61. package/dist/development/lib/server-runtime/dev.js +1 -1
  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 +7 -6
  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 +1 -1
  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 +1 -1
  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 +42 -48
  87. package/dist/production/index-react-server.js +75 -31
  88. package/dist/production/index.d.ts +2 -2
  89. package/dist/production/index.js +3 -3
  90. package/dist/production/lib/actions.js +1 -1
  91. package/dist/production/lib/components.js +45 -8
  92. package/dist/production/lib/context.d.ts +13 -5
  93. package/dist/production/lib/context.js +11 -3
  94. package/dist/production/lib/dom/dom.js +1 -1
  95. package/dist/production/lib/dom/lib.js +14 -32
  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 +15 -23
  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 +33 -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 +10 -19
  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 +49 -44
  118. package/dist/production/lib/href.js +1 -1
  119. package/dist/production/lib/router/history.js +1 -1
  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 +1 -1
  128. package/dist/production/lib/router/router.d.ts +13 -7
  129. package/dist/production/lib/router/router.js +81 -66
  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 +6 -4
  133. package/dist/production/lib/rsc/browser.js +2 -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 +2 -4
  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 +25 -21
  140. package/dist/production/lib/server-runtime/cookies.js +1 -1
  141. package/dist/production/lib/server-runtime/crypto.js +1 -1
  142. package/dist/production/lib/server-runtime/data.js +1 -1
  143. package/dist/production/lib/server-runtime/dev.js +1 -1
  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 +7 -6
  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 +1 -1
  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 +1 -1
  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.1
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.1
2
+ * react-router v8.4.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -12,7 +12,7 @@ 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
13
  import { getNavigatorCurrentUrl, validateNavigationTarget } from "./router/navigation.js";
14
14
  import { IDLE_BLOCKER, hasInvalidProtocol } from "./router/router.js";
15
- 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";
16
16
  import { decodeRedirectErrorDigest, decodeRouteErrorResponseDigest } from "./errors.js";
17
17
  import * as React$1 from "react";
18
18
  //#region lib/hooks.tsx
@@ -269,8 +269,7 @@ const navigateEffectWarning = "You should call navigate() in a React.useEffect()
269
269
  * @returns A navigate function for programmatic navigation
270
270
  */
271
271
  function useNavigate() {
272
- let { isDataRoute } = React$1.useContext(RouteContext);
273
- return isDataRoute ? useNavigateStable() : useNavigateUnstable();
272
+ return React$1.useContext(IsDataRouteContext) ? useNavigateStable() : useNavigateUnstable();
274
273
  }
275
274
  function useNavigateUnstable() {
276
275
  invariant(useInRouterContext(), `useNavigate() may be used only in the context of a <Router> component.`);
@@ -599,7 +598,10 @@ function useRoutesImpl(routes, locationArg, dataRouterOpts) {
599
598
  let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
600
599
  remainingPathname = "/" + pathname.replace(/^\//, "").split("/").slice(parentSegments.length).join("/");
601
600
  }
602
- 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 });
603
605
  let renderedMatches = _renderMatches(matches && matches.map((match) => Object.assign({}, match, {
604
606
  params: Object.assign({}, parentParams, match.params),
605
607
  pathname: joinPaths([parentPathnameBase, navigator.encodeLocation ? navigator.encodeLocation(match.pathname.replace(/%/g, "%25").replace(/\?/g, "%3F").replace(/#/g, "%23")).pathname : match.pathname]),
@@ -664,10 +666,10 @@ var RenderErrorBoundary = class extends React$1.Component {
664
666
  const decoded = decodeRouteErrorResponseDigest(error.digest);
665
667
  if (decoded) error = decoded;
666
668
  }
667
- 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, {
668
670
  value: error,
669
671
  children: this.props.component
670
- })) : this.props.children;
672
+ })))) : this.props.children;
671
673
  if (this.context) return /* @__PURE__ */ React$1.createElement(RSCErrorHandler, { error }, result);
672
674
  return result;
673
675
  }
@@ -701,7 +703,7 @@ function RSCErrorHandler({ children, error }) {
701
703
  function RenderedRoute({ routeContext, match, children }) {
702
704
  let dataRouterContext = React$1.useContext(DataRouterContext);
703
705
  if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
704
- 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)));
705
707
  }
706
708
  function _renderMatches(matches, parentMatches = [], dataRouterOpts) {
707
709
  let dataRouterState = dataRouterOpts?.state;
@@ -811,25 +813,25 @@ function useDataRouterState(hookName) {
811
813
  invariant(state, getDataRouterConsoleError(hookName));
812
814
  return state;
813
815
  }
814
- function useRouteContext(hookName) {
815
- let route = React$1.useContext(RouteContext);
816
- invariant(route, getDataRouterConsoleError(hookName));
817
- return route;
816
+ function useDataRouterFetchers(hookName) {
817
+ let fetchers = React$1.useContext(FetchersContext);
818
+ invariant(fetchers, getDataRouterConsoleError(hookName));
819
+ return fetchers;
818
820
  }
819
- function useCurrentRouteId(hookName) {
820
- let route = useRouteContext(hookName);
821
- let thisRoute = route.matches[route.matches.length - 1];
822
- invariant(thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"`);
823
- return thisRoute.route.id;
821
+ function useDataRouterData(hookName) {
822
+ let data = React$1.useContext(DataRouterDataContext);
823
+ invariant(data, getDataRouterConsoleError(hookName));
824
+ return data;
824
825
  }
825
- /**
826
- * Returns the ID for the nearest contextual route
827
- *
828
- * @category Hooks
829
- * @returns The ID of the nearest contextual route
830
- */
831
- function useRouteId() {
832
- 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;
833
835
  }
834
836
  /**
835
837
  * Returns the current {@link Navigation}, defaulting to an "idle" navigation
@@ -854,11 +856,11 @@ function useRouteId() {
854
856
  * @returns The current {@link Navigation} object
855
857
  */
856
858
  function useNavigation() {
857
- let state = useDataRouterState("useNavigation");
859
+ let { navigation } = useDataRouterNavigation("useNavigation");
858
860
  return React$1.useMemo(() => {
859
- let { matches, historyAction, ...rest } = state.navigation;
861
+ let { matches, historyAction, ...rest } = navigation;
860
862
  return rest;
861
- }, [state.navigation]);
863
+ }, [navigation]);
862
864
  }
863
865
  /**
864
866
  * Revalidate the data on the page for reasons outside of normal data mutations
@@ -897,14 +899,14 @@ function useNavigation() {
897
899
  */
898
900
  function useRevalidator() {
899
901
  let dataRouterContext = useDataRouterContext("useRevalidator");
900
- let state = useDataRouterState("useRevalidator");
902
+ let { revalidation } = useDataRouterNavigation("useRevalidator");
901
903
  let revalidate = React$1.useCallback(async () => {
902
904
  await dataRouterContext.router.revalidate();
903
905
  }, [dataRouterContext.router]);
904
906
  return React$1.useMemo(() => ({
905
907
  revalidate,
906
- state: state.revalidation
907
- }), [revalidate, state.revalidation]);
908
+ state: revalidation
909
+ }), [revalidate, revalidation]);
908
910
  }
909
911
  /**
910
912
  * Returns the active route matches, useful for accessing `loaderData` for
@@ -941,7 +943,8 @@ function useRevalidator() {
941
943
  * @returns An array of {@link UIMatch | UI matches} for the current route hierarchy
942
944
  */
943
945
  function useMatches() {
944
- let { matches, loaderData } = useDataRouterState("useMatches");
946
+ let { matches } = useDataRouterState("useMatches");
947
+ let { loaderData } = useDataRouterData("useMatches");
945
948
  return React$1.useMemo(() => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
946
949
  }
947
950
  /**
@@ -968,9 +971,9 @@ function useMatches() {
968
971
  * @returns The data returned from the route's [`loader`](../../start/framework/route-module#loader) or [`clientLoader`](../../start/framework/route-module#clientloader) function
969
972
  */
970
973
  function useLoaderData() {
971
- let state = useDataRouterState("useLoaderData");
974
+ let data = useDataRouterData("useLoaderData");
972
975
  let routeId = useCurrentRouteId("useLoaderData");
973
- return state.loaderData[routeId];
976
+ return data.loaderData[routeId];
974
977
  }
975
978
  /**
976
979
  * Returns the [`loader`](../../start/framework/route-module#loader) data for a
@@ -1005,7 +1008,7 @@ function useLoaderData() {
1005
1008
  * function, or `undefined` if not found
1006
1009
  */
1007
1010
  function useRouteLoaderData(routeId) {
1008
- return useDataRouterState("useRouteLoaderData").loaderData[routeId];
1011
+ return useDataRouterData("useRouteLoaderData").loaderData[routeId];
1009
1012
  }
1010
1013
  /**
1011
1014
  * Returns the [`action`](../../start/framework/route-module#action) data from
@@ -1040,9 +1043,9 @@ function useRouteLoaderData(routeId) {
1040
1043
  * has been called
1041
1044
  */
1042
1045
  function useActionData() {
1043
- let state = useDataRouterState("useActionData");
1044
- let routeId = useCurrentRouteId("useLoaderData");
1045
- 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;
1046
1049
  }
1047
1050
  /**
1048
1051
  * Accesses the error thrown during an
@@ -1066,10 +1069,10 @@ function useActionData() {
1066
1069
  */
1067
1070
  function useRouteError() {
1068
1071
  let error = React$1.useContext(RouteErrorContext);
1069
- let state = useDataRouterState("useRouteError");
1072
+ let data = useDataRouterData("useRouteError");
1070
1073
  let routeId = useCurrentRouteId("useRouteError");
1071
1074
  if (error !== void 0) return error;
1072
- return state.errors?.[routeId];
1075
+ return data.errors?.[routeId];
1073
1076
  }
1074
1077
  /**
1075
1078
  * Returns the resolved promise value from the closest {@link Await | `<Await>`}.
@@ -1294,12 +1297,13 @@ function useRoute(...args) {
1294
1297
  const currentRouteId = useCurrentRouteId("useRoute");
1295
1298
  const id = args[0] ?? currentRouteId;
1296
1299
  const state = useDataRouterState("useRoute");
1300
+ const data = useDataRouterData("useRoute");
1297
1301
  const route = state.matches.find(({ route }) => route.id === id);
1298
1302
  if (route === void 0) return void 0;
1299
1303
  return {
1300
1304
  handle: route.route.handle,
1301
- loaderData: state.loaderData[id],
1302
- actionData: state.actionData?.[id]
1305
+ loaderData: data.loaderData[id],
1306
+ actionData: data.actionData?.[id]
1303
1307
  };
1304
1308
  }
1305
1309
  function toRouterStateMatch(match) {
@@ -1353,7 +1357,8 @@ function toRouterStateMatch(match) {
1353
1357
  * @returns The current router state with `active` and `pending` variants
1354
1358
  */
1355
1359
  function useRouterState() {
1356
- let { location, historyAction: type, matches, navigation } = useDataRouterState("unstable_useRouterState");
1360
+ let { location, historyAction: type, matches } = useDataRouterState("unstable_useRouterState");
1361
+ let { navigation } = useDataRouterNavigation("unstable_useRouterState");
1357
1362
  let active = React$1.useMemo(() => ({
1358
1363
  type,
1359
1364
  location,
@@ -1400,4 +1405,4 @@ function useRouterState() {
1400
1405
  }), [active, pending]);
1401
1406
  }
1402
1407
  //#endregion
1403
- 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.1
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.1
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.1
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 };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.4.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { Action, History, Location, Path, To } from "./history.js";
3
- import { DataRouteMatch, DataRouteObject, DataStrategyFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, MaybePromise, PatchRoutesOnNavigationFunction, RouteBranch, RouteData, RouteManifest, RouteObject, RouterContextProvider, Submission, UIMatch } from "./utils.js";
3
+ import { DataRouteMatch, DataRouteObject, DataStrategyFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, MaybePromise, PatchRoutesOnNavigationFunction, RouteData, RouteManifest, RouteObject, RouterContextProvider, Submission, UIMatch } from "./utils.js";
4
4
  import { ClientInstrumentation, ServerInstrumentation } from "./instrumentation.js";
5
5
 
6
6
  //#region lib/router/router.d.ts
@@ -40,9 +40,10 @@ interface Router {
40
40
  * @private
41
41
  * PRIVATE - DO NOT USE
42
42
  *
43
- * Return the route branches for this router instance
43
+ * Match routes against a location using the router's configured route
44
+ * matching implementation.
44
45
  */
45
- get branches(): RouteBranch<DataRouteObject>[] | undefined;
46
+ match(locationArg: Partial<Location> | string): DataRouteMatch[] | null;
46
47
  /**
47
48
  * @private
48
49
  * PRIVATE - DO NOT USE
@@ -304,7 +305,10 @@ type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "e
304
305
  /**
305
306
  * Future flags to toggle new feature behavior
306
307
  */
307
- interface FutureConfig {}
308
+ interface FutureConfig {
309
+ /** Enables route-pattern matching after calling `unstable_preloadRoutePattern()`. */
310
+ unstable_routePatternMatching?: boolean;
311
+ }
308
312
  /**
309
313
  * Initialization options for createRouter
310
314
  */
@@ -336,6 +340,8 @@ interface StaticHandlerContext {
336
340
  loaderHeaders: Record<string, Headers>;
337
341
  actionHeaders: Record<string, Headers>;
338
342
  _deepestRenderedBoundaryId?: string | null;
343
+ /** @private */
344
+ _match: StaticHandler["match"];
339
345
  }
340
346
  /**
341
347
  * A StaticHandler instance manages a singular SSR navigation/fetch event
@@ -349,10 +355,10 @@ interface StaticHandler {
349
355
  * @private
350
356
  * PRIVATE - DO NOT USE
351
357
  *
352
- * The route branches derived from the data routes, used for internal route
353
- * matching in Framework Mode
358
+ * Match routes against a location using the handler's configured route
359
+ * matching implementation.
354
360
  */
355
- _internalRouteBranches: RouteBranch<DataRouteObject>[];
361
+ match(locationArg: Partial<Location> | string): DataRouteMatch[] | null;
356
362
  /**
357
363
  * Perform a query for a given request - executing all matched route
358
364
  * loaders/actions. Used for document requests.