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.
package/dist/index.js CHANGED
@@ -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,10 +8,27 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { invariant, resolveTo, getToPathname, joinPaths, matchPath, warning, parsePath, matchRoutes, isRouteErrorResponse, createMemoryHistory, Action, stripBasename, createMemoryRouter } 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
+ function _extends() {
16
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
17
+ for (var i = 1; i < arguments.length; i++) {
18
+ var source = arguments[i];
19
+
20
+ for (var key in source) {
21
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
22
+ target[key] = source[key];
23
+ }
24
+ }
25
+ }
26
+
27
+ return target;
28
+ };
29
+ return _extends.apply(this, arguments);
30
+ }
31
+
15
32
  /**
16
33
  * Copyright (c) Facebook, Inc. and its affiliates.
17
34
  *
@@ -188,10 +205,15 @@ function useSyncExternalStore$1(subscribe, getSnapshot, getServerSnapshot) {
188
205
  const canUseDOM = !!(typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined");
189
206
  const isServerEnvironment = !canUseDOM;
190
207
  const shim = isServerEnvironment ? useSyncExternalStore$1 : useSyncExternalStore$2;
191
- const useSyncExternalStore = "useSyncExternalStore" in React ? // @ts-expect-error
192
- (module => module.useSyncExternalStore)(React) : shim;
208
+ const useSyncExternalStore = "useSyncExternalStore" in React ? (module => module.useSyncExternalStore)(React) : shim;
193
209
 
194
210
  // Contexts for data routers
211
+ const DataStaticRouterContext = /*#__PURE__*/React.createContext(null);
212
+
213
+ if (process.env.NODE_ENV !== "production") {
214
+ DataStaticRouterContext.displayName = "DataStaticRouterContext";
215
+ }
216
+
195
217
  const DataRouterContext = /*#__PURE__*/React.createContext(null);
196
218
 
