UNPKG

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