UNPKG

52.9 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
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/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/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/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/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/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, 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/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/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/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/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/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/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?.errors) {
483 // Don't bail if we have data router errors so we can render them in the
484 // boundary. Use the pre-matched (or shimmed) matches
485 matches = dataRouterState.matches;
486 } else {
487 return null;
488 }
489 }
490 let renderedMatches = matches;
491 // If we have data errors, trim matches to the highest error boundary
492 let errors = dataRouterState?.errors;
493 if (errors != null) {
494 let errorIndex = renderedMatches.findIndex(m => m.route.id && errors?.[m.route.id]);
495 !(errorIndex >= 0) ? UNSAFE_invariant(false, `Could not find a matching route for errors on route IDs: ${Object.keys(errors).join(",")}`) : void 0;
496 renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
497 }
498 // If we're in a partial hydration mode, detect if we need to render down to
499 // a given HydrateFallback while we load the rest of the hydration data
500 let renderFallback = false;
501 let fallbackIndex = -1;
502 if (dataRouterState && future && future.v7_partialHydration) {
503 for (let i = 0; i < renderedMatches.length; i++) {
504 let match = renderedMatches[i];
505 // Track the deepest fallback up until the first route without data
506 if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
507 fallbackIndex = i;
508 }
509 if (match.route.id) {
510 let {
511 loaderData,
512 errors: _errors
513 } = dataRouterState;
514 let needsToRunLoader = match.route.loader && loaderData[match.route.id] === undefined && (!_errors || _errors[match.route.id] === undefined);
515 if (match.route.lazy || needsToRunLoader) {
516 // We found the first route that's not ready to render (waiting on
517 // lazy, or has a loader that hasn't run yet). Flag that we need to
518 // render a fallback and render up until the appropriate fallback
519 renderFallback = true;
520 if (fallbackIndex >= 0) {
521 renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
522 } else {
523 renderedMatches = [renderedMatches[0]];
524 }
525 break;
526 }
527 }
528 }
529 }
530 return renderedMatches.reduceRight((outlet, match, index) => {
531 // Only data routers handle errors/fallbacks
532 let error;
533 let shouldRenderHydrateFallback = false;
534 let errorElement = null;
535 let hydrateFallbackElement = null;
536 if (dataRouterState) {
537 error = errors && match.route.id ? errors[match.route.id] : undefined;
538 errorElement = match.route.errorElement || defaultErrorElement;
539 if (renderFallback) {
540 if (fallbackIndex < 0 && index === 0) {
541 warningOnce("route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration");
542 shouldRenderHydrateFallback = true;
543 hydrateFallbackElement = null;
544 } else if (fallbackIndex === index) {
545 shouldRenderHydrateFallback = true;
546 hydrateFallbackElement = match.route.hydrateFallbackElement || null;
547 }
548 }
549 }
550 let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
551 let getChildren = () => {
552 let children;
553 if (error) {
554 children = errorElement;
555 } else if (shouldRenderHydrateFallback) {
556 children = hydrateFallbackElement;
557 } else if (match.route.Component) {
558 // Note: This is a de-optimized path since React won't re-use the
559 // ReactElement since it's identity changes with each new
560 // React.createElement call. We keep this so folks can use
561 // `<Route Component={...}>` in `<Routes>` but generally `Component`
562 // usage is only advised in `RouterProvider` when we can convert it to
563 // `element` ahead of time.
564 children = /*#__PURE__*/React.createElement(match.route.Component, null);
565 } else if (match.route.element) {
566 children = match.route.element;
567 } else {
568 children = outlet;
569 }
570 return /*#__PURE__*/React.createElement(RenderedRoute, {
571 match: match,
572 routeContext: {
573 outlet,
574 matches,
575 isDataRoute: dataRouterState != null
576 },
577 children: children
578 });
579 };
580 // Only wrap in an error boundary within data router usages when we have an
581 // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to
582 // an ancestor ErrorBoundary/errorElement
583 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /*#__PURE__*/React.createElement(RenderErrorBoundary, {
584 location: dataRouterState.location,
585 revalidation: dataRouterState.revalidation,
586 component: errorElement,
587 error: error,
588 children: getChildren(),
589 routeContext: {
590 outlet: null,
591 matches,
592 isDataRoute: true
593 }
594 }) : getChildren();
595 }, null);
596}
597var DataRouterHook;
598(function (DataRouterHook) {
599 DataRouterHook["UseBlocker"] = "useBlocker";
600 DataRouterHook["UseRevalidator"] = "useRevalidator";
601 DataRouterHook["UseNavigateStable"] = "useNavigate";
602})(DataRouterHook || (DataRouterHook = {}));
603var DataRouterStateHook;
604(function (DataRouterStateHook) {
605 DataRouterStateHook["UseBlocker"] = "useBlocker";
606 DataRouterStateHook["UseLoaderData"] = "useLoaderData";
607 DataRouterStateHook["UseActionData"] = "useActionData";
608 DataRouterStateHook["UseRouteError"] = "useRouteError";
609 DataRouterStateHook["UseNavigation"] = "useNavigation";
610 DataRouterStateHook["UseRouteLoaderData"] = "useRouteLoaderData";
611 DataRouterStateHook["UseMatches"] = "useMatches";
612 DataRouterStateHook["UseRevalidator"] = "useRevalidator";
613 DataRouterStateHook["UseNavigateStable"] = "useNavigate";
614 DataRouterStateHook["UseRouteId"] = "useRouteId";
615})(DataRouterStateHook || (DataRouterStateHook = {}));
616function getDataRouterConsoleError(hookName) {
617 return `${hookName} must be used within a data router. See https://reactrouter.com/routers/picking-a-router.`;
618}
619function useDataRouterContext(hookName) {
620 let ctx = React.useContext(DataRouterContext);
621 !ctx ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
622 return ctx;
623}
624function useDataRouterState(hookName) {
625 let state = React.useContext(DataRouterStateContext);
626 !state ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
627 return state;
628}
629function useRouteContext(hookName) {
630 let route = React.useContext(RouteContext);
631 !route ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
632 return route;
633}
634// Internal version with hookName-aware debugging
635function useCurrentRouteId(hookName) {
636 let route = useRouteContext(hookName);
637 let thisRoute = route.matches[route.matches.length - 1];
638 !thisRoute.route.id ? UNSAFE_invariant(false, `${hookName} can only be used on routes that contain a unique "id"`) : void 0;
639 return thisRoute.route.id;
640}
641/**
642 * Returns the ID for the nearest contextual route
643 */
644function useRouteId() {
645 return useCurrentRouteId(DataRouterStateHook.UseRouteId);
646}
647/**
648 * Returns the current navigation, defaulting to an "idle" navigation when
649 * no navigation is in progress
650 */
651function useNavigation() {
652 let state = useDataRouterState(DataRouterStateHook.UseNavigation);
653 return state.navigation;
654}
655/**
656 * Returns a revalidate function for manually triggering revalidation, as well
657 * as the current state of any manual revalidations
658 */
659function useRevalidator() {
660 let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);
661 let state = useDataRouterState(DataRouterStateHook.UseRevalidator);
662 return React.useMemo(() => ({
663 revalidate: dataRouterContext.router.revalidate,
664 state: state.revalidation
665 }), [dataRouterContext.router.revalidate, state.revalidation]);
666}
667/**
668 * Returns the active route matches, useful for accessing loaderData for
669 * parent/child routes or the route "handle" property
670 */
671function useMatches() {
672 let {
673 matches,
674 loaderData
675 } = useDataRouterState(DataRouterStateHook.UseMatches);
676 return React.useMemo(() => matches.map(m => UNSAFE_convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
677}
678/**
679 * Returns the loader data for the nearest ancestor Route loader
680 */
681function useLoaderData() {
682 let state = useDataRouterState(DataRouterStateHook.UseLoaderData);
683 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
684 if (state.errors && state.errors[routeId] != null) {
685 console.error(`You cannot \`useLoaderData\` in an errorElement (routeId: ${routeId})`);
686 return undefined;
687 }
688 return state.loaderData[routeId];
689}
690/**
691 * Returns the loaderData for the given routeId
692 */
693function useRouteLoaderData(routeId) {
694 let state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);
695 return state.loaderData[routeId];
696}
697/**
698 * Returns the action data for the nearest ancestor Route action
699 */
700function useActionData() {
701 let state = useDataRouterState(DataRouterStateHook.UseActionData);
702 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
703 return state.actionData ? state.actionData[routeId] : undefined;
704}
705/**
706 * Returns the nearest ancestor Route error, which could be a loader/action
707 * error or a render error. This is intended to be called from your
708 * ErrorBoundary/errorElement to display a proper error message.
709 */
710function useRouteError() {
711 let error = React.useContext(RouteErrorContext);
712 let state = useDataRouterState(DataRouterStateHook.UseRouteError);
713 let routeId = useCurrentRouteId(DataRouterStateHook.UseRouteError);
714 // If this was a render error, we put it in a RouteError context inside
715 // of RenderErrorBoundary
716 if (error !== undefined) {
717 return error;
718 }
719 // Otherwise look for errors from our data router state
720 return state.errors?.[routeId];
721}
722/**
723 * Returns the happy-path data from the nearest ancestor `<Await />` value
724 */
725function useAsyncValue() {
726 let value = React.useContext(AwaitContext);
727 return value?._data;
728}
729/**
730 * Returns the error from the nearest ancestor `<Await />` value
731 */
732function useAsyncError() {
733 let value = React.useContext(AwaitContext);
734 return value?._error;
735}
736let blockerId = 0;
737/**
738 * Allow the application to block navigations within the SPA and present the
739 * user a confirmation dialog to confirm the navigation. Mostly used to avoid
740 * using half-filled form data. This does not handle hard-reloads or
741 * cross-origin navigations.
742 */
743function useBlocker(shouldBlock) {
744 let {
745 router,
746 basename
747 } = useDataRouterContext(DataRouterHook.UseBlocker);
748 let state = useDataRouterState(DataRouterStateHook.UseBlocker);
749 let [blockerKey, setBlockerKey] = React.useState("");
750 let blockerFunction = React.useCallback(arg => {
751 if (typeof shouldBlock !== "function") {
752 return !!shouldBlock;
753 }
754 if (basename === "/") {
755 return shouldBlock(arg);
756 }
757 // If they provided us a function and we've got an active basename, strip
758 // it from the locations we expose to the user to match the behavior of
759 // useLocation
760 let {
761 currentLocation,
762 nextLocation,
763 historyAction
764 } = arg;
765 return shouldBlock({
766 currentLocation: {
767 ...currentLocation,
768 pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
769 },
770 nextLocation: {
771 ...nextLocation,
772 pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
773 },
774 historyAction
775 });
776 }, [basename, shouldBlock]);
777 // This effect is in charge of blocker key assignment and deletion (which is
778 // tightly coupled to the key)
779 React.useEffect(() => {
780 let key = String(++blockerId);
781 setBlockerKey(key);
782 return () => router.deleteBlocker(key);
783 }, [router]);
784 // This effect handles assigning the blockerFunction. This is to handle
785 // unstable blocker function identities, and happens only after the prior
786 // effect so we don't get an orphaned blockerFunction in the router with a
787 // key of "". Until then we just have the IDLE_BLOCKER.
788 React.useEffect(() => {
789 if (blockerKey !== "") {
790 router.getBlocker(blockerKey, blockerFunction);
791 }
792 }, [router, blockerKey, blockerFunction]);
793 // Prefer the blocker from `state` not `router.state` since DataRouterContext
794 // is memoized so this ensures we update on blocker state updates
795 return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER;
796}
797/**
798 * Stable version of useNavigate that is used when we are in the context of
799 * a RouterProvider.
800 */
801function useNavigateStable() {
802 let {
803 router
804 } = useDataRouterContext(DataRouterHook.UseNavigateStable);
805 let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);
806 let activeRef = React.useRef(false);
807 useIsomorphicLayoutEffect(() => {
808 activeRef.current = true;
809 });
810 let navigate = React.useCallback((to, options = {}) => {
811 UNSAFE_warning(activeRef.current, navigateEffectWarning) ;
812 // Short circuit here since if this happens on first render the navigate
813 // is useless because we haven't wired up our router subscriber yet
814 if (!activeRef.current) return;
815 if (typeof to === "number") {
816 router.navigate(to);
817 } else {
818 router.navigate(to, {
819 fromRouteId: id,
820 ...options
821 });
822 }
823 }, [router, id]);
824 return navigate;
825}
826const alreadyWarned = {};
827function warningOnce(key, cond, message) {
828 if (!cond && !alreadyWarned[key]) {
829 alreadyWarned[key] = true;
830 UNSAFE_warning(false, message) ;
831 }
832}
833
834/**
835 Webpack + React 17 fails to compile on any of the following because webpack
836 complains that `startTransition` doesn't exist in `React`:
837 * import { startTransition } from "react"
838 * import * as React from from "react";
839 "startTransition" in React ? React.startTransition(() => setState()) : setState()
840 * import * as React from from "react";
841 "startTransition" in React ? React["startTransition"](() => setState()) : setState()
842
843 Moving it to a constant such as the following solves the Webpack/React 17 issue:
844 * import * as React from from "react";
845 const START_TRANSITION = "startTransition";
846 START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
847
848 However, that introduces webpack/terser minification issues in production builds
849 in React 18 where minification/obfuscation ends up removing the call of
850 React.startTransition entirely from the first half of the ternary. Grabbing
851 this exported reference once up front resolves that issue.
852
853 See https://github.com/remix-run/react-router/issues/10579
854*/
855const START_TRANSITION = "startTransition";
856const startTransitionImpl = React[START_TRANSITION];
857/**
858 * Given a Remix Router instance, render the appropriate UI
859 */
860function RouterProvider({
861 fallbackElement,
862 router,
863 future
864}) {
865 let [state, setStateImpl] = React.useState(router.state);
866 let {
867 v7_startTransition
868 } = future || {};
869 let setState = React.useCallback(newState => {
870 if (v7_startTransition && startTransitionImpl) {
871 startTransitionImpl(() => setStateImpl(newState));
872 } else {
873 setStateImpl(newState);
874 }
875 }, [setStateImpl, v7_startTransition]);
876 // Need to use a layout effect here so we are subscribed early enough to
877 // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
878 React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
879 React.useEffect(() => {
880 UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") ;
881 // Only log this once on initial mount
882 // eslint-disable-next-line react-hooks/exhaustive-deps
883 }, []);
884 let navigator = React.useMemo(() => {
885 return {
886 createHref: router.createHref,
887 encodeLocation: router.encodeLocation,
888 go: n => router.navigate(n),
889 push: (to, state, opts) => router.navigate(to, {
890 state,
891 preventScrollReset: opts?.preventScrollReset
892 }),
893 replace: (to, state, opts) => router.navigate(to, {
894 replace: true,
895 state,
896 preventScrollReset: opts?.preventScrollReset
897 })
898 };
899 }, [router]);
900 let basename = router.basename || "/";
901 let dataRouterContext = React.useMemo(() => ({
902 router,
903 navigator,
904 static: false,
905 basename
906 }), [router, navigator, basename]);
907 // The fragment and {null} here are important! We need them to keep React 18's
908 // useId happy when we are server-rendering since we may have a <script> here
909 // containing the hydrated server-side staticContext (from StaticRouterProvider).
910 // useId relies on the component tree structure to generate deterministic id's
911 // so we need to ensure it remains the same on the client even though
912 // we don't need the <script> tag
913 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DataRouterContext.Provider, {
914 value: dataRouterContext
915 }, /*#__PURE__*/React.createElement(DataRouterStateContext.Provider, {
916 value: state
917 }, /*#__PURE__*/React.createElement(Router, {
918 basename: basename,
919 location: state.location,
920 navigationType: state.historyAction,
921 navigator: navigator,
922 future: {
923 v7_relativeSplatPath: router.future.v7_relativeSplatPath
924 }
925 }, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/React.createElement(DataRoutes, {
926 routes: router.routes,
927 future: router.future,
928 state: state
929 }) : fallbackElement))), null);
930}
931function DataRoutes({
932 routes,
933 future,
934 state
935}) {
936 return useRoutesImpl(routes, undefined, state, future);
937}
938/**
939 * A `<Router>` that stores all entries in memory.
940 *
941 * @see https://reactrouter.com/router-components/memory-router
942 */
943function MemoryRouter({
944 basename,
945 children,
946 initialEntries,
947 initialIndex,
948 future
949}) {
950 let historyRef = React.useRef();
951 if (historyRef.current == null) {
952 historyRef.current = createMemoryHistory({
953 initialEntries,
954 initialIndex,
955 v5Compat: true
956 });
957 }
958 let history = historyRef.current;
959 let [state, setStateImpl] = React.useState({
960 action: history.action,
961 location: history.location
962 });
963 let {
964 v7_startTransition
965 } = future || {};
966 let setState = React.useCallback(newState => {
967 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
968 }, [setStateImpl, v7_startTransition]);
969 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
970 return /*#__PURE__*/React.createElement(Router, {
971 basename: basename,
972 children: children,
973 location: state.location,
974 navigationType: state.action,
975 navigator: history,
976 future: future
977 });
978}
979/**
980 * Changes the current location.
981 *
982 * Note: This API is mostly useful in React.Component subclasses that are not
983 * able to use hooks. In functional components, we recommend you use the
984 * `useNavigate` hook instead.
985 *
986 * @see https://reactrouter.com/components/navigate
987 */
988function Navigate({
989 to,
990 replace,
991 state,
992 relative
993}) {
994 !useInRouterContext() ? UNSAFE_invariant(false,
995 // TODO: This error is probably because they somehow have 2 versions of
996 // the router loaded. We can help them understand how to avoid that.
997 `<Navigate> may be used only in the context of a <Router> component.`) : void 0;
998 let {
999 future,
1000 static: isStatic
1001 } = React.useContext(NavigationContext);
1002 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.`) ;
1003 let {
1004 matches
1005 } = React.useContext(RouteContext);
1006 let {
1007 pathname: locationPathname
1008 } = useLocation();
1009 let navigate = useNavigate();
1010 // Resolve the path outside of the effect so that when effects run twice in
1011 // StrictMode they navigate to the same place
1012 let path = resolveTo(to, UNSAFE_getResolveToMatches(matches, future.v7_relativeSplatPath), locationPathname, relative === "path");
1013 let jsonPath = JSON.stringify(path);
1014 React.useEffect(() => navigate(JSON.parse(jsonPath), {
1015 replace,
1016 state,
1017 relative
1018 }), [navigate, jsonPath, relative, replace, state]);
1019 return null;
1020}
1021/**
1022 * Renders the child route's element, if there is one.
1023 *
1024 * @see https://reactrouter.com/components/outlet
1025 */
1026function Outlet(props) {
1027 return useOutlet(props.context);
1028}
1029/**
1030 * Declares an element that should be rendered at a certain URL path.
1031 *
1032 * @see https://reactrouter.com/components/route
1033 */
1034function Route(_props) {
1035 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>.`) ;
1036}
1037/**
1038 * Provides location context for the rest of the app.
1039 *
1040 * Note: You usually won't render a `<Router>` directly. Instead, you'll render a
1041 * router that is more specific to your environment such as a `<BrowserRouter>`
1042 * in web browsers or a `<StaticRouter>` for server rendering.
1043 *
1044 * @see https://reactrouter.com/router-components/router
1045 */
1046function Router({
1047 basename: basenameProp = "/",
1048 children = null,
1049 location: locationProp,
1050 navigationType = Action.Pop,
1051 navigator,
1052 static: staticProp = false,
1053 future
1054}) {
1055 !!useInRouterContext() ? UNSAFE_invariant(false, `You cannot render a <Router> inside another <Router>.` + ` You should never have more than one in your app.`) : void 0;
1056 // Preserve trailing slashes on basename, so we can let the user control
1057 // the enforcement of trailing slashes throughout the app
1058 let basename = basenameProp.replace(/^\/*/, "/");
1059 let navigationContext = React.useMemo(() => ({
1060 basename,
1061 navigator,
1062 static: staticProp,
1063 future: {
1064 v7_relativeSplatPath: false,
1065 ...future
1066 }
1067 }), [basename, future, navigator, staticProp]);
1068 if (typeof locationProp === "string") {
1069 locationProp = parsePath(locationProp);
1070 }
1071 let {
1072 pathname = "/",
1073 search = "",
1074 hash = "",
1075 state = null,
1076 key = "default"
1077 } = locationProp;
1078 let locationContext = React.useMemo(() => {
1079 let trailingPathname = stripBasename(pathname, basename);
1080 if (trailingPathname == null) {
1081 return null;
1082 }
1083 return {
1084 location: {
1085 pathname: trailingPathname,
1086 search,
1087 hash,
1088 state,
1089 key
1090 },
1091 navigationType
1092 };
1093 }, [basename, pathname, search, hash, state, key, navigationType]);
1094 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.`) ;
1095 if (locationContext == null) {
1096 return null;
1097 }
1098 return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
1099 value: navigationContext
1100 }, /*#__PURE__*/React.createElement(LocationContext.Provider, {
1101 children: children,
1102 value: locationContext
1103 }));
1104}
1105/**
1106 * A container for a nested tree of `<Route>` elements that renders the branch
1107 * that best matches the current location.
1108 *
1109 * @see https://reactrouter.com/components/routes
1110 */
1111function Routes({
1112 children,
1113 location
1114}) {
1115 return useRoutes(createRoutesFromChildren(children), location);
1116}
1117/**
1118 * Component to use for rendering lazily loaded data from returning defer()
1119 * in a loader function
1120 */
1121function Await({
1122 children,
1123 errorElement,
1124 resolve
1125}) {
1126 return /*#__PURE__*/React.createElement(AwaitErrorBoundary, {
1127 resolve: resolve,
1128 errorElement: errorElement
1129 }, /*#__PURE__*/React.createElement(ResolveAwait, null, children));
1130}
1131var AwaitRenderStatus;
1132(function (AwaitRenderStatus) {
1133 AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
1134 AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
1135 AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
1136})(AwaitRenderStatus || (AwaitRenderStatus = {}));
1137const neverSettledPromise = new Promise(() => {});
1138class AwaitErrorBoundary extends React.Component {
1139 constructor(props) {
1140 super(props);
1141 this.state = {
1142 error: null
1143 };
1144 }
1145 static getDerivedStateFromError(error) {
1146 return {
1147 error
1148 };
1149 }
1150 componentDidCatch(error, errorInfo) {
1151 console.error("<Await> caught the following error during render", error, errorInfo);
1152 }
1153 render() {
1154 let {
1155 children,
1156 errorElement,
1157 resolve
1158 } = this.props;
1159 let promise = null;
1160 let status = AwaitRenderStatus.pending;
1161 if (!(resolve instanceof Promise)) {
1162 // Didn't get a promise - provide as a resolved promise
1163 status = AwaitRenderStatus.success;
1164 promise = Promise.resolve();
1165 Object.defineProperty(promise, "_tracked", {
1166 get: () => true
1167 });
1168 Object.defineProperty(promise, "_data", {
1169 get: () => resolve
1170 });
1171 } else if (this.state.error) {
1172 // Caught a render error, provide it as a rejected promise
1173 status = AwaitRenderStatus.error;
1174 let renderError = this.state.error;
1175 promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
1176 Object.defineProperty(promise, "_tracked", {
1177 get: () => true
1178 });
1179 Object.defineProperty(promise, "_error", {
1180 get: () => renderError
1181 });
1182 } else if (resolve._tracked) {
1183 // Already tracked promise - check contents
1184 promise = resolve;
1185 status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
1186 } else {
1187 // Raw (untracked) promise - track it
1188 status = AwaitRenderStatus.pending;
1189 Object.defineProperty(resolve, "_tracked", {
1190 get: () => true
1191 });
1192 promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
1193 get: () => data
1194 }), error => Object.defineProperty(resolve, "_error", {
1195 get: () => error
1196 }));
1197 }
1198 if (status === AwaitRenderStatus.error && promise._error instanceof AbortedDeferredError) {
1199 // Freeze the UI by throwing a never resolved promise
1200 throw neverSettledPromise;
1201 }
1202 if (status === AwaitRenderStatus.error && !errorElement) {
1203 // No errorElement, throw to the nearest route-level error boundary
1204 throw promise._error;
1205 }
1206 if (status === AwaitRenderStatus.error) {
1207 // Render via our errorElement
1208 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1209 value: promise,
1210 children: errorElement
1211 });
1212 }
1213 if (status === AwaitRenderStatus.success) {
1214 // Render children with resolved value
1215 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1216 value: promise,
1217 children: children
1218 });
1219 }
1220 // Throw to the suspense boundary
1221 throw promise;
1222 }
1223}
1224/**
1225 * @private
1226 * Indirection to leverage useAsyncValue for a render-prop API on `<Await>`
1227 */
1228function ResolveAwait({
1229 children
1230}) {
1231 let data = useAsyncValue();
1232 let toRender = typeof children === "function" ? children(data) : children;
1233 return /*#__PURE__*/React.createElement(React.Fragment, null, toRender);
1234}
1235///////////////////////////////////////////////////////////////////////////////
1236// UTILS
1237///////////////////////////////////////////////////////////////////////////////
1238/**
1239 * Creates a route config from a React "children" object, which is usually
1240 * either a `<Route>` element or an array of them. Used internally by
1241 * `<Routes>` to create a route config from its children.
1242 *
1243 * @see https://reactrouter.com/utils/create-routes-from-children
1244 */
1245function createRoutesFromChildren(children, parentPath = []) {
1246 let routes = [];
1247 React.Children.forEach(children, (element, index) => {
1248 if (! /*#__PURE__*/React.isValidElement(element)) {
1249 // Ignore non-elements. This allows people to more easily inline
1250 // conditionals in their route config.
1251 return;
1252 }
1253 let treePath = [...parentPath, index];
1254 if (element.type === React.Fragment) {
1255 // Transparently support React.Fragment and its children.
1256 routes.push.apply(routes, createRoutesFromChildren(element.props.children, treePath));
1257 return;
1258 }
1259 !(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;
1260 !(!element.props.index || !element.props.children) ? UNSAFE_invariant(false, "An index route cannot have child routes.") : void 0;
1261 let route = {
1262 id: element.props.id || treePath.join("-"),
1263 caseSensitive: element.props.caseSensitive,
1264 element: element.props.element,
1265 Component: element.props.Component,
1266 index: element.props.index,
1267 path: element.props.path,
1268 loader: element.props.loader,
1269 action: element.props.action,
1270 errorElement: element.props.errorElement,
1271 ErrorBoundary: element.props.ErrorBoundary,
1272 hasErrorBoundary: element.props.ErrorBoundary != null || element.props.errorElement != null,
1273 shouldRevalidate: element.props.shouldRevalidate,
1274 handle: element.props.handle,
1275 lazy: element.props.lazy
1276 };
1277 if (element.props.children) {
1278 route.children = createRoutesFromChildren(element.props.children, treePath);
1279 }
1280 routes.push(route);
1281 });
1282 return routes;
1283}
1284/**
1285 * Renders the result of `matchRoutes()` into a React element.
1286 */
1287function renderMatches(matches) {
1288 return _renderMatches(matches);
1289}
1290
1291function mapRouteProperties(route) {
1292 let updates = {
1293 // Note: this check also occurs in createRoutesFromChildren so update
1294 // there if you change this -- please and thank you!
1295 hasErrorBoundary: route.ErrorBoundary != null || route.errorElement != null
1296 };
1297 if (route.Component) {
1298 {
1299 if (route.element) {
1300 UNSAFE_warning(false, "You should not include both `Component` and `element` on your route - " + "`Component` will be used.") ;
1301 }
1302 }
1303 Object.assign(updates, {
1304 element: /*#__PURE__*/React.createElement(route.Component),
1305 Component: undefined
1306 });
1307 }
1308 if (route.HydrateFallback) {
1309 {
1310 if (route.hydrateFallbackElement) {
1311 UNSAFE_warning(false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - " + "`HydrateFallback` will be used.") ;
1312 }
1313 }
1314 Object.assign(updates, {
1315 hydrateFallbackElement: /*#__PURE__*/React.createElement(route.HydrateFallback),
1316 HydrateFallback: undefined
1317 });
1318 }
1319 if (route.ErrorBoundary) {
1320 {
1321 if (route.errorElement) {
1322 UNSAFE_warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`ErrorBoundary` will be used.") ;
1323 }
1324 }
1325 Object.assign(updates, {
1326 errorElement: /*#__PURE__*/React.createElement(route.ErrorBoundary),
1327 ErrorBoundary: undefined
1328 });
1329 }
1330 return updates;
1331}
1332function createMemoryRouter(routes, opts) {
1333 return createRouter({
1334 basename: opts?.basename,
1335 future: {
1336 ...opts?.future,
1337 v7_prependBasename: true
1338 },
1339 history: createMemoryHistory({
1340 initialEntries: opts?.initialEntries,
1341 initialIndex: opts?.initialIndex
1342 }),
1343 hydrationData: opts?.hydrationData,
1344 routes,
1345 mapRouteProperties
1346 }).initialize();
1347}
1348
1349export { 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 };
1350//# sourceMappingURL=react-router.development.js.map