react-router 0.0.0-experimental-28357fd2a → 0.0.0-experimental-2eb7164

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 (58) hide show
  1. package/CHANGELOG.md +51 -48
  2. package/dist/development/{chunk-Z4HFX7Q2.mjs → chunk-433YBOKX.mjs} +102 -37
  3. package/dist/development/{chunk-QT7WPDUY.mjs → chunk-CM3L6EBM.mjs} +147 -33
  4. package/dist/development/{chunk-5CCVAEBF.js → chunk-DMYOHO3D.js} +210 -169
  5. package/dist/development/{chunk-EU7MB5YT.js → chunk-PFFPX2WQ.js} +77 -53
  6. package/dist/{production/context-DohQKLID.d.mts → development/context-DY_GBoQM.d.mts} +843 -6
  7. package/dist/development/dom-export.d.mts +20 -2
  8. package/dist/development/dom-export.d.ts +20 -1
  9. package/dist/development/dom-export.js +10 -4
  10. package/dist/development/dom-export.mjs +10 -4
  11. package/dist/development/{index-react-server-client-DXb0OgpJ.d.mts → index-react-server-client-ByWQ94sU.d.mts} +2 -3
  12. package/dist/{production/index-react-server-client-CMphySRb.d.ts → development/index-react-server-client-pJZFIoFI.d.ts} +6 -816
  13. package/dist/development/index-react-server-client.d.mts +3 -4
  14. package/dist/development/index-react-server-client.d.ts +2 -2
  15. package/dist/development/index-react-server-client.js +4 -4
  16. package/dist/development/index-react-server-client.mjs +2 -2
  17. package/dist/development/index-react-server.js +21 -7
  18. package/dist/development/index-react-server.mjs +21 -7
  19. package/dist/development/index.d.mts +7 -9
  20. package/dist/development/index.d.ts +5 -5
  21. package/dist/development/index.js +242 -128
  22. package/dist/development/index.mjs +3 -3
  23. package/dist/development/lib/types/internal.d.mts +2 -2
  24. package/dist/development/lib/types/internal.d.ts +1 -1
  25. package/dist/development/lib/types/internal.js +1 -1
  26. package/dist/development/lib/types/internal.mjs +1 -1
  27. package/dist/development/{route-data-CpB5xtMm.d.mts → route-data-DZyLihZ0.d.mts} +1 -1
  28. package/dist/development/{routeModules-qBivMBjd.d.ts → routeModules-iYhSy-FD.d.ts} +843 -6
  29. package/dist/production/{chunk-EQ3NKH5J.mjs → chunk-G343FNS2.mjs} +102 -37
  30. package/dist/production/{chunk-DOZCQHLU.js → chunk-GALNUNJG.js} +210 -169
  31. package/dist/production/{chunk-2DWPJCWX.js → chunk-MFKHDFBJ.js} +77 -53
  32. package/dist/production/{chunk-GPXYCHV5.mjs → chunk-VQTSL3FX.mjs} +147 -33
  33. package/dist/{development/context-DohQKLID.d.mts → production/context-DY_GBoQM.d.mts} +843 -6
  34. package/dist/production/dom-export.d.mts +20 -2
  35. package/dist/production/dom-export.d.ts +20 -1
  36. package/dist/production/dom-export.js +10 -4
  37. package/dist/production/dom-export.mjs +10 -4
  38. package/dist/production/{index-react-server-client-DXb0OgpJ.d.mts → index-react-server-client-ByWQ94sU.d.mts} +2 -3
  39. package/dist/{development/index-react-server-client-CMphySRb.d.ts → production/index-react-server-client-pJZFIoFI.d.ts} +6 -816
  40. package/dist/production/index-react-server-client.d.mts +3 -4
  41. package/dist/production/index-react-server-client.d.ts +2 -2
  42. package/dist/production/index-react-server-client.js +4 -4
  43. package/dist/production/index-react-server-client.mjs +2 -2
  44. package/dist/production/index-react-server.js +21 -7
  45. package/dist/production/index-react-server.mjs +21 -7
  46. package/dist/production/index.d.mts +7 -9
  47. package/dist/production/index.d.ts +5 -5
  48. package/dist/production/index.js +242 -128
  49. package/dist/production/index.mjs +3 -3
  50. package/dist/production/lib/types/internal.d.mts +2 -2
  51. package/dist/production/lib/types/internal.d.ts +1 -1
  52. package/dist/production/lib/types/internal.js +1 -1
  53. package/dist/production/lib/types/internal.mjs +1 -1
  54. package/dist/production/{route-data-CpB5xtMm.d.mts → route-data-DZyLihZ0.d.mts} +1 -1
  55. package/dist/production/{routeModules-qBivMBjd.d.ts → routeModules-iYhSy-FD.d.ts} +843 -6
  56. package/package.json +1 -1
  57. package/dist/development/components-CuPfnyiZ.d.mts +0 -814
  58. package/dist/production/components-CuPfnyiZ.d.mts +0 -814
