react-router 0.0.0-experimental-e56aa53bc → 0.0.0-experimental-e6fb6e074

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