UNPKG

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