UNPKG

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