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
  *
@@ -9,7 +9,7 @@
9
9
  * @license MIT
10
10
  */
11
11
  import { createPath } from "../../router/history.js";
12
- import { joinPaths, matchRoutesImpl } from "../../router/utils.js";
12
+ import { joinPaths } from "../../router/utils.js";
13
13
  import { createClientRoutes } from "./routes.js";
14
14
  import * as React$1 from "react";
15
15
  //#region lib/dom/ssr/fog-of-war.ts
@@ -39,7 +39,7 @@ function getPartialManifest({ sri, ...manifest }, router) {
39
39
  segments.pop();
40
40
  }
41
41
  paths.forEach((path) => {
42
- let matches = matchRoutesImpl(router.routes, path, router.basename || "/", false, router.branches);
42
+ let matches = router.match(path);
43
43
  if (matches) matches.forEach((m) => routeIds.add(m.route.id));
44
44
  });
45
45
  let initialRoutes = [...routeIds].reduce((acc, id) => Object.assign(acc, { [id]: manifest.routes[id] }), {});
@@ -110,7 +110,10 @@ function getManifestPath(_manifestPath, basename) {
110
110
  return basename == null ? manifestPath : joinPaths([basename, manifestPath]);
111
111
  }
112
112
  const MANIFEST_VERSION_STORAGE_KEY = "react-router-manifest-version";
113
+ const MANIFEST_RELOAD_TIMEOUT = 5e3;
114
+ let pendingManifestReload;
113
115
  async function handleClientVersionMismatch(needsReload, version, errorReloadPath) {
116
+ if (pendingManifestReload) return pendingManifestReload;
114
117
  if (!needsReload) {
115
118
  try {
116
119
  sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
@@ -121,17 +124,35 @@ async function handleClientVersionMismatch(needsReload, version, errorReloadPath
121
124
  console.warn("Detected a manifest version mismatch during eager route discovery. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest.");
122
125
  return true;
123
126
  }
127
+ let alreadyReloaded = false;
124
128
  try {
125
- if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === version) {
126
- console.error("Unable to discover routes due to manifest version mismatch.");
127
- return true;
128
- }
129
- sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, version);
129
+ alreadyReloaded = sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === version;
130
+ if (!alreadyReloaded) sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, version);
130
131
  } catch {}
131
- window.location.href = errorReloadPath;
132
- console.warn("Detected manifest version mismatch, reloading...");
133
- await new Promise(() => {});
134
- return true;
132
+ if (alreadyReloaded) throw new Error("Unable to discover routes due to manifest version mismatch.");
133
+ let rejectReload;
134
+ let reloadPromise = new Promise((_, reject) => {
135
+ rejectReload = reject;
136
+ });
137
+ pendingManifestReload = reloadPromise;
138
+ let failReload = () => {
139
+ clearTimeout(timeout);
140
+ window.removeEventListener("pageshow", onPageShow);
141
+ pendingManifestReload = void 0;
142
+ rejectReload(/* @__PURE__ */ new Error("Unable to discover routes due to manifest version mismatch."));
143
+ };
144
+ let timeout = setTimeout(failReload, MANIFEST_RELOAD_TIMEOUT);
145
+ let onPageShow = (event) => {
146
+ if (event.persisted) failReload();
147
+ };
148
+ window.addEventListener("pageshow", onPageShow);
149
+ try {
150
+ window.location.href = errorReloadPath;
151
+ console.warn("Detected manifest version mismatch, reloading...");
152
+ } catch {
153
+ failReload();
154
+ }
155
+ return reloadPromise;
135
156
  }
