react-router 6.4.0-pre.8 → 6.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router v6.4.0-pre.8
2
+ * React Router v6.4.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { invariant, resolveTo, getToPathname, joinPaths, matchPath, warning, parsePath, matchRoutes, isRouteErrorResponse, createMemoryRouter, createMemoryHistory, stripBasename, Action } from '@remix-run/router';
12
- export { Action as NavigationType, createPath, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, resolvePath } from '@remix-run/router';
11
+ import { invariant, resolveTo, joinPaths, matchPath, warning, parsePath, matchRoutes, Action, isRouteErrorResponse, createMemoryHistory, stripBasename, AbortedDeferredError, createRouter } from '@remix-run/router';
12
+ export { AbortedDeferredError, Action as NavigationType, createPath, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, resolvePath } from '@remix-run/router';
13
13
  import * as React from 'react';
14
14
 
15
15
  /**
@@ -188,8 +188,13 @@ function useSyncExternalStore$1(subscribe, getSnapshot, getServerSnapshot) {
188
188
  const canUseDOM = !!(typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined");
189
189
  const isServerEnvironment = !canUseDOM;
190
190
  const shim = isServerEnvironment ? useSyncExternalStore$1 : useSyncExternalStore$2;
191
- const useSyncExternalStore = "useSyncExternalStore" in React ? // @ts-expect-error
192
- (module => module.useSyncExternalStore)(React) : shim;
191
+ const useSyncExternalStore = "useSyncExternalStore" in React ? (module => module.useSyncExternalStore)(React) : shim;
192
+
193
+ const DataStaticRouterContext = /*#__PURE__*/React.createContext(null);
194
+
195
+ {
196
+ DataStaticRouterContext.displayName = "DataStaticRouterContext";
197
+ }
193
198
 
194
199
  const DataRouterContext = /*#__PURE__*/React.createContext(null);
195
200
 
@@ -203,6 +208,12 @@ const DataRouterStateContext = /*#__PURE__*/React.createContext(null);
203
208
  DataRouterStateContext.displayName = "DataRouterState";
204
209
  }
205
210
 
211
+ const AwaitContext = /*#__PURE__*/React.createContext(null);
212
+
213
+ {
214
+ AwaitContext.displayName = "Await";
215
+ }
216
+
206
217
  const NavigationContext = /*#__PURE__*/React.createContext(null);
207
218
 
