react-router.development.js 46 KB

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