UNPKG

57.5 kBJavaScriptView Raw
1/**
2 * React Router v6.22.3
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import * as React from 'react';
12import { UNSAFE_invariant, joinPaths, matchPath, UNSAFE_getResolveToMatches, UNSAFE_warning, resolveTo, parsePath, matchRoutes, Action, UNSAFE_convertRouteMatchToUiMatch, stripBasename, IDLE_BLOCKER, isRouteErrorResponse, createMemoryHistory, AbortedDeferredError, createRouter } from '@remix-run/router';
13export { AbortedDeferredError, Action as NavigationType, createPath, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, resolvePath } from '@remix-run/router';
14
15function _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 for (var key in source) {
20 if (Object.prototype.hasOwnProperty.call(source, key)) {
21 target[key] = source[key];
22 }
23 }
24 }
25 return target;
26 };
27 return _extends.apply(this, arguments);
28}
29
30// Create react-specific types from the agnostic types in @remix-run/router to
31// export from react-router
32const DataRouterContext = /*#__PURE__*/React.createContext(null);
33if (process.env.NODE_ENV !== "production") {
34 DataRouterContext.displayName = "DataRouter";
35}
36const DataRouterStateContext = /*#__PURE__*/React.createContext(null);
37if (process.env.NODE_ENV !== "production") {
38 DataRouterStateContext.displayName = "DataRouterState";
39}
40const AwaitContext = /*#__PURE__*/React.createContext(null);
41if (process.env.NODE_ENV !== "production") {
42 AwaitContext.displayName = "Await";
43}
44
45/**
46 * A Navigator is a "location changer"; it's how you get to different locations.
47 *
48 * Every history instance conforms to the Navigator interface, but the
49 * distinction is useful primarily when it comes to the low-level `<Router>` API
50 * where both the location and a navigator must be provided separately in order
51 * to avoid "tearing" that may occur in a suspense-enabled app if the action
52 * and/or location were to be read directly from the history instance.
53 */
54
55const NavigationContext = /*#__PURE__*/React.createContext(null);
56if (process.env.NODE_ENV !== "production") {
57 NavigationContext.displayName = "Navigation";
58}
59const LocationContext = /*#__PURE__*/React.createContext(null);
60if (process.env.NODE_ENV !== "production") {
61 LocationContext.displayName = "Location";
62}
63const RouteContext = /*#__PURE__*/React.createContext({
64 outlet: null,
65 matches: [],
66 isDataRoute: false
67});
68if (process.env.NODE_ENV !== "production") {
69 RouteContext.displayName = "Route";
70}
71const RouteErrorContext = /*#__PURE__*/React.createContext(null);
72if (process.env.NODE_ENV !== "production") {
73 RouteErrorContext.displayName = "RouteError";
74}
75
76/**
77 * Returns the full href for the given "to" value. This is useful for building
78 * custom links that are also accessible and preserve right-click behavior.
79 *
80 * @see https://reactrouter.com/hooks/use-href
81 */
82function useHref(to, _temp) {
83 let {
84 relative
85 } = _temp === void 0 ? {} : _temp;
86 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
87 // router loaded. We can help them understand how to avoid that.
88 "useHref() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
89 let {
90 basename,
91 navigator
92 } = React.useContext(NavigationContext);
93 let {
94 hash,
95 pathname,
96 search
97 } = useResolvedPath(to, {
98 relative
99 });
100 let joinedPathname = pathname;
101
102 // If we're operating within a basename, prepend it to the pathname prior
103 // to creating the href. If this is a root navigation, then just use the raw
104 // basename which allows the basename to have full control over the presence
105 // of a trailing slash on root links
106 if (basename !== "/") {
107 joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
108 }
109 return navigator.createHref({
110 pathname: joinedPathname,
111 search,
112 hash
113 });
114}
115
116/**
117 * Returns true if this component is a descendant of a `<Router>`.
118 *
119 * @see https://reactrouter.com/hooks/use-in-router-context
120 */
121function useInRouterContext() {
122 return React.useContext(LocationContext) != null;
123}
124
125/**
126 * Returns the current location object, which represents the current URL in web
127 * browsers.
128 *
129 * Note: If you're using this it may mean you're doing some of your own
130 * "routing" in your app, and we'd like to know what your use case is. We may
131 * be able to provide something higher-level to better suit your needs.
132 *
133 * @see https://reactrouter.com/hooks/use-location
134 */
135function useLocation() {
136 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
137 // router loaded. We can help them understand how to avoid that.
138 "useLocation() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
139 return React.useContext(LocationContext).location;
140}
141
142/**
143 * Returns the current navigation action which describes how the router came to
144 * the current location, either by a pop, push, or replace on the history stack.
145 *
146 * @see https://reactrouter.com/hooks/use-navigation-type
147 */
148function useNavigationType() {
149 return React.useContext(LocationContext).navigationType;
150}
151
152/**
153 * Returns a PathMatch object if the given pattern matches the current URL.
154 * This is useful for components that need to know "active" state, e.g.
155 * `<NavLink>`.
156 *
157 * @see https://reactrouter.com/hooks/use-match
158 */
159function useMatch(pattern) {
160 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
161 // router loaded. We can help them understand how to avoid that.
162 "useMatch() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
163 let {
164 pathname
165 } = useLocation();
166 return React.useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
167}
168
169/**
170 * The interface for the navigate() function returned from useNavigate().
171 */
172
173const navigateEffectWarning = "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.";
174
175// Mute warnings for calls to useNavigate in SSR environments
176function useIsomorphicLayoutEffect(cb) {
177 let isStatic = React.useContext(NavigationContext).static;
178 if (!isStatic) {
179 // We should be able to get rid of this once react 18.3 is released
180 // See: https://github.com/facebook/react/pull/26395
181 // eslint-disable-next-line react-hooks/rules-of-hooks
182 React.useLayoutEffect(cb);
183 }
184}
185
186/**
187 * Returns an imperative method for changing the location. Used by `<Link>`s, but
188 * may also be used by other elements to change the location.
189 *
190 * @see https://reactrouter.com/hooks/use-navigate
191 */
192function useNavigate() {
193 let {
194 isDataRoute
195 } = React.useContext(RouteContext);
196 // Conditional usage is OK here because the usage of a data router is static
197 // eslint-disable-next-line react-hooks/rules-of-hooks
198 return isDataRoute ? useNavigateStable() : useNavigateUnstable();
199}
200function useNavigateUnstable() {
201 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
202 // router loaded. We can help them understand how to avoid that.
203 "useNavigate() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
204 let dataRouterContext = React.useContext(DataRouterContext);
205 let {
206 basename,
207 future,
208 navigator
209 } = React.useContext(NavigationContext);
210 let {
211 matches
212 } = React.useContext(RouteContext);
213 let {
214 pathname: locationPathname
215 } = useLocation();
216 let routePathnamesJson = JSON.stringify(UNSAFE_getResolveToMatches(matches, future.v7_relativeSplatPath));
217 let activeRef = React.useRef(false);
218 useIsomorphicLayoutEffect(() => {
219 activeRef.current = true;
220 });
221 let navigate = React.useCallback(function (to, options) {
222 if (options === void 0) {
223 options = {};
224 }
225 process.env.NODE_ENV !== "production" ? UNSAFE_warning(activeRef.current, navigateEffectWarning) : void 0;
226
227 // Short circuit here since if this happens on first render the navigate
228 // is useless because we haven't wired up our history listener yet
229 if (!activeRef.current) return;
230 if (typeof to === "number") {
231 navigator.go(to);
232 return;
233 }
234 let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
235
236 // If we're operating within a basename, prepend it to the pathname prior
237 // to handing off to history (but only if we're not in a data router,
238 // otherwise it'll prepend the basename inside of the router).
239 // If this is a root navigation, then we navigate to the raw basename
240 // which allows the basename to have full control over the presence of a
241 // trailing slash on root links
242 if (dataRouterContext == null && basename !== "/") {
243 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
244 }
245 (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
246 }, [basename, navigator, routePathnamesJson, locationPathname, dataRouterContext]);
247 return navigate;
248}
249const OutletContext = /*#__PURE__*/React.createContext(null);
250
251/**
252 * Returns the context (if provided) for the child route at this level of the route
253 * hierarchy.
254 * @see https://reactrouter.com/hooks/use-outlet-context
255 */
256function useOutletContext() {
257 return React.useContext(OutletContext);
258}
259
260/**
261 * Returns the element for the child route at this level of the route
262 * hierarchy. Used internally by `<Outlet>` to render child routes.
263 *
264 * @see https://reactrouter.com/hooks/use-outlet
265 */
266function useOutlet(context) {
267 let outlet = React.useContext(RouteContext).outlet;
268 if (outlet) {
269 return /*#__PURE__*/React.createElement(OutletContext.Provider, {
270 value: context
271 }, outlet);
272 }
273 return outlet;
274}
275
276/**
277 * Returns an object of key/value pairs of the dynamic params from the current
278 * URL that were matched by the route path.
279 *
280 * @see https://reactrouter.com/hooks/use-params
281 */
282function useParams() {
283 let {
284 matches
285 } = React.useContext(RouteContext);
286 let routeMatch = matches[matches.length - 1];
287 return routeMatch ? routeMatch.params : {};
288}
289
290/**
291 * Resolves the pathname of the given `to` value against the current location.
292 *
293 * @see https://reactrouter.com/hooks/use-resolved-path
294 */
295function useResolvedPath(to, _temp2) {
296 let {
297 relative
298 } = _temp2 === void 0 ? {} : _temp2;
299 let {
300 future
301 } = React.useContext(NavigationContext);
302 let {
303 matches
304 } = React.useContext(RouteContext);
305 let {
306 pathname: locationPathname
307 } = useLocation();
308 let routePathnamesJson = JSON.stringify(UNSAFE_getResolveToMatches(matches, future.v7_relativeSplatPath));
309 return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
310}
311
312/**
313 * Returns the element of the route that matched the current location, prepared
314 * with the correct context to render the remainder of the route tree. Route
315 * elements in the tree must render an `<Outlet>` to render their child route's
316 * element.
317 *
318 * @see https://reactrouter.com/hooks/use-routes
319 */
320function useRoutes(routes, locationArg) {
321 return useRoutesImpl(routes, locationArg);
322}
323
324// Internal implementation with accept optional param for RouterProvider usage
325function useRoutesImpl(routes, locationArg, dataRouterState, future) {
326 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
327 // router loaded. We can help them understand how to avoid that.
328 "useRoutes() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
329 let {
330 navigator
331 } = React.useContext(NavigationContext);
332 let {
333 matches: parentMatches
334 } = React.useContext(RouteContext);
335 let routeMatch = parentMatches[parentMatches.length - 1];
336 let parentParams = routeMatch ? routeMatch.params : {};
337 let parentPathname = routeMatch ? routeMatch.pathname : "/";
338 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
339 let parentRoute = routeMatch && routeMatch.route;
340 if (process.env.NODE_ENV !== "production") {
341 // You won't get a warning about 2 different <Routes> under a <Route>
342 // without a trailing *, but this is a best-effort warning anyway since we
343 // cannot even give the warning unless they land at the parent route.
344 //
345 // Example:
346 //
347 // <Routes>
348 // {/* This route path MUST end with /* because otherwise
349 // it will never match /blog/post/123 */}
350 // <Route path="blog" element={<Blog />} />
351 // <Route path="blog/feed" element={<BlogFeed />} />
352 // </Routes>
353 //
354 // function Blog() {
355 // return (
356 // <Routes>
357 // <Route path="post/:id" element={<Post />} />
358 // </Routes>
359 // );
360 // }
361 let parentPath = parentRoute && parentRoute.path || "";
362 warningOnce(parentPathname, !parentRoute || parentPath.endsWith("*"), "You rendered descendant <Routes> (or called `useRoutes()`) at " + ("\"" + parentPathname + "\" (under <Route path=\"" + parentPath + "\">) but the ") + "parent route path has no trailing \"*\". This means if you navigate " + "deeper, the parent won't match anymore and therefore the child " + "routes will never render.\n\n" + ("Please change the parent <Route path=\"" + parentPath + "\"> to <Route ") + ("path=\"" + (parentPath === "/" ? "*" : parentPath + "/*") + "\">."));
363 }
364 let locationFromContext = useLocation();
365 let location;
366 if (locationArg) {
367 var _parsedLocationArg$pa;
368 let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
369 !(parentPathnameBase === "/" || ((_parsedLocationArg$pa = parsedLocationArg.pathname) == null ? void 0 : _parsedLocationArg$pa.startsWith(parentPathnameBase))) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "When overriding the location using `<Routes location>` or `useRoutes(routes, location)`, " + "the location pathname must begin with the portion of the URL pathname that was " + ("matched by all parent routes. The current pathname base is \"" + parentPathnameBase + "\" ") + ("but pathname \"" + parsedLocationArg.pathname + "\" was given in the `location` prop.")) : UNSAFE_invariant(false) : void 0;
370 location = parsedLocationArg;
371 } else {
372 location = locationFromContext;
373 }
374 let pathname = location.pathname || "/";
375 let remainingPathname = pathname;
376 if (parentPathnameBase !== "/") {
377 // Determine the remaining pathname by removing the # of URL segments the
378 // parentPathnameBase has, instead of removing based on character count.
379 // This is because we can't guarantee that incoming/outgoing encodings/
380 // decodings will match exactly.
381 // We decode paths before matching on a per-segment basis with
382 // decodeURIComponent(), but we re-encode pathnames via `new URL()` so they
383 // match what `window.location.pathname` would reflect. Those don't 100%
384 // align when it comes to encoded URI characters such as % and &.
385 //
386 // So we may end up with:
387 // pathname: "/descendant/a%25b/match"
388 // parentPathnameBase: "/descendant/a%b"
389 //
390 // And the direct substring removal approach won't work :/
391 let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
392 let segments = pathname.replace(/^\//, "").split("/");
393 remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
394 }
395 let matches = matchRoutes(routes, {
396 pathname: remainingPathname
397 });
398 if (process.env.NODE_ENV !== "production") {
399 process.env.NODE_ENV !== "production" ? UNSAFE_warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") : void 0;
400 process.env.NODE_ENV !== "production" ? UNSAFE_warning(matches == null || matches[matches.length - 1].route.element !== undefined || matches[matches.length - 1].route.Component !== undefined || matches[matches.length - 1].route.lazy !== undefined, "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.") : void 0;
401 }
402 let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
403 params: Object.assign({}, parentParams, match.params),
404 pathname: joinPaths([parentPathnameBase,
405 // Re-encode pathnames that were decoded inside matchRoutes
406 navigator.encodeLocation ? navigator.encodeLocation(match.pathname).pathname : match.pathname]),
407 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase,
408 // Re-encode pathnames that were decoded inside matchRoutes
409 navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase).pathname : match.pathnameBase])
410 })), parentMatches, dataRouterState, future);
411
412 // When a user passes in a `locationArg`, the associated routes need to
413 // be wrapped in a new `LocationContext.Provider` in order for `useLocation`
414 // to use the scoped location instead of the global location.
415 if (locationArg && renderedMatches) {
416 return /*#__PURE__*/React.createElement(LocationContext.Provider, {
417 value: {
418 location: _extends({
419 pathname: "/",
420 search: "",
421 hash: "",
422 state: null,
423 key: "default"
424 }, location),
425 navigationType: Action.Pop
426 }
427 }, renderedMatches);
428 }
429 return renderedMatches;
430}
431function DefaultErrorComponent() {
432 let error = useRouteError();
433 let message = isRouteErrorResponse(error) ? error.status + " " + error.statusText : error instanceof Error ? error.message : JSON.stringify(error);
434 let stack = error instanceof Error ? error.stack : null;
435 let lightgrey = "rgba(200,200,200, 0.5)";
436 let preStyles = {
437 padding: "0.5rem",
438 backgroundColor: lightgrey
439 };
440 let codeStyles = {
441 padding: "2px 4px",
442 backgroundColor: lightgrey
443 };
444 let devInfo = null;
445 if (process.env.NODE_ENV !== "production") {
446 console.error("Error handled by React Router default ErrorBoundary:", error);
447 devInfo = /*#__PURE__*/React.createElement(React.Fragment, 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 ", /*#__PURE__*/React.createElement("code", {
448 style: codeStyles
449 }, "ErrorBoundary"), " or", " ", /*#__PURE__*/React.createElement("code", {
450 style: codeStyles
451 }, "errorElement"), " prop on your route."));
452 }
453 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h2", null, "Unexpected Application Error!"), /*#__PURE__*/React.createElement("h3", {
454 style: {
455 fontStyle: "italic"
456 }
457 }, message), stack ? /*#__PURE__*/React.createElement("pre", {
458 style: preStyles
459 }, stack) : null, devInfo);
460}
461const defaultErrorElement = /*#__PURE__*/React.createElement(DefaultErrorComponent, null);
462class RenderErrorBoundary extends React.Component {
463 constructor(props) {
464 super(props);
465 this.state = {
466 location: props.location,
467 revalidation: props.revalidation,
468 error: props.error
469 };
470 }
471 static getDerivedStateFromError(error) {
472 return {
473 error: error
474 };
475 }
476 static getDerivedStateFromProps(props, state) {
477 // When we get into an error state, the user will likely click "back" to the
478 // previous page that didn't have an error. Because this wraps the entire
479 // application, that will have no effect--the error page continues to display.
480 // This gives us a mechanism to recover from the error when the location changes.
481 //
482 // Whether we're in an error state or not, we update the location in state
483 // so that when we are in an error state, it gets reset when a new location
484 // comes in and the user recovers from the error.
485 if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
486 return {
487 error: props.error,
488 location: props.location,
489 revalidation: props.revalidation
490 };
491 }
492
493 // If we're not changing locations, preserve the location but still surface
494 // any new errors that may come through. We retain the existing error, we do
495 // this because the error provided from the app state may be cleared without
496 // the location changing.
497 return {
498 error: props.error !== undefined ? props.error : state.error,
499 location: state.location,
500 revalidation: props.revalidation || state.revalidation
501 };
502 }
503 componentDidCatch(error, errorInfo) {
504 console.error("React Router caught the following error during render", error, errorInfo);
505 }
506 render() {
507 return this.state.error !== undefined ? /*#__PURE__*/React.createElement(RouteContext.Provider, {
508 value: this.props.routeContext
509 }, /*#__PURE__*/React.createElement(RouteErrorContext.Provider, {
510 value: this.state.error,
511 children: this.props.component
512 })) : this.props.children;
513 }
514}
515function RenderedRoute(_ref) {
516 let {
517 routeContext,
518 match,
519 children
520 } = _ref;
521 let dataRouterContext = React.useContext(DataRouterContext);
522
523 // Track how deep we got in our render pass to emulate SSR componentDidCatch
524 // in a DataStaticRouter
525 if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
526 dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
527 }
528 return /*#__PURE__*/React.createElement(RouteContext.Provider, {
529 value: routeContext
530 }, children);
531}
532function _renderMatches(matches, parentMatches, dataRouterState, future) {
533 var _dataRouterState2;
534 if (parentMatches === void 0) {
535 parentMatches = [];
536 }
537 if (dataRouterState === void 0) {
538 dataRouterState = null;
539 }
540 if (future === void 0) {
541 future = null;
542 }
543 if (matches == null) {
544 var _dataRouterState;
545 if ((_dataRouterState = dataRouterState) != null && _dataRouterState.errors) {
546 // Don't bail if we have data router errors so we can render them in the
547 // boundary. Use the pre-matched (or shimmed) matches
548 matches = dataRouterState.matches;
549 } else {
550 return null;
551 }
552 }
553 let renderedMatches = matches;
554
555 // If we have data errors, trim matches to the highest error boundary
556 let errors = (_dataRouterState2 = dataRouterState) == null ? void 0 : _dataRouterState2.errors;
557 if (errors != null) {
558 let errorIndex = renderedMatches.findIndex(m => m.route.id && (errors == null ? void 0 : errors[m.route.id]));
559 !(errorIndex >= 0) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "Could not find a matching route for errors on route IDs: " + Object.keys(errors).join(",")) : UNSAFE_invariant(false) : void 0;
560 renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
561 }
562
563 // If we're in a partial hydration mode, detect if we need to render down to
564 // a given HydrateFallback while we load the rest of the hydration data
565 let renderFallback = false;
566 let fallbackIndex = -1;
567 if (dataRouterState && future && future.v7_partialHydration) {
568 for (let i = 0; i < renderedMatches.length; i++) {
569 let match = renderedMatches[i];
570 // Track the deepest fallback up until the first route without data
571 if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
572 fallbackIndex = i;
573 }
574 if (match.route.id) {
575 let {
576 loaderData,
577 errors
578 } = dataRouterState;
579 let needsToRunLoader = match.route.loader && loaderData[match.route.id] === undefined && (!errors || errors[match.route.id] === undefined);
580 if (match.route.lazy || needsToRunLoader) {
581 // We found the first route that's not ready to render (waiting on
582 // lazy, or has a loader that hasn't run yet). Flag that we need to
583 // render a fallback and render up until the appropriate fallback
584 renderFallback = true;
585 if (fallbackIndex >= 0) {
586 renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
587 } else {
588 renderedMatches = [renderedMatches[0]];
589 }
590 break;
591 }
592 }
593 }
594 }
595 return renderedMatches.reduceRight((outlet, match, index) => {
596 // Only data routers handle errors/fallbacks
597 let error;
598 let shouldRenderHydrateFallback = false;
599 let errorElement = null;
600 let hydrateFallbackElement = null;
601 if (dataRouterState) {
602 error = errors && match.route.id ? errors[match.route.id] : undefined;
603 errorElement = match.route.errorElement || defaultErrorElement;
604 if (renderFallback) {
605 if (fallbackIndex < 0 && index === 0) {
606 warningOnce("route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration");
607 shouldRenderHydrateFallback = true;
608 hydrateFallbackElement = null;
609 } else if (fallbackIndex === index) {
610 shouldRenderHydrateFallback = true;
611 hydrateFallbackElement = match.route.hydrateFallbackElement || null;
612 }
613 }
614 }
615 let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
616 let getChildren = () => {
617 let children;
618 if (error) {
619 children = errorElement;
620 } else if (shouldRenderHydrateFallback) {
621 children = hydrateFallbackElement;
622 } else if (match.route.Component) {
623 // Note: This is a de-optimized path since React won't re-use the
624 // ReactElement since it's identity changes with each new
625 // React.createElement call. We keep this so folks can use
626 // `<Route Component={...}>` in `<Routes>` but generally `Component`
627 // usage is only advised in `RouterProvider` when we can convert it to
628 // `element` ahead of time.
629 children = /*#__PURE__*/React.createElement(match.route.Component, null);
630 } else if (match.route.element) {
631 children = match.route.element;
632 } else {
633 children = outlet;
634 }
635 return /*#__PURE__*/React.createElement(RenderedRoute, {
636 match: match,
637 routeContext: {
638 outlet,
639 matches,
640 isDataRoute: dataRouterState != null
641 },
642 children: children
643 });
644 };
645 // Only wrap in an error boundary within data router usages when we have an
646 // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to
647 // an ancestor ErrorBoundary/errorElement
648 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /*#__PURE__*/React.createElement(RenderErrorBoundary, {
649 location: dataRouterState.location,
650 revalidation: dataRouterState.revalidation,
651 component: errorElement,
652 error: error,
653 children: getChildren(),
654 routeContext: {
655 outlet: null,
656 matches,
657 isDataRoute: true
658 }
659 }) : getChildren();
660 }, null);
661}
662var DataRouterHook = /*#__PURE__*/function (DataRouterHook) {
663 DataRouterHook["UseBlocker"] = "useBlocker";
664 DataRouterHook["UseRevalidator"] = "useRevalidator";
665 DataRouterHook["UseNavigateStable"] = "useNavigate";
666 return DataRouterHook;
667}(DataRouterHook || {});
668var DataRouterStateHook = /*#__PURE__*/function (DataRouterStateHook) {
669 DataRouterStateHook["UseBlocker"] = "useBlocker";
670 DataRouterStateHook["UseLoaderData"] = "useLoaderData";
671 DataRouterStateHook["UseActionData"] = "useActionData";
672 DataRouterStateHook["UseRouteError"] = "useRouteError";
673 DataRouterStateHook["UseNavigation"] = "useNavigation";
674 DataRouterStateHook["UseRouteLoaderData"] = "useRouteLoaderData";
675 DataRouterStateHook["UseMatches"] = "useMatches";
676 DataRouterStateHook["UseRevalidator"] = "useRevalidator";
677 DataRouterStateHook["UseNavigateStable"] = "useNavigate";
678 DataRouterStateHook["UseRouteId"] = "useRouteId";
679 return DataRouterStateHook;
680}(DataRouterStateHook || {});
681function getDataRouterConsoleError(hookName) {
682 return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
683}
684function useDataRouterContext(hookName) {
685 let ctx = React.useContext(DataRouterContext);
686 !ctx ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
687 return ctx;
688}
689function useDataRouterState(hookName) {
690 let state = React.useContext(DataRouterStateContext);
691 !state ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
692 return state;
693}
694function useRouteContext(hookName) {
695 let route = React.useContext(RouteContext);
696 !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
697 return route;
698}
699
700// Internal version with hookName-aware debugging
701function useCurrentRouteId(hookName) {
702 let route = useRouteContext(hookName);
703 let thisRoute = route.matches[route.matches.length - 1];
704 !thisRoute.route.id ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, hookName + " can only be used on routes that contain a unique \"id\"") : UNSAFE_invariant(false) : void 0;
705 return thisRoute.route.id;
706}
707
708/**
709 * Returns the ID for the nearest contextual route
710 */
711function useRouteId() {
712 return useCurrentRouteId(DataRouterStateHook.UseRouteId);
713}
714
715/**
716 * Returns the current navigation, defaulting to an "idle" navigation when
717 * no navigation is in progress
718 */
719function useNavigation() {
720 let state = useDataRouterState(DataRouterStateHook.UseNavigation);
721 return state.navigation;
722}
723
724/**
725 * Returns a revalidate function for manually triggering revalidation, as well
726 * as the current state of any manual revalidations
727 */
728function useRevalidator() {
729 let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);
730 let state = useDataRouterState(DataRouterStateHook.UseRevalidator);
731 return React.useMemo(() => ({
732 revalidate: dataRouterContext.router.revalidate,
733 state: state.revalidation
734 }), [dataRouterContext.router.revalidate, state.revalidation]);
735}
736
737/**
738 * Returns the active route matches, useful for accessing loaderData for
739 * parent/child routes or the route "handle" property
740 */
741function useMatches() {
742 let {
743 matches,
744 loaderData
745 } = useDataRouterState(DataRouterStateHook.UseMatches);
746 return React.useMemo(() => matches.map(m => UNSAFE_convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
747}
748
749/**
750 * Returns the loader data for the nearest ancestor Route loader
751 */
752function useLoaderData() {
753 let state = useDataRouterState(DataRouterStateHook.UseLoaderData);
754 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
755 if (state.errors && state.errors[routeId] != null) {
756 console.error("You cannot `useLoaderData` in an errorElement (routeId: " + routeId + ")");
757 return undefined;
758 }
759 return state.loaderData[routeId];
760}
761
762/**
763 * Returns the loaderData for the given routeId
764 */
765function useRouteLoaderData(routeId) {
766 let state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);
767 return state.loaderData[routeId];
768}
769
770/**
771 * Returns the action data for the nearest ancestor Route action
772 */
773function useActionData() {
774 let state = useDataRouterState(DataRouterStateHook.UseActionData);
775 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
776 return state.actionData ? state.actionData[routeId] : undefined;
777}
778
779/**
780 * Returns the nearest ancestor Route error, which could be a loader/action
781 * error or a render error. This is intended to be called from your
782 * ErrorBoundary/errorElement to display a proper error message.
783 */
784function useRouteError() {
785 var _state$errors;
786 let error = React.useContext(RouteErrorContext);
787 let state = useDataRouterState(DataRouterStateHook.UseRouteError);
788 let routeId = useCurrentRouteId(DataRouterStateHook.UseRouteError);
789
790 // If this was a render error, we put it in a RouteError context inside
791 // of RenderErrorBoundary
792 if (error !== undefined) {
793 return error;
794 }
795
796 // Otherwise look for errors from our data router state
797 return (_state$errors = state.errors) == null ? void 0 : _state$errors[routeId];
798}
799
800/**
801 * Returns the happy-path data from the nearest ancestor `<Await />` value
802 */
803function useAsyncValue() {
804 let value = React.useContext(AwaitContext);
805 return value == null ? void 0 : value._data;
806}
807
808/**
809 * Returns the error from the nearest ancestor `<Await />` value
810 */
811function useAsyncError() {
812 let value = React.useContext(AwaitContext);
813 return value == null ? void 0 : value._error;
814}
815let blockerId = 0;
816
817/**
818 * Allow the application to block navigations within the SPA and present the
819 * user a confirmation dialog to confirm the navigation. Mostly used to avoid
820 * using half-filled form data. This does not handle hard-reloads or
821 * cross-origin navigations.
822 */
823function useBlocker(shouldBlock) {
824 let {
825 router,
826 basename
827 } = useDataRouterContext(DataRouterHook.UseBlocker);
828 let state = useDataRouterState(DataRouterStateHook.UseBlocker);
829 let [blockerKey, setBlockerKey] = React.useState("");
830 let blockerFunction = React.useCallback(arg => {
831 if (typeof shouldBlock !== "function") {
832 return !!shouldBlock;
833 }
834 if (basename === "/") {
835 return shouldBlock(arg);
836 }
837
838 // If they provided us a function and we've got an active basename, strip
839 // it from the locations we expose to the user to match the behavior of
840 // useLocation
841 let {
842 currentLocation,
843 nextLocation,
844 historyAction
845 } = arg;
846 return shouldBlock({
847 currentLocation: _extends({}, currentLocation, {
848 pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
849 }),
850 nextLocation: _extends({}, nextLocation, {
851 pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
852 }),
853 historyAction
854 });
855 }, [basename, shouldBlock]);
856
857 // This effect is in charge of blocker key assignment and deletion (which is
858 // tightly coupled to the key)
859 React.useEffect(() => {
860 let key = String(++blockerId);
861 setBlockerKey(key);
862 return () => router.deleteBlocker(key);
863 }, [router]);
864
865 // This effect handles assigning the blockerFunction. This is to handle
866 // unstable blocker function identities, and happens only after the prior
867 // effect so we don't get an orphaned blockerFunction in the router with a
868 // key of "". Until then we just have the IDLE_BLOCKER.
869 React.useEffect(() => {
870 if (blockerKey !== "") {
871 router.getBlocker(blockerKey, blockerFunction);
872 }
873 }, [router, blockerKey, blockerFunction]);
874
875 // Prefer the blocker from `state` not `router.state` since DataRouterContext
876 // is memoized so this ensures we update on blocker state updates
877 return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER;
878}
879
880/**
881 * Stable version of useNavigate that is used when we are in the context of
882 * a RouterProvider.
883 */
884function useNavigateStable() {
885 let {
886 router
887 } = useDataRouterContext(DataRouterHook.UseNavigateStable);
888 let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);
889 let activeRef = React.useRef(false);
890 useIsomorphicLayoutEffect(() => {
891 activeRef.current = true;
892 });
893 let navigate = React.useCallback(function (to, options) {
894 if (options === void 0) {
895 options = {};
896 }
897 process.env.NODE_ENV !== "production" ? UNSAFE_warning(activeRef.current, navigateEffectWarning) : void 0;
898
899 // Short circuit here since if this happens on first render the navigate
900 // is useless because we haven't wired up our router subscriber yet
901 if (!activeRef.current) return;
902 if (typeof to === "number") {
903 router.navigate(to);
904 } else {
905 router.navigate(to, _extends({
906 fromRouteId: id
907 }, options));
908 }
909 }, [router, id]);
910 return navigate;
911}
912const alreadyWarned = {};
913function warningOnce(key, cond, message) {
914 if (!cond && !alreadyWarned[key]) {
915 alreadyWarned[key] = true;
916 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, message) : void 0;
917 }
918}
919
920/**
921 Webpack + React 17 fails to compile on any of the following because webpack
922 complains that `startTransition` doesn't exist in `React`:
923 * import { startTransition } from "react"
924 * import * as React from from "react";
925 "startTransition" in React ? React.startTransition(() => setState()) : setState()
926 * import * as React from from "react";
927 "startTransition" in React ? React["startTransition"](() => setState()) : setState()
928
929 Moving it to a constant such as the following solves the Webpack/React 17 issue:
930 * import * as React from from "react";
931 const START_TRANSITION = "startTransition";
932 START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
933
934 However, that introduces webpack/terser minification issues in production builds
935 in React 18 where minification/obfuscation ends up removing the call of
936 React.startTransition entirely from the first half of the ternary. Grabbing
937 this exported reference once up front resolves that issue.
938
939 See https://github.com/remix-run/react-router/issues/10579
940*/
941const START_TRANSITION = "startTransition";
942const startTransitionImpl = React[START_TRANSITION];
943
944/**
945 * Given a Remix Router instance, render the appropriate UI
946 */
947function RouterProvider(_ref) {
948 let {
949 fallbackElement,
950 router,
951 future
952 } = _ref;
953 let [state, setStateImpl] = React.useState(router.state);
954 let {
955 v7_startTransition
956 } = future || {};
957 let setState = React.useCallback(newState => {
958 if (v7_startTransition && startTransitionImpl) {
959 startTransitionImpl(() => setStateImpl(newState));
960 } else {
961 setStateImpl(newState);
962 }
963 }, [setStateImpl, v7_startTransition]);
964
965 // Need to use a layout effect here so we are subscribed early enough to
966 // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
967 React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
968 React.useEffect(() => {
969 process.env.NODE_ENV !== "production" ? UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") : void 0;
970 // Only log this once on initial mount
971 // eslint-disable-next-line react-hooks/exhaustive-deps
972 }, []);
973 let navigator = React.useMemo(() => {
974 return {
975 createHref: router.createHref,
976 encodeLocation: router.encodeLocation,
977 go: n => router.navigate(n),
978 push: (to, state, opts) => router.navigate(to, {
979 state,
980 preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
981 }),
982 replace: (to, state, opts) => router.navigate(to, {
983 replace: true,
984 state,
985 preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
986 })
987 };
988 }, [router]);
989 let basename = router.basename || "/";
990 let dataRouterContext = React.useMemo(() => ({
991 router,
992 navigator,
993 static: false,
994 basename
995 }), [router, navigator, basename]);
996
997 // The fragment and {null} here are important! We need them to keep React 18's
998 // useId happy when we are server-rendering since we may have a <script> here
999 // containing the hydrated server-side staticContext (from StaticRouterProvider).
1000 // useId relies on the component tree structure to generate deterministic id's
1001 // so we need to ensure it remains the same on the client even though
1002 // we don't need the <script> tag
1003 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DataRouterContext.Provider, {
1004 value: dataRouterContext
1005 }, /*#__PURE__*/React.createElement(DataRouterStateContext.Provider, {
1006 value: state
1007 }, /*#__PURE__*/React.createElement(Router, {
1008 basename: basename,
1009 location: state.location,
1010 navigationType: state.historyAction,
1011 navigator: navigator,
1012 future: {
1013 v7_relativeSplatPath: router.future.v7_relativeSplatPath
1014 }
1015 }, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/React.createElement(DataRoutes, {
1016 routes: router.routes,
1017 future: router.future,
1018 state: state
1019 }) : fallbackElement))), null);
1020}
1021function DataRoutes(_ref2) {
1022 let {
1023 routes,
1024 future,
1025 state
1026 } = _ref2;
1027 return useRoutesImpl(routes, undefined, state, future);
1028}
1029/**
1030 * A `<Router>` that stores all entries in memory.
1031 *
1032 * @see https://reactrouter.com/router-components/memory-router
1033 */
1034function MemoryRouter(_ref3) {
1035 let {
1036 basename,
1037 children,
1038 initialEntries,
1039 initialIndex,
1040 future
1041 } = _ref3;
1042 let historyRef = React.useRef();
1043 if (historyRef.current == null) {
1044 historyRef.current = createMemoryHistory({
1045 initialEntries,
1046 initialIndex,
1047 v5Compat: true
1048 });
1049 }
1050 let history = historyRef.current;
1051 let [state, setStateImpl] = React.useState({
1052 action: history.action,
1053 location: history.location
1054 });
1055 let {
1056 v7_startTransition
1057 } = future || {};
1058 let setState = React.useCallback(newState => {
1059 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
1060 }, [setStateImpl, v7_startTransition]);
1061 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
1062 return /*#__PURE__*/React.createElement(Router, {
1063 basename: basename,
1064 children: children,
1065 location: state.location,
1066 navigationType: state.action,
1067 navigator: history,
1068 future: future
1069 });
1070}
1071/**
1072 * Changes the current location.
1073 *
1074 * Note: This API is mostly useful in React.Component subclasses that are not
1075 * able to use hooks. In functional components, we recommend you use the
1076 * `useNavigate` hook instead.
1077 *
1078 * @see https://reactrouter.com/components/navigate
1079 */
1080function Navigate(_ref4) {
1081 let {
1082 to,
1083 replace,
1084 state,
1085 relative
1086 } = _ref4;
1087 !useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of
1088 // the router loaded. We can help them understand how to avoid that.
1089 "<Navigate> may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
1090 let {
1091 future,
1092 static: isStatic
1093 } = React.useContext(NavigationContext);
1094 process.env.NODE_ENV !== "production" ? UNSAFE_warning(!isStatic, "<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;
1095 let {
1096 matches
1097 } = React.useContext(RouteContext);
1098 let {
1099 pathname: locationPathname
1100 } = useLocation();
1101 let navigate = useNavigate();
1102
1103 // Resolve the path outside of the effect so that when effects run twice in
1104 // StrictMode they navigate to the same place
1105 let path = resolveTo(to, UNSAFE_getResolveToMatches(matches, future.v7_relativeSplatPath), locationPathname, relative === "path");
1106 let jsonPath = JSON.stringify(path);
1107 React.useEffect(() => navigate(JSON.parse(jsonPath), {
1108 replace,
1109 state,
1110 relative
1111 }), [navigate, jsonPath, relative, replace, state]);
1112 return null;
1113}
1114/**
1115 * Renders the child route's element, if there is one.
1116 *
1117 * @see https://reactrouter.com/components/outlet
1118 */
1119function Outlet(props) {
1120 return useOutlet(props.context);
1121}
1122/**
1123 * Declares an element that should be rendered at a certain URL path.
1124 *
1125 * @see https://reactrouter.com/components/route
1126 */
1127function Route(_props) {
1128 process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "A <Route> is only ever to be used as the child of <Routes> element, " + "never rendered directly. Please wrap your <Route> in a <Routes>.") : UNSAFE_invariant(false) ;
1129}
1130/**
1131 * Provides location context for the rest of the app.
1132 *
1133 * Note: You usually won't render a `<Router>` directly. Instead, you'll render a
1134 * router that is more specific to your environment such as a `<BrowserRouter>`
1135 * in web browsers or a `<StaticRouter>` for server rendering.
1136 *
1137 * @see https://reactrouter.com/router-components/router
1138 */
1139function Router(_ref5) {
1140 let {
1141 basename: basenameProp = "/",
1142 children = null,
1143 location: locationProp,
1144 navigationType = Action.Pop,
1145 navigator,
1146 static: staticProp = false,
1147 future
1148 } = _ref5;
1149 !!useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : UNSAFE_invariant(false) : void 0;
1150
1151 // Preserve trailing slashes on basename, so we can let the user control
1152 // the enforcement of trailing slashes throughout the app
1153 let basename = basenameProp.replace(/^\/*/, "/");
1154 let navigationContext = React.useMemo(() => ({
1155 basename,
1156 navigator,
1157 static: staticProp,
1158 future: _extends({
1159 v7_relativeSplatPath: false
1160 }, future)
1161 }), [basename, future, navigator, staticProp]);
1162 if (typeof locationProp === "string") {
1163 locationProp = parsePath(locationProp);
1164 }
1165 let {
1166 pathname = "/",
1167 search = "",
1168 hash = "",
1169 state = null,
1170 key = "default"
1171 } = locationProp;
1172 let locationContext = React.useMemo(() => {
1173 let trailingPathname = stripBasename(pathname, basename);
1174 if (trailingPathname == null) {
1175 return null;
1176 }
1177 return {
1178 location: {
1179 pathname: trailingPathname,
1180 search,
1181 hash,
1182 state,
1183 key
1184 },
1185 navigationType
1186 };
1187 }, [basename, pathname, search, hash, state, key, navigationType]);
1188 process.env.NODE_ENV !== "production" ? UNSAFE_warning(locationContext != null, "<Router basename=\"" + basename + "\"> is not able to match the URL " + ("\"" + pathname + search + hash + "\" because it does not start with the ") + "basename, so the <Router> won't render anything.") : void 0;
1189 if (locationContext == null) {
1190 return null;
1191 }
1192 return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
1193 value: navigationContext
1194 }, /*#__PURE__*/React.createElement(LocationContext.Provider, {
1195 children: children,
1196 value: locationContext
1197 }));
1198}
1199/**
1200 * A container for a nested tree of `<Route>` elements that renders the branch
1201 * that best matches the current location.
1202 *
1203 * @see https://reactrouter.com/components/routes
1204 */
1205function Routes(_ref6) {
1206 let {
1207 children,
1208 location
1209 } = _ref6;
1210 return useRoutes(createRoutesFromChildren(children), location);
1211}
1212/**
1213 * Component to use for rendering lazily loaded data from returning defer()
1214 * in a loader function
1215 */
1216function Await(_ref7) {
1217 let {
1218 children,
1219 errorElement,
1220 resolve
1221 } = _ref7;
1222 return /*#__PURE__*/React.createElement(AwaitErrorBoundary, {
1223 resolve: resolve,
1224 errorElement: errorElement
1225 }, /*#__PURE__*/React.createElement(ResolveAwait, null, children));
1226}
1227var AwaitRenderStatus = /*#__PURE__*/function (AwaitRenderStatus) {
1228 AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
1229 AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
1230 AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
1231 return AwaitRenderStatus;
1232}(AwaitRenderStatus || {});
1233const neverSettledPromise = new Promise(() => {});
1234class AwaitErrorBoundary extends React.Component {
1235 constructor(props) {
1236 super(props);
1237 this.state = {
1238 error: null
1239 };
1240 }
1241 static getDerivedStateFromError(error) {
1242 return {
1243 error
1244 };
1245 }
1246 componentDidCatch(error, errorInfo) {
1247 console.error("<Await> caught the following error during render", error, errorInfo);
1248 }
1249 render() {
1250 let {
1251 children,
1252 errorElement,
1253 resolve
1254 } = this.props;
1255 let promise = null;
1256 let status = AwaitRenderStatus.pending;
1257 if (!(resolve instanceof Promise)) {
1258 // Didn't get a promise - provide as a resolved promise
1259 status = AwaitRenderStatus.success;
1260 promise = Promise.resolve();
1261 Object.defineProperty(promise, "_tracked", {
1262 get: () => true
1263 });
1264 Object.defineProperty(promise, "_data", {
1265 get: () => resolve
1266 });
1267 } else if (this.state.error) {
1268 // Caught a render error, provide it as a rejected promise
1269 status = AwaitRenderStatus.error;
1270 let renderError = this.state.error;
1271 promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
1272 Object.defineProperty(promise, "_tracked", {
1273 get: () => true
1274 });
1275 Object.defineProperty(promise, "_error", {
1276 get: () => renderError
1277 });
1278 } else if (resolve._tracked) {
1279 // Already tracked promise - check contents
1280 promise = resolve;
1281 status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
1282 } else {
1283 // Raw (untracked) promise - track it
1284 status = AwaitRenderStatus.pending;
1285 Object.defineProperty(resolve, "_tracked", {
1286 get: () => true
1287 });
1288 promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
1289 get: () => data
1290 }), error => Object.defineProperty(resolve, "_error", {
1291 get: () => error
1292 }));
1293 }
1294 if (status === AwaitRenderStatus.error && promise._error instanceof AbortedDeferredError) {
1295 // Freeze the UI by throwing a never resolved promise
1296 throw neverSettledPromise;
1297 }
1298 if (status === AwaitRenderStatus.error && !errorElement) {
1299 // No errorElement, throw to the nearest route-level error boundary
1300 throw promise._error;
1301 }
1302 if (status === AwaitRenderStatus.error) {
1303 // Render via our errorElement
1304 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1305 value: promise,
1306 children: errorElement
1307 });
1308 }
1309 if (status === AwaitRenderStatus.success) {
1310 // Render children with resolved value
1311 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1312 value: promise,
1313 children: children
1314 });
1315 }
1316
1317 // Throw to the suspense boundary
1318 throw promise;
1319 }
1320}
1321
1322/**
1323 * @private
1324 * Indirection to leverage useAsyncValue for a render-prop API on `<Await>`
1325 */
1326function ResolveAwait(_ref8) {
1327 let {
1328 children
1329 } = _ref8;
1330 let data = useAsyncValue();
1331 let toRender = typeof children === "function" ? children(data) : children;
1332 return /*#__PURE__*/React.createElement(React.Fragment, null, toRender);
1333}
1334
1335///////////////////////////////////////////////////////////////////////////////
1336// UTILS
1337///////////////////////////////////////////////////////////////////////////////
1338
1339/**
1340 * Creates a route config from a React "children" object, which is usually
1341 * either a `<Route>` element or an array of them. Used internally by
1342 * `<Routes>` to create a route config from its children.
1343 *
1344 * @see https://reactrouter.com/utils/create-routes-from-children
1345 */
1346function createRoutesFromChildren(children, parentPath) {
1347 if (parentPath === void 0) {
1348 parentPath = [];
1349 }
1350 let routes = [];
1351 React.Children.forEach(children, (element, index) => {
1352 if (! /*#__PURE__*/React.isValidElement(element)) {
1353 // Ignore non-elements. This allows people to more easily inline
1354 // conditionals in their route config.
1355 return;
1356 }
1357 let treePath = [...parentPath, index];
1358 if (element.type === React.Fragment) {
1359 // Transparently support React.Fragment and its children.
1360 routes.push.apply(routes, createRoutesFromChildren(element.props.children, treePath));
1361 return;
1362 }
1363 !(element.type === Route) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "[" + (typeof element.type === "string" ? element.type : element.type.name) + "] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>") : UNSAFE_invariant(false) : void 0;
1364 !(!element.props.index || !element.props.children) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "An index route cannot have child routes.") : UNSAFE_invariant(false) : void 0;
1365 let route = {
1366 id: element.props.id || treePath.join("-"),
1367 caseSensitive: element.props.caseSensitive,
1368 element: element.props.element,
1369 Component: element.props.Component,
1370 index: element.props.index,
1371 path: element.props.path,
1372 loader: element.props.loader,
1373 action: element.props.action,
1374 errorElement: element.props.errorElement,
1375 ErrorBoundary: element.props.ErrorBoundary,
1376 hasErrorBoundary: element.props.ErrorBoundary != null || element.props.errorElement != null,
1377 shouldRevalidate: element.props.shouldRevalidate,
1378 handle: element.props.handle,
1379 lazy: element.props.lazy
1380 };
1381 if (element.props.children) {
1382 route.children = createRoutesFromChildren(element.props.children, treePath);
1383 }
1384 routes.push(route);
1385 });
1386 return routes;
1387}
1388
1389/**
1390 * Renders the result of `matchRoutes()` into a React element.
1391 */
1392function renderMatches(matches) {
1393 return _renderMatches(matches);
1394}
1395
1396function mapRouteProperties(route) {
1397 let updates = {
1398 // Note: this check also occurs in createRoutesFromChildren so update
1399 // there if you change this -- please and thank you!
1400 hasErrorBoundary: route.ErrorBoundary != null || route.errorElement != null
1401 };
1402 if (route.Component) {
1403 if (process.env.NODE_ENV !== "production") {
1404 if (route.element) {
1405 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "You should not include both `Component` and `element` on your route - " + "`Component` will be used.") : void 0;
1406 }
1407 }
1408 Object.assign(updates, {
1409 element: /*#__PURE__*/React.createElement(route.Component),
1410 Component: undefined
1411 });
1412 }
1413 if (route.HydrateFallback) {
1414 if (process.env.NODE_ENV !== "production") {
1415 if (route.hydrateFallbackElement) {
1416 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - " + "`HydrateFallback` will be used.") : void 0;
1417 }
1418 }
1419 Object.assign(updates, {
1420 hydrateFallbackElement: /*#__PURE__*/React.createElement(route.HydrateFallback),
1421 HydrateFallback: undefined
1422 });
1423 }
1424 if (route.ErrorBoundary) {
1425 if (process.env.NODE_ENV !== "production") {
1426 if (route.errorElement) {
1427 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`ErrorBoundary` will be used.") : void 0;
1428 }
1429 }
1430 Object.assign(updates, {
1431 errorElement: /*#__PURE__*/React.createElement(route.ErrorBoundary),
1432 ErrorBoundary: undefined
1433 });
1434 }
1435 return updates;
1436}
1437function createMemoryRouter(routes, opts) {
1438 return createRouter({
1439 basename: opts == null ? void 0 : opts.basename,
1440 future: _extends({}, opts == null ? void 0 : opts.future, {
1441 v7_prependBasename: true
1442 }),
1443 history: createMemoryHistory({
1444 initialEntries: opts == null ? void 0 : opts.initialEntries,
1445 initialIndex: opts == null ? void 0 : opts.initialIndex
1446 }),
1447 hydrationData: opts == null ? void 0 : opts.hydrationData,
1448 routes,
1449 mapRouteProperties
1450 }).initialize();
1451}
1452
1453export { Await, MemoryRouter, Navigate, Outlet, Route, Router, RouterProvider, Routes, DataRouterContext as UNSAFE_DataRouterContext, DataRouterStateContext as UNSAFE_DataRouterStateContext, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, mapRouteProperties as UNSAFE_mapRouteProperties, useRouteId as UNSAFE_useRouteId, useRoutesImpl as UNSAFE_useRoutesImpl, createMemoryRouter, createRoutesFromChildren, createRoutesFromChildren as createRoutesFromElements, renderMatches, useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes };
1454//# sourceMappingURL=index.js.map