197
219
  if (process.env.NODE_ENV !== "production") {
@@ -204,6 +226,12 @@ if (process.env.NODE_ENV !== "production") {
204
226
  DataRouterStateContext.displayName = "DataRouterState";
205
227
  }
206
228
 
229
+ const AwaitContext = /*#__PURE__*/React.createContext(null);
230
+
231
+ if (process.env.NODE_ENV !== "production") {
232
+ AwaitContext.displayName = "Await";
233
+ }
234
+
207
235
  const NavigationContext = /*#__PURE__*/React.createContext(null);
208
236
 
209
237
  if (process.env.NODE_ENV !== "production") {
@@ -238,7 +266,10 @@ if (process.env.NODE_ENV !== "production") {
238
266
  * @see https://reactrouter.com/docs/en/v6/hooks/use-href
239
267
  */
240
268
 
241
- function useHref(to) {
269
+ function useHref(to, _temp) {
270
+ let {
271
+ relative
272
+ } = _temp === void 0 ? {} : _temp;
242
273
  !useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
243
274
  // router loaded. We can help them understand how to avoid that.
244
275
  "useHref() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
@@ -250,23 +281,16 @@ function useHref(to) {
250
281
  hash,
251
282
  pathname,
252
283
  search
253
- } = useResolvedPath(to);
254
- let joinedPathname = pathname;
284
+ } = useResolvedPath(to, {
285
+ relative
286
+ });
287
+ let joinedPathname = pathname; // If we're operating within a basename, prepend it to the pathname prior
288
+ // to creating the href. If this is a root navigation, then just use the raw
289
+ // basename which allows the basename to have full control over the presence
290
+ // of a trailing slash on root links
255
291
 
256
292
  if (basename !== "/") {
257
- let toPathname = getToPathname(to); // Only append a trailing slash to the raw basename if the basename doesn't
258
- // already have one and this wasn't specifically a route to "". This
259
- // allows folks to control the trailing slash behavior when using a basename
260
-
261
- let appendSlash = !basename.endsWith("/") && to !== "" && (to == null ? void 0 : to.pathname) !== "" && toPathname != null && toPathname.endsWith("/");
262
-
263
- if (pathname !== "/") {
264
- joinedPathname = joinPaths([basename, pathname]);
265
- } else if (appendSlash) {
266
- joinedPathname = basename + "/";
267
- } else {
268
- joinedPathname = basename;
269
- }
293
+ joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
270
294
  }
271
295
 
272
296
  return navigator.createHref({
@@ -396,14 +420,13 @@ function useNavigate() {
396
420
  return;
397
421
  }
398
422
 
399
- let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
423
+ let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path"); // If we're operating within a basename, prepend it to the pathname prior
424
+ // to handing off to history. If this is a root navigation, then we
425
+ // navigate to the raw basename which allows the basename to have full
426
+ // control over the presence of a trailing slash on root links
400
427
 
401
428
  if (basename !== "/") {
402
- // If this was a blank path, just use the basename directly, this gives
403
- // the user control over trailing slash behavior
404
- let toPath = typeof to === "string" ? parsePath(to) : to;
405
- let isBlankPath = toPath.pathname == null || toPath.pathname === "";
406
- path.pathname = isBlankPath ? basename : joinPaths([basename, path.pathname]);
429
+ path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
407
430
  }
408
431
 
409
432
  (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
@@ -458,7 +481,10 @@ function useParams() {
458
481
  * @see https://reactrouter.com/docs/en/v6/hooks/use-resolved-path
459
482
  */
460
483
 
461
- function useResolvedPath(to) {
484
+ function useResolvedPath(to, _temp2) {
485
+ let {
486
+ relative
487
+ } = _temp2 === void 0 ? {} : _temp2;
462
488
  let {
463
489
  matches
464
490
  } = React.useContext(RouteContext);
@@ -466,7 +492,7 @@ function useResolvedPath(to) {
466
492
  pathname: locationPathname
467
493
  } = useLocation();
468
494
  let routePathnamesJson = JSON.stringify(getPathContributingMatches(matches).map(match => match.pathnameBase));
469
- return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
495
+ return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
470
496
  }
471
497
  /**
472
498
  * Returns the element of the route that matched the current location, prepared
@@ -540,16 +566,37 @@ function useRoutes(routes, locationArg) {
540
566
  process.env.NODE_ENV !== "production" ? 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.") : void 0;
541
567
  }
542
568
 
543
- return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
569
+ let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
544
570
  params: Object.assign({}, parentParams, match.params),
545
571
  pathname: joinPaths([parentPathnameBase, match.pathname]),
546
572
  pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
547
- })), parentMatches, dataRouterStateContext || undefined);
573
+ })), parentMatches, dataRouterStateContext || undefined); // When a user passes in a `locationArg`, the associated routes need to
574
+ // be wrapped in a new `LocationContext.Provider` in order for `useLocation`
575
+ // to use the scoped location instead of the global location.
576
+
577
+
578
+ if (locationArg) {
579
+ return /*#__PURE__*/React.createElement(LocationContext.Provider, {
580
+ value: {
581
+ location: _extends({
582
+ pathname: "/",
583
+ search: "",
584
+ hash: "",
585
+ state: null,
586
+ key: "default"
587
+ }, location),
588
+ navigationType: Action.Pop
589
+ }
590
+ }, renderedMatches);
591
+ }
592
+
593
+ return renderedMatches;
548
594
  }
549
595
 
550
596
  function DefaultErrorElement() {
551
597
  let error = useRouteError();
552
- let message = isRouteErrorResponse(error) ? error.status + " " + error.statusText : (error == null ? void 0 : error.message) || JSON.stringify(error);
598
+ let message = isRouteErrorResponse(error) ? error.status + " " + error.statusText : error instanceof Error ? error.message : JSON.stringify(error);
599
+ let stack = error instanceof Error ? error.stack : null;
553
600
  let lightgrey = "rgba(200,200,200, 0.5)";
554
601
  let preStyles = {
555
602
  padding: "0.5rem",
@@ -563,9 +610,9 @@ function DefaultErrorElement() {
563
610
  style: {
564
611
  fontStyle: "italic"
565
612
  }
566
- }, message), error != null && error.stack ? /*#__PURE__*/React.createElement("pre", {
613
+ }, message), stack ? /*#__PURE__*/React.createElement("pre", {
567
614
  style: preStyles
568
- }, error == null ? void 0 : 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\xA0", /*#__PURE__*/React.createElement("code", {
615
+ }, 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\xA0", /*#__PURE__*/React.createElement("code", {
569
616
  style: codeStyles
570
617
  }, "errorElement"), " props on\xA0", /*#__PURE__*/React.createElement("code", {
571
618
  style: codeStyles
@@ -625,6 +672,25 @@ class RenderErrorBoundary extends React.Component {
625
672
  }
626
673
 
627
674
  }
675
+
676
+ function RenderedRoute(_ref) {
677
+ let {
678
+ routeContext,
679
+ match,
680
+ children
681
+ } = _ref;
682
+ let dataStaticRouterContext = React.useContext(DataStaticRouterContext); // Track how deep we got in our render pass to emulate SSR componentDidCatch
683
+ // in a DataStaticRouter
684
+
685
+ if (dataStaticRouterContext && match.route.errorElement) {
686
+ dataStaticRouterContext._deepestRenderedBoundaryId = match.route.id;
687
+ }
688
+
689
+ return /*#__PURE__*/React.createElement(RouteContext.Provider, {
690
+ value: routeContext
691
+ }, children);
692
+ }
693
+
628
694
  function _renderMatches(matches, parentMatches, dataRouterState) {
629
695
  if (parentMatches === void 0) {
630
696
  parentMatches = [];
@@ -655,13 +721,13 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
655
721
 
656
722
  let errorElement = dataRouterState ? match.route.errorElement || /*#__PURE__*/React.createElement(DefaultErrorElement, null) : null;
657
723
 
658
- let getChildren = () => /*#__PURE__*/React.createElement(RouteContext.Provider, {
659
- children: error ? errorElement : match.route.element !== undefined ? match.route.element : outlet,
660
- value: {
724
+ let getChildren = () => /*#__PURE__*/React.createElement(RenderedRoute, {
725
+ match: match,
726
+ routeContext: {
661
727
  outlet,
662
728
  matches: parentMatches.concat(renderedMatches.slice(0, index + 1))
663
729
  }
664
- }); // Only wrap in an error boundary within data router usages when we have an
730
+ }, error ? errorElement : match.route.element !== undefined ? match.route.element : outlet); // Only wrap in an error boundary within data router usages when we have an
665
731
  // errorElement on this route. Otherwise let it bubble up to an ancestor
666
732
  // errorElement
667
733
 
@@ -688,7 +754,7 @@ var DataRouterHook;
688
754
 
689
755
  function useDataRouterState(hookName) {
690
756
  let state = React.useContext(DataRouterStateContext);
691
- !state ? process.env.NODE_ENV !== "production" ? invariant(false, hookName + " must be used within a DataRouter") : invariant(false) : void 0;
757
+ !state ? process.env.NODE_ENV !== "production" ? invariant(false, hookName + " must be used within a DataRouterStateContext") : invariant(false) : void 0;
692
758
  return state;
693
759
  }
694
760
  /**
@@ -707,11 +773,11 @@ function useNavigation() {
707
773
  */
708
774
 
709
775
  function useRevalidator() {
710
- let router = React.useContext(DataRouterContext);
711
- !router ? process.env.NODE_ENV !== "production" ? invariant(false, "useRevalidator must be used within a DataRouter") : invariant(false) : void 0;
776
+ let dataRouterContext = React.useContext(DataRouterContext);
777
+ !dataRouterContext ? process.env.NODE_ENV !== "production" ? invariant(false, "useRevalidator must be used within a DataRouterContext") : invariant(false) : void 0;
712
778
  let state = useDataRouterState(DataRouterHook.UseRevalidator);
713
779
  return {
714
- revalidate: router.revalidate,
780
+ revalidate: dataRouterContext.router.revalidate,
715
781
  state: state.revalidation
716
782
  };
717
783
  }
@@ -729,7 +795,10 @@ function useMatches() {
729
795
  let {
730
796
  pathname,
731
797
  params
732
- } = match;
798
+ } = match; // Note: This structure matches that created by createUseMatchesMatch
799
+ // in the @remix-run/router , so if you change this please also change
800
+ // that :) Eventually we'll DRY this up
801
+
733
802
  return {
734
803
  id: match.route.id,
735
804
  pathname,
@@ -793,6 +862,22 @@ function useRouteError() {
793
862
 
794
863
  return (_state$errors = state.errors) == null ? void 0 : _state$errors[thisRoute.route.id];
795
864
  }
865
+ /**
866
+ * Returns the happy-path data from the nearest ancestor <Await /> value
867
+ */
868
+
869
+ function useAsyncValue() {
870
+ let value = React.useContext(AwaitContext);
871
+ return value == null ? void 0 : value._data;
872
+ }
873
+ /**
874
+ * Returns the error from the nearest ancestor <Await /> value
875
+ */
876
+
877
+ function useAsyncError() {
878
+ let value = React.useContext(AwaitContext);
879
+ return value == null ? void 0 : value._error;
880
+ }
796
881
  const alreadyWarned = {};
797
882
 
798
883
  function warningOnce(key, cond, message) {
@@ -802,83 +887,51 @@ function warningOnce(key, cond, message) {
802
887
  }
803
888
  }
804
889
 
805
- // to avoid issues w.r.t. dual initialization fetches in concurrent rendering.
806
- // Data router apps are expected to have a static route tree and are not intended
807
- // to be unmounted/remounted at runtime.
808
-
809
- let routerSingleton;
810
890
  /**
811
- * @private
891
+ * Given a Remix Router instance, render the appropriate UI
812
892
  */
813
-
814
- function useRenderDataRouter(_ref) {
893
+ function RouterProvider(_ref) {
815
894
  let {
816
- children,
817
895
  fallbackElement,
818
- routes,
819
- createRouter
896
+ router
820
897
  } = _ref;
821
-
822
- if (!routerSingleton) {
823
- routerSingleton = createRouter(routes || createRoutesFromChildren(children)).initialize();
824
- }
825
-
826
- let router = routerSingleton; // Sync router state to our component state to force re-renders
827
-
828
- let state = useSyncExternalStore(router.subscribe, () => router.state);
898
+ // Sync router state to our component state to force re-renders
899
+ let state = useSyncExternalStore(router.subscribe, () => router.state, // We have to provide this so React@18 doesn't complain during hydration,
900
+ // but we pass our serialized hydration data into the router so state here
901
+ // is already synced with what the server saw
902
+ () => router.state);
829
903
  let navigator = React.useMemo(() => {
830
904
  return {
831
905
  createHref: router.createHref,
832
906
  go: n => router.navigate(n),
833
907
  push: (to, state, opts) => router.navigate(to, {
834
908
  state,
835
- resetScroll: opts == null ? void 0 : opts.resetScroll
909
+ preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
836
910
  }),
837
911
  replace: (to, state, opts) => router.navigate(to, {
838
912
  replace: true,
839
913
  state,
840
- resetScroll: opts == null ? void 0 : opts.resetScroll
914
+ preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
841
915
  })
842
916
  };
843
917
  }, [router]);
844
-
845
- if (!state.initialized) {
846
- return /*#__PURE__*/React.createElement(React.Fragment, null, fallbackElement);
847
- }
848
-
918
+ let basename = router.basename || "/";
849
919
  return /*#__PURE__*/React.createElement(DataRouterContext.Provider, {
850
- value: router
920
+ value: {
921
+ router,
922
+ navigator,
923
+ static: false,
924
+ // Do we need this?
925
+ basename
926
+ }
851
927
  }, /*#__PURE__*/React.createElement(DataRouterStateContext.Provider, {
852
928
  value: state
853
929
  }, /*#__PURE__*/React.createElement(Router, {
854
- location: state.location,
855
- navigationType: state.historyAction,
930
+ basename: router.basename,
931
+ location: router.state.location,
932
+ navigationType: router.state.historyAction,
856
933
  navigator: navigator
857
- }, /*#__PURE__*/React.createElement(DataRoutes, {
858
- routes: routes,
859
- children: children
860
- }))));
861
- }
862
- function DataMemoryRouter(_ref2) {
863
- let {
864
- children,
865
- initialEntries,
866
- initialIndex,
867
- hydrationData,
868
- fallbackElement,
869
- routes
870
- } = _ref2;
871
- return useRenderDataRouter({
872
- children,
873
- fallbackElement,
874
- routes,
875
- createRouter: routes => createMemoryRouter({
876
- initialEntries,
877
- initialIndex,
878
- routes,
879
- hydrationData
880
- })
881
- });
934
+ }, router.state.initialized ? /*#__PURE__*/React.createElement(Routes, null) : fallbackElement)));
882
935
  }
883
936
 
884
937
  /**
@@ -886,13 +939,13 @@ function DataMemoryRouter(_ref2) {
886
939
  *
887
940
  * @see https://reactrouter.com/docs/en/v6/routers/memory-router
888
941
  */
889
- function MemoryRouter(_ref3) {
942
+ function MemoryRouter(_ref2) {
890
943
  let {
891
944
  basename,
892
945
  children,
893
946
  initialEntries,
894
947
  initialIndex
895
- } = _ref3;
948
+ } = _ref2;
896
949
  let historyRef = React.useRef();
897
950
 
898
951
  if (historyRef.current == null) {
@@ -927,21 +980,31 @@ function MemoryRouter(_ref3) {
927
980
  *
928
981
  * @see https://reactrouter.com/docs/en/v6/components/navigate
929
982
  */
930
- function Navigate(_ref4) {
983
+ function Navigate(_ref3) {
931
984
  let {
932
985
  to,
933
986
  replace,
934
- state
935
- } = _ref4;
987
+ state,
988
+ relative
989
+ } = _ref3;
936
990
  !useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
937
991
  // the router loaded. We can help them understand how to avoid that.
938
992
  "<Navigate> may be used only in the context of a <Router> component.") : invariant(false) : void 0;
939
993
  process.env.NODE_ENV !== "production" ? 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.") : void 0;
994
+ let dataRouterState = React.useContext(DataRouterStateContext);
940
995
  let navigate = useNavigate();
941
996
  React.useEffect(() => {
997
+ // Avoid kicking off multiple navigations if we're in the middle of a
998
+ // data-router navigation, since components get re-rendered when we enter
999
+ // a submitting/loading state
1000
+ if (dataRouterState && dataRouterState.navigation.state !== "idle") {
1001
+ return;
1002
+ }
1003
+
942
1004
  navigate(to, {
943
1005
  replace,
944
- state
1006
+ state,
1007
+ relative
945
1008
  });
946
1009
  });
947
1010
  return null;
@@ -974,7 +1037,7 @@ function Route(_props) {
974
1037
  *
975
1038
  * @see https://reactrouter.com/docs/en/v6/routers/router
976
1039
  */
977
- function Router(_ref5) {
1040
+ function Router(_ref4) {
978
1041
  let {
979
1042
  basename: basenameProp = "/",
980
1043
  children = null,
@@ -982,7 +1045,7 @@ function Router(_ref5) {
982
1045
  navigationType = Action.Pop,
983
1046
  navigator,
984
1047
  static: staticProp = false
985
- } = _ref5;
1048
+ } = _ref4;
986
1049
  !!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : invariant(false) : void 0; // Preserve trailing slashes on basename, so we can let the user control
987
1050
  // the enforcement of trailing slashes throughout the app
988
1051
 
@@ -1042,27 +1105,158 @@ function Router(_ref5) {
1042
1105
  *
1043
1106
  * @see https://reactrouter.com/docs/en/v6/components/routes
1044
1107
  */
1045
- function Routes(_ref6) {
1108
+ function Routes(_ref5) {
1046
1109
  let {
1047
1110
  children,
1048
1111
  location
1112
+ } = _ref5;
1113
+ let dataRouterContext = React.useContext(DataRouterContext); // When in a DataRouterContext _without_ children, we use the router routes
1114
+ // directly. If we have children, then we're in a descendant tree and we
1115
+ // need to use child routes.
1116
+
1117
+ let routes = dataRouterContext && !children ? dataRouterContext.router.routes : createRoutesFromChildren(children);
1118
+ return useRoutes(routes, location);
1119
+ }
1120
+
1121
+ /**
1122
+ * Component to use for rendering lazily loaded data from returning defer()
1123
+ * in a loader function
1124
+ */
1125
+ function Await(_ref6) {
1126
+ let {
1127
+ children,
1128
+ errorElement,
1129
+ resolve
1049
1130
  } = _ref6;
1050
- return useRoutes(createRoutesFromChildren(children), location);
1131
+ return /*#__PURE__*/React.createElement(AwaitErrorBoundary, {
1132
+ resolve: resolve,
1133
+ errorElement: errorElement
1134
+ }, /*#__PURE__*/React.createElement(ResolveAwait, null, children));
1051
1135
  }
1136
+ var AwaitRenderStatus;
1137
+
1138
+ (function (AwaitRenderStatus) {
1139
+ AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
1140
+ AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
1141
+ AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
1142
+ })(AwaitRenderStatus || (AwaitRenderStatus = {}));
1143
+
1144
+ const neverSettledPromise = new Promise(() => {});
1145
+
1146
+ class AwaitErrorBoundary extends React.Component {
1147
+ constructor(props) {
1148
+ super(props);
1149
+ this.state = {
1150
+ error: null
1151
+ };
1152
+ }
1153
+
1154
+ static getDerivedStateFromError(error) {
1155
+ return {
1156
+ error
1157
+ };
1158
+ }
1159
+
1160
+ componentDidCatch(error, errorInfo) {
1161
+ console.error("<Await> caught the following error during render", error, errorInfo);
1162
+ }
1163
+
1164
+ render() {
1165
+ let {
1166
+ children,
1167
+ errorElement,
1168
+ resolve
1169
+ } = this.props;
1170
+ let promise = null;
1171
+ let status = AwaitRenderStatus.pending;
1172
+
1173
+ if (!(resolve instanceof Promise)) {
1174
+ // Didn't get a promise - provide as a resolved promise
1175
+ status = AwaitRenderStatus.success;
1176
+ promise = Promise.resolve();
1177
+ Object.defineProperty(promise, "_tracked", {
1178
+ get: () => true
1179
+ });
1180
+ Object.defineProperty(promise, "_data", {
1181
+ get: () => resolve
1182
+ });
1183
+ } else if (this.state.error) {
1184
+ // Caught a render error, provide it as a rejected promise
1185
+ status = AwaitRenderStatus.error;
1186
+ let renderError = this.state.error;
1187
+ promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
1188
+
1189
+ Object.defineProperty(promise, "_tracked", {
1190
+ get: () => true
1191
+ });
1192
+ Object.defineProperty(promise, "_error", {
1193
+ get: () => renderError
1194
+ });
1195
+ } else if (resolve._tracked) {
1196
+ // Already tracked promise - check contents
1197
+ promise = resolve;
1198
+ status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
1199
+ } else {
1200
+ // Raw (untracked) promise - track it
1201
+ status = AwaitRenderStatus.pending;
1202
+ Object.defineProperty(resolve, "_tracked", {
1203
+ get: () => true
1204
+ });
1205
+ promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
1206
+ get: () => data
1207
+ }), error => Object.defineProperty(resolve, "_error", {
1208
+ get: () => error
1209
+ }));
1210
+ }
1052
1211
 
1212
+ if (status === AwaitRenderStatus.error && promise._error instanceof AbortedDeferredError) {
1213
+ // Freeze the UI by throwing a never resolved promise
1214
+ throw neverSettledPromise;
1215
+ }
1216
+
1217
+ if (status === AwaitRenderStatus.error && !errorElement) {
1218
+ // No errorElement, throw to the nearest route-level error boundary
1219
+ throw promise._error;
1220
+ }
1221
+
1222
+ if (status === AwaitRenderStatus.error) {
1223
+ // Render via our errorElement
1224
+ return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1225
+ value: promise,
1226
+ children: errorElement
1227
+ });
1228
+ }
1229
+
1230
+ if (status === AwaitRenderStatus.success) {
1231
+ // Render children with resolved value
1232
+ return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1233
+ value: promise,
1234
+ children: children
1235
+ });
1236
+ } // Throw to the suspense boundary
1237
+
1238
+
1239
+ throw promise;
1240
+ }
1241
+
1242
+ }
1053
1243
  /**
1054
1244
  * @private
1055
- * Used as an extension to <Routes> and accepts a manual `routes` array to be
1056
- * instead of using JSX children. Extracted to it's own component to avoid
1057
- * conditional usage of `useRoutes` if we have to render a `fallbackElement`
1245
+ * Indirection to leverage useAsyncValue for a render-prop API on <Await>
1058
1246
  */
1059
- function DataRoutes(_ref7) {
1247
+
1248
+
1249
+ function ResolveAwait(_ref7) {
1060
1250
  let {
1061
- children,
1062
- location,
1063
- routes
1251
+ children
1064
1252
  } = _ref7;
1065
- return useRoutes(routes || createRoutesFromChildren(children), location);
1253
+ let data = useAsyncValue();
1254
+
1255
+ if (typeof children === "function") {
1256
+ return children(data);
1257
+ }
1258
+
1259
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
1066
1260
  } ///////////////////////////////////////////////////////////////////////////////
1067
1261
  // UTILS
1068
1262
  ///////////////////////////////////////////////////////////////////////////////
@@ -1106,6 +1300,7 @@ function createRoutesFromChildren(children, parentPath) {
1106
1300
  loader: element.props.loader,
1107
1301
  action: element.props.action,
1108
1302
  errorElement: element.props.errorElement,
1303
+ hasErrorBoundary: element.props.errorElement != null,
1109
1304
  shouldRevalidate: element.props.shouldRevalidate,
1110
1305
  handle: element.props.handle
1111
1306
  };
@@ -1125,6 +1320,39 @@ function createRoutesFromChildren(children, parentPath) {
1125
1320
  function renderMatches(matches) {
1126
1321
  return _renderMatches(matches);
1127
1322
  }
1323
+ /**
1324
+ * @private
1325
+ * Walk the route tree and add hasErrorBoundary if it's not provided, so that
1326
+ * users providing manual route arrays can just specify errorElement
1327
+ */
1328
+
1329
+ function enhanceManualRouteObjects(routes) {
1330
+ return routes.map(route => {
1331
+ let routeClone = _extends({}, route);
1332
+
1333
+ if (routeClone.hasErrorBoundary == null) {
1334
+ routeClone.hasErrorBoundary = routeClone.errorElement != null;
1335
+ }
1336
+
1337
+ if (routeClone.children) {
1338
+ routeClone.children = enhanceManualRouteObjects(routeClone.children);
1339
+ }
1340
+
1341
+ return routeClone;
1342
+ });
1343
+ }
1344
+
1345
+ function createMemoryRouter(routes, opts) {
1346
+ return createRouter({
1347
+ basename: opts == null ? void 0 : opts.basename,
1348
+ history: createMemoryHistory({
1349
+ initialEntries: opts == null ? void 0 : opts.initialEntries,
1350
+ initialIndex: opts == null ? void 0 : opts.initialIndex
1351
+ }),
1352
+ hydrationData: opts == null ? void 0 : opts.hydrationData,
1353
+ routes: enhanceManualRouteObjects(routes)
1354
+ }).initialize();
1355
+ } ///////////////////////////////////////////////////////////////////////////////
1128
1356
 
1129
- 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 };
1357
+ 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 };
1130
1358
  //# sourceMappingURL=index.js.map