UNPKG

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