UNPKG

35.2 kBJavaScriptView Raw
1/**
2 * React Router v6.3.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11(function (global, factory) {
12 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('history'), require('react')) :
13 typeof define === 'function' && define.amd ? define(['exports', 'history', 'react'], factory) :
14 (global = global || self, factory(global.ReactRouter = {}, global.HistoryLibrary, global.React));
15}(this, (function (exports, history, React) { 'use strict';
16
17 const NavigationContext = /*#__PURE__*/React.createContext(null);
18
19 {
20 NavigationContext.displayName = "Navigation";
21 }
22
23 const LocationContext = /*#__PURE__*/React.createContext(null);
24
25 {
26 LocationContext.displayName = "Location";
27 }
28
29 const RouteContext = /*#__PURE__*/React.createContext({
30 outlet: null,
31 matches: []
32 });
33
34 {
35 RouteContext.displayName = "Route";
36 }
37
38 function invariant(cond, message) {
39 if (!cond) throw new Error(message);
40 }
41 function warning(cond, message) {
42 if (!cond) {
43 // eslint-disable-next-line no-console
44 if (typeof console !== "undefined") console.warn(message);
45
46 try {
47 // Welcome to debugging React Router!
48 //
49 // This error is thrown as a convenience so you can more easily
50 // find the source for a warning that appears in the console by
51 // enabling "pause on exceptions" in your JavaScript debugger.
52 throw new Error(message); // eslint-disable-next-line no-empty
53 } catch (e) {}
54 }
55 }
56 const alreadyWarned = {};
57 function warningOnce(key, cond, message) {
58 if (!cond && !alreadyWarned[key]) {
59 alreadyWarned[key] = true;
60 warning(false, message) ;
61 }
62 }
63
64 /**
65 * Returns a path with params interpolated.
66 *
67 * @see https://reactrouter.com/docs/en/v6/api#generatepath
68 */
69 function generatePath(path, params) {
70 if (params === void 0) {
71 params = {};
72 }
73
74 return path.replace(/:(\w+)/g, (_, key) => {
75 !(params[key] != null) ? invariant(false, "Missing \":" + key + "\" param") : void 0;
76 return params[key];
77 }).replace(/\/*\*$/, _ => params["*"] == null ? "" : params["*"].replace(/^\/*/, "/"));
78 }
79 /**
80 * A RouteMatch contains info about how a route matched a URL.
81 */
82
83 /**
84 * Matches the given routes to a location and returns the match data.
85 *
86 * @see https://reactrouter.com/docs/en/v6/api#matchroutes
87 */
88 function matchRoutes(routes, locationArg, basename) {
89 if (basename === void 0) {
90 basename = "/";
91 }
92
93 let location = typeof locationArg === "string" ? history.parsePath(locationArg) : locationArg;
94 let pathname = stripBasename(location.pathname || "/", basename);
95
96 if (pathname == null) {
97 return null;
98 }
99
100 let branches = flattenRoutes(routes);
101 rankRouteBranches(branches);
102 let matches = null;
103
104 for (let i = 0; matches == null && i < branches.length; ++i) {
105 matches = matchRouteBranch(branches[i], pathname);
106 }
107
108 return matches;
109 }
110
111 function flattenRoutes(routes, branches, parentsMeta, parentPath) {
112 if (branches === void 0) {
113 branches = [];
114 }
115
116 if (parentsMeta === void 0) {
117 parentsMeta = [];
118 }
119
120 if (parentPath === void 0) {
121 parentPath = "";
122 }
123
124 routes.forEach((route, index) => {
125 let meta = {
126 relativePath: route.path || "",
127 caseSensitive: route.caseSensitive === true,
128 childrenIndex: index,
129 route
130 };
131
132 if (meta.relativePath.startsWith("/")) {
133 !meta.relativePath.startsWith(parentPath) ? invariant(false, "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes.") : void 0;
134 meta.relativePath = meta.relativePath.slice(parentPath.length);
135 }
136
137 let path = joinPaths([parentPath, meta.relativePath]);
138 let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
139 // route tree depth-first and child routes appear before their parents in
140 // the "flattened" version.
141
142 if (route.children && route.children.length > 0) {
143 !(route.index !== true) ? invariant(false, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")) : void 0;
144 flattenRoutes(route.children, branches, routesMeta, path);
145 } // Routes without a path shouldn't ever match by themselves unless they are
146 // index routes, so don't add them to the list of possible branches.
147
148
149 if (route.path == null && !route.index) {
150 return;
151 }
152
153 branches.push({
154 path,
155 score: computeScore(path, route.index),
156 routesMeta
157 });
158 });
159 return branches;
160 }
161
162 function rankRouteBranches(branches) {
163 branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
164 : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
165 }
166
167 const paramRe = /^:\w+$/;
168 const dynamicSegmentValue = 3;
169 const indexRouteValue = 2;
170 const emptySegmentValue = 1;
171 const staticSegmentValue = 10;
172 const splatPenalty = -2;
173
174 const isSplat = s => s === "*";
175
176 function computeScore(path, index) {
177 let segments = path.split("/");
178 let initialScore = segments.length;
179
180 if (segments.some(isSplat)) {
181 initialScore += splatPenalty;
182 }
183
184 if (index) {
185 initialScore += indexRouteValue;
186 }
187
188 return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
189 }
190
191 function compareIndexes(a, b) {
192 let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
193 return siblings ? // If two routes are siblings, we should try to match the earlier sibling
194 // first. This allows people to have fine-grained control over the matching
195 // behavior by simply putting routes with identical paths in the order they
196 // want them tried.
197 a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
198 // so they sort equally.
199 0;
200 }
201
202 function matchRouteBranch(branch, pathname) {
203 let {
204 routesMeta
205 } = branch;
206 let matchedParams = {};
207 let matchedPathname = "/";
208 let matches = [];
209
210 for (let i = 0; i < routesMeta.length; ++i) {
211 let meta = routesMeta[i];
212 let end = i === routesMeta.length - 1;
213 let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
214 let match = matchPath({
215 path: meta.relativePath,
216 caseSensitive: meta.caseSensitive,
217 end
218 }, remainingPathname);
219 if (!match) return null;
220 Object.assign(matchedParams, match.params);
221 let route = meta.route;
222 matches.push({
223 params: matchedParams,
224 pathname: joinPaths([matchedPathname, match.pathname]),
225 pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
226 route
227 });
228
229 if (match.pathnameBase !== "/") {
230 matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
231 }
232 }
233
234 return matches;
235 }
236 /**
237 * A PathPattern is used to match on some portion of a URL pathname.
238 */
239
240
241 /**
242 * Performs pattern matching on a URL pathname and returns information about
243 * the match.
244 *
245 * @see https://reactrouter.com/docs/en/v6/api#matchpath
246 */
247 function matchPath(pattern, pathname) {
248 if (typeof pattern === "string") {
249 pattern = {
250 path: pattern,
251 caseSensitive: false,
252 end: true
253 };
254 }
255
256 let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
257 let match = pathname.match(matcher);
258 if (!match) return null;
259 let matchedPathname = match[0];
260 let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
261 let captureGroups = match.slice(1);
262 let params = paramNames.reduce((memo, paramName, index) => {
263 // We need to compute the pathnameBase here using the raw splat value
264 // instead of using params["*"] later because it will be decoded then
265 if (paramName === "*") {
266 let splatValue = captureGroups[index] || "";
267 pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
268 }
269
270 memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
271 return memo;
272 }, {});
273 return {
274 params,
275 pathname: matchedPathname,
276 pathnameBase,
277 pattern
278 };
279 }
280
281 function compilePath(path, caseSensitive, end) {
282 if (caseSensitive === void 0) {
283 caseSensitive = false;
284 }
285
286 if (end === void 0) {
287 end = true;
288 }
289
290 warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")) ;
291 let paramNames = [];
292 let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
293 .replace(/^\/*/, "/") // Make sure it has a leading /
294 .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
295 .replace(/:(\w+)/g, (_, paramName) => {
296 paramNames.push(paramName);
297 return "([^\\/]+)";
298 });
299
300 if (path.endsWith("*")) {
301 paramNames.push("*");
302 regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
303 : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
304 } else {
305 regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
306 : // Otherwise, match a word boundary or a proceeding /. The word boundary restricts
307 // parent routes to matching only their own words and nothing more, e.g. parent
308 // route "/home" should not match "/home2".
309 // Additionally, allow paths starting with `.`, `-`, `~`, and url-encoded entities,
310 // but do not consume the character in the matched path so they can match against
311 // nested paths.
312 "(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";
313 }
314
315 let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
316 return [matcher, paramNames];
317 }
318
319 function safelyDecodeURIComponent(value, paramName) {
320 try {
321 return decodeURIComponent(value);
322 } catch (error) {
323 warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ").")) ;
324 return value;
325 }
326 }
327 /**
328 * Returns a resolved path object relative to the given pathname.
329 *
330 * @see https://reactrouter.com/docs/en/v6/api#resolvepath
331 */
332
333
334 function resolvePath(to, fromPathname) {
335 if (fromPathname === void 0) {
336 fromPathname = "/";
337 }
338
339 let {
340 pathname: toPathname,
341 search = "",
342 hash = ""
343 } = typeof to === "string" ? history.parsePath(to) : to;
344 let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
345 return {
346 pathname,
347 search: normalizeSearch(search),
348 hash: normalizeHash(hash)
349 };
350 }
351
352 function resolvePathname(relativePath, fromPathname) {
353 let segments = fromPathname.replace(/\/+$/, "").split("/");
354 let relativeSegments = relativePath.split("/");
355 relativeSegments.forEach(segment => {
356 if (segment === "..") {
357 // Keep the root "" segment so the pathname starts at /
358 if (segments.length > 1) segments.pop();
359 } else if (segment !== ".") {
360 segments.push(segment);
361 }
362 });
363 return segments.length > 1 ? segments.join("/") : "/";
364 }
365
366 function resolveTo(toArg, routePathnames, locationPathname) {
367 let to = typeof toArg === "string" ? history.parsePath(toArg) : toArg;
368 let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
369 // route context. This is explained in `Note on `<Link to>` values` in our
370 // migration guide from v5 as a means of disambiguation between `to` values
371 // that begin with `/` and those that do not. However, this is problematic for
372 // `to` values that do not provide a pathname. `to` can simply be a search or
373 // hash string, in which case we should assume that the navigation is relative
374 // to the current location's pathname and *not* the route pathname.
375
376 let from;
377
378 if (toPathname == null) {
379 from = locationPathname;
380 } else {
381 let routePathnameIndex = routePathnames.length - 1;
382
383 if (toPathname.startsWith("..")) {
384 let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
385 // URL segment". This is a key difference from how <a href> works and a
386 // major reason we call this a "to" value instead of a "href".
387
388 while (toSegments[0] === "..") {
389 toSegments.shift();
390 routePathnameIndex -= 1;
391 }
392
393 to.pathname = toSegments.join("/");
394 } // If there are more ".." segments than parent routes, resolve relative to
395 // the root / URL.
396
397
398 from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
399 }
400
401 let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
402
403 if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
404 path.pathname += "/";
405 }
406
407 return path;
408 }
409 function getToPathname(to) {
410 // Empty strings should be treated the same as / paths
411 return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? history.parsePath(to).pathname : to.pathname;
412 }
413 function stripBasename(pathname, basename) {
414 if (basename === "/") return pathname;
415
416 if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
417 return null;
418 }
419
420 let nextChar = pathname.charAt(basename.length);
421
422 if (nextChar && nextChar !== "/") {
423 // pathname does not start with basename/
424 return null;
425 }
426
427 return pathname.slice(basename.length) || "/";
428 }
429 const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
430 const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
431
432 const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
433
434 const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
435
436 /**
437 * Returns the full href for the given "to" value. This is useful for building
438 * custom links that are also accessible and preserve right-click behavior.
439 *
440 * @see https://reactrouter.com/docs/en/v6/api#usehref
441 */
442
443 function useHref(to) {
444 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
445 // router loaded. We can help them understand how to avoid that.
446 "useHref() may be used only in the context of a <Router> component.") : void 0;
447 let {
448 basename,
449 navigator
450 } = React.useContext(NavigationContext);
451 let {
452 hash,
453 pathname,
454 search
455 } = useResolvedPath(to);
456 let joinedPathname = pathname;
457
458 if (basename !== "/") {
459 let toPathname = getToPathname(to);
460 let endsWithSlash = toPathname != null && toPathname.endsWith("/");
461 joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
462 }
463
464 return navigator.createHref({
465 pathname: joinedPathname,
466 search,
467 hash
468 });
469 }
470 /**
471 * Returns true if this component is a descendant of a <Router>.
472 *
473 * @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
474 */
475
476 function useInRouterContext() {
477 return React.useContext(LocationContext) != null;
478 }
479 /**
480 * Returns the current location object, which represents the current URL in web
481 * browsers.
482 *
483 * Note: If you're using this it may mean you're doing some of your own
484 * "routing" in your app, and we'd like to know what your use case is. We may
485 * be able to provide something higher-level to better suit your needs.
486 *
487 * @see https://reactrouter.com/docs/en/v6/api#uselocation
488 */
489
490 function useLocation() {
491 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
492 // router loaded. We can help them understand how to avoid that.
493 "useLocation() may be used only in the context of a <Router> component.") : void 0;
494 return React.useContext(LocationContext).location;
495 }
496 /**
497 * Returns the current navigation action which describes how the router came to
498 * the current location, either by a pop, push, or replace on the history stack.
499 *
500 * @see https://reactrouter.com/docs/en/v6/api#usenavigationtype
501 */
502
503 function useNavigationType() {
504 return React.useContext(LocationContext).navigationType;
505 }
506 /**
507 * Returns true if the URL for the given "to" value matches the current URL.
508 * This is useful for components that need to know "active" state, e.g.
509 * <NavLink>.
510 *
511 * @see https://reactrouter.com/docs/en/v6/api#usematch
512 */
513
514 function useMatch(pattern) {
515 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
516 // router loaded. We can help them understand how to avoid that.
517 "useMatch() may be used only in the context of a <Router> component.") : void 0;
518 let {
519 pathname
520 } = useLocation();
521 return React.useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
522 }
523 /**
524 * The interface for the navigate() function returned from useNavigate().
525 */
526
527 /**
528 * Returns an imperative method for changing the location. Used by <Link>s, but
529 * may also be used by other elements to change the location.
530 *
531 * @see https://reactrouter.com/docs/en/v6/api#usenavigate
532 */
533 function useNavigate() {
534 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
535 // router loaded. We can help them understand how to avoid that.
536 "useNavigate() may be used only in the context of a <Router> component.") : void 0;
537 let {
538 basename,
539 navigator
540 } = React.useContext(NavigationContext);
541 let {
542 matches
543 } = React.useContext(RouteContext);
544 let {
545 pathname: locationPathname
546 } = useLocation();
547 let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
548 let activeRef = React.useRef(false);
549 React.useEffect(() => {
550 activeRef.current = true;
551 });
552 let navigate = React.useCallback(function (to, options) {
553 if (options === void 0) {
554 options = {};
555 }
556
557 warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") ;
558 if (!activeRef.current) return;
559
560 if (typeof to === "number") {
561 navigator.go(to);
562 return;
563 }
564
565 let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
566
567 if (basename !== "/") {
568 path.pathname = joinPaths([basename, path.pathname]);
569 }
570
571 (!!options.replace ? navigator.replace : navigator.push)(path, options.state);
572 }, [basename, navigator, routePathnamesJson, locationPathname]);
573 return navigate;
574 }
575 const OutletContext = /*#__PURE__*/React.createContext(null);
576 /**
577 * Returns the context (if provided) for the child route at this level of the route
578 * hierarchy.
579 * @see https://reactrouter.com/docs/en/v6/api#useoutletcontext
580 */
581
582 function useOutletContext() {
583 return React.useContext(OutletContext);
584 }
585 /**
586 * Returns the element for the child route at this level of the route
587 * hierarchy. Used internally by <Outlet> to render child routes.
588 *
589 * @see https://reactrouter.com/docs/en/v6/api#useoutlet
590 */
591
592 function useOutlet(context) {
593 let outlet = React.useContext(RouteContext).outlet;
594
595 if (outlet) {
596 return /*#__PURE__*/React.createElement(OutletContext.Provider, {
597 value: context
598 }, outlet);
599 }
600
601 return outlet;
602 }
603 /**
604 * Returns an object of key/value pairs of the dynamic params from the current
605 * URL that were matched by the route path.
606 *
607 * @see https://reactrouter.com/docs/en/v6/api#useparams
608 */
609
610 function useParams() {
611 let {
612 matches
613 } = React.useContext(RouteContext);
614 let routeMatch = matches[matches.length - 1];
615 return routeMatch ? routeMatch.params : {};
616 }
617 /**
618 * Resolves the pathname of the given `to` value against the current location.
619 *
620 * @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
621 */
622
623 function useResolvedPath(to) {
624 let {
625 matches
626 } = React.useContext(RouteContext);
627 let {
628 pathname: locationPathname
629 } = useLocation();
630 let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
631 return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
632 }
633 /**
634 * Returns the element of the route that matched the current location, prepared
635 * with the correct context to render the remainder of the route tree. Route
636 * elements in the tree must render an <Outlet> to render their child route's
637 * element.
638 *
639 * @see https://reactrouter.com/docs/en/v6/api#useroutes
640 */
641
642 function useRoutes(routes, locationArg) {
643 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
644 // router loaded. We can help them understand how to avoid that.
645 "useRoutes() may be used only in the context of a <Router> component.") : void 0;
646 let {
647 matches: parentMatches
648 } = React.useContext(RouteContext);
649 let routeMatch = parentMatches[parentMatches.length - 1];
650 let parentParams = routeMatch ? routeMatch.params : {};
651 let parentPathname = routeMatch ? routeMatch.pathname : "/";
652 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
653 let parentRoute = routeMatch && routeMatch.route;
654
655 {
656 // You won't get a warning about 2 different <Routes> under a <Route>
657 // without a trailing *, but this is a best-effort warning anyway since we
658 // cannot even give the warning unless they land at the parent route.
659 //
660 // Example:
661 //
662 // <Routes>
663 // {/* This route path MUST end with /* because otherwise
664 // it will never match /blog/post/123 */}
665 // <Route path="blog" element={<Blog />} />
666 // <Route path="blog/feed" element={<BlogFeed />} />
667 // </Routes>
668 //
669 // function Blog() {
670 // return (
671 // <Routes>
672 // <Route path="post/:id" element={<Post />} />
673 // </Routes>
674 // );
675 // }
676 let parentPath = parentRoute && parentRoute.path || "";
677 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 + "/*") + "\">."));
678 }
679
680 let locationFromContext = useLocation();
681 let location;
682
683 if (locationArg) {
684 var _parsedLocationArg$pa;
685
686 let parsedLocationArg = typeof locationArg === "string" ? history.parsePath(locationArg) : locationArg;
687 !(parentPathnameBase === "/" || ((_parsedLocationArg$pa = parsedLocationArg.pathname) == null ? void 0 : _parsedLocationArg$pa.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;
688 location = parsedLocationArg;
689 } else {
690 location = locationFromContext;
691 }
692
693 let pathname = location.pathname || "/";
694 let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
695 let matches = matchRoutes(routes, {
696 pathname: remainingPathname
697 });
698
699 {
700 warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") ;
701 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.") ;
702 }
703
704 return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
705 params: Object.assign({}, parentParams, match.params),
706 pathname: joinPaths([parentPathnameBase, match.pathname]),
707 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
708 })), parentMatches);
709 }
710 function _renderMatches(matches, parentMatches) {
711 if (parentMatches === void 0) {
712 parentMatches = [];
713 }
714
715 if (matches == null) return null;
716 return matches.reduceRight((outlet, match, index) => {
717 return /*#__PURE__*/React.createElement(RouteContext.Provider, {
718 children: match.route.element !== undefined ? match.route.element : outlet,
719 value: {
720 outlet,
721 matches: parentMatches.concat(matches.slice(0, index + 1))
722 }
723 });
724 }, null);
725 }
726
727 /**
728 * A <Router> that stores all entries in memory.
729 *
730 * @see https://reactrouter.com/docs/en/v6/api#memoryrouter
731 */
732 function MemoryRouter(_ref) {
733 let {
734 basename,
735 children,
736 initialEntries,
737 initialIndex
738 } = _ref;
739 let historyRef = React.useRef();
740
741 if (historyRef.current == null) {
742 historyRef.current = history.createMemoryHistory({
743 initialEntries,
744 initialIndex
745 });
746 }
747
748 let history$1 = historyRef.current;
749 let [state, setState] = React.useState({
750 action: history$1.action,
751 location: history$1.location
752 });
753 React.useLayoutEffect(() => history$1.listen(setState), [history$1]);
754 return /*#__PURE__*/React.createElement(Router, {
755 basename: basename,
756 children: children,
757 location: state.location,
758 navigationType: state.action,
759 navigator: history$1
760 });
761 }
762
763 /**
764 * Changes the current location.
765 *
766 * Note: This API is mostly useful in React.Component subclasses that are not
767 * able to use hooks. In functional components, we recommend you use the
768 * `useNavigate` hook instead.
769 *
770 * @see https://reactrouter.com/docs/en/v6/api#navigate
771 */
772 function Navigate(_ref2) {
773 let {
774 to,
775 replace,
776 state
777 } = _ref2;
778 !useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
779 // the router loaded. We can help them understand how to avoid that.
780 "<Navigate> may be used only in the context of a <Router> component.") : void 0;
781 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.") ;
782 let navigate = useNavigate();
783 React.useEffect(() => {
784 navigate(to, {
785 replace,
786 state
787 });
788 });
789 return null;
790 }
791
792 /**
793 * Renders the child route's element, if there is one.
794 *
795 * @see https://reactrouter.com/docs/en/v6/api#outlet
796 */
797 function Outlet(props) {
798 return useOutlet(props.context);
799 }
800
801 /**
802 * Declares an element that should be rendered at a certain URL path.
803 *
804 * @see https://reactrouter.com/docs/en/v6/api#route
805 */
806 function Route(_props) {
807 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>.") ;
808 }
809
810 /**
811 * Provides location context for the rest of the app.
812 *
813 * Note: You usually won't render a <Router> directly. Instead, you'll render a
814 * router that is more specific to your environment such as a <BrowserRouter>
815 * in web browsers or a <StaticRouter> for server rendering.
816 *
817 * @see https://reactrouter.com/docs/en/v6/api#router
818 */
819 function Router(_ref3) {
820 let {
821 basename: basenameProp = "/",
822 children = null,
823 location: locationProp,
824 navigationType = history.Action.Pop,
825 navigator,
826 static: staticProp = false
827 } = _ref3;
828 !!useInRouterContext() ? invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : void 0;
829 let basename = normalizePathname(basenameProp);
830 let navigationContext = React.useMemo(() => ({
831 basename,
832 navigator,
833 static: staticProp
834 }), [basename, navigator, staticProp]);
835
836 if (typeof locationProp === "string") {
837 locationProp = history.parsePath(locationProp);
838 }
839
840 let {
841 pathname = "/",
842 search = "",
843 hash = "",
844 state = null,
845 key = "default"
846 } = locationProp;
847 let location = React.useMemo(() => {
848 let trailingPathname = stripBasename(pathname, basename);
849
850 if (trailingPathname == null) {
851 return null;
852 }
853
854 return {
855 pathname: trailingPathname,
856 search,
857 hash,
858 state,
859 key
860 };
861 }, [basename, pathname, search, hash, state, key]);
862 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.") ;
863
864 if (location == null) {
865 return null;
866 }
867
868 return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
869 value: navigationContext
870 }, /*#__PURE__*/React.createElement(LocationContext.Provider, {
871 children: children,
872 value: {
873 location,
874 navigationType
875 }
876 }));
877 }
878
879 /**
880 * A container for a nested tree of <Route> elements that renders the branch
881 * that best matches the current location.
882 *
883 * @see https://reactrouter.com/docs/en/v6/api#routes
884 */
885 function Routes(_ref4) {
886 let {
887 children,
888 location
889 } = _ref4;
890 return useRoutes(createRoutesFromChildren(children), location);
891 } ///////////////////////////////////////////////////////////////////////////////
892 // UTILS
893 ///////////////////////////////////////////////////////////////////////////////
894
895 /**
896 * Creates a route config from a React "children" object, which is usually
897 * either a `<Route>` element or an array of them. Used internally by
898 * `<Routes>` to create a route config from its children.
899 *
900 * @see https://reactrouter.com/docs/en/v6/api#createroutesfromchildren
901 */
902
903 function createRoutesFromChildren(children) {
904 let routes = [];
905 React.Children.forEach(children, element => {
906 if (! /*#__PURE__*/React.isValidElement(element)) {
907 // Ignore non-elements. This allows people to more easily inline
908 // conditionals in their route config.
909 return;
910 }
911
912 if (element.type === React.Fragment) {
913 // Transparently support React.Fragment and its children.
914 routes.push.apply(routes, createRoutesFromChildren(element.props.children));
915 return;
916 }
917
918 !(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;
919 let route = {
920 caseSensitive: element.props.caseSensitive,
921 element: element.props.element,
922 index: element.props.index,
923 path: element.props.path
924 };
925
926 if (element.props.children) {
927 route.children = createRoutesFromChildren(element.props.children);
928 }
929
930 routes.push(route);
931 });
932 return routes;
933 }
934 /**
935 * Renders the result of `matchRoutes()` into a React element.
936 */
937
938 function renderMatches(matches) {
939 return _renderMatches(matches);
940 }
941
942 Object.defineProperty(exports, 'NavigationType', {
943 enumerable: true,
944 get: function () {
945 return history.Action;
946 }
947 });
948 Object.defineProperty(exports, 'createPath', {
949 enumerable: true,
950 get: function () {
951 return history.createPath;
952 }
953 });
954 Object.defineProperty(exports, 'parsePath', {
955 enumerable: true,
956 get: function () {
957 return history.parsePath;
958 }
959 });
960 exports.MemoryRouter = MemoryRouter;
961 exports.Navigate = Navigate;
962 exports.Outlet = Outlet;
963 exports.Route = Route;
964 exports.Router = Router;
965 exports.Routes = Routes;
966 exports.UNSAFE_LocationContext = LocationContext;
967 exports.UNSAFE_NavigationContext = NavigationContext;
968 exports.UNSAFE_RouteContext = RouteContext;
969 exports.createRoutesFromChildren = createRoutesFromChildren;
970 exports.generatePath = generatePath;
971 exports.matchPath = matchPath;
972 exports.matchRoutes = matchRoutes;
973 exports.renderMatches = renderMatches;
974 exports.resolvePath = resolvePath;
975 exports.useHref = useHref;
976 exports.useInRouterContext = useInRouterContext;
977 exports.useLocation = useLocation;
978 exports.useMatch = useMatch;
979 exports.useNavigate = useNavigate;
980 exports.useNavigationType = useNavigationType;
981 exports.useOutlet = useOutlet;
982 exports.useOutletContext = useOutletContext;
983 exports.useParams = useParams;
984 exports.useResolvedPath = useResolvedPath;
985 exports.useRoutes = useRoutes;
986
987 Object.defineProperty(exports, '__esModule', { value: true });
988
989})));
990//# sourceMappingURL=react-router.development.js.map