136
157
  async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, manifestPath, patchRoutes, signal) {
137
158
  paths = getPathsWithAncestors(paths);
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { Path } from "../../router/history.js";
3
3
  import { DataRouteObject } from "../../router/utils.js";
4
- import { HydrationState, Router } from "../../router/router.js";
4
+ import { FutureConfig, HydrationState, Router } from "../../router/router.js";
5
5
  import { ClientLoaderFunction } from "./routeModules.js";
6
6
 
7
7
  //#region lib/dom/ssr/hydration.d.ts
@@ -11,6 +11,7 @@ declare function getHydrationData({
11
11
  getRouteInfo,
12
12
  location,
13
13
  basename,
14
+ future,
14
15
  isSpaMode
15
16
  }: {
16
17
  state: {
@@ -26,6 +27,7 @@ declare function getHydrationData({
26
27
  };
27
28
  location: Path;
28
29
  basename: string | undefined;
30
+ future: FutureConfig;
29
31
  isSpaMode: boolean;
30
32
  }): HydrationState;
31
33
  //#endregion
@@ -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
  *
@@ -8,15 +8,17 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { matchRoutes } from "../../router/utils.js";
11
+ import { createDataRouteMatcher } from "../../router/router.js";
12
12
  import { shouldHydrateRouteLoader } from "./routes.js";
13
13
  //#region lib/dom/ssr/hydration.tsx
14
- function getHydrationData({ state, routes, getRouteInfo, location, basename, isSpaMode }) {
14
+ function getHydrationData({ state, routes, getRouteInfo, location, basename, future, isSpaMode }) {
15
15
  let hydrationData = {
16
16
  ...state,
17
17
  loaderData: { ...state.loaderData }
18
18
  };
19
- let initialMatches = matchRoutes(routes, location, basename);
19
+ let dataRouteMatcher = createDataRouteMatcher(future, basename || "/");
20
+ dataRouteMatcher.update(routes);
21
+ let initialMatches = dataRouteMatcher.match(location);
20
22
  if (initialMatches) for (let match of initialMatches) {
21
23
  let routeId = match.route.id;
22
24
  let routeInfo = getRouteInfo(routeId);
@@ -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
  *
@@ -20,5 +20,8 @@ const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
20
20
  function escapeHtml(html) {
21
21
  return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
22
22
  }
23
+ function escapeAttribute(value) {
24
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
25
+ }
23
26
  //#endregion
24
- export { escapeHtml };
27
+ export { escapeAttribute, escapeHtml };
@@ -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
  *
@@ -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
  *
@@ -40,7 +40,7 @@ function ServerRouter({ context, url, nonce }) {
40
40
  let manifestRoute = context.manifest.routes[routeId];
41
41
  if (route && manifestRoute && shouldHydrateRouteLoader(routeId, route.clientLoader, manifestRoute.hasLoader, context.isSpaMode) && (route.HydrateFallback || !manifestRoute.hasLoader)) delete context.staticHandlerContext.loaderData[routeId];
42
42
  }
43
- let router = createStaticRouter(routes, context.staticHandlerContext, { branches: context.branches });
43
+ let router = createStaticRouter(routes, context.staticHandlerContext, { future: context.future });
44
44
  return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(FrameworkContext.Provider, { value: {
45
45
  manifest,
46
46
  routeModules,
@@ -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
  *
@@ -101,25 +101,16 @@ async function singleFetchActionStrategy(args, fetchAndDecode) {
101
101
  async function nonSsrStrategy(args, getRouteInfo, fetchAndDecode) {
102
102
  let matchesToLoad = args.matches.filter((m) => m.shouldCallHandler());
103
103
  let results = {};
104
- await Promise.all(matchesToLoad.map((m) => m.resolve(async (handler) => {
105
- try {
104
+ await Promise.all(matchesToLoad.map(async (m) => {
105
+ let routeId = m.route.id;
106
+ results[routeId] = await m.resolve(async (handler) => {
106
107
  let { hasClientLoader } = getRouteInfo(m);
107
- let routeId = m.route.id;
108
- let result = hasClientLoader ? await handler(async () => {
108
+ return hasClientLoader ? handler(async () => {
109
109
  let { data } = await fetchAndDecode(args, [routeId]);
110
110
  return unwrapSingleFetchResult(data, routeId);
111
- }) : await handler();
112
- results[m.route.id] = {
113
- type: "data",
114
- result
115
- };
116
- } catch (e) {
117
- results[m.route.id] = {
118
- type: "error",
119
- result: e
120
- };
121
- }
122
- })));
111
+ }) : handler();
112
+ });
113
+ }));
123
114
  return results;
124
115
  }
125
116
  async function singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut = () => true) {
@@ -277,8 +268,8 @@ async function fetchAndDecodeViaTurboStream(args, targetRoutes) {
277
268
  status: res.status,
278
269
  data
279
270
  };
280
- } catch {
281
- throw new Error("Unable to decode turbo-stream response");
271
+ } catch (cause) {
272
+ throw new Error("Unable to decode turbo-stream response", { cause });
282
273
  }
283
274
  }
284
275
  function decodeViaTurboStream(body, global) {
@@ -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
  *
@@ -67,6 +67,7 @@ function createHydratedRouter({ getContext, instrumentations }) {
67
67
  }),
68
68
  location: window.location,
69
69
  basename: window.__reactRouterContext?.basename,
70
+ future: ssrInfo.context.future,
70
71
  isSpaMode: ssrInfo.context.isSpaMode
71
72
  });
72
73
  if (window.history.state && window.history.state.masked) window.history.replaceState({
@@ -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.`);
@@ -603,7 +602,10 @@ function useRoutesImpl(routes, locationArg, dataRouterOpts) {
603
602
  let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
604
603
  remainingPathname = "/" + pathname.replace(/^\//, "").split("/").slice(parentSegments.length).join("/");
605
604
  }
606
- 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 });
605
+ let matches;
606
+ if (dataRouterOpts) if (dataRouterOpts.state.matches.length) matches = dataRouterOpts.state.matches.map((m) => Object.assign(m, { route: dataRouterOpts.manifest[m.route.id] || m.route }));
607
+ else matches = dataRouterOpts.router.match(dataRouterOpts.state.location);
608
+ else matches = matchRoutes(routes, { pathname: remainingPathname });
607
609
  warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `);
608
610
  warning(matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0, `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`);
609
611
  let renderedMatches = _renderMatches(matches && matches.map((match) => Object.assign({}, match, {
@@ -679,10 +681,10 @@ var RenderErrorBoundary = class extends React$1.Component {
679
681
  const decoded = decodeRouteErrorResponseDigest(error.digest);
680
682
  if (decoded) error = decoded;
681
683
  }
682
- let result = error !== void 0 ? /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React$1.createElement(RouteErrorContext.Provider, {
684
+ 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, {
683
685
  value: error,
684
686
  children: this.props.component
685
- })) : this.props.children;
687
+ })))) : this.props.children;
686
688
  if (this.context) return /* @__PURE__ */ React$1.createElement(RSCErrorHandler, { error }, result);
687
689
  return result;
688
690
  }
@@ -716,7 +718,7 @@ function RSCErrorHandler({ children, error }) {
716
718
  function RenderedRoute({ routeContext, match, children }) {
717
719
  let dataRouterContext = React$1.useContext(DataRouterContext);
718
720
  if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
719
- return /* @__PURE__ */ React$1.createElement(RouteContext.Provider, { value: routeContext }, children);
721
+ 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)));
720
722
  }
721
723
  function _renderMatches(matches, parentMatches = [], dataRouterOpts) {
722
724
  let dataRouterState = dataRouterOpts?.state;
@@ -826,25 +828,25 @@ function useDataRouterState(hookName) {
826
828
  invariant(state, getDataRouterConsoleError(hookName));
827
829
  return state;
828
830
  }
829
- function useRouteContext(hookName) {
830
- let route = React$1.useContext(RouteContext);
831
- invariant(route, getDataRouterConsoleError(hookName));
832
- return route;
831
+ function useDataRouterFetchers(hookName) {
832
+ let fetchers = React$1.useContext(FetchersContext);
833
+ invariant(fetchers, getDataRouterConsoleError(hookName));
834
+ return fetchers;
833
835
  }
834
- function useCurrentRouteId(hookName) {
835
- let route = useRouteContext(hookName);
836
- let thisRoute = route.matches[route.matches.length - 1];
837
- invariant(thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"`);
838
- return thisRoute.route.id;
836
+ function useDataRouterData(hookName) {
837
+ let data = React$1.useContext(DataRouterDataContext);
838
+ invariant(data, getDataRouterConsoleError(hookName));
839
+ return data;
839
840
  }
840
- /**
841
- * Returns the ID for the nearest contextual route
842
- *
843
- * @category Hooks
844
- * @returns The ID of the nearest contextual route
845
- */
846
- function useRouteId() {
847
- return useCurrentRouteId("useRouteId");
841
+ function useDataRouterNavigation(hookName) {
842
+ let navigation = React$1.useContext(DataRouterNavigationContext);
843
+ invariant(navigation, getDataRouterConsoleError(hookName));
844
+ return navigation;
845
+ }
846
+ function useCurrentRouteId(hookName) {
847
+ let routeId = React$1.useContext(RouteIdContext);
848
+ invariant(routeId, `${hookName} can only be used on routes that contain a unique "id"`);
849
+ return routeId;
848
850
  }
849
851
  /**
850
852
  * Returns the current {@link Navigation}, defaulting to an "idle" navigation
@@ -869,11 +871,11 @@ function useRouteId() {
869
871
  * @returns The current {@link Navigation} object
870
872
  */
871
873
  function useNavigation() {
872
- let state = useDataRouterState("useNavigation");
874
+ let { navigation } = useDataRouterNavigation("useNavigation");
873
875
  return React$1.useMemo(() => {
874
- let { matches, historyAction, ...rest } = state.navigation;
876
+ let { matches, historyAction, ...rest } = navigation;
875
877
  return rest;
876
- }, [state.navigation]);
878
+ }, [navigation]);
877
879
  }
878
880
  /**
879
881
  * Revalidate the data on the page for reasons outside of normal data mutations
@@ -912,14 +914,14 @@ function useNavigation() {
912
914
  */
913
915
  function useRevalidator() {
914
916
  let dataRouterContext = useDataRouterContext("useRevalidator");
915
- let state = useDataRouterState("useRevalidator");
917
+ let { revalidation } = useDataRouterNavigation("useRevalidator");
916
918
  let revalidate = React$1.useCallback(async () => {
917
919
  await dataRouterContext.router.revalidate();
918
920
  }, [dataRouterContext.router]);
919
921
  return React$1.useMemo(() => ({
920
922
  revalidate,
921
- state: state.revalidation
922
- }), [revalidate, state.revalidation]);
923
+ state: revalidation
924
+ }), [revalidate, revalidation]);
923
925
  }
924
926
  /**
925
927
  * Returns the active route matches, useful for accessing `loaderData` for
@@ -956,7 +958,8 @@ function useRevalidator() {
956
958
  * @returns An array of {@link UIMatch | UI matches} for the current route hierarchy
957
959
  */
958
960
  function useMatches() {
959
- let { matches, loaderData } = useDataRouterState("useMatches");
961
+ let { matches } = useDataRouterState("useMatches");
962
+ let { loaderData } = useDataRouterData("useMatches");
960
963
  return React$1.useMemo(() => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
961
964
  }
962
965
  /**
@@ -983,9 +986,9 @@ function useMatches() {
983
986
  * @returns The data returned from the route's [`loader`](../../start/framework/route-module#loader) or [`clientLoader`](../../start/framework/route-module#clientloader) function
984
987
  */
985
988
  function useLoaderData() {
986
- let state = useDataRouterState("useLoaderData");
989
+ let data = useDataRouterData("useLoaderData");
987
990
  let routeId = useCurrentRouteId("useLoaderData");
988
- return state.loaderData[routeId];
991
+ return data.loaderData[routeId];
989
992
  }
990
993
  /**
991
994
  * Returns the [`loader`](../../start/framework/route-module#loader) data for a
@@ -1020,7 +1023,7 @@ function useLoaderData() {
1020
1023
  * function, or `undefined` if not found
1021
1024
  */
1022
1025
  function useRouteLoaderData(routeId) {
1023
- return useDataRouterState("useRouteLoaderData").loaderData[routeId];
1026
+ return useDataRouterData("useRouteLoaderData").loaderData[routeId];
1024
1027
  }
1025
1028
  /**
1026
1029
  * Returns the [`action`](../../start/framework/route-module#action) data from
@@ -1055,9 +1058,9 @@ function useRouteLoaderData(routeId) {
1055
1058
  * has been called
1056
1059
  */
1057
1060
  function useActionData() {
1058
- let state = useDataRouterState("useActionData");
1059
- let routeId = useCurrentRouteId("useLoaderData");
1060
- return state.actionData ? state.actionData[routeId] : void 0;
1061
+ let data = useDataRouterData("useActionData");
1062
+ let routeId = useCurrentRouteId("useActionData");
1063
+ return data.actionData ? data.actionData[routeId] : void 0;
1061
1064
  }
1062
1065
  /**
1063
1066
  * Accesses the error thrown during an
@@ -1081,10 +1084,10 @@ function useActionData() {
1081
1084
  */
1082
1085
  function useRouteError() {
1083
1086
  let error = React$1.useContext(RouteErrorContext);
1084
- let state = useDataRouterState("useRouteError");
1087
+ let data = useDataRouterData("useRouteError");
1085
1088
  let routeId = useCurrentRouteId("useRouteError");
1086
1089
  if (error !== void 0) return error;
1087
- return state.errors?.[routeId];
1090
+ return data.errors?.[routeId];
1088
1091
  }
1089
1092
  /**
1090
1093
  * Returns the resolved promise value from the closest {@link Await | `<Await>`}.
@@ -1309,12 +1312,13 @@ function useRoute(...args) {
1309
1312
  const currentRouteId = useCurrentRouteId("useRoute");
1310
1313
  const id = args[0] ?? currentRouteId;
1311
1314
  const state = useDataRouterState("useRoute");
1315
+ const data = useDataRouterData("useRoute");
1312
1316
  const route = state.matches.find(({ route }) => route.id === id);
1313
1317
  if (route === void 0) return void 0;
1314
1318
  return {
1315
1319
  handle: route.route.handle,
1316
- loaderData: state.loaderData[id],
1317
- actionData: state.actionData?.[id]
1320
+ loaderData: data.loaderData[id],
1321
+ actionData: data.actionData?.[id]
1318
1322
  };
1319
1323
  }
1320
1324
  function toRouterStateMatch(match) {
@@ -1368,7 +1372,8 @@ function toRouterStateMatch(match) {
1368
1372
  * @returns The current router state with `active` and `pending` variants
1369
1373
  */
1370
1374
  function useRouterState() {
1371
- let { location, historyAction: type, matches, navigation } = useDataRouterState("unstable_useRouterState");
1375
+ let { location, historyAction: type, matches } = useDataRouterState("unstable_useRouterState");
1376
+ let { navigation } = useDataRouterNavigation("unstable_useRouterState");
1372
1377
  let active = React$1.useMemo(() => ({
1373
1378
  type,
1374
1379
  location,
@@ -1415,4 +1420,4 @@ function useRouterState() {
1415
1420
  }), [active, pending]);
1416
1421
  }
1417
1422
  //#endregion
1418
- 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 };
1423
+ 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
  *