package/CHANGELOG.md CHANGED
@@ -1,18 +1,6 @@
1
1
  # `react-router`
2
2
 
3
- ## 7.8.0-pre.2
4
-
5
- ### Patch Changes
6
-
7
- - proxy server action side-effect redirects from actions for document and callServer requests ([#14131](https://github.com/remix-run/react-router/pull/14131))
8
-
9
- ## 7.8.0-pre.1
10
-
11
- ### Patch Changes
12
-
13
- - [REMOVE] Few additional fixes for returning/throwing data from middleware - attach to #14093 ([#14128](https://github.com/remix-run/react-router/pull/14128))
14
-
15
- ## 7.8.0-pre.0
3
+ ## 7.8.0
16
4
 
17
5
  ### Minor Changes
18
6
 
@@ -23,14 +11,50 @@
23
11
 
24
12
  ### Patch Changes
25
13
 
26
- - [UNSTABLE] Ensure resource route errors go through `handleError` w/middleware enabled ([#14078](https://github.com/remix-run/react-router/pull/14078))
27
14
  - Prevent _"Did not find corresponding fetcher result"_ console error when navigating during a `fetcher.submit` revalidation ([#14114](https://github.com/remix-run/react-router/pull/14114))
15
+
16
+ - Bubble client-side middleware errors prior to `next` to the appropriate ancestor error boundary ([#14138](https://github.com/remix-run/react-router/pull/14138))
17
+
28
18
  - Switch Lazy Route Discovery manifest URL generation to usea standalone `URLSearchParams` instance instead of `URL.searchParams` to avoid a major performance bottleneck in Chrome ([#14084](https://github.com/remix-run/react-router/pull/14084))
29
- - [UNSTABLE] Propagate returned Response from server middleware if next wasn't called ([#14093](https://github.com/remix-run/react-router/pull/14093))
30
- - [UNSTABLE] Allow server middlewares to return `data()` values which will be converted into a `Response` ([#14093](https://github.com/remix-run/react-router/pull/14093))
31
- - [UNSTABLE] Update middleware error handling so that the `next` function never throws and instead handles any middleware errors at the proper `ErrorBoundary` and returns the `Response` up through the ancestor `next` function ([#14118](https://github.com/remix-run/react-router/pull/14118))
32
- - - [UNSTABLE] When middleware is enabled, make the `context` parameter read-only (via `Readonly<unstable_RouterContextProvider>`) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. ([#14097](https://github.com/remix-run/react-router/pull/14097))
33
- - [UNSTABLE] Rename and alter the signature/functionality of the `unstable_respond` API in `staticHandler.query`/`staticHandler.queryRoute` ([#14103](https://github.com/remix-run/react-router/pull/14103))
19
+
20
+ - Adjust internal RSC usage of `React.use` to avoid Webpack compilation errors when using React 18 ([#14113](https://github.com/remix-run/react-router/pull/14113))
21
+
22
+ - Remove dependency on `@types/node` in TypeScript declaration files ([#14059](https://github.com/remix-run/react-router/pull/14059))
23
+
24
+ - Fix types for `UIMatch` to reflect that the `loaderData`/`data` properties may be `undefined` ([#12206](https://github.com/remix-run/react-router/pull/12206))
25
+ - When an `ErrorBoundary` is being rendered, not all active matches will have loader data available, since it may have been their `loader` that threw to trigger the boundary
26
+ - The `UIMatch.data` type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an `ErrorBoundary` was rendered
27
+ - ⚠️ This may cause some type errors to show up in your code for unguarded `match.data` accesses - you should properly guard for `undefined` values in those scenarios.
28
+
29
+ ```tsx
30
+ // app/root.tsx
31
+ export function loader() {
32
+ someFunctionThatThrows(); // ❌ Throws an Error
33
+ return { title: "My Title" };
34
+ }
35
+
36
+ export function Layout({ children }: { children: React.ReactNode }) {
37
+ let matches = useMatches();
38
+ let rootMatch = matches[0] as UIMatch<Awaited<ReturnType<typeof loader>>>;
39
+ // ^ rootMatch.data is incorrectly typed here, so TypeScript does not
40
+ // complain if you do the following which throws an error at runtime:
41
+ let { title } = rootMatch.data; // 💥
42
+
43
+ return <html>...</html>;
44
+ }
45
+ ```
46
+
47
+ - \[UNSTABLE] Ensure resource route errors go through `handleError` w/middleware enabled ([#14078](https://github.com/remix-run/react-router/pull/14078))
48
+
49
+ - \[UNSTABLE] Propagate returned Response from server middleware if next wasn't called ([#14093](https://github.com/remix-run/react-router/pull/14093))
50
+
51
+ - \[UNSTABLE] Allow server middlewares to return `data()` values which will be converted into a `Response` ([#14093](https://github.com/remix-run/react-router/pull/14093))
52
+
53
+ - \[UNSTABLE] Update middleware error handling so that the `next` function never throws and instead handles any middleware errors at the proper `ErrorBoundary` and returns the `Response` up through the ancestor `next` function ([#14118](https://github.com/remix-run/react-router/pull/14118))
54
+
55
+ - \[UNSTABLE] When middleware is enabled, make the `context` parameter read-only (via `Readonly<unstable_RouterContextProvider>`) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. ([#14097](https://github.com/remix-run/react-router/pull/14097))
56
+
57
+ - \[UNSTABLE] Rename and alter the signature/functionality of the `unstable_respond` API in `staticHandler.query`/`staticHandler.queryRoute` ([#14103](https://github.com/remix-run/react-router/pull/14103))
34
58
  - The API has been renamed to `unstable_generateMiddlewareResponse` for clarity
35
59
  - The main functional change is that instead of running the loaders/actions before calling `unstable_respond` and handing you the result, we now pass a `query`/`queryRoute` function as a parameter and you execute the loaders/actions inside your callback, giving you full access to pre-processing and error handling
36
60
  - The `query` version of the API now has a signature of `(query: (r: Request) => Promise<StaticHandlerContext | Response>) => Promise<Response>`
@@ -57,41 +81,20 @@
57
81
  });
58
82
  ```
59
83
 
60
- - [UNSTABLE] Convert internal middleware implementations to use the new `unstable_generateMiddlewareResponse` API ([#14103](https://github.com/remix-run/react-router/pull/14103))
61
- - Adjust internal RSC usage of `React.use` to avoid Webpack compilation errors when using React 18 ([#14113](https://github.com/remix-run/react-router/pull/14113))
62
- - [UNSTABLE] Change `getLoadContext` signature (`type GetLoadContextFunction`) when `future.unstable_middleware` is enabled so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
84
+ - \[UNSTABLE] Convert internal middleware implementations to use the new `unstable_generateMiddlewareResponse` API ([#14103](https://github.com/remix-run/react-router/pull/14103))
85
+
86
+ - \[UNSTABLE] Change `getLoadContext` signature (`type GetLoadContextFunction`) when `future.unstable_middleware` is enabled so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
63
87
  - This also removes the `type unstable_InitialContext` export
64
88
  - ⚠️ This is a breaking change if you have adopted middleware and are using a custom server with a `getLoadContext` function
65
89
 
66
- - Remove dependency on `@types/node` in TypeScript declaration files ([#14059](https://github.com/remix-run/react-router/pull/14059))
67
- - Fix types for `UIMatch` to reflect that the `loaderData`/`data` properties may be `undefined` ([#12206](https://github.com/remix-run/react-router/pull/12206))
68
- - When an `ErrorBoundary` is being rendered, not all active matches will have loader data available, since it may have been their `loader` that threw to trigger the boundary
69
- - The `UIMatch.data` type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an `ErrorBoundary` was rendered
70
- - ⚠️ This may cause some type errors to show up in your code for unguarded `match.data` accesses - you should properly guard for `undefined` values in those scenarios.
71
-
72
- ```tsx
73
- // app/root.tsx
74
- export function loader() {
75
- someFunctionThatThrows(); // ❌ Throws an Error
76
- return { title: "My Title" };
77
- }
78
-
79
- export function Layout({ children }: { children: React.ReactNode }) {
80
- let matches = useMatches();
81
- let rootMatch = matches[0] as UIMatch<Awaited<ReturnType<typeof loader>>>;
82
- // ^ rootMatch.data is incorrectly typed here, so TypeScript does not
83
- // complain if you do the following which throws an error at runtime:
84
- let { title } = rootMatch.data; // 💥
85
-
86
- return <html>...</html>;
87
- }
88
- ```
90
+ - \[UNSTABLE] Run client middleware on client navigations even if no loaders exist ([#14106](https://github.com/remix-run/react-router/pull/14106))
89
91
 
90
- - [UNSTABLE] Run client middleware on client navigations even if no loaders exist ([#14106](https://github.com/remix-run/react-router/pull/14106))
91
- - [UNSTABLE] Change the `unstable_getContext` signature on `RouterProvider`/`HydratedRouter`/`unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
92
+ - \[UNSTABLE] Change the `unstable_getContext` signature on `RouterProvider`/`HydratedRouter`/`unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
92
93
  - ⚠️ This is a breaking change if you have adopted the `unstable_getContext` prop
93
94
 
94
- - Fix RSC Data Mode issue where routes that return `false` from `shouldRevalidate` would be replaced by an `<Outlet />` ([#14071](https://github.com/remix-run/react-router/pull/14071))
95
+ - [UNSTABLE] proxy server action side-effect redirects from actions for document and callServer requests ([#14131](https://github.com/remix-run/react-router/pull/14131))
96
+
97
+ - [UNSTABLE] Fix RSC Data Mode issue where routes that return `false` from `shouldRevalidate` would be replaced by an `<Outlet />` ([#14071](https://github.com/remix-run/react-router/pull/14071))
95
98
 
96
99
  ## 7.7.1
97
100
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-28357fd2a
2
+ * react-router v0.0.0-experimental-2eb7164
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -513,8 +513,8 @@ function convertRouteMatchToUiMatch(match, loaderData) {
513
513
  handle: route.handle
514
514
  };
515
515
  }
516
- function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
517
- let flattenRoute = (route, index, relativePath) => {
516
+ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
517
+ let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath) => {
518
518
  let meta = {
519
519
  relativePath: relativePath === void 0 ? route.path || "" : relativePath,
520
520
  caseSensitive: route.caseSensitive === true,
@@ -522,6 +522,9 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
522
522
  route
523
523
  };
524
524
  if (meta.relativePath.startsWith("/")) {
525
+ if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) {
526
+ return;
527
+ }
525
528
  invariant(
526
529
  meta.relativePath.startsWith(parentPath),
527
530
  `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.`
@@ -537,7 +540,13 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
537
540
  route.index !== true,
538
541
  `Index routes must not have child routes. Please remove all child routes from route path "${path}".`
539
542
  );
540
- flattenRoutes(route.children, branches, routesMeta, path);
543
+ flattenRoutes(
544
+ route.children,
545
+ branches,
546
+ routesMeta,
547
+ path,
548
+ hasParentOptionalSegments
549
+ );
541
550
  }
542
551
  if (route.path == null && !route.index) {
543
552
  return;
@@ -553,7 +562,7 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
553
562
  flattenRoute(route, index);
554
563
  } else {
555
564
  for (let exploded of explodeOptionalSegments(route.path)) {
556
- flattenRoute(route, index, exploded);
565
+ flattenRoute(route, index, true, exploded);
557
566
  }
558
567
  }
559
568
  });
@@ -745,7 +754,7 @@ function compilePath(path, caseSensitive = false, end = true) {
745
754
  params.push({ paramName, isOptional: isOptional != null });
746
755
  return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
747
756
  }
748
- );
757
+ ).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2");
749
758
  if (path.endsWith("*")) {
750
759
  params.push({ paramName: "*" });
751
760
  regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
@@ -3941,9 +3950,15 @@ function clientMiddlewareErrorHandler(error, routeId, matches, didCallHandler) {
3941
3950
  [routeId]: { type: "error", result: error }
3942
3951
  };
3943
3952
  } else {
3953
+ let maxBoundaryIdx = Math.min(
3954
+ // Throwing route
3955
+ matches.findIndex((m) => m.route.id === routeId) || 0,
3956
+ // or the shallowest route that needs to load data
3957
+ matches.findIndex((m) => m.unstable_shouldCallHandler()) || 0
3958
+ );
3944
3959
  let boundaryRouteId = findNearestBoundary(
3945
3960
  matches,
3946
- matches.find((m) => m.route.id === routeId || m.route.loader)?.route.id || routeId
3961
+ matches[maxBoundaryIdx].route.id
3947
3962
  ).route.id;
3948
3963
  return {
3949
3964
  [boundaryRouteId]: { type: "error", result: error }
@@ -5134,7 +5149,7 @@ function useResolvedPath(to, { relative } = {}) {
5134
5149
  function useRoutes(routes, locationArg) {
5135
5150
  return useRoutesImpl(routes, locationArg);
5136
5151
  }
5137
- function useRoutesImpl(routes, locationArg, dataRouterState, future) {
5152
+ function useRoutesImpl(routes, locationArg, dataRouterState, unstable_handleError, future) {
5138
5153
  invariant(
5139
5154
  useInRouterContext(),
5140
5155
  // TODO: This error is probably because they somehow have 2 versions of the
@@ -5206,6 +5221,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
5206
5221
  ),
5207
5222
  parentMatches,
5208
5223
  dataRouterState,
5224
+ unstable_handleError,
5209
5225
  future
5210
5226
  );
5211
5227
  if (locationArg && renderedMatches) {
@@ -5274,11 +5290,14 @@ var RenderErrorBoundary = class extends React2.Component {
5274
5290
  };
5275
5291
  }
5276
5292
  componentDidCatch(error, errorInfo) {
5277
- console.error(
5278
- "React Router caught the following error during render",
5279
- error,
5280
- errorInfo
5281
- );
5293
+ if (this.props.unstable_handleError) {
5294
+ this.props.unstable_handleError(error, errorInfo);
5295
+ } else {
5296
+ console.error(
5297
+ "React Router caught the following error during render",
5298
+ error
5299
+ );
5300
+ }
5282
5301
  }
5283
5302
  render() {
5284
5303
  return this.state.error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement(
@@ -5297,7 +5316,7 @@ function RenderedRoute({ routeContext, match, children }) {
5297
5316
  }
5298
5317
  return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children);
5299
5318
  }
5300
- function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) {
5319
+ function _renderMatches(matches, parentMatches = [], dataRouterState = null, unstable_handleError = null, future = null) {
5301
5320
  if (matches == null) {
5302
5321
  if (!dataRouterState) {
5303
5322
  return null;
@@ -5409,7 +5428,8 @@ function _renderMatches(matches, parentMatches = [], dataRouterState = null, fut
5409
5428
  component: errorElement,
5410
5429
  error,
5411
5430
  children: getChildren(),
5412
- routeContext: { outlet: null, matches: matches2, isDataRoute: true }
5431
+ routeContext: { outlet: null, matches: matches2, isDataRoute: true },
5432
+ unstable_handleError
5413
5433
  }
5414
5434
  ) : getChildren();
5415
5435
  },
@@ -5675,7 +5695,8 @@ var Deferred = class {
5675
5695
  };
5676
5696
  function RouterProvider({
5677
5697
  router,
5678
- flushSync: reactDomFlushSyncImpl
5698
+ flushSync: reactDomFlushSyncImpl,
5699
+ unstable_handleError
5679
5700
  }) {
5680
5701
  let [state, setStateImpl] = React3.useState(router.state);
5681
5702
  let [pendingState, setPendingState] = React3.useState();
@@ -5686,6 +5707,21 @@ function RouterProvider({
5686
5707
  let [transition, setTransition] = React3.useState();
5687
5708
  let [interruption, setInterruption] = React3.useState();
5688
5709
  let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
5710
+ let logErrorsAndSetState = React3.useCallback(
5711
+ (newState) => {
5712
+ setStateImpl((prevState) => {
5713
+ if (newState.errors && unstable_handleError) {
5714
+ Object.entries(newState.errors).forEach(([routeId, error]) => {
5715
+ if (prevState.errors?.[routeId] !== error) {
5716
+ unstable_handleError(error);
5717
+ }
5718
+ });
5719
+ }
5720
+ return newState;
5721
+ });
5722
+ },
5723
+ [unstable_handleError]
5724
+ );
5689
5725
  let setState = React3.useCallback(
5690
5726
  (newState, { deletedFetchers, flushSync, viewTransitionOpts }) => {
5691
5727
  newState.fetchers.forEach((fetcher, key) => {
@@ -5705,9 +5741,9 @@ function RouterProvider({
5705
5741
  );
5706
5742
  if (!viewTransitionOpts || !isViewTransitionAvailable) {
5707
5743
  if (reactDomFlushSyncImpl && flushSync) {
5708
- reactDomFlushSyncImpl(() => setStateImpl(newState));
5744
+ reactDomFlushSyncImpl(() => logErrorsAndSetState(newState));
5709
5745
  } else {
5710
- React3.startTransition(() => setStateImpl(newState));
5746
+ React3.startTransition(() => logErrorsAndSetState(newState));
5711
5747
  }
5712
5748
  return;
5713
5749
  }
@@ -5725,7 +5761,7 @@ function RouterProvider({
5725
5761
  });
5726
5762
  });
5727
5763
  let t = router.window.document.startViewTransition(() => {
5728
- reactDomFlushSyncImpl(() => setStateImpl(newState));
5764
+ reactDomFlushSyncImpl(() => logErrorsAndSetState(newState));
5729
5765
  });
5730
5766
  t.finished.finally(() => {
5731
5767
  reactDomFlushSyncImpl(() => {
@@ -5756,7 +5792,13 @@ function RouterProvider({
5756
5792
  });
5757
5793
  }
5758
5794
  },
5759
- [router.window, reactDomFlushSyncImpl, transition, renderDfd]
5795
+ [
5796
+ router.window,
5797
+ reactDomFlushSyncImpl,
5798
+ transition,
5799
+ renderDfd,
5800
+ logErrorsAndSetState
5801
+ ]
5760
5802
  );
5761
5803
  React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
5762
5804
  React3.useEffect(() => {
@@ -5769,7 +5811,7 @@ function RouterProvider({
5769
5811
  let newState = pendingState;
5770
5812
  let renderPromise = renderDfd.promise;
5771
5813
  let transition2 = router.window.document.startViewTransition(async () => {
5772
- React3.startTransition(() => setStateImpl(newState));
5814
+ React3.startTransition(() => logErrorsAndSetState(newState));
5773
5815
  await renderPromise;
5774
5816
  });
5775
5817
  transition2.finished.finally(() => {
@@ -5780,7 +5822,7 @@ function RouterProvider({
5780
5822
  });
5781
5823
  setTransition(transition2);
5782
5824
  }
5783
- }, [pendingState, renderDfd, router.window]);
5825
+ }, [pendingState, renderDfd, router.window, logErrorsAndSetState]);
5784
5826
  React3.useEffect(() => {
5785
5827
  if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
5786
5828
  renderDfd.resolve();
@@ -5820,9 +5862,10 @@ function RouterProvider({
5820
5862
  router,
5821
5863
  navigator,
5822
5864
  static: false,
5823
- basename
5865
+ basename,
5866
+ unstable_handleError
5824
5867
  }),
5825
- [router, navigator, basename]
5868
+ [router, navigator, basename, unstable_handleError]
5826
5869
  );
5827
5870
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(ViewTransitionContext.Provider, { value: vtContext }, /* @__PURE__ */ React3.createElement(
5828
5871
  Router,
@@ -5837,7 +5880,8 @@ function RouterProvider({
5837
5880
  {
5838
5881
  routes: router.routes,
5839
5882
  future: router.future,
5840
- state
5883
+ state,
5884
+ unstable_handleError
5841
5885
  }
5842
5886
  )
5843
5887
  ))))), null);
@@ -5846,9 +5890,10 @@ var MemoizedDataRoutes = React3.memo(DataRoutes);
5846
5890
  function DataRoutes({
5847
5891
  routes,
5848
5892
  future,
5849
- state
5893
+ state,
5894
+ unstable_handleError
5850
5895
  }) {
5851
- return useRoutesImpl(routes, void 0, state, future);
5896
+ return useRoutesImpl(routes, void 0, state, unstable_handleError, future);
5852
5897
  }
5853
5898
  function MemoryRouter({
5854
5899
  basename,
@@ -5996,7 +6041,16 @@ function Await({
5996
6041
  errorElement,
5997
6042
  resolve
5998
6043
  }) {
5999
- return /* @__PURE__ */ React3.createElement(AwaitErrorBoundary, { resolve, errorElement }, /* @__PURE__ */ React3.createElement(ResolveAwait, null, children));
6044
+ let dataRouterContext = React3.useContext(DataRouterContext);
6045
+ return /* @__PURE__ */ React3.createElement(
6046
+ AwaitErrorBoundary,
6047
+ {
6048
+ resolve,
6049
+ errorElement,
6050
+ unstable_handleError: dataRouterContext?.unstable_handleError
6051
+ },
6052
+ /* @__PURE__ */ React3.createElement(ResolveAwait, null, children)
6053
+ );
6000
6054
  }
6001
6055
  var AwaitErrorBoundary = class extends React3.Component {
6002
6056
  constructor(props) {
@@ -6007,11 +6061,15 @@ var AwaitErrorBoundary = class extends React3.Component {
6007
6061
  return { error };
6008
6062
  }
6009
6063
  componentDidCatch(error, errorInfo) {
6010
- console.error(
6011
- "<Await> caught the following error during render",
6012
- error,
6013
- errorInfo
6014
- );
6064
+ if (this.props.unstable_handleError) {
6065
+ this.props.unstable_handleError(error, errorInfo);
6066
+ } else {
6067
+ console.error(
6068
+ "<Await> caught the following error during render",
6069
+ error,
6070
+ errorInfo
6071
+ );
6072
+ }
6015
6073
  }
6016
6074
  render() {
6017
6075
  let { children, errorElement, resolve } = this.props;
@@ -6037,7 +6095,10 @@ var AwaitErrorBoundary = class extends React3.Component {
6037
6095
  Object.defineProperty(resolve, "_tracked", { get: () => true });
6038
6096
  promise = resolve.then(
6039
6097
  (data2) => Object.defineProperty(resolve, "_data", { get: () => data2 }),
6040
- (error) => Object.defineProperty(resolve, "_error", { get: () => error })
6098
+ (error) => {
6099
+ this.props.unstable_handleError?.(error);
6100
+ Object.defineProperty(resolve, "_error", { get: () => error });
6101
+ }
6041
6102
  );
6042
6103
  }
6043
6104
  if (status === 2 /* error */ && !errorElement) {
@@ -8698,6 +8759,9 @@ function isValidMetaTag(tagName) {
8698
8759
  return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
8699
8760
  }
8700
8761
  var isHydrated = false;
8762
+ function setIsHydrated() {
8763
+ isHydrated = true;
8764
+ }
8701
8765
  function Scripts(scriptProps) {
8702
8766
  let {
8703
8767
  manifest,
@@ -8716,7 +8780,7 @@ function Scripts(scriptProps) {
8716
8780
  }
8717
8781
  let matches = getActiveMatches(routerMatches, null, isSpaMode);
8718
8782
  React8.useEffect(() => {
8719
- isHydrated = true;
8783
+ setIsHydrated();
8720
8784
  }, []);
8721
8785
  let initialScripts = React8.useMemo(() => {
8722
8786
  if (isRSCRouterContext) {
@@ -8972,7 +9036,7 @@ var isBrowser = typeof window !== "undefined" && typeof window.document !== "und
8972
9036
  try {
8973
9037
  if (isBrowser) {
8974
9038
  window.__reactRouterVersion = // @ts-expect-error
8975
- "0.0.0-experimental-28357fd2a";
9039
+ "0.0.0-experimental-2eb7164";
8976
9040
  }
8977
9041
  } catch (e) {
8978
9042
  }
@@ -9879,7 +9943,7 @@ function DataRoutes2({
9879
9943
  future,
9880
9944
  state
9881
9945
  }) {
9882
- return useRoutesImpl(routes, void 0, state, future);
9946
+ return useRoutesImpl(routes, void 0, state, void 0, future);
9883
9947
  }
9884
9948
  function serializeErrors(errors) {
9885
9949
  if (!errors) return null;
@@ -10171,6 +10235,7 @@ export {
10171
10235
  Links,
10172
10236
  PrefetchPageLinks,
10173
10237
  Meta,
10238
+ setIsHydrated,
10174
10239
  Scripts,
10175
10240
  createBrowserRouter,
10176
10241
  createHashRouter,