208
219
  {
@@ -237,7 +248,9 @@ const RouteErrorContext = /*#__PURE__*/React.createContext(null);
237
248
  * @see https://reactrouter.com/docs/en/v6/hooks/use-href
238
249
  */
239
250
 
240
- function useHref(to) {
251
+ function useHref(to, {
252
+ relative
253
+ } = {}) {
241
254
  !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
242
255
  // router loaded. We can help them understand how to avoid that.
243
256
  `useHref() may be used only in the context of a <Router> component.`) : void 0;
@@ -249,23 +262,16 @@ function useHref(to) {
249
262
  hash,
250
263
  pathname,
251
264
  search
252
- } = useResolvedPath(to);
253
- let joinedPathname = pathname;
265
+ } = useResolvedPath(to, {
266
+ relative
267
+ });
268
+ let joinedPathname = pathname; // If we're operating within a basename, prepend it to the pathname prior
269
+ // to creating the href. If this is a root navigation, then just use the raw
270
+ // basename which allows the basename to have full control over the presence
271
+ // of a trailing slash on root links
254
272
 
255
273
  if (basename !== "/") {
256
- let toPathname = getToPathname(to); // Only append a trailing slash to the raw basename if the basename doesn't
257
- // already have one and this wasn't specifically a route to "". This
258
- // allows folks to control the trailing slash behavior when using a basename
259
-
260
- let appendSlash = !basename.endsWith("/") && to !== "" && to?.pathname !== "" && toPathname != null && toPathname.endsWith("/");
261
-
262
- if (pathname !== "/") {
263
- joinedPathname = joinPaths([basename, pathname]);
264
- } else if (appendSlash) {
265
- joinedPathname = basename + "/";
266
- } else {
267
- joinedPathname = basename;
268
- }
274
+ joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
269
275
  }
270
276
 
271
277
  return navigator.createHref({
@@ -388,14 +394,13 @@ function useNavigate() {
388
394
  return;
389
395
  }
390
396
 
391
- let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
397
+ let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path"); // If we're operating within a basename, prepend it to the pathname prior
398
+ // to handing off to history. If this is a root navigation, then we
399
+ // navigate to the raw basename which allows the basename to have full
400
+ // control over the presence of a trailing slash on root links
392
401
 
393
402
  if (basename !== "/") {
394
- // If this was a blank path, just use the basename directly, this gives
395
- // the user control over trailing slash behavior
396
- let toPath = typeof to === "string" ? parsePath(to) : to;
397
- let isBlankPath = toPath.pathname == null || toPath.pathname === "";
398
- path.pathname = isBlankPath ? basename : joinPaths([basename, path.pathname]);
403
+ path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
399
404
  }
400
405
 
401
406
  (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
@@ -450,7 +455,9 @@ function useParams() {
450
455
  * @see https://reactrouter.com/docs/en/v6/hooks/use-resolved-path
451
456
  */
452
457
 
453
- function useResolvedPath(to) {
458
+ function useResolvedPath(to, {
459
+ relative
460
+ } = {}) {
454
461
  let {
455
462
  matches
456
463
  } = React.useContext(RouteContext);
@@ -458,7 +465,7 @@ function useResolvedPath(to) {
458
465
  pathname: locationPathname
459
466
  } = useLocation();
460
467
  let routePathnamesJson = JSON.stringify(getPathContributingMatches(matches).map(match => match.pathnameBase));
461
- return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
468
+ return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
462
469
  }
463
470
  /**
464
471
  * Returns the element of the route that matched the current location, prepared
@@ -530,16 +537,38 @@ function useRoutes(routes, locationArg) {
530
537
  warning(matches == null || matches[matches.length - 1].route.element !== undefined, `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element. ` + `This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`) ;
531
538
  }
532
539
 
533
- return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
540
+ let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
534
541
  params: Object.assign({}, parentParams, match.params),
535
542
  pathname: joinPaths([parentPathnameBase, match.pathname]),
536
543
  pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
537
- })), parentMatches, dataRouterStateContext || undefined);
544
+ })), parentMatches, dataRouterStateContext || undefined); // When a user passes in a `locationArg`, the associated routes need to
545
+ // be wrapped in a new `LocationContext.Provider` in order for `useLocation`
546
+ // to use the scoped location instead of the global location.
547
+
548
+
549
+ if (locationArg) {
550
+ return /*#__PURE__*/React.createElement(LocationContext.Provider, {
551
+ value: {
552
+ location: {
553
+ pathname: "/",
554
+ search: "",
555
+ hash: "",
556
+ state: null,
557
+ key: "default",
558
+ ...location
559
+ },
560
+ navigationType: Action.Pop
561
+ }
562
+ }, renderedMatches);
563
+ }
564
+
565
+ return renderedMatches;
538
566
  }
539
567
 
540
568
  function DefaultErrorElement() {
541
569
  let error = useRouteError();
542
- let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error?.message || JSON.stringify(error);
570
+ let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
571
+ let stack = error instanceof Error ? error.stack : null;
543
572
  let lightgrey = "rgba(200,200,200, 0.5)";
544
573
  let preStyles = {
545
574
  padding: "0.5rem",
@@ -553,9 +582,9 @@ function DefaultErrorElement() {
553
582
  style: {
554
583
  fontStyle: "italic"
555
584
  }
556
- }, message), error?.stack ? /*#__PURE__*/React.createElement("pre", {
585
+ }, message), stack ? /*#__PURE__*/React.createElement("pre", {
557
586
  style: preStyles
558
- }, error?.stack) : null, /*#__PURE__*/React.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/React.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own\u00A0", /*#__PURE__*/React.createElement("code", {
587
+ }, stack) : null, /*#__PURE__*/React.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/React.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own\u00A0", /*#__PURE__*/React.createElement("code", {
559
588
  style: codeStyles
560
589
  }, "errorElement"), " props on\u00A0", /*#__PURE__*/React.createElement("code", {
561
590
  style: codeStyles
@@ -615,6 +644,24 @@ class RenderErrorBoundary extends React.Component {
615
644
  }
616
645
 
617
646
  }
647
+
648
+ function RenderedRoute({
649
+ routeContext,
650
+ match,
651
+ children
652
+ }) {
653
+ let dataStaticRouterContext = React.useContext(DataStaticRouterContext); // Track how deep we got in our render pass to emulate SSR componentDidCatch
654
+ // in a DataStaticRouter
655
+
656
+ if (dataStaticRouterContext && match.route.errorElement) {
657
+ dataStaticRouterContext._deepestRenderedBoundaryId = match.route.id;
658
+ }
659
+
660
+ return /*#__PURE__*/React.createElement(RouteContext.Provider, {
661
+ value: routeContext
662
+ }, children);
663
+ }
664
+
618
665
  function _renderMatches(matches, parentMatches = [], dataRouterState) {
619
666
  if (matches == null) {
620
667
  if (dataRouterState?.errors) {
@@ -641,13 +688,13 @@ function _renderMatches(matches, parentMatches = [], dataRouterState) {
641
688
 
642
689
  let errorElement = dataRouterState ? match.route.errorElement || /*#__PURE__*/React.createElement(DefaultErrorElement, null) : null;
643
690
 
644
- let getChildren = () => /*#__PURE__*/React.createElement(RouteContext.Provider, {
645
- children: error ? errorElement : match.route.element !== undefined ? match.route.element : outlet,
646
- value: {
691
+ let getChildren = () => /*#__PURE__*/React.createElement(RenderedRoute, {
692
+ match: match,
693
+ routeContext: {
647
694
  outlet,
648
695
  matches: parentMatches.concat(renderedMatches.slice(0, index + 1))
649
696
  }
650
- }); // Only wrap in an error boundary within data router usages when we have an
697
+ }, error ? errorElement : match.route.element !== undefined ? match.route.element : outlet); // Only wrap in an error boundary within data router usages when we have an
651
698
  // errorElement on this route. Otherwise let it bubble up to an ancestor
652
699
  // errorElement
653
700
 
@@ -674,7 +721,7 @@ var DataRouterHook;
674
721
 
675
722
  function useDataRouterState(hookName) {
676
723
  let state = React.useContext(DataRouterStateContext);
677
- !state ? invariant(false, `${hookName} must be used within a DataRouter`) : void 0;
724
+ !state ? invariant(false, `${hookName} must be used within a DataRouterStateContext`) : void 0;
678
725
  return state;
679
726
  }
680
727
  /**
@@ -693,11 +740,11 @@ function useNavigation() {
693
740
  */
694
741
 
695
742
  function useRevalidator() {
696
- let router = React.useContext(DataRouterContext);
697
- !router ? invariant(false, `useRevalidator must be used within a DataRouter`) : void 0;
743
+ let dataRouterContext = React.useContext(DataRouterContext);
744
+ !dataRouterContext ? invariant(false, `useRevalidator must be used within a DataRouterContext`) : void 0;
698
745
  let state = useDataRouterState(DataRouterHook.UseRevalidator);
699
746
  return {
700
- revalidate: router.revalidate,
747
+ revalidate: dataRouterContext.router.revalidate,
701
748
  state: state.revalidation
702
749
  };
703
750
  }
@@ -715,7 +762,10 @@ function useMatches() {
715
762
  let {
716
763
  pathname,
717
764
  params
718
- } = match;
765
+ } = match; // Note: This structure matches that created by createUseMatchesMatch
766
+ // in the @remix-run/router , so if you change this please also change
767
+ // that :) Eventually we'll DRY this up
768
+
719
769
  return {
720
770
  id: match.route.id,
721
771
  pathname,
@@ -777,6 +827,22 @@ function useRouteError() {
777
827
 
778
828
  return state.errors?.[thisRoute.route.id];
779
829
  }
830
+ /**
831
+ * Returns the happy-path data from the nearest ancestor <Await /> value
832
+ */
833
+
834
+ function useAsyncValue() {
835
+ let value = React.useContext(AwaitContext);
836
+ return value?._data;
837
+ }
838
+ /**
839
+ * Returns the error from the nearest ancestor <Await /> value
840
+ */
841
+
842
+ function useAsyncError() {
843
+ let value = React.useContext(AwaitContext);
844
+ return value?._error;
845
+ }
780
846
  const alreadyWarned = {};
781
847
 
782
848
  function warningOnce(key, cond, message) {
@@ -786,80 +852,51 @@ function warningOnce(key, cond, message) {
786
852
  }
787
853
  }
788
854
 
789
- // to avoid issues w.r.t. dual initialization fetches in concurrent rendering.
790
- // Data router apps are expected to have a static route tree and are not intended
791
- // to be unmounted/remounted at runtime.
792
-
793
- let routerSingleton;
794
855
  /**
795
- * @private
856
+ * Given a Remix Router instance, render the appropriate UI
796
857
  */
797
858
 
798
- function useRenderDataRouter({
799
- children,
859
+ function RouterProvider({
800
860
  fallbackElement,
801
- routes,
802
- createRouter
861
+ router
803
862
  }) {
804
- if (!routerSingleton) {
805
- routerSingleton = createRouter(routes || createRoutesFromChildren(children)).initialize();
806
- }
807
-
808
- let router = routerSingleton; // Sync router state to our component state to force re-renders
809
-
810
- let state = useSyncExternalStore(router.subscribe, () => router.state);
863
+ // Sync router state to our component state to force re-renders
864
+ let state = useSyncExternalStore(router.subscribe, () => router.state, // We have to provide this so React@18 doesn't complain during hydration,
865
+ // but we pass our serialized hydration data into the router so state here
866
+ // is already synced with what the server saw
867
+ () => router.state);
811
868
  let navigator = React.useMemo(() => {
812
869
  return {
813
870
  createHref: router.createHref,
814
871
  go: n => router.navigate(n),
815
872
  push: (to, state, opts) => router.navigate(to, {
816
873
  state,
817
- resetScroll: opts?.resetScroll
874
+ preventScrollReset: opts?.preventScrollReset
818
875
  }),
819
876
  replace: (to, state, opts) => router.navigate(to, {
820
877
  replace: true,
821
878
  state,
822
- resetScroll: opts?.resetScroll
879
+ preventScrollReset: opts?.preventScrollReset
823
880
  })
824
881
  };
825
882
  }, [router]);
826
-
827
- if (!state.initialized) {
828
- return /*#__PURE__*/React.createElement(React.Fragment, null, fallbackElement);
829
- }
830
-
883
+ let basename = router.basename || "/";
831
884
  return /*#__PURE__*/React.createElement(DataRouterContext.Provider, {
832
- value: router
885
+ value: {
886
+ router,
887
+ navigator,
888
+ static: false,
889
+ // Do we need this?
890
+ basename
891
+ }
833
892
  }, /*#__PURE__*/React.createElement(DataRouterStateContext.Provider, {
834
893
  value: state
835
894
  }, /*#__PURE__*/React.createElement(Router, {
836
- location: state.location,
837
- navigationType: state.historyAction,
895
+ basename: router.basename,
896
+ location: router.state.location,
897
+ navigationType: router.state.historyAction,
838
898
  navigator: navigator
839
- }, /*#__PURE__*/React.createElement(DataRoutes, {
840
- routes: routes,
841
- children: children
842
- }))));
843
- }
844
- function DataMemoryRouter({
845
- children,
846
- initialEntries,
847
- initialIndex,
848
- hydrationData,
849
- fallbackElement,
850
- routes
851
- }) {
852
- return useRenderDataRouter({
853
- children,
854
- fallbackElement,
855
- routes,
856
- createRouter: routes => createMemoryRouter({
857
- initialEntries,
858
- initialIndex,
859
- routes,
860
- hydrationData
861
- })
862
- });
899
+ }, router.state.initialized ? /*#__PURE__*/React.createElement(Routes, null) : fallbackElement)));
863
900
  }
864
901
  /**
865
902
  * A <Router> that stores all entries in memory.
@@ -910,17 +947,27 @@ function MemoryRouter({
910
947
  function Navigate({
911
948
  to,
912
949
  replace,
913
- state
950
+ state,
951
+ relative
914
952
  }) {
915
953
  !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
916
954
  // the router loaded. We can help them understand how to avoid that.
917
955
  `<Navigate> may be used only in the context of a <Router> component.`) : void 0;
918
956
  warning(!React.useContext(NavigationContext).static, `<Navigate> must not be used on the initial render in a <StaticRouter>. ` + `This is a no-op, but you should modify your code so the <Navigate> is ` + `only ever rendered in response to some user interaction or state change.`) ;
957
+ let dataRouterState = React.useContext(DataRouterStateContext);
919
958
  let navigate = useNavigate();
920
959
  React.useEffect(() => {
960
+ // Avoid kicking off multiple navigations if we're in the middle of a
961
+ // data-router navigation, since components get re-rendered when we enter
962
+ // a submitting/loading state
963
+ if (dataRouterState && dataRouterState.navigation.state !== "idle") {
964
+ return;
965
+ }
966
+
921
967
  navigate(to, {
922
968
  replace,
923
- state
969
+ state,
970
+ relative
924
971
  });
925
972
  });
926
973
  return null;
@@ -1024,21 +1071,151 @@ function Routes({
1024
1071
  children,
1025
1072
  location
1026
1073
  }) {
1027
- return useRoutes(createRoutesFromChildren(children), location);
1074
+ let dataRouterContext = React.useContext(DataRouterContext); // When in a DataRouterContext _without_ children, we use the router routes
1075
+ // directly. If we have children, then we're in a descendant tree and we
1076
+ // need to use child routes.
1077
+
1078
+ let routes = dataRouterContext && !children ? dataRouterContext.router.routes : createRoutesFromChildren(children);
1079
+ return useRoutes(routes, location);
1028
1080
  }
1029
1081
  /**
1030
- * @private
1031
- * Used as an extension to <Routes> and accepts a manual `routes` array to be
1032
- * instead of using JSX children. Extracted to it's own component to avoid
1033
- * conditional usage of `useRoutes` if we have to render a `fallbackElement`
1082
+ * Component to use for rendering lazily loaded data from returning defer()
1083
+ * in a loader function
1034
1084
  */
1035
1085
 
1036
- function DataRoutes({
1086
+ function Await({
1037
1087
  children,
1038
- location,
1039
- routes
1088
+ errorElement,
1089
+ resolve
1040
1090
  }) {
1041
- return useRoutes(routes || createRoutesFromChildren(children), location);
1091
+ return /*#__PURE__*/React.createElement(AwaitErrorBoundary, {
1092
+ resolve: resolve,
1093
+ errorElement: errorElement
1094
+ }, /*#__PURE__*/React.createElement(ResolveAwait, null, children));
1095
+ }
1096
+ var AwaitRenderStatus;
1097
+
1098
+ (function (AwaitRenderStatus) {
1099
+ AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
1100
+ AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
1101
+ AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
1102
+ })(AwaitRenderStatus || (AwaitRenderStatus = {}));
1103
+
1104
+ const neverSettledPromise = new Promise(() => {});
1105
+
1106
+ class AwaitErrorBoundary extends React.Component {
1107
+ constructor(props) {
1108
+ super(props);
1109
+ this.state = {
1110
+ error: null
1111
+ };
1112
+ }
1113
+
1114
+ static getDerivedStateFromError(error) {
1115
+ return {
1116
+ error
1117
+ };
1118
+ }
1119
+
1120
+ componentDidCatch(error, errorInfo) {
1121
+ console.error("<Await> caught the following error during render", error, errorInfo);
1122
+ }
1123
+
1124
+ render() {
1125
+ let {
1126
+ children,
1127
+ errorElement,
1128
+ resolve
1129
+ } = this.props;
1130
+ let promise = null;
1131
+ let status = AwaitRenderStatus.pending;
1132
+
1133
+ if (!(resolve instanceof Promise)) {
1134
+ // Didn't get a promise - provide as a resolved promise
1135
+ status = AwaitRenderStatus.success;
1136
+ promise = Promise.resolve();
1137
+ Object.defineProperty(promise, "_tracked", {
1138
+ get: () => true
1139
+ });
1140
+ Object.defineProperty(promise, "_data", {
1141
+ get: () => resolve
1142
+ });
1143
+ } else if (this.state.error) {
1144
+ // Caught a render error, provide it as a rejected promise
1145
+ status = AwaitRenderStatus.error;
1146
+ let renderError = this.state.error;
1147
+ promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
1148
+
1149
+ Object.defineProperty(promise, "_tracked", {
1150
+ get: () => true
1151
+ });
1152
+ Object.defineProperty(promise, "_error", {
1153
+ get: () => renderError
1154
+ });
1155
+ } else if (resolve._tracked) {
1156
+ // Already tracked promise - check contents
1157
+ promise = resolve;
1158
+ status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
1159
+ } else {
1160
+ // Raw (untracked) promise - track it
1161
+ status = AwaitRenderStatus.pending;
1162
+ Object.defineProperty(resolve, "_tracked", {
1163
+ get: () => true
1164
+ });
1165
+ promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
1166
+ get: () => data
1167
+ }), error => Object.defineProperty(resolve, "_error", {
1168
+ get: () => error
1169
+ }));
1170
+ }
1171
+
1172
+ if (status === AwaitRenderStatus.error && promise._error instanceof AbortedDeferredError) {
1173
+ // Freeze the UI by throwing a never resolved promise
1174
+ throw neverSettledPromise;
1175
+ }
1176
+
1177
+ if (status === AwaitRenderStatus.error && !errorElement) {
1178
+ // No errorElement, throw to the nearest route-level error boundary
1179
+ throw promise._error;
1180
+ }
1181
+
1182
+ if (status === AwaitRenderStatus.error) {
1183
+ // Render via our errorElement
1184
+ return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1185
+ value: promise,
1186
+ children: errorElement
1187
+ });
1188
+ }
1189
+
1190
+ if (status === AwaitRenderStatus.success) {
1191
+ // Render children with resolved value
1192
+ return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1193
+ value: promise,
1194
+ children: children
1195
+ });
1196
+ } // Throw to the suspense boundary
1197
+
1198
+
1199
+ throw promise;
1200
+ }
1201
+
1202
+ }
1203
+ /**
1204
+ * @private
1205
+ * Indirection to leverage useAsyncValue for a render-prop API on <Await>
1206
+ */
1207
+
1208
+
1209
+ function ResolveAwait({
1210
+ children
1211
+ }) {
1212
+ let data = useAsyncValue();
1213
+
1214
+ if (typeof children === "function") {
1215
+ return children(data);
1216
+ }
1217
+
1218
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
1042
1219
  } ///////////////////////////////////////////////////////////////////////////////
1043
1220
  // UTILS
1044
1221
  ///////////////////////////////////////////////////////////////////////////////
@@ -1078,6 +1255,7 @@ function createRoutesFromChildren(children, parentPath = []) {
1078
1255
  loader: element.props.loader,
1079
1256
  action: element.props.action,
1080
1257
  errorElement: element.props.errorElement,
1258
+ hasErrorBoundary: element.props.errorElement != null,
1081
1259
  shouldRevalidate: element.props.shouldRevalidate,
1082
1260
  handle: element.props.handle
1083
1261
  };
@@ -1097,6 +1275,40 @@ function createRoutesFromChildren(children, parentPath = []) {
1097
1275
  function renderMatches(matches) {
1098
1276
  return _renderMatches(matches);
1099
1277
  }
1278
+ /**
1279
+ * @private
1280
+ * Walk the route tree and add hasErrorBoundary if it's not provided, so that
1281
+ * users providing manual route arrays can just specify errorElement
1282
+ */
1283
+
1284
+ function enhanceManualRouteObjects(routes) {
1285
+ return routes.map(route => {
1286
+ let routeClone = { ...route
1287
+ };
1288
+
1289
+ if (routeClone.hasErrorBoundary == null) {
1290
+ routeClone.hasErrorBoundary = routeClone.errorElement != null;
1291
+ }
1292
+
1293
+ if (routeClone.children) {
1294
+ routeClone.children = enhanceManualRouteObjects(routeClone.children);
1295
+ }
1296
+
1297
+ return routeClone;
1298
+ });
1299
+ }
1300
+
1301
+ function createMemoryRouter(routes, opts) {
1302
+ return createRouter({
1303
+ basename: opts?.basename,
1304
+ history: createMemoryHistory({
1305
+ initialEntries: opts?.initialEntries,
1306
+ initialIndex: opts?.initialIndex
1307
+ }),
1308
+ hydrationData: opts?.hydrationData,
1309
+ routes: enhanceManualRouteObjects(routes)
1310
+ }).initialize();
1311
+ } ///////////////////////////////////////////////////////////////////////////////
1100
1312
 
1101
- export { DataMemoryRouter, MemoryRouter, Navigate, Outlet, Route, Router, Routes, DataRouterContext as UNSAFE_DataRouterContext, DataRouterStateContext as UNSAFE_DataRouterStateContext, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, createRoutesFromChildren, renderMatches, useActionData, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useRenderDataRouter, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes };
1313
+ export { Await, MemoryRouter, Navigate, Outlet, Route, Router, RouterProvider, Routes, DataRouterContext as UNSAFE_DataRouterContext, DataRouterStateContext as UNSAFE_DataRouterStateContext, DataStaticRouterContext as UNSAFE_DataStaticRouterContext, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, enhanceManualRouteObjects as UNSAFE_enhanceManualRouteObjects, createMemoryRouter, createRoutesFromChildren, createRoutesFromChildren as createRoutesFromElements, renderMatches, useActionData, useAsyncError, useAsyncValue, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes };
1102
1314
  //# sourceMappingURL=react-router.development.js.map