Project files
This commit is contained in:
1 parent
695abe054b
commit
c415135aae
8554 files changed
+858111
No files matched your search
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) React Training 2015-2019
|
||||
Copyright (c) Remix Software 2020-2021
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# React Router
|
||||
|
||||
The `react-router` package is the heart of [React Router](https://github.com/remix-run/react-router) and provides all
|
||||
the core functionality for both
|
||||
[`react-router-dom`](/packages/react-router-dom)
|
||||
and
|
||||
[`react-router-native`](/packages/react-router-native).
|
||||
|
||||
If you're using React Router, you should never `import` anything directly from
|
||||
the `react-router` package, but you should have everything you need in either
|
||||
`react-router-dom` or `react-router-native`. Both of those packages re-export
|
||||
everything from `react-router`.
|
||||
|
||||
If you'd like to extend React Router and you know what you're doing, you should
|
||||
add `react-router` **as a peer dependency, not a regular dependency** in your
|
||||
package.
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import type { Hash, Location, Path, Pathname, Search, To } from "history";
|
||||
import { Action as NavigationType, parsePath, createPath } from "history";
|
||||
import type { MemoryRouterProps, NavigateProps, OutletProps, RouteProps, PathRouteProps, LayoutRouteProps, IndexRouteProps, RouterProps, RoutesProps } from "./lib/components";
|
||||
import { createRoutesFromChildren, renderMatches, MemoryRouter, Navigate, Outlet, Route, Router, Routes } from "./lib/components";
|
||||
import type { Navigator } from "./lib/context";
|
||||
import { LocationContext, NavigationContext, RouteContext } from "./lib/context";
|
||||
import type { NavigateFunction, NavigateOptions } from "./lib/hooks";
|
||||
import { useHref, useInRouterContext, useLocation, useMatch, useNavigationType, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes } from "./lib/hooks";
|
||||
import type { Params, PathMatch, PathPattern, RouteMatch, RouteObject } from "./lib/router";
|
||||
import { generatePath, matchPath, matchRoutes, resolvePath } from "./lib/router";
|
||||
export type { Hash, IndexRouteProps, LayoutRouteProps, Location, MemoryRouterProps, NavigateFunction, NavigateOptions, NavigateProps, OutletProps, PathMatch, PathPattern, PathRouteProps, RouteMatch, RouteObject, RouteProps, RouterProps, RoutesProps, Navigator, Params, Path, Pathname, Search, To, };
|
||||
export { MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, Routes, createPath, createRoutesFromChildren, generatePath, matchPath, matchRoutes, parsePath, renderMatches, resolvePath, useHref, useInRouterContext, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, };
|
||||
/** @internal */
|
||||
export { NavigationContext as UNSAFE_NavigationContext, LocationContext as UNSAFE_LocationContext, RouteContext as UNSAFE_RouteContext, };
|
||||
+941
@@ -0,0 +1,941 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
import { parsePath, createMemoryHistory, Action } from 'history';
|
||||
export { Action as NavigationType, createPath, parsePath } from 'history';
|
||||
import { createContext, useContext, useMemo, useRef, useEffect, useCallback, createElement, useState, useLayoutEffect, Children, isValidElement, Fragment } from 'react';
|
||||
|
||||
const NavigationContext = /*#__PURE__*/createContext(null);
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
NavigationContext.displayName = "Navigation";
|
||||
}
|
||||
|
||||
const LocationContext = /*#__PURE__*/createContext(null);
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
LocationContext.displayName = "Location";
|
||||
}
|
||||
|
||||
const RouteContext = /*#__PURE__*/createContext({
|
||||
outlet: null,
|
||||
matches: []
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
RouteContext.displayName = "Route";
|
||||
}
|
||||
|
||||
function invariant(cond, message) {
|
||||
if (!cond) throw new Error(message);
|
||||
}
|
||||
function warning(cond, message) {
|
||||
if (!cond) {
|
||||
// eslint-disable-next-line no-console
|
||||
if (typeof console !== "undefined") console.warn(message);
|
||||
|
||||
try {
|
||||
// Welcome to debugging React Router!
|
||||
//
|
||||
// This error is thrown as a convenience so you can more easily
|
||||
// find the source for a warning that appears in the console by
|
||||
// enabling "pause on exceptions" in your JavaScript debugger.
|
||||
throw new Error(message); // eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
const alreadyWarned = {};
|
||||
function warningOnce(key, cond, message) {
|
||||
if (!cond && !alreadyWarned[key]) {
|
||||
alreadyWarned[key] = true;
|
||||
process.env.NODE_ENV !== "production" ? warning(false, message) : void 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path with params interpolated.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#generatepath
|
||||
*/
|
||||
function generatePath(path, params) {
|
||||
if (params === void 0) {
|
||||
params = {};
|
||||
}
|
||||
|
||||
return path.replace(/:(\w+)/g, (_, key) => {
|
||||
!(params[key] != null) ? process.env.NODE_ENV !== "production" ? invariant(false, "Missing \":" + key + "\" param") : invariant(false) : void 0;
|
||||
return params[key];
|
||||
}).replace(/\/*\*$/, _ => params["*"] == null ? "" : params["*"].replace(/^\/*/, "/"));
|
||||
}
|
||||
/**
|
||||
* A RouteMatch contains info about how a route matched a URL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Matches the given routes to a location and returns the match data.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchroutes
|
||||
*/
|
||||
function matchRoutes(routes, locationArg, basename) {
|
||||
if (basename === void 0) {
|
||||
basename = "/";
|
||||
}
|
||||
|
||||
let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
||||
let pathname = stripBasename(location.pathname || "/", basename);
|
||||
|
||||
if (pathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let branches = flattenRoutes(routes);
|
||||
rankRouteBranches(branches);
|
||||
let matches = null;
|
||||
|
||||
for (let i = 0; matches == null && i < branches.length; ++i) {
|
||||
matches = matchRouteBranch(branches[i], pathname);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
function flattenRoutes(routes, branches, parentsMeta, parentPath) {
|
||||
if (branches === void 0) {
|
||||
branches = [];
|
||||
}
|
||||
|
||||
if (parentsMeta === void 0) {
|
||||
parentsMeta = [];
|
||||
}
|
||||
|
||||
if (parentPath === void 0) {
|
||||
parentPath = "";
|
||||
}
|
||||
|
||||
routes.forEach((route, index) => {
|
||||
let meta = {
|
||||
relativePath: route.path || "",
|
||||
caseSensitive: route.caseSensitive === true,
|
||||
childrenIndex: index,
|
||||
route
|
||||
};
|
||||
|
||||
if (meta.relativePath.startsWith("/")) {
|
||||
!meta.relativePath.startsWith(parentPath) ? process.env.NODE_ENV !== "production" ? 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.") : invariant(false) : void 0;
|
||||
meta.relativePath = meta.relativePath.slice(parentPath.length);
|
||||
}
|
||||
|
||||
let path = joinPaths([parentPath, meta.relativePath]);
|
||||
let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
|
||||
// route tree depth-first and child routes appear before their parents in
|
||||
// the "flattened" version.
|
||||
|
||||
if (route.children && route.children.length > 0) {
|
||||
!(route.index !== true) ? process.env.NODE_ENV !== "production" ? invariant(false, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")) : invariant(false) : void 0;
|
||||
flattenRoutes(route.children, branches, routesMeta, path);
|
||||
} // Routes without a path shouldn't ever match by themselves unless they are
|
||||
// index routes, so don't add them to the list of possible branches.
|
||||
|
||||
|
||||
if (route.path == null && !route.index) {
|
||||
return;
|
||||
}
|
||||
|
||||
branches.push({
|
||||
path,
|
||||
score: computeScore(path, route.index),
|
||||
routesMeta
|
||||
});
|
||||
});
|
||||
return branches;
|
||||
}
|
||||
|
||||
function rankRouteBranches(branches) {
|
||||
branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
|
||||
: compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
|
||||
}
|
||||
|
||||
const paramRe = /^:\w+$/;
|
||||
const dynamicSegmentValue = 3;
|
||||
const indexRouteValue = 2;
|
||||
const emptySegmentValue = 1;
|
||||
const staticSegmentValue = 10;
|
||||
const splatPenalty = -2;
|
||||
|
||||
const isSplat = s => s === "*";
|
||||
|
||||
function computeScore(path, index) {
|
||||
let segments = path.split("/");
|
||||
let initialScore = segments.length;
|
||||
|
||||
if (segments.some(isSplat)) {
|
||||
initialScore += splatPenalty;
|
||||
}
|
||||
|
||||
if (index) {
|
||||
initialScore += indexRouteValue;
|
||||
}
|
||||
|
||||
return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
||||
}
|
||||
|
||||
function compareIndexes(a, b) {
|
||||
let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
|
||||
return siblings ? // If two routes are siblings, we should try to match the earlier sibling
|
||||
// first. This allows people to have fine-grained control over the matching
|
||||
// behavior by simply putting routes with identical paths in the order they
|
||||
// want them tried.
|
||||
a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
|
||||
// so they sort equally.
|
||||
0;
|
||||
}
|
||||
|
||||
function matchRouteBranch(branch, pathname) {
|
||||
let {
|
||||
routesMeta
|
||||
} = branch;
|
||||
let matchedParams = {};
|
||||
let matchedPathname = "/";
|
||||
let matches = [];
|
||||
|
||||
for (let i = 0; i < routesMeta.length; ++i) {
|
||||
let meta = routesMeta[i];
|
||||
let end = i === routesMeta.length - 1;
|
||||
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
||||
let match = matchPath({
|
||||
path: meta.relativePath,
|
||||
caseSensitive: meta.caseSensitive,
|
||||
end
|
||||
}, remainingPathname);
|
||||
if (!match) return null;
|
||||
Object.assign(matchedParams, match.params);
|
||||
let route = meta.route;
|
||||
matches.push({
|
||||
params: matchedParams,
|
||||
pathname: joinPaths([matchedPathname, match.pathname]),
|
||||
pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
|
||||
route
|
||||
});
|
||||
|
||||
if (match.pathnameBase !== "/") {
|
||||
matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
/**
|
||||
* A PathPattern is used to match on some portion of a URL pathname.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Performs pattern matching on a URL pathname and returns information about
|
||||
* the match.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchpath
|
||||
*/
|
||||
function matchPath(pattern, pathname) {
|
||||
if (typeof pattern === "string") {
|
||||
pattern = {
|
||||
path: pattern,
|
||||
caseSensitive: false,
|
||||
end: true
|
||||
};
|
||||
}
|
||||
|
||||
let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
||||
let match = pathname.match(matcher);
|
||||
if (!match) return null;
|
||||
let matchedPathname = match[0];
|
||||
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
||||
let captureGroups = match.slice(1);
|
||||
let params = paramNames.reduce((memo, paramName, index) => {
|
||||
// We need to compute the pathnameBase here using the raw splat value
|
||||
// instead of using params["*"] later because it will be decoded then
|
||||
if (paramName === "*") {
|
||||
let splatValue = captureGroups[index] || "";
|
||||
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
||||
}
|
||||
|
||||
memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
|
||||
return memo;
|
||||
}, {});
|
||||
return {
|
||||
params,
|
||||
pathname: matchedPathname,
|
||||
pathnameBase,
|
||||
pattern
|
||||
};
|
||||
}
|
||||
|
||||
function compilePath(path, caseSensitive, end) {
|
||||
if (caseSensitive === void 0) {
|
||||
caseSensitive = false;
|
||||
}
|
||||
|
||||
if (end === void 0) {
|
||||
end = true;
|
||||
}
|
||||
|
||||
process.env.NODE_ENV !== "production" ? 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(/\*$/, "/*") + "\".")) : void 0;
|
||||
let paramNames = [];
|
||||
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
||||
.replace(/^\/*/, "/") // Make sure it has a leading /
|
||||
.replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
|
||||
.replace(/:(\w+)/g, (_, paramName) => {
|
||||
paramNames.push(paramName);
|
||||
return "([^\\/]+)";
|
||||
});
|
||||
|
||||
if (path.endsWith("*")) {
|
||||
paramNames.push("*");
|
||||
regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
|
||||
: "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
|
||||
} else {
|
||||
regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
|
||||
: // Otherwise, match a word boundary or a proceeding /. The word boundary restricts
|
||||
// parent routes to matching only their own words and nothing more, e.g. parent
|
||||
// route "/home" should not match "/home2".
|
||||
// Additionally, allow paths starting with `.`, `-`, `~`, and url-encoded entities,
|
||||
// but do not consume the character in the matched path so they can match against
|
||||
// nested paths.
|
||||
"(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";
|
||||
}
|
||||
|
||||
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
||||
return [matcher, paramNames];
|
||||
}
|
||||
|
||||
function safelyDecodeURIComponent(value, paramName) {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
process.env.NODE_ENV !== "production" ? 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 + ").")) : void 0;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a resolved path object relative to the given pathname.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#resolvepath
|
||||
*/
|
||||
|
||||
|
||||
function resolvePath(to, fromPathname) {
|
||||
if (fromPathname === void 0) {
|
||||
fromPathname = "/";
|
||||
}
|
||||
|
||||
let {
|
||||
pathname: toPathname,
|
||||
search = "",
|
||||
hash = ""
|
||||
} = typeof to === "string" ? parsePath(to) : to;
|
||||
let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
|
||||
return {
|
||||
pathname,
|
||||
search: normalizeSearch(search),
|
||||
hash: normalizeHash(hash)
|
||||
};
|
||||
}
|
||||
|
||||
function resolvePathname(relativePath, fromPathname) {
|
||||
let segments = fromPathname.replace(/\/+$/, "").split("/");
|
||||
let relativeSegments = relativePath.split("/");
|
||||
relativeSegments.forEach(segment => {
|
||||
if (segment === "..") {
|
||||
// Keep the root "" segment so the pathname starts at /
|
||||
if (segments.length > 1) segments.pop();
|
||||
} else if (segment !== ".") {
|
||||
segments.push(segment);
|
||||
}
|
||||
});
|
||||
return segments.length > 1 ? segments.join("/") : "/";
|
||||
}
|
||||
|
||||
function resolveTo(toArg, routePathnames, locationPathname) {
|
||||
let to = typeof toArg === "string" ? parsePath(toArg) : toArg;
|
||||
let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
|
||||
// route context. This is explained in `Note on `<Link to>` values` in our
|
||||
// migration guide from v5 as a means of disambiguation between `to` values
|
||||
// that begin with `/` and those that do not. However, this is problematic for
|
||||
// `to` values that do not provide a pathname. `to` can simply be a search or
|
||||
// hash string, in which case we should assume that the navigation is relative
|
||||
// to the current location's pathname and *not* the route pathname.
|
||||
|
||||
let from;
|
||||
|
||||
if (toPathname == null) {
|
||||
from = locationPathname;
|
||||
} else {
|
||||
let routePathnameIndex = routePathnames.length - 1;
|
||||
|
||||
if (toPathname.startsWith("..")) {
|
||||
let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
|
||||
// URL segment". This is a key difference from how <a href> works and a
|
||||
// major reason we call this a "to" value instead of a "href".
|
||||
|
||||
while (toSegments[0] === "..") {
|
||||
toSegments.shift();
|
||||
routePathnameIndex -= 1;
|
||||
}
|
||||
|
||||
to.pathname = toSegments.join("/");
|
||||
} // If there are more ".." segments than parent routes, resolve relative to
|
||||
// the root / URL.
|
||||
|
||||
|
||||
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
||||
}
|
||||
|
||||
let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
|
||||
|
||||
if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
|
||||
path.pathname += "/";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
function getToPathname(to) {
|
||||
// Empty strings should be treated the same as / paths
|
||||
return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
|
||||
}
|
||||
function stripBasename(pathname, basename) {
|
||||
if (basename === "/") return pathname;
|
||||
|
||||
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nextChar = pathname.charAt(basename.length);
|
||||
|
||||
if (nextChar && nextChar !== "/") {
|
||||
// pathname does not start with basename/
|
||||
return null;
|
||||
}
|
||||
|
||||
return pathname.slice(basename.length) || "/";
|
||||
}
|
||||
const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
|
||||
const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
|
||||
|
||||
const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
||||
|
||||
const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
||||
|
||||
/**
|
||||
* Returns the full href for the given "to" value. This is useful for building
|
||||
* custom links that are also accessible and preserve right-click behavior.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usehref
|
||||
*/
|
||||
|
||||
function useHref(to) {
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useHref() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = useContext(NavigationContext);
|
||||
let {
|
||||
hash,
|
||||
pathname,
|
||||
search
|
||||
} = useResolvedPath(to);
|
||||
let joinedPathname = pathname;
|
||||
|
||||
if (basename !== "/") {
|
||||
let toPathname = getToPathname(to);
|
||||
let endsWithSlash = toPathname != null && toPathname.endsWith("/");
|
||||
joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
|
||||
}
|
||||
|
||||
return navigator.createHref({
|
||||
pathname: joinedPathname,
|
||||
search,
|
||||
hash
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns true if this component is a descendant of a <Router>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
|
||||
*/
|
||||
|
||||
function useInRouterContext() {
|
||||
return useContext(LocationContext) != null;
|
||||
}
|
||||
/**
|
||||
* Returns the current location object, which represents the current URL in web
|
||||
* browsers.
|
||||
*
|
||||
* Note: If you're using this it may mean you're doing some of your own
|
||||
* "routing" in your app, and we'd like to know what your use case is. We may
|
||||
* be able to provide something higher-level to better suit your needs.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#uselocation
|
||||
*/
|
||||
|
||||
function useLocation() {
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useLocation() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
return useContext(LocationContext).location;
|
||||
}
|
||||
/**
|
||||
* Returns the current navigation action which describes how the router came to
|
||||
* the current location, either by a pop, push, or replace on the history stack.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigationtype
|
||||
*/
|
||||
|
||||
function useNavigationType() {
|
||||
return useContext(LocationContext).navigationType;
|
||||
}
|
||||
/**
|
||||
* Returns true if the URL for the given "to" value matches the current URL.
|
||||
* This is useful for components that need to know "active" state, e.g.
|
||||
* <NavLink>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usematch
|
||||
*/
|
||||
|
||||
function useMatch(pattern) {
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useMatch() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
let {
|
||||
pathname
|
||||
} = useLocation();
|
||||
return useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
|
||||
}
|
||||
/**
|
||||
* The interface for the navigate() function returned from useNavigate().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an imperative method for changing the location. Used by <Link>s, but
|
||||
* may also be used by other elements to change the location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigate
|
||||
*/
|
||||
function useNavigate() {
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useNavigate() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = useContext(NavigationContext);
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
let activeRef = useRef(false);
|
||||
useEffect(() => {
|
||||
activeRef.current = true;
|
||||
});
|
||||
let navigate = useCallback(function (to, options) {
|
||||
if (options === void 0) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
process.env.NODE_ENV !== "production" ? warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") : void 0;
|
||||
if (!activeRef.current) return;
|
||||
|
||||
if (typeof to === "number") {
|
||||
navigator.go(to);
|
||||
return;
|
||||
}
|
||||
|
||||
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
|
||||
|
||||
if (basename !== "/") {
|
||||
path.pathname = joinPaths([basename, path.pathname]);
|
||||
}
|
||||
|
||||
(!!options.replace ? navigator.replace : navigator.push)(path, options.state);
|
||||
}, [basename, navigator, routePathnamesJson, locationPathname]);
|
||||
return navigate;
|
||||
}
|
||||
const OutletContext = /*#__PURE__*/createContext(null);
|
||||
/**
|
||||
* Returns the context (if provided) for the child route at this level of the route
|
||||
* hierarchy.
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutletcontext
|
||||
*/
|
||||
|
||||
function useOutletContext() {
|
||||
return useContext(OutletContext);
|
||||
}
|
||||
/**
|
||||
* Returns the element for the child route at this level of the route
|
||||
* hierarchy. Used internally by <Outlet> to render child routes.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutlet
|
||||
*/
|
||||
|
||||
function useOutlet(context) {
|
||||
let outlet = useContext(RouteContext).outlet;
|
||||
|
||||
if (outlet) {
|
||||
return /*#__PURE__*/createElement(OutletContext.Provider, {
|
||||
value: context
|
||||
}, outlet);
|
||||
}
|
||||
|
||||
return outlet;
|
||||
}
|
||||
/**
|
||||
* Returns an object of key/value pairs of the dynamic params from the current
|
||||
* URL that were matched by the route path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useparams
|
||||
*/
|
||||
|
||||
function useParams() {
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let routeMatch = matches[matches.length - 1];
|
||||
return routeMatch ? routeMatch.params : {};
|
||||
}
|
||||
/**
|
||||
* Resolves the pathname of the given `to` value against the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
|
||||
*/
|
||||
|
||||
function useResolvedPath(to) {
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
return useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
|
||||
}
|
||||
/**
|
||||
* Returns the element of the route that matched the current location, prepared
|
||||
* with the correct context to render the remainder of the route tree. Route
|
||||
* elements in the tree must render an <Outlet> to render their child route's
|
||||
* element.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useroutes
|
||||
*/
|
||||
|
||||
function useRoutes(routes, locationArg) {
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useRoutes() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
let {
|
||||
matches: parentMatches
|
||||
} = useContext(RouteContext);
|
||||
let routeMatch = parentMatches[parentMatches.length - 1];
|
||||
let parentParams = routeMatch ? routeMatch.params : {};
|
||||
let parentPathname = routeMatch ? routeMatch.pathname : "/";
|
||||
let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
|
||||
let parentRoute = routeMatch && routeMatch.route;
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
// You won't get a warning about 2 different <Routes> under a <Route>
|
||||
// without a trailing *, but this is a best-effort warning anyway since we
|
||||
// cannot even give the warning unless they land at the parent route.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// <Routes>
|
||||
// {/* This route path MUST end with /* because otherwise
|
||||
// it will never match /blog/post/123 */}
|
||||
// <Route path="blog" element={<Blog />} />
|
||||
// <Route path="blog/feed" element={<BlogFeed />} />
|
||||
// </Routes>
|
||||
//
|
||||
// function Blog() {
|
||||
// return (
|
||||
// <Routes>
|
||||
// <Route path="post/:id" element={<Post />} />
|
||||
// </Routes>
|
||||
// );
|
||||
// }
|
||||
let parentPath = parentRoute && parentRoute.path || "";
|
||||
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 + "/*") + "\">."));
|
||||
}
|
||||
|
||||
let locationFromContext = useLocation();
|
||||
let location;
|
||||
|
||||
if (locationArg) {
|
||||
var _parsedLocationArg$pa;
|
||||
|
||||
let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
||||
!(parentPathnameBase === "/" || ((_parsedLocationArg$pa = parsedLocationArg.pathname) == null ? void 0 : _parsedLocationArg$pa.startsWith(parentPathnameBase))) ? process.env.NODE_ENV !== "production" ? 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.")) : invariant(false) : void 0;
|
||||
location = parsedLocationArg;
|
||||
} else {
|
||||
location = locationFromContext;
|
||||
}
|
||||
|
||||
let pathname = location.pathname || "/";
|
||||
let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
|
||||
let matches = matchRoutes(routes, {
|
||||
pathname: remainingPathname
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
process.env.NODE_ENV !== "production" ? warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") : void 0;
|
||||
process.env.NODE_ENV !== "production" ? 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.") : void 0;
|
||||
}
|
||||
|
||||
return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
|
||||
params: Object.assign({}, parentParams, match.params),
|
||||
pathname: joinPaths([parentPathnameBase, match.pathname]),
|
||||
pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
|
||||
})), parentMatches);
|
||||
}
|
||||
function _renderMatches(matches, parentMatches) {
|
||||
if (parentMatches === void 0) {
|
||||
parentMatches = [];
|
||||
}
|
||||
|
||||
if (matches == null) return null;
|
||||
return matches.reduceRight((outlet, match, index) => {
|
||||
return /*#__PURE__*/createElement(RouteContext.Provider, {
|
||||
children: match.route.element !== undefined ? match.route.element : outlet,
|
||||
value: {
|
||||
outlet,
|
||||
matches: parentMatches.concat(matches.slice(0, index + 1))
|
||||
}
|
||||
});
|
||||
}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A <Router> that stores all entries in memory.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#memoryrouter
|
||||
*/
|
||||
function MemoryRouter(_ref) {
|
||||
let {
|
||||
basename,
|
||||
children,
|
||||
initialEntries,
|
||||
initialIndex
|
||||
} = _ref;
|
||||
let historyRef = useRef();
|
||||
|
||||
if (historyRef.current == null) {
|
||||
historyRef.current = createMemoryHistory({
|
||||
initialEntries,
|
||||
initialIndex
|
||||
});
|
||||
}
|
||||
|
||||
let history = historyRef.current;
|
||||
let [state, setState] = useState({
|
||||
action: history.action,
|
||||
location: history.location
|
||||
});
|
||||
useLayoutEffect(() => history.listen(setState), [history]);
|
||||
return /*#__PURE__*/createElement(Router, {
|
||||
basename: basename,
|
||||
children: children,
|
||||
location: state.location,
|
||||
navigationType: state.action,
|
||||
navigator: history
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current location.
|
||||
*
|
||||
* Note: This API is mostly useful in React.Component subclasses that are not
|
||||
* able to use hooks. In functional components, we recommend you use the
|
||||
* `useNavigate` hook instead.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#navigate
|
||||
*/
|
||||
function Navigate(_ref2) {
|
||||
let {
|
||||
to,
|
||||
replace,
|
||||
state
|
||||
} = _ref2;
|
||||
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
|
||||
// the router loaded. We can help them understand how to avoid that.
|
||||
"<Navigate> may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
||||
process.env.NODE_ENV !== "production" ? warning(!useContext(NavigationContext).static, "<Navigate> must not be used on the initial render in a <StaticRouter>. " + "This is a no-op, but you should modify your code so the <Navigate> is " + "only ever rendered in response to some user interaction or state change.") : void 0;
|
||||
let navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
navigate(to, {
|
||||
replace,
|
||||
state
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the child route's element, if there is one.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#outlet
|
||||
*/
|
||||
function Outlet(props) {
|
||||
return useOutlet(props.context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares an element that should be rendered at a certain URL path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#route
|
||||
*/
|
||||
function Route(_props) {
|
||||
process.env.NODE_ENV !== "production" ? 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>.") : invariant(false) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides location context for the rest of the app.
|
||||
*
|
||||
* Note: You usually won't render a <Router> directly. Instead, you'll render a
|
||||
* router that is more specific to your environment such as a <BrowserRouter>
|
||||
* in web browsers or a <StaticRouter> for server rendering.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#router
|
||||
*/
|
||||
function Router(_ref3) {
|
||||
let {
|
||||
basename: basenameProp = "/",
|
||||
children = null,
|
||||
location: locationProp,
|
||||
navigationType = Action.Pop,
|
||||
navigator,
|
||||
static: staticProp = false
|
||||
} = _ref3;
|
||||
!!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : invariant(false) : void 0;
|
||||
let basename = normalizePathname(basenameProp);
|
||||
let navigationContext = useMemo(() => ({
|
||||
basename,
|
||||
navigator,
|
||||
static: staticProp
|
||||
}), [basename, navigator, staticProp]);
|
||||
|
||||
if (typeof locationProp === "string") {
|
||||
locationProp = parsePath(locationProp);
|
||||
}
|
||||
|
||||
let {
|
||||
pathname = "/",
|
||||
search = "",
|
||||
hash = "",
|
||||
state = null,
|
||||
key = "default"
|
||||
} = locationProp;
|
||||
let location = useMemo(() => {
|
||||
let trailingPathname = stripBasename(pathname, basename);
|
||||
|
||||
if (trailingPathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
pathname: trailingPathname,
|
||||
search,
|
||||
hash,
|
||||
state,
|
||||
key
|
||||
};
|
||||
}, [basename, pathname, search, hash, state, key]);
|
||||
process.env.NODE_ENV !== "production" ? 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.") : void 0;
|
||||
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return /*#__PURE__*/createElement(NavigationContext.Provider, {
|
||||
value: navigationContext
|
||||
}, /*#__PURE__*/createElement(LocationContext.Provider, {
|
||||
children: children,
|
||||
value: {
|
||||
location,
|
||||
navigationType
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for a nested tree of <Route> elements that renders the branch
|
||||
* that best matches the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#routes
|
||||
*/
|
||||
function Routes(_ref4) {
|
||||
let {
|
||||
children,
|
||||
location
|
||||
} = _ref4;
|
||||
return useRoutes(createRoutesFromChildren(children), location);
|
||||
} ///////////////////////////////////////////////////////////////////////////////
|
||||
// UTILS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a route config from a React "children" object, which is usually
|
||||
* either a `<Route>` element or an array of them. Used internally by
|
||||
* `<Routes>` to create a route config from its children.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#createroutesfromchildren
|
||||
*/
|
||||
|
||||
function createRoutesFromChildren(children) {
|
||||
let routes = [];
|
||||
Children.forEach(children, element => {
|
||||
if (! /*#__PURE__*/isValidElement(element)) {
|
||||
// Ignore non-elements. This allows people to more easily inline
|
||||
// conditionals in their route config.
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.type === Fragment) {
|
||||
// Transparently support React.Fragment and its children.
|
||||
routes.push.apply(routes, createRoutesFromChildren(element.props.children));
|
||||
return;
|
||||
}
|
||||
|
||||
!(element.type === Route) ? process.env.NODE_ENV !== "production" ? 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>") : invariant(false) : void 0;
|
||||
let route = {
|
||||
caseSensitive: element.props.caseSensitive,
|
||||
element: element.props.element,
|
||||
index: element.props.index,
|
||||
path: element.props.path
|
||||
};
|
||||
|
||||
if (element.props.children) {
|
||||
route.children = createRoutesFromChildren(element.props.children);
|
||||
}
|
||||
|
||||
routes.push(route);
|
||||
});
|
||||
return routes;
|
||||
}
|
||||
/**
|
||||
* Renders the result of `matchRoutes()` into a React element.
|
||||
*/
|
||||
|
||||
function renderMatches(matches) {
|
||||
return _renderMatches(matches);
|
||||
}
|
||||
|
||||
export { MemoryRouter, Navigate, Outlet, Route, Router, Routes, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, createRoutesFromChildren, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, useHref, useInRouterContext, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes };
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sources":["../../../packages/react-router/lib/context.ts","../../../packages/react-router/lib/router.ts","../../../packages/react-router/lib/hooks.tsx","../../../packages/react-router/lib/components.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { History, Location } from \"history\";\nimport { Action as NavigationType } from \"history\";\n\nimport type { RouteMatch } from \"./router\";\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level <Router> API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport type Navigator = Pick<History, \"go\" | \"push\" | \"replace\" | \"createHref\">;\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n}\n\nexport const NavigationContext = React.createContext<NavigationContextObject>(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext<LocationContextObject>(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\ninterface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n}\n\nexport const RouteContext = React.createContext<RouteContextObject>({\n outlet: null,\n matches: [],\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n","import type { Location, Path, To } from \"history\";\nimport { parsePath } from \"history\";\n\nexport function invariant(cond: any, message: string): asserts cond {\n if (!cond) throw new Error(message);\n}\n\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nconst alreadyWarned: Record<string, boolean> = {};\nexport function warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n\ntype ParamParseFailed = { failed: true };\n\ntype ParamParseSegment<Segment extends string> =\n // Check here if there exists a forward slash in the string.\n Segment extends `${infer LeftSegment}/${infer RightSegment}`\n ? // If there is a forward slash, then attempt to parse each side of the\n // forward slash.\n ParamParseSegment<LeftSegment> extends infer LeftResult\n ? ParamParseSegment<RightSegment> extends infer RightResult\n ? LeftResult extends string\n ? // If the left side is successfully parsed as a param, then check if\n // the right side can be successfully parsed as well. If both sides\n // can be parsed, then the result is a union of the two sides\n // (read: \"foo\" | \"bar\").\n RightResult extends string\n ? LeftResult | RightResult\n : LeftResult\n : // If the left side is not successfully parsed as a param, then check\n // if only the right side can be successfully parse as a param. If it\n // can, then the result is just right, else it's a failure.\n RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If the left side didn't parse into a param, then just check the right\n // side.\n ParamParseSegment<RightSegment> extends infer RightResult\n ? RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If there's no forward slash, then check if this segment starts with a\n // colon. If it does, then this is a dynamic segment, so the result is\n // just the remainder of the string. Otherwise, it's a failure.\n Segment extends `:${infer Remaining}`\n ? Remaining\n : ParamParseFailed;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey<Segment extends string> =\n ParamParseSegment<SLine truncated
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
module.exports = require("./umd/react-router.production.min.js");
|
||||
} else {
|
||||
module.exports = require("./umd/react-router.development.js");
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "react-router",
|
||||
"version": "6.3.0",
|
||||
"author": "Remix Software <hello@remix.run>",
|
||||
"description": "Declarative routing for React",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/remix-run/react-router.git",
|
||||
"directory": "packages/react-router"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./main.js",
|
||||
"module": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"unpkg": "./umd/react-router.production.min.js",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"history": "^5.2.0"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"keywords": [
|
||||
"react",
|
||||
"router",
|
||||
"route",
|
||||
"routing",
|
||||
"history",
|
||||
"link"
|
||||
]
|
||||
}
|
||||
+895
@@ -0,0 +1,895 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
import { parsePath, createMemoryHistory, Action } from 'history';
|
||||
export { Action as NavigationType, createPath, parsePath } from 'history';
|
||||
import { createContext, useContext, useMemo, useRef, useEffect, useCallback, createElement, useState, useLayoutEffect, Children, isValidElement, Fragment } from 'react';
|
||||
|
||||
const NavigationContext = /*#__PURE__*/createContext(null);
|
||||
|
||||
{
|
||||
NavigationContext.displayName = "Navigation";
|
||||
}
|
||||
|
||||
const LocationContext = /*#__PURE__*/createContext(null);
|
||||
|
||||
{
|
||||
LocationContext.displayName = "Location";
|
||||
}
|
||||
|
||||
const RouteContext = /*#__PURE__*/createContext({
|
||||
outlet: null,
|
||||
matches: []
|
||||
});
|
||||
|
||||
{
|
||||
RouteContext.displayName = "Route";
|
||||
}
|
||||
|
||||
function invariant(cond, message) {
|
||||
if (!cond) throw new Error(message);
|
||||
}
|
||||
function warning(cond, message) {
|
||||
if (!cond) {
|
||||
// eslint-disable-next-line no-console
|
||||
if (typeof console !== "undefined") console.warn(message);
|
||||
|
||||
try {
|
||||
// Welcome to debugging React Router!
|
||||
//
|
||||
// This error is thrown as a convenience so you can more easily
|
||||
// find the source for a warning that appears in the console by
|
||||
// enabling "pause on exceptions" in your JavaScript debugger.
|
||||
throw new Error(message); // eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
const alreadyWarned = {};
|
||||
function warningOnce(key, cond, message) {
|
||||
if (!cond && !alreadyWarned[key]) {
|
||||
alreadyWarned[key] = true;
|
||||
warning(false, message) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path with params interpolated.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#generatepath
|
||||
*/
|
||||
function generatePath(path, params = {}) {
|
||||
return path.replace(/:(\w+)/g, (_, key) => {
|
||||
!(params[key] != null) ? invariant(false, `Missing ":${key}" param`) : void 0;
|
||||
return params[key];
|
||||
}).replace(/\/*\*$/, _ => params["*"] == null ? "" : params["*"].replace(/^\/*/, "/"));
|
||||
}
|
||||
/**
|
||||
* A RouteMatch contains info about how a route matched a URL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Matches the given routes to a location and returns the match data.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchroutes
|
||||
*/
|
||||
function matchRoutes(routes, locationArg, basename = "/") {
|
||||
let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
||||
let pathname = stripBasename(location.pathname || "/", basename);
|
||||
|
||||
if (pathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let branches = flattenRoutes(routes);
|
||||
rankRouteBranches(branches);
|
||||
let matches = null;
|
||||
|
||||
for (let i = 0; matches == null && i < branches.length; ++i) {
|
||||
matches = matchRouteBranch(branches[i], pathname);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
|
||||
routes.forEach((route, index) => {
|
||||
let meta = {
|
||||
relativePath: route.path || "",
|
||||
caseSensitive: route.caseSensitive === true,
|
||||
childrenIndex: index,
|
||||
route
|
||||
};
|
||||
|
||||
if (meta.relativePath.startsWith("/")) {
|
||||
!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;
|
||||
meta.relativePath = meta.relativePath.slice(parentPath.length);
|
||||
}
|
||||
|
||||
let path = joinPaths([parentPath, meta.relativePath]);
|
||||
let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
|
||||
// route tree depth-first and child routes appear before their parents in
|
||||
// the "flattened" version.
|
||||
|
||||
if (route.children && route.children.length > 0) {
|
||||
!(route.index !== true) ? invariant(false, `Index routes must not have child routes. Please remove ` + `all child routes from route path "${path}".`) : void 0;
|
||||
flattenRoutes(route.children, branches, routesMeta, path);
|
||||
} // Routes without a path shouldn't ever match by themselves unless they are
|
||||
// index routes, so don't add them to the list of possible branches.
|
||||
|
||||
|
||||
if (route.path == null && !route.index) {
|
||||
return;
|
||||
}
|
||||
|
||||
branches.push({
|
||||
path,
|
||||
score: computeScore(path, route.index),
|
||||
routesMeta
|
||||
});
|
||||
});
|
||||
return branches;
|
||||
}
|
||||
|
||||
function rankRouteBranches(branches) {
|
||||
branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
|
||||
: compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
|
||||
}
|
||||
|
||||
const paramRe = /^:\w+$/;
|
||||
const dynamicSegmentValue = 3;
|
||||
const indexRouteValue = 2;
|
||||
const emptySegmentValue = 1;
|
||||
const staticSegmentValue = 10;
|
||||
const splatPenalty = -2;
|
||||
|
||||
const isSplat = s => s === "*";
|
||||
|
||||
function computeScore(path, index) {
|
||||
let segments = path.split("/");
|
||||
let initialScore = segments.length;
|
||||
|
||||
if (segments.some(isSplat)) {
|
||||
initialScore += splatPenalty;
|
||||
}
|
||||
|
||||
if (index) {
|
||||
initialScore += indexRouteValue;
|
||||
}
|
||||
|
||||
return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
||||
}
|
||||
|
||||
function compareIndexes(a, b) {
|
||||
let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
|
||||
return siblings ? // If two routes are siblings, we should try to match the earlier sibling
|
||||
// first. This allows people to have fine-grained control over the matching
|
||||
// behavior by simply putting routes with identical paths in the order they
|
||||
// want them tried.
|
||||
a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
|
||||
// so they sort equally.
|
||||
0;
|
||||
}
|
||||
|
||||
function matchRouteBranch(branch, pathname) {
|
||||
let {
|
||||
routesMeta
|
||||
} = branch;
|
||||
let matchedParams = {};
|
||||
let matchedPathname = "/";
|
||||
let matches = [];
|
||||
|
||||
for (let i = 0; i < routesMeta.length; ++i) {
|
||||
let meta = routesMeta[i];
|
||||
let end = i === routesMeta.length - 1;
|
||||
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
||||
let match = matchPath({
|
||||
path: meta.relativePath,
|
||||
caseSensitive: meta.caseSensitive,
|
||||
end
|
||||
}, remainingPathname);
|
||||
if (!match) return null;
|
||||
Object.assign(matchedParams, match.params);
|
||||
let route = meta.route;
|
||||
matches.push({
|
||||
params: matchedParams,
|
||||
pathname: joinPaths([matchedPathname, match.pathname]),
|
||||
pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
|
||||
route
|
||||
});
|
||||
|
||||
if (match.pathnameBase !== "/") {
|
||||
matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
/**
|
||||
* A PathPattern is used to match on some portion of a URL pathname.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Performs pattern matching on a URL pathname and returns information about
|
||||
* the match.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchpath
|
||||
*/
|
||||
function matchPath(pattern, pathname) {
|
||||
if (typeof pattern === "string") {
|
||||
pattern = {
|
||||
path: pattern,
|
||||
caseSensitive: false,
|
||||
end: true
|
||||
};
|
||||
}
|
||||
|
||||
let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
||||
let match = pathname.match(matcher);
|
||||
if (!match) return null;
|
||||
let matchedPathname = match[0];
|
||||
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
||||
let captureGroups = match.slice(1);
|
||||
let params = paramNames.reduce((memo, paramName, index) => {
|
||||
// We need to compute the pathnameBase here using the raw splat value
|
||||
// instead of using params["*"] later because it will be decoded then
|
||||
if (paramName === "*") {
|
||||
let splatValue = captureGroups[index] || "";
|
||||
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
||||
}
|
||||
|
||||
memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
|
||||
return memo;
|
||||
}, {});
|
||||
return {
|
||||
params,
|
||||
pathname: matchedPathname,
|
||||
pathnameBase,
|
||||
pattern
|
||||
};
|
||||
}
|
||||
|
||||
function compilePath(path, caseSensitive = false, end = true) {
|
||||
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(/\*$/, "/*")}".`) ;
|
||||
let paramNames = [];
|
||||
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
||||
.replace(/^\/*/, "/") // Make sure it has a leading /
|
||||
.replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
|
||||
.replace(/:(\w+)/g, (_, paramName) => {
|
||||
paramNames.push(paramName);
|
||||
return "([^\\/]+)";
|
||||
});
|
||||
|
||||
if (path.endsWith("*")) {
|
||||
paramNames.push("*");
|
||||
regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
|
||||
: "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
|
||||
} else {
|
||||
regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
|
||||
: // Otherwise, match a word boundary or a proceeding /. The word boundary restricts
|
||||
// parent routes to matching only their own words and nothing more, e.g. parent
|
||||
// route "/home" should not match "/home2".
|
||||
// Additionally, allow paths starting with `.`, `-`, `~`, and url-encoded entities,
|
||||
// but do not consume the character in the matched path so they can match against
|
||||
// nested paths.
|
||||
"(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";
|
||||
}
|
||||
|
||||
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
||||
return [matcher, paramNames];
|
||||
}
|
||||
|
||||
function safelyDecodeURIComponent(value, paramName) {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
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}).`) ;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a resolved path object relative to the given pathname.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#resolvepath
|
||||
*/
|
||||
|
||||
|
||||
function resolvePath(to, fromPathname = "/") {
|
||||
let {
|
||||
pathname: toPathname,
|
||||
search = "",
|
||||
hash = ""
|
||||
} = typeof to === "string" ? parsePath(to) : to;
|
||||
let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
|
||||
return {
|
||||
pathname,
|
||||
search: normalizeSearch(search),
|
||||
hash: normalizeHash(hash)
|
||||
};
|
||||
}
|
||||
|
||||
function resolvePathname(relativePath, fromPathname) {
|
||||
let segments = fromPathname.replace(/\/+$/, "").split("/");
|
||||
let relativeSegments = relativePath.split("/");
|
||||
relativeSegments.forEach(segment => {
|
||||
if (segment === "..") {
|
||||
// Keep the root "" segment so the pathname starts at /
|
||||
if (segments.length > 1) segments.pop();
|
||||
} else if (segment !== ".") {
|
||||
segments.push(segment);
|
||||
}
|
||||
});
|
||||
return segments.length > 1 ? segments.join("/") : "/";
|
||||
}
|
||||
|
||||
function resolveTo(toArg, routePathnames, locationPathname) {
|
||||
let to = typeof toArg === "string" ? parsePath(toArg) : toArg;
|
||||
let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
|
||||
// route context. This is explained in `Note on `<Link to>` values` in our
|
||||
// migration guide from v5 as a means of disambiguation between `to` values
|
||||
// that begin with `/` and those that do not. However, this is problematic for
|
||||
// `to` values that do not provide a pathname. `to` can simply be a search or
|
||||
// hash string, in which case we should assume that the navigation is relative
|
||||
// to the current location's pathname and *not* the route pathname.
|
||||
|
||||
let from;
|
||||
|
||||
if (toPathname == null) {
|
||||
from = locationPathname;
|
||||
} else {
|
||||
let routePathnameIndex = routePathnames.length - 1;
|
||||
|
||||
if (toPathname.startsWith("..")) {
|
||||
let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
|
||||
// URL segment". This is a key difference from how <a href> works and a
|
||||
// major reason we call this a "to" value instead of a "href".
|
||||
|
||||
while (toSegments[0] === "..") {
|
||||
toSegments.shift();
|
||||
routePathnameIndex -= 1;
|
||||
}
|
||||
|
||||
to.pathname = toSegments.join("/");
|
||||
} // If there are more ".." segments than parent routes, resolve relative to
|
||||
// the root / URL.
|
||||
|
||||
|
||||
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
||||
}
|
||||
|
||||
let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
|
||||
|
||||
if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
|
||||
path.pathname += "/";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
function getToPathname(to) {
|
||||
// Empty strings should be treated the same as / paths
|
||||
return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
|
||||
}
|
||||
function stripBasename(pathname, basename) {
|
||||
if (basename === "/") return pathname;
|
||||
|
||||
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nextChar = pathname.charAt(basename.length);
|
||||
|
||||
if (nextChar && nextChar !== "/") {
|
||||
// pathname does not start with basename/
|
||||
return null;
|
||||
}
|
||||
|
||||
return pathname.slice(basename.length) || "/";
|
||||
}
|
||||
const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
|
||||
const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
|
||||
|
||||
const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
||||
|
||||
const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
||||
|
||||
/**
|
||||
* Returns the full href for the given "to" value. This is useful for building
|
||||
* custom links that are also accessible and preserve right-click behavior.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usehref
|
||||
*/
|
||||
|
||||
function useHref(to) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
`useHref() may be used only in the context of a <Router> component.`) : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = useContext(NavigationContext);
|
||||
let {
|
||||
hash,
|
||||
pathname,
|
||||
search
|
||||
} = useResolvedPath(to);
|
||||
let joinedPathname = pathname;
|
||||
|
||||
if (basename !== "/") {
|
||||
let toPathname = getToPathname(to);
|
||||
let endsWithSlash = toPathname != null && toPathname.endsWith("/");
|
||||
joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
|
||||
}
|
||||
|
||||
return navigator.createHref({
|
||||
pathname: joinedPathname,
|
||||
search,
|
||||
hash
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns true if this component is a descendant of a <Router>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
|
||||
*/
|
||||
|
||||
function useInRouterContext() {
|
||||
return useContext(LocationContext) != null;
|
||||
}
|
||||
/**
|
||||
* Returns the current location object, which represents the current URL in web
|
||||
* browsers.
|
||||
*
|
||||
* Note: If you're using this it may mean you're doing some of your own
|
||||
* "routing" in your app, and we'd like to know what your use case is. We may
|
||||
* be able to provide something higher-level to better suit your needs.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#uselocation
|
||||
*/
|
||||
|
||||
function useLocation() {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
`useLocation() may be used only in the context of a <Router> component.`) : void 0;
|
||||
return useContext(LocationContext).location;
|
||||
}
|
||||
/**
|
||||
* Returns the current navigation action which describes how the router came to
|
||||
* the current location, either by a pop, push, or replace on the history stack.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigationtype
|
||||
*/
|
||||
|
||||
function useNavigationType() {
|
||||
return useContext(LocationContext).navigationType;
|
||||
}
|
||||
/**
|
||||
* Returns true if the URL for the given "to" value matches the current URL.
|
||||
* This is useful for components that need to know "active" state, e.g.
|
||||
* <NavLink>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usematch
|
||||
*/
|
||||
|
||||
function useMatch(pattern) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
`useMatch() may be used only in the context of a <Router> component.`) : void 0;
|
||||
let {
|
||||
pathname
|
||||
} = useLocation();
|
||||
return useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
|
||||
}
|
||||
/**
|
||||
* The interface for the navigate() function returned from useNavigate().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an imperative method for changing the location. Used by <Link>s, but
|
||||
* may also be used by other elements to change the location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigate
|
||||
*/
|
||||
function useNavigate() {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
`useNavigate() may be used only in the context of a <Router> component.`) : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = useContext(NavigationContext);
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
let activeRef = useRef(false);
|
||||
useEffect(() => {
|
||||
activeRef.current = true;
|
||||
});
|
||||
let navigate = useCallback((to, options = {}) => {
|
||||
warning(activeRef.current, `You should call navigate() in a React.useEffect(), not when ` + `your component is first rendered.`) ;
|
||||
if (!activeRef.current) return;
|
||||
|
||||
if (typeof to === "number") {
|
||||
navigator.go(to);
|
||||
return;
|
||||
}
|
||||
|
||||
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
|
||||
|
||||
if (basename !== "/") {
|
||||
path.pathname = joinPaths([basename, path.pathname]);
|
||||
}
|
||||
|
||||
(!!options.replace ? navigator.replace : navigator.push)(path, options.state);
|
||||
}, [basename, navigator, routePathnamesJson, locationPathname]);
|
||||
return navigate;
|
||||
}
|
||||
const OutletContext = /*#__PURE__*/createContext(null);
|
||||
/**
|
||||
* Returns the context (if provided) for the child route at this level of the route
|
||||
* hierarchy.
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutletcontext
|
||||
*/
|
||||
|
||||
function useOutletContext() {
|
||||
return useContext(OutletContext);
|
||||
}
|
||||
/**
|
||||
* Returns the element for the child route at this level of the route
|
||||
* hierarchy. Used internally by <Outlet> to render child routes.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutlet
|
||||
*/
|
||||
|
||||
function useOutlet(context) {
|
||||
let outlet = useContext(RouteContext).outlet;
|
||||
|
||||
if (outlet) {
|
||||
return /*#__PURE__*/createElement(OutletContext.Provider, {
|
||||
value: context
|
||||
}, outlet);
|
||||
}
|
||||
|
||||
return outlet;
|
||||
}
|
||||
/**
|
||||
* Returns an object of key/value pairs of the dynamic params from the current
|
||||
* URL that were matched by the route path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useparams
|
||||
*/
|
||||
|
||||
function useParams() {
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let routeMatch = matches[matches.length - 1];
|
||||
return routeMatch ? routeMatch.params : {};
|
||||
}
|
||||
/**
|
||||
* Resolves the pathname of the given `to` value against the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
|
||||
*/
|
||||
|
||||
function useResolvedPath(to) {
|
||||
let {
|
||||
matches
|
||||
} = useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
return useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
|
||||
}
|
||||
/**
|
||||
* Returns the element of the route that matched the current location, prepared
|
||||
* with the correct context to render the remainder of the route tree. Route
|
||||
* elements in the tree must render an <Outlet> to render their child route's
|
||||
* element.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useroutes
|
||||
*/
|
||||
|
||||
function useRoutes(routes, locationArg) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
`useRoutes() may be used only in the context of a <Router> component.`) : void 0;
|
||||
let {
|
||||
matches: parentMatches
|
||||
} = useContext(RouteContext);
|
||||
let routeMatch = parentMatches[parentMatches.length - 1];
|
||||
let parentParams = routeMatch ? routeMatch.params : {};
|
||||
let parentPathname = routeMatch ? routeMatch.pathname : "/";
|
||||
let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
|
||||
let parentRoute = routeMatch && routeMatch.route;
|
||||
|
||||
{
|
||||
// You won't get a warning about 2 different <Routes> under a <Route>
|
||||
// without a trailing *, but this is a best-effort warning anyway since we
|
||||
// cannot even give the warning unless they land at the parent route.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// <Routes>
|
||||
// {/* This route path MUST end with /* because otherwise
|
||||
// it will never match /blog/post/123 */}
|
||||
// <Route path="blog" element={<Blog />} />
|
||||
// <Route path="blog/feed" element={<BlogFeed />} />
|
||||
// </Routes>
|
||||
//
|
||||
// function Blog() {
|
||||
// return (
|
||||
// <Routes>
|
||||
// <Route path="post/:id" element={<Post />} />
|
||||
// </Routes>
|
||||
// );
|
||||
// }
|
||||
let parentPath = parentRoute && parentRoute.path || "";
|
||||
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}/*`}">.`);
|
||||
}
|
||||
|
||||
let locationFromContext = useLocation();
|
||||
let location;
|
||||
|
||||
if (locationArg) {
|
||||
let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
||||
!(parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase)) ? invariant(false, `When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, ` + `the location pathname must begin with the portion of the URL pathname that was ` + `matched by all parent routes. The current pathname base is "${parentPathnameBase}" ` + `but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.`) : void 0;
|
||||
location = parsedLocationArg;
|
||||
} else {
|
||||
location = locationFromContext;
|
||||
}
|
||||
|
||||
let pathname = location.pathname || "/";
|
||||
let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
|
||||
let matches = matchRoutes(routes, {
|
||||
pathname: remainingPathname
|
||||
});
|
||||
|
||||
{
|
||||
warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `) ;
|
||||
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.`) ;
|
||||
}
|
||||
|
||||
return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
|
||||
params: Object.assign({}, parentParams, match.params),
|
||||
pathname: joinPaths([parentPathnameBase, match.pathname]),
|
||||
pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
|
||||
})), parentMatches);
|
||||
}
|
||||
function _renderMatches(matches, parentMatches = []) {
|
||||
if (matches == null) return null;
|
||||
return matches.reduceRight((outlet, match, index) => {
|
||||
return /*#__PURE__*/createElement(RouteContext.Provider, {
|
||||
children: match.route.element !== undefined ? match.route.element : outlet,
|
||||
value: {
|
||||
outlet,
|
||||
matches: parentMatches.concat(matches.slice(0, index + 1))
|
||||
}
|
||||
});
|
||||
}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A <Router> that stores all entries in memory.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#memoryrouter
|
||||
*/
|
||||
function MemoryRouter({
|
||||
basename,
|
||||
children,
|
||||
initialEntries,
|
||||
initialIndex
|
||||
}) {
|
||||
let historyRef = useRef();
|
||||
|
||||
if (historyRef.current == null) {
|
||||
historyRef.current = createMemoryHistory({
|
||||
initialEntries,
|
||||
initialIndex
|
||||
});
|
||||
}
|
||||
|
||||
let history = historyRef.current;
|
||||
let [state, setState] = useState({
|
||||
action: history.action,
|
||||
location: history.location
|
||||
});
|
||||
useLayoutEffect(() => history.listen(setState), [history]);
|
||||
return /*#__PURE__*/createElement(Router, {
|
||||
basename: basename,
|
||||
children: children,
|
||||
location: state.location,
|
||||
navigationType: state.action,
|
||||
navigator: history
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current location.
|
||||
*
|
||||
* Note: This API is mostly useful in React.Component subclasses that are not
|
||||
* able to use hooks. In functional components, we recommend you use the
|
||||
* `useNavigate` hook instead.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#navigate
|
||||
*/
|
||||
function Navigate({
|
||||
to,
|
||||
replace,
|
||||
state
|
||||
}) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
|
||||
// the router loaded. We can help them understand how to avoid that.
|
||||
`<Navigate> may be used only in the context of a <Router> component.`) : void 0;
|
||||
warning(!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.`) ;
|
||||
let navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
navigate(to, {
|
||||
replace,
|
||||
state
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the child route's element, if there is one.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#outlet
|
||||
*/
|
||||
function Outlet(props) {
|
||||
return useOutlet(props.context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares an element that should be rendered at a certain URL path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#route
|
||||
*/
|
||||
function Route(_props) {
|
||||
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>.`) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides location context for the rest of the app.
|
||||
*
|
||||
* Note: You usually won't render a <Router> directly. Instead, you'll render a
|
||||
* router that is more specific to your environment such as a <BrowserRouter>
|
||||
* in web browsers or a <StaticRouter> for server rendering.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#router
|
||||
*/
|
||||
function Router({
|
||||
basename: basenameProp = "/",
|
||||
children = null,
|
||||
location: locationProp,
|
||||
navigationType = Action.Pop,
|
||||
navigator,
|
||||
static: staticProp = false
|
||||
}) {
|
||||
!!useInRouterContext() ? invariant(false, `You cannot render a <Router> inside another <Router>.` + ` You should never have more than one in your app.`) : void 0;
|
||||
let basename = normalizePathname(basenameProp);
|
||||
let navigationContext = useMemo(() => ({
|
||||
basename,
|
||||
navigator,
|
||||
static: staticProp
|
||||
}), [basename, navigator, staticProp]);
|
||||
|
||||
if (typeof locationProp === "string") {
|
||||
locationProp = parsePath(locationProp);
|
||||
}
|
||||
|
||||
let {
|
||||
pathname = "/",
|
||||
search = "",
|
||||
hash = "",
|
||||
state = null,
|
||||
key = "default"
|
||||
} = locationProp;
|
||||
let location = useMemo(() => {
|
||||
let trailingPathname = stripBasename(pathname, basename);
|
||||
|
||||
if (trailingPathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
pathname: trailingPathname,
|
||||
search,
|
||||
hash,
|
||||
state,
|
||||
key
|
||||
};
|
||||
}, [basename, pathname, search, hash, state, key]);
|
||||
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.`) ;
|
||||
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return /*#__PURE__*/createElement(NavigationContext.Provider, {
|
||||
value: navigationContext
|
||||
}, /*#__PURE__*/createElement(LocationContext.Provider, {
|
||||
children: children,
|
||||
value: {
|
||||
location,
|
||||
navigationType
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for a nested tree of <Route> elements that renders the branch
|
||||
* that best matches the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#routes
|
||||
*/
|
||||
function Routes({
|
||||
children,
|
||||
location
|
||||
}) {
|
||||
return useRoutes(createRoutesFromChildren(children), location);
|
||||
} ///////////////////////////////////////////////////////////////////////////////
|
||||
// UTILS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a route config from a React "children" object, which is usually
|
||||
* either a `<Route>` element or an array of them. Used internally by
|
||||
* `<Routes>` to create a route config from its children.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#createroutesfromchildren
|
||||
*/
|
||||
|
||||
function createRoutesFromChildren(children) {
|
||||
let routes = [];
|
||||
Children.forEach(children, element => {
|
||||
if (! /*#__PURE__*/isValidElement(element)) {
|
||||
// Ignore non-elements. This allows people to more easily inline
|
||||
// conditionals in their route config.
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.type === Fragment) {
|
||||
// Transparently support React.Fragment and its children.
|
||||
routes.push.apply(routes, createRoutesFromChildren(element.props.children));
|
||||
return;
|
||||
}
|
||||
|
||||
!(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;
|
||||
let route = {
|
||||
caseSensitive: element.props.caseSensitive,
|
||||
element: element.props.element,
|
||||
index: element.props.index,
|
||||
path: element.props.path
|
||||
};
|
||||
|
||||
if (element.props.children) {
|
||||
route.children = createRoutesFromChildren(element.props.children);
|
||||
}
|
||||
|
||||
routes.push(route);
|
||||
});
|
||||
return routes;
|
||||
}
|
||||
/**
|
||||
* Renders the result of `matchRoutes()` into a React element.
|
||||
*/
|
||||
|
||||
function renderMatches(matches) {
|
||||
return _renderMatches(matches);
|
||||
}
|
||||
|
||||
export { MemoryRouter, Navigate, Outlet, Route, Router, Routes, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, createRoutesFromChildren, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, useHref, useInRouterContext, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes };
|
||||
//# sourceMappingURL=react-router.development.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"react-router.development.js","sources":["../../../packages/react-router/lib/context.ts","../../../packages/react-router/lib/router.ts","../../../packages/react-router/lib/hooks.tsx","../../../packages/react-router/lib/components.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { History, Location } from \"history\";\nimport { Action as NavigationType } from \"history\";\n\nimport type { RouteMatch } from \"./router\";\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level <Router> API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport type Navigator = Pick<History, \"go\" | \"push\" | \"replace\" | \"createHref\">;\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n}\n\nexport const NavigationContext = React.createContext<NavigationContextObject>(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext<LocationContextObject>(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\ninterface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n}\n\nexport const RouteContext = React.createContext<RouteContextObject>({\n outlet: null,\n matches: [],\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n","import type { Location, Path, To } from \"history\";\nimport { parsePath } from \"history\";\n\nexport function invariant(cond: any, message: string): asserts cond {\n if (!cond) throw new Error(message);\n}\n\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nconst alreadyWarned: Record<string, boolean> = {};\nexport function warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n\ntype ParamParseFailed = { failed: true };\n\ntype ParamParseSegment<Segment extends string> =\n // Check here if there exists a forward slash in the string.\n Segment extends `${infer LeftSegment}/${infer RightSegment}`\n ? // If there is a forward slash, then attempt to parse each side of the\n // forward slash.\n ParamParseSegment<LeftSegment> extends infer LeftResult\n ? ParamParseSegment<RightSegment> extends infer RightResult\n ? LeftResult extends string\n ? // If the left side is successfully parsed as a param, then check if\n // the right side can be successfully parsed as well. If both sides\n // can be parsed, then the result is a union of the two sides\n // (read: \"foo\" | \"bar\").\n RightResult extends string\n ? LeftResult | RightResult\n : LeftResult\n : // If the left side is not successfully parsed as a param, then check\n // if only the right side can be successfully parse as a param. If it\n // can, then the result is just right, else it's a failure.\n RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If the left side didn't parse into a param, then just check the right\n // side.\n ParamParseSegment<RightSegment> extends infer RightResult\n ? RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If there's no forward slash, then check if this segment starts with a\n // colon. If it does, then this is a dynamic segment, so the result is\n // just the remainder of the string. Otherwise, it's a failure.\n Segment extends `:${infer Remaining}`\n ? Remaining\n : ParamParseFailed;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey<Segment extends string> =\n Line truncated
|
||||
Generated
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
import{parsePath as e,createMemoryHistory as t,Action as n}from"history";export{Action as NavigationType,createPath,parsePath}from"history";import{createContext as a,useContext as r,useMemo as l,useRef as i,useEffect as s,useCallback as o,createElement as h,useState as c,useLayoutEffect as u,Children as p,isValidElement as m,Fragment as f}from"react";const g=a(null),d=a(null),v=a({outlet:null,matches:[]});function y(e,t){if(!e)throw new Error(t)}function x(e,t={}){return e.replace(/:(\w+)/g,((e,n)=>(null==t[n]&&y(!1),t[n]))).replace(/\/*\*$/,(e=>null==t["*"]?"":t["*"].replace(/^\/*/,"/")))}function S(t,n,a="/"){let r=O(("string"==typeof n?e(n):n).pathname||"/",a);if(null==r)return null;let l=$(t);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,n)=>e===t[n]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(l);let i=null;for(let e=0;null==i&&e<l.length;++e)i=B(l[e],r);return i}function $(e,t=[],n=[],a=""){return e.forEach(((e,r)=>{let l={relativePath:e.path||"",caseSensitive:!0===e.caseSensitive,childrenIndex:r,route:e};l.relativePath.startsWith("/")&&(l.relativePath.startsWith(a)||y(!1),l.relativePath=l.relativePath.slice(a.length));let i=j([a,l.relativePath]),s=n.concat(l);e.children&&e.children.length>0&&(!0===e.index&&y(!1),$(e.children,t,s,i)),(null!=e.path||e.index)&&t.push({path:i,score:b(i,e.index),routesMeta:s})})),t}const P=/^:\w+$/,W=e=>"*"===e;function b(e,t){let n=e.split("/"),a=n.length;return n.some(W)&&(a+=-2),t&&(a+=2),n.filter((e=>!W(e))).reduce(((e,t)=>e+(P.test(t)?3:""===t?1:10)),a)}function B(e,t){let{routesMeta:n}=e,a={},r="/",l=[];for(let i=0;i<n.length;++i){let e=n[i],s=i===n.length-1,o="/"===r?t:t.slice(r.length)||"/",h=E({path:e.relativePath,caseSensitive:e.caseSensitive,end:s},o);if(!h)return null;Object.assign(a,h.params);let c=e.route;l.push({params:a,pathname:j([r,h.pathname]),pathnameBase:A(j([r,h.pathnameBase])),route:c}),"/"!==h.pathnameBase&&(r=j([r,h.pathnameBase]))}return l}function E(e,t){"string"==typeof e&&(e={path:e,caseSensitive:!1,end:!0});let[n,a]=function(e,t=!1,n=!0){let a=[],r="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/:(\w+)/g,((e,t)=>(a.push(t),"([^\\/]+)")));e.endsWith("*")?(a.push("*"),r+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r+=n?"\\/*$":"(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";return[new RegExp(r,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),r=t.match(n);if(!r)return null;let l=r[0],i=l.replace(/(.)\/+$/,"$1"),s=r.slice(1);return{params:a.reduce(((e,t,n)=>{if("*"===t){let e=s[n]||"";i=l.slice(0,l.length-e.length).replace(/(.)\/+$/,"$1")}return e[t]=function(e,t){try{return decodeURIComponent(e)}catch(n){return e}}(s[n]||""),e}),{}),pathname:l,pathnameBase:i,pattern:e}}function N(t,n="/"){let{pathname:a,search:r="",hash:l=""}="string"==typeof t?e(t):t,i=a?a.startsWith("/")?a:function(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?n.length>1&&n.pop():"."!==e&&n.push(e)})),n.length>1?n.join("/"):"/"}(a,n):n;return{pathname:i,search:C(r),hash:I(l)}}function w(t,n,a){let r,l="string"==typeof t?e(t):t,i=""===t||""===l.pathname?"/":l.pathname;if(null==i)r=a;else{let e=n.length-1;if(i.startsWith("..")){let t=i.split("/");for(;".."===t[0];)t.shift(),e-=1;l.pathname=t.join("/")}r=e>=0?n[e]:"/"}let s=N(l,r);return i&&"/"!==i&&i.endsWith("/")&&!s.pathname.endsWith("/")&&(s.pathname+="/"),s}function O(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=e.charAt(t.length);return n&&"/"!==n?null:e.slice(t.length)||"/"}const j=e=>e.join("/").replace(/\/\/+/g,"/"),A=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),C=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",I=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";function T(t){F()||y(!1);let{basename:n,navigator:a}=r(g),{hash:l,pathname:i,search:s}=q(t),o=i;if("/"!==n){let a=function(t){return""===t||""===t.pathname?"/":"string"==typeof t?e(t).pathname:t.pathname}(t),r=null!=a&&a.endsWith("/");o="/"===i?n+(r?"/":""):j([n,i])}return a.createHref({pathname:o,search:s,hash:l})}function F(){return null!=r(d)}function J(){return F()||y(!1),r(d).location}function M(){return r(d).navigationType}function R(e){F()||y(!1);let{pathname:t}=J();return l((()=>E(e,t)),[t,e])}function U(){F()||y(!1);let{basename:e,navigator:t}=r(g),{matches:n}=r(v),{pathname:a}=J(),l=JSON.stringify(n.map((e=>e.pathnameBase))),h=i(!1);return s((()=>{h.current=!0})),o(((n,r={})=>{if(!h.current)return;if("number"==typeof n)return void t.go(n);let i=w(n,JSON.parse(l),a);"/"!==e&&(i.pathname=j([e,i.pathname])),(r.replace?t.replace:t.push)(i,r.state)}),[e,t,l,a])}const L=a(null);function _(){return r(L)}function k(e){let t=r(v).outlet;return t?h(L.Provider,{value:e},t):t}function H(){let{matches:e}=r(v),t=e[e.length-1];return t?t.params:{}}function q(e){let{matches:t}=r(v),{pathname:n}=J(),a=JSON.strLine truncated
|
||||
//# sourceMappingURL=react-router.production.min.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"react-router.production.min.js","sources":["../../../packages/react-router/lib/context.ts","../../../packages/react-router/lib/router.ts","../../../packages/react-router/lib/hooks.tsx","../../../packages/react-router/lib/components.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { History, Location } from \"history\";\nimport { Action as NavigationType } from \"history\";\n\nimport type { RouteMatch } from \"./router\";\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level <Router> API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport type Navigator = Pick<History, \"go\" | \"push\" | \"replace\" | \"createHref\">;\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n}\n\nexport const NavigationContext = React.createContext<NavigationContextObject>(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext<LocationContextObject>(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\ninterface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n}\n\nexport const RouteContext = React.createContext<RouteContextObject>({\n outlet: null,\n matches: [],\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n","import type { Location, Path, To } from \"history\";\nimport { parsePath } from \"history\";\n\nexport function invariant(cond: any, message: string): asserts cond {\n if (!cond) throw new Error(message);\n}\n\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nconst alreadyWarned: Record<string, boolean> = {};\nexport function warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n\ntype ParamParseFailed = { failed: true };\n\ntype ParamParseSegment<Segment extends string> =\n // Check here if there exists a forward slash in the string.\n Segment extends `${infer LeftSegment}/${infer RightSegment}`\n ? // If there is a forward slash, then attempt to parse each side of the\n // forward slash.\n ParamParseSegment<LeftSegment> extends infer LeftResult\n ? ParamParseSegment<RightSegment> extends infer RightResult\n ? LeftResult extends string\n ? // If the left side is successfully parsed as a param, then check if\n // the right side can be successfully parsed as well. If both sides\n // can be parsed, then the result is a union of the two sides\n // (read: \"foo\" | \"bar\").\n RightResult extends string\n ? LeftResult | RightResult\n : LeftResult\n : // If the left side is not successfully parsed as a param, then check\n // if only the right side can be successfully parse as a param. If it\n // can, then the result is just right, else it's a failure.\n RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If the left side didn't parse into a param, then just check the right\n // side.\n ParamParseSegment<RightSegment> extends infer RightResult\n ? RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If there's no forward slash, then check if this segment starts with a\n // colon. If it does, then this is a dynamic segment, so the result is\n // just the remainder of the string. Otherwise, it's a failure.\n Segment extends `:${infer Remaining}`\n ? Remaining\n : ParamParseFailed;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey<Segment extends string> =\Line truncated
|
||||
Generated
Vendored
+990
@@ -0,0 +1,990 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('history'), require('react')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', 'history', 'react'], factory) :
|
||||
(global = global || self, factory(global.ReactRouter = {}, global.HistoryLibrary, global.React));
|
||||
}(this, (function (exports, history, React) { 'use strict';
|
||||
|
||||
const NavigationContext = /*#__PURE__*/React.createContext(null);
|
||||
|
||||
{
|
||||
NavigationContext.displayName = "Navigation";
|
||||
}
|
||||
|
||||
const LocationContext = /*#__PURE__*/React.createContext(null);
|
||||
|
||||
{
|
||||
LocationContext.displayName = "Location";
|
||||
}
|
||||
|
||||
const RouteContext = /*#__PURE__*/React.createContext({
|
||||
outlet: null,
|
||||
matches: []
|
||||
});
|
||||
|
||||
{
|
||||
RouteContext.displayName = "Route";
|
||||
}
|
||||
|
||||
function invariant(cond, message) {
|
||||
if (!cond) throw new Error(message);
|
||||
}
|
||||
function warning(cond, message) {
|
||||
if (!cond) {
|
||||
// eslint-disable-next-line no-console
|
||||
if (typeof console !== "undefined") console.warn(message);
|
||||
|
||||
try {
|
||||
// Welcome to debugging React Router!
|
||||
//
|
||||
// This error is thrown as a convenience so you can more easily
|
||||
// find the source for a warning that appears in the console by
|
||||
// enabling "pause on exceptions" in your JavaScript debugger.
|
||||
throw new Error(message); // eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
const alreadyWarned = {};
|
||||
function warningOnce(key, cond, message) {
|
||||
if (!cond && !alreadyWarned[key]) {
|
||||
alreadyWarned[key] = true;
|
||||
warning(false, message) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path with params interpolated.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#generatepath
|
||||
*/
|
||||
function generatePath(path, params) {
|
||||
if (params === void 0) {
|
||||
params = {};
|
||||
}
|
||||
|
||||
return path.replace(/:(\w+)/g, (_, key) => {
|
||||
!(params[key] != null) ? invariant(false, "Missing \":" + key + "\" param") : void 0;
|
||||
return params[key];
|
||||
}).replace(/\/*\*$/, _ => params["*"] == null ? "" : params["*"].replace(/^\/*/, "/"));
|
||||
}
|
||||
/**
|
||||
* A RouteMatch contains info about how a route matched a URL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Matches the given routes to a location and returns the match data.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchroutes
|
||||
*/
|
||||
function matchRoutes(routes, locationArg, basename) {
|
||||
if (basename === void 0) {
|
||||
basename = "/";
|
||||
}
|
||||
|
||||
let location = typeof locationArg === "string" ? history.parsePath(locationArg) : locationArg;
|
||||
let pathname = stripBasename(location.pathname || "/", basename);
|
||||
|
||||
if (pathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let branches = flattenRoutes(routes);
|
||||
rankRouteBranches(branches);
|
||||
let matches = null;
|
||||
|
||||
for (let i = 0; matches == null && i < branches.length; ++i) {
|
||||
matches = matchRouteBranch(branches[i], pathname);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
function flattenRoutes(routes, branches, parentsMeta, parentPath) {
|
||||
if (branches === void 0) {
|
||||
branches = [];
|
||||
}
|
||||
|
||||
if (parentsMeta === void 0) {
|
||||
parentsMeta = [];
|
||||
}
|
||||
|
||||
if (parentPath === void 0) {
|
||||
parentPath = "";
|
||||
}
|
||||
|
||||
routes.forEach((route, index) => {
|
||||
let meta = {
|
||||
relativePath: route.path || "",
|
||||
caseSensitive: route.caseSensitive === true,
|
||||
childrenIndex: index,
|
||||
route
|
||||
};
|
||||
|
||||
if (meta.relativePath.startsWith("/")) {
|
||||
!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;
|
||||
meta.relativePath = meta.relativePath.slice(parentPath.length);
|
||||
}
|
||||
|
||||
let path = joinPaths([parentPath, meta.relativePath]);
|
||||
let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
|
||||
// route tree depth-first and child routes appear before their parents in
|
||||
// the "flattened" version.
|
||||
|
||||
if (route.children && route.children.length > 0) {
|
||||
!(route.index !== true) ? invariant(false, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")) : void 0;
|
||||
flattenRoutes(route.children, branches, routesMeta, path);
|
||||
} // Routes without a path shouldn't ever match by themselves unless they are
|
||||
// index routes, so don't add them to the list of possible branches.
|
||||
|
||||
|
||||
if (route.path == null && !route.index) {
|
||||
return;
|
||||
}
|
||||
|
||||
branches.push({
|
||||
path,
|
||||
score: computeScore(path, route.index),
|
||||
routesMeta
|
||||
});
|
||||
});
|
||||
return branches;
|
||||
}
|
||||
|
||||
function rankRouteBranches(branches) {
|
||||
branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
|
||||
: compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
|
||||
}
|
||||
|
||||
const paramRe = /^:\w+$/;
|
||||
const dynamicSegmentValue = 3;
|
||||
const indexRouteValue = 2;
|
||||
const emptySegmentValue = 1;
|
||||
const staticSegmentValue = 10;
|
||||
const splatPenalty = -2;
|
||||
|
||||
const isSplat = s => s === "*";
|
||||
|
||||
function computeScore(path, index) {
|
||||
let segments = path.split("/");
|
||||
let initialScore = segments.length;
|
||||
|
||||
if (segments.some(isSplat)) {
|
||||
initialScore += splatPenalty;
|
||||
}
|
||||
|
||||
if (index) {
|
||||
initialScore += indexRouteValue;
|
||||
}
|
||||
|
||||
return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
||||
}
|
||||
|
||||
function compareIndexes(a, b) {
|
||||
let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
|
||||
return siblings ? // If two routes are siblings, we should try to match the earlier sibling
|
||||
// first. This allows people to have fine-grained control over the matching
|
||||
// behavior by simply putting routes with identical paths in the order they
|
||||
// want them tried.
|
||||
a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
|
||||
// so they sort equally.
|
||||
0;
|
||||
}
|
||||
|
||||
function matchRouteBranch(branch, pathname) {
|
||||
let {
|
||||
routesMeta
|
||||
} = branch;
|
||||
let matchedParams = {};
|
||||
let matchedPathname = "/";
|
||||
let matches = [];
|
||||
|
||||
for (let i = 0; i < routesMeta.length; ++i) {
|
||||
let meta = routesMeta[i];
|
||||
let end = i === routesMeta.length - 1;
|
||||
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
||||
let match = matchPath({
|
||||
path: meta.relativePath,
|
||||
caseSensitive: meta.caseSensitive,
|
||||
end
|
||||
}, remainingPathname);
|
||||
if (!match) return null;
|
||||
Object.assign(matchedParams, match.params);
|
||||
let route = meta.route;
|
||||
matches.push({
|
||||
params: matchedParams,
|
||||
pathname: joinPaths([matchedPathname, match.pathname]),
|
||||
pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
|
||||
route
|
||||
});
|
||||
|
||||
if (match.pathnameBase !== "/") {
|
||||
matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
/**
|
||||
* A PathPattern is used to match on some portion of a URL pathname.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Performs pattern matching on a URL pathname and returns information about
|
||||
* the match.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#matchpath
|
||||
*/
|
||||
function matchPath(pattern, pathname) {
|
||||
if (typeof pattern === "string") {
|
||||
pattern = {
|
||||
path: pattern,
|
||||
caseSensitive: false,
|
||||
end: true
|
||||
};
|
||||
}
|
||||
|
||||
let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
||||
let match = pathname.match(matcher);
|
||||
if (!match) return null;
|
||||
let matchedPathname = match[0];
|
||||
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
||||
let captureGroups = match.slice(1);
|
||||
let params = paramNames.reduce((memo, paramName, index) => {
|
||||
// We need to compute the pathnameBase here using the raw splat value
|
||||
// instead of using params["*"] later because it will be decoded then
|
||||
if (paramName === "*") {
|
||||
let splatValue = captureGroups[index] || "";
|
||||
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
||||
}
|
||||
|
||||
memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
|
||||
return memo;
|
||||
}, {});
|
||||
return {
|
||||
params,
|
||||
pathname: matchedPathname,
|
||||
pathnameBase,
|
||||
pattern
|
||||
};
|
||||
}
|
||||
|
||||
function compilePath(path, caseSensitive, end) {
|
||||
if (caseSensitive === void 0) {
|
||||
caseSensitive = false;
|
||||
}
|
||||
|
||||
if (end === void 0) {
|
||||
end = true;
|
||||
}
|
||||
|
||||
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(/\*$/, "/*") + "\".")) ;
|
||||
let paramNames = [];
|
||||
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
||||
.replace(/^\/*/, "/") // Make sure it has a leading /
|
||||
.replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
|
||||
.replace(/:(\w+)/g, (_, paramName) => {
|
||||
paramNames.push(paramName);
|
||||
return "([^\\/]+)";
|
||||
});
|
||||
|
||||
if (path.endsWith("*")) {
|
||||
paramNames.push("*");
|
||||
regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
|
||||
: "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
|
||||
} else {
|
||||
regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
|
||||
: // Otherwise, match a word boundary or a proceeding /. The word boundary restricts
|
||||
// parent routes to matching only their own words and nothing more, e.g. parent
|
||||
// route "/home" should not match "/home2".
|
||||
// Additionally, allow paths starting with `.`, `-`, `~`, and url-encoded entities,
|
||||
// but do not consume the character in the matched path so they can match against
|
||||
// nested paths.
|
||||
"(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";
|
||||
}
|
||||
|
||||
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
||||
return [matcher, paramNames];
|
||||
}
|
||||
|
||||
function safelyDecodeURIComponent(value, paramName) {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
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 + ").")) ;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a resolved path object relative to the given pathname.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#resolvepath
|
||||
*/
|
||||
|
||||
|
||||
function resolvePath(to, fromPathname) {
|
||||
if (fromPathname === void 0) {
|
||||
fromPathname = "/";
|
||||
}
|
||||
|
||||
let {
|
||||
pathname: toPathname,
|
||||
search = "",
|
||||
hash = ""
|
||||
} = typeof to === "string" ? history.parsePath(to) : to;
|
||||
let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
|
||||
return {
|
||||
pathname,
|
||||
search: normalizeSearch(search),
|
||||
hash: normalizeHash(hash)
|
||||
};
|
||||
}
|
||||
|
||||
function resolvePathname(relativePath, fromPathname) {
|
||||
let segments = fromPathname.replace(/\/+$/, "").split("/");
|
||||
let relativeSegments = relativePath.split("/");
|
||||
relativeSegments.forEach(segment => {
|
||||
if (segment === "..") {
|
||||
// Keep the root "" segment so the pathname starts at /
|
||||
if (segments.length > 1) segments.pop();
|
||||
} else if (segment !== ".") {
|
||||
segments.push(segment);
|
||||
}
|
||||
});
|
||||
return segments.length > 1 ? segments.join("/") : "/";
|
||||
}
|
||||
|
||||
function resolveTo(toArg, routePathnames, locationPathname) {
|
||||
let to = typeof toArg === "string" ? history.parsePath(toArg) : toArg;
|
||||
let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
|
||||
// route context. This is explained in `Note on `<Link to>` values` in our
|
||||
// migration guide from v5 as a means of disambiguation between `to` values
|
||||
// that begin with `/` and those that do not. However, this is problematic for
|
||||
// `to` values that do not provide a pathname. `to` can simply be a search or
|
||||
// hash string, in which case we should assume that the navigation is relative
|
||||
// to the current location's pathname and *not* the route pathname.
|
||||
|
||||
let from;
|
||||
|
||||
if (toPathname == null) {
|
||||
from = locationPathname;
|
||||
} else {
|
||||
let routePathnameIndex = routePathnames.length - 1;
|
||||
|
||||
if (toPathname.startsWith("..")) {
|
||||
let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
|
||||
// URL segment". This is a key difference from how <a href> works and a
|
||||
// major reason we call this a "to" value instead of a "href".
|
||||
|
||||
while (toSegments[0] === "..") {
|
||||
toSegments.shift();
|
||||
routePathnameIndex -= 1;
|
||||
}
|
||||
|
||||
to.pathname = toSegments.join("/");
|
||||
} // If there are more ".." segments than parent routes, resolve relative to
|
||||
// the root / URL.
|
||||
|
||||
|
||||
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
||||
}
|
||||
|
||||
let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
|
||||
|
||||
if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
|
||||
path.pathname += "/";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
function getToPathname(to) {
|
||||
// Empty strings should be treated the same as / paths
|
||||
return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? history.parsePath(to).pathname : to.pathname;
|
||||
}
|
||||
function stripBasename(pathname, basename) {
|
||||
if (basename === "/") return pathname;
|
||||
|
||||
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nextChar = pathname.charAt(basename.length);
|
||||
|
||||
if (nextChar && nextChar !== "/") {
|
||||
// pathname does not start with basename/
|
||||
return null;
|
||||
}
|
||||
|
||||
return pathname.slice(basename.length) || "/";
|
||||
}
|
||||
const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
|
||||
const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
|
||||
|
||||
const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
||||
|
||||
const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
||||
|
||||
/**
|
||||
* Returns the full href for the given "to" value. This is useful for building
|
||||
* custom links that are also accessible and preserve right-click behavior.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usehref
|
||||
*/
|
||||
|
||||
function useHref(to) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useHref() may be used only in the context of a <Router> component.") : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = React.useContext(NavigationContext);
|
||||
let {
|
||||
hash,
|
||||
pathname,
|
||||
search
|
||||
} = useResolvedPath(to);
|
||||
let joinedPathname = pathname;
|
||||
|
||||
if (basename !== "/") {
|
||||
let toPathname = getToPathname(to);
|
||||
let endsWithSlash = toPathname != null && toPathname.endsWith("/");
|
||||
joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
|
||||
}
|
||||
|
||||
return navigator.createHref({
|
||||
pathname: joinedPathname,
|
||||
search,
|
||||
hash
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns true if this component is a descendant of a <Router>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useinroutercontext
|
||||
*/
|
||||
|
||||
function useInRouterContext() {
|
||||
return React.useContext(LocationContext) != null;
|
||||
}
|
||||
/**
|
||||
* Returns the current location object, which represents the current URL in web
|
||||
* browsers.
|
||||
*
|
||||
* Note: If you're using this it may mean you're doing some of your own
|
||||
* "routing" in your app, and we'd like to know what your use case is. We may
|
||||
* be able to provide something higher-level to better suit your needs.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#uselocation
|
||||
*/
|
||||
|
||||
function useLocation() {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useLocation() may be used only in the context of a <Router> component.") : void 0;
|
||||
return React.useContext(LocationContext).location;
|
||||
}
|
||||
/**
|
||||
* Returns the current navigation action which describes how the router came to
|
||||
* the current location, either by a pop, push, or replace on the history stack.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigationtype
|
||||
*/
|
||||
|
||||
function useNavigationType() {
|
||||
return React.useContext(LocationContext).navigationType;
|
||||
}
|
||||
/**
|
||||
* Returns true if the URL for the given "to" value matches the current URL.
|
||||
* This is useful for components that need to know "active" state, e.g.
|
||||
* <NavLink>.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usematch
|
||||
*/
|
||||
|
||||
function useMatch(pattern) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useMatch() may be used only in the context of a <Router> component.") : void 0;
|
||||
let {
|
||||
pathname
|
||||
} = useLocation();
|
||||
return React.useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
|
||||
}
|
||||
/**
|
||||
* The interface for the navigate() function returned from useNavigate().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an imperative method for changing the location. Used by <Link>s, but
|
||||
* may also be used by other elements to change the location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#usenavigate
|
||||
*/
|
||||
function useNavigate() {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useNavigate() may be used only in the context of a <Router> component.") : void 0;
|
||||
let {
|
||||
basename,
|
||||
navigator
|
||||
} = React.useContext(NavigationContext);
|
||||
let {
|
||||
matches
|
||||
} = React.useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
let activeRef = React.useRef(false);
|
||||
React.useEffect(() => {
|
||||
activeRef.current = true;
|
||||
});
|
||||
let navigate = React.useCallback(function (to, options) {
|
||||
if (options === void 0) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
warning(activeRef.current, "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.") ;
|
||||
if (!activeRef.current) return;
|
||||
|
||||
if (typeof to === "number") {
|
||||
navigator.go(to);
|
||||
return;
|
||||
}
|
||||
|
||||
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
|
||||
|
||||
if (basename !== "/") {
|
||||
path.pathname = joinPaths([basename, path.pathname]);
|
||||
}
|
||||
|
||||
(!!options.replace ? navigator.replace : navigator.push)(path, options.state);
|
||||
}, [basename, navigator, routePathnamesJson, locationPathname]);
|
||||
return navigate;
|
||||
}
|
||||
const OutletContext = /*#__PURE__*/React.createContext(null);
|
||||
/**
|
||||
* Returns the context (if provided) for the child route at this level of the route
|
||||
* hierarchy.
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutletcontext
|
||||
*/
|
||||
|
||||
function useOutletContext() {
|
||||
return React.useContext(OutletContext);
|
||||
}
|
||||
/**
|
||||
* Returns the element for the child route at this level of the route
|
||||
* hierarchy. Used internally by <Outlet> to render child routes.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useoutlet
|
||||
*/
|
||||
|
||||
function useOutlet(context) {
|
||||
let outlet = React.useContext(RouteContext).outlet;
|
||||
|
||||
if (outlet) {
|
||||
return /*#__PURE__*/React.createElement(OutletContext.Provider, {
|
||||
value: context
|
||||
}, outlet);
|
||||
}
|
||||
|
||||
return outlet;
|
||||
}
|
||||
/**
|
||||
* Returns an object of key/value pairs of the dynamic params from the current
|
||||
* URL that were matched by the route path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useparams
|
||||
*/
|
||||
|
||||
function useParams() {
|
||||
let {
|
||||
matches
|
||||
} = React.useContext(RouteContext);
|
||||
let routeMatch = matches[matches.length - 1];
|
||||
return routeMatch ? routeMatch.params : {};
|
||||
}
|
||||
/**
|
||||
* Resolves the pathname of the given `to` value against the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useresolvedpath
|
||||
*/
|
||||
|
||||
function useResolvedPath(to) {
|
||||
let {
|
||||
matches
|
||||
} = React.useContext(RouteContext);
|
||||
let {
|
||||
pathname: locationPathname
|
||||
} = useLocation();
|
||||
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
||||
return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
|
||||
}
|
||||
/**
|
||||
* Returns the element of the route that matched the current location, prepared
|
||||
* with the correct context to render the remainder of the route tree. Route
|
||||
* elements in the tree must render an <Outlet> to render their child route's
|
||||
* element.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#useroutes
|
||||
*/
|
||||
|
||||
function useRoutes(routes, locationArg) {
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
||||
// router loaded. We can help them understand how to avoid that.
|
||||
"useRoutes() may be used only in the context of a <Router> component.") : void 0;
|
||||
let {
|
||||
matches: parentMatches
|
||||
} = React.useContext(RouteContext);
|
||||
let routeMatch = parentMatches[parentMatches.length - 1];
|
||||
let parentParams = routeMatch ? routeMatch.params : {};
|
||||
let parentPathname = routeMatch ? routeMatch.pathname : "/";
|
||||
let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
|
||||
let parentRoute = routeMatch && routeMatch.route;
|
||||
|
||||
{
|
||||
// You won't get a warning about 2 different <Routes> under a <Route>
|
||||
// without a trailing *, but this is a best-effort warning anyway since we
|
||||
// cannot even give the warning unless they land at the parent route.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// <Routes>
|
||||
// {/* This route path MUST end with /* because otherwise
|
||||
// it will never match /blog/post/123 */}
|
||||
// <Route path="blog" element={<Blog />} />
|
||||
// <Route path="blog/feed" element={<BlogFeed />} />
|
||||
// </Routes>
|
||||
//
|
||||
// function Blog() {
|
||||
// return (
|
||||
// <Routes>
|
||||
// <Route path="post/:id" element={<Post />} />
|
||||
// </Routes>
|
||||
// );
|
||||
// }
|
||||
let parentPath = parentRoute && parentRoute.path || "";
|
||||
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 + "/*") + "\">."));
|
||||
}
|
||||
|
||||
let locationFromContext = useLocation();
|
||||
let location;
|
||||
|
||||
if (locationArg) {
|
||||
var _parsedLocationArg$pa;
|
||||
|
||||
let parsedLocationArg = typeof locationArg === "string" ? history.parsePath(locationArg) : locationArg;
|
||||
!(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;
|
||||
location = parsedLocationArg;
|
||||
} else {
|
||||
location = locationFromContext;
|
||||
}
|
||||
|
||||
let pathname = location.pathname || "/";
|
||||
let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
|
||||
let matches = matchRoutes(routes, {
|
||||
pathname: remainingPathname
|
||||
});
|
||||
|
||||
{
|
||||
warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") ;
|
||||
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.") ;
|
||||
}
|
||||
|
||||
return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
|
||||
params: Object.assign({}, parentParams, match.params),
|
||||
pathname: joinPaths([parentPathnameBase, match.pathname]),
|
||||
pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
|
||||
})), parentMatches);
|
||||
}
|
||||
function _renderMatches(matches, parentMatches) {
|
||||
if (parentMatches === void 0) {
|
||||
parentMatches = [];
|
||||
}
|
||||
|
||||
if (matches == null) return null;
|
||||
return matches.reduceRight((outlet, match, index) => {
|
||||
return /*#__PURE__*/React.createElement(RouteContext.Provider, {
|
||||
children: match.route.element !== undefined ? match.route.element : outlet,
|
||||
value: {
|
||||
outlet,
|
||||
matches: parentMatches.concat(matches.slice(0, index + 1))
|
||||
}
|
||||
});
|
||||
}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A <Router> that stores all entries in memory.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#memoryrouter
|
||||
*/
|
||||
function MemoryRouter(_ref) {
|
||||
let {
|
||||
basename,
|
||||
children,
|
||||
initialEntries,
|
||||
initialIndex
|
||||
} = _ref;
|
||||
let historyRef = React.useRef();
|
||||
|
||||
if (historyRef.current == null) {
|
||||
historyRef.current = history.createMemoryHistory({
|
||||
initialEntries,
|
||||
initialIndex
|
||||
});
|
||||
}
|
||||
|
||||
let history$1 = historyRef.current;
|
||||
let [state, setState] = React.useState({
|
||||
action: history$1.action,
|
||||
location: history$1.location
|
||||
});
|
||||
React.useLayoutEffect(() => history$1.listen(setState), [history$1]);
|
||||
return /*#__PURE__*/React.createElement(Router, {
|
||||
basename: basename,
|
||||
children: children,
|
||||
location: state.location,
|
||||
navigationType: state.action,
|
||||
navigator: history$1
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current location.
|
||||
*
|
||||
* Note: This API is mostly useful in React.Component subclasses that are not
|
||||
* able to use hooks. In functional components, we recommend you use the
|
||||
* `useNavigate` hook instead.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#navigate
|
||||
*/
|
||||
function Navigate(_ref2) {
|
||||
let {
|
||||
to,
|
||||
replace,
|
||||
state
|
||||
} = _ref2;
|
||||
!useInRouterContext() ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of
|
||||
// the router loaded. We can help them understand how to avoid that.
|
||||
"<Navigate> may be used only in the context of a <Router> component.") : void 0;
|
||||
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.") ;
|
||||
let navigate = useNavigate();
|
||||
React.useEffect(() => {
|
||||
navigate(to, {
|
||||
replace,
|
||||
state
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the child route's element, if there is one.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#outlet
|
||||
*/
|
||||
function Outlet(props) {
|
||||
return useOutlet(props.context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares an element that should be rendered at a certain URL path.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#route
|
||||
*/
|
||||
function Route(_props) {
|
||||
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>.") ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides location context for the rest of the app.
|
||||
*
|
||||
* Note: You usually won't render a <Router> directly. Instead, you'll render a
|
||||
* router that is more specific to your environment such as a <BrowserRouter>
|
||||
* in web browsers or a <StaticRouter> for server rendering.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#router
|
||||
*/
|
||||
function Router(_ref3) {
|
||||
let {
|
||||
basename: basenameProp = "/",
|
||||
children = null,
|
||||
location: locationProp,
|
||||
navigationType = history.Action.Pop,
|
||||
navigator,
|
||||
static: staticProp = false
|
||||
} = _ref3;
|
||||
!!useInRouterContext() ? invariant(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : void 0;
|
||||
let basename = normalizePathname(basenameProp);
|
||||
let navigationContext = React.useMemo(() => ({
|
||||
basename,
|
||||
navigator,
|
||||
static: staticProp
|
||||
}), [basename, navigator, staticProp]);
|
||||
|
||||
if (typeof locationProp === "string") {
|
||||
locationProp = history.parsePath(locationProp);
|
||||
}
|
||||
|
||||
let {
|
||||
pathname = "/",
|
||||
search = "",
|
||||
hash = "",
|
||||
state = null,
|
||||
key = "default"
|
||||
} = locationProp;
|
||||
let location = React.useMemo(() => {
|
||||
let trailingPathname = stripBasename(pathname, basename);
|
||||
|
||||
if (trailingPathname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
pathname: trailingPathname,
|
||||
search,
|
||||
hash,
|
||||
state,
|
||||
key
|
||||
};
|
||||
}, [basename, pathname, search, hash, state, key]);
|
||||
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.") ;
|
||||
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
|
||||
value: navigationContext
|
||||
}, /*#__PURE__*/React.createElement(LocationContext.Provider, {
|
||||
children: children,
|
||||
value: {
|
||||
location,
|
||||
navigationType
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for a nested tree of <Route> elements that renders the branch
|
||||
* that best matches the current location.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#routes
|
||||
*/
|
||||
function Routes(_ref4) {
|
||||
let {
|
||||
children,
|
||||
location
|
||||
} = _ref4;
|
||||
return useRoutes(createRoutesFromChildren(children), location);
|
||||
} ///////////////////////////////////////////////////////////////////////////////
|
||||
// UTILS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a route config from a React "children" object, which is usually
|
||||
* either a `<Route>` element or an array of them. Used internally by
|
||||
* `<Routes>` to create a route config from its children.
|
||||
*
|
||||
* @see https://reactrouter.com/docs/en/v6/api#createroutesfromchildren
|
||||
*/
|
||||
|
||||
function createRoutesFromChildren(children) {
|
||||
let routes = [];
|
||||
React.Children.forEach(children, element => {
|
||||
if (! /*#__PURE__*/React.isValidElement(element)) {
|
||||
// Ignore non-elements. This allows people to more easily inline
|
||||
// conditionals in their route config.
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.type === React.Fragment) {
|
||||
// Transparently support React.Fragment and its children.
|
||||
routes.push.apply(routes, createRoutesFromChildren(element.props.children));
|
||||
return;
|
||||
}
|
||||
|
||||
!(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;
|
||||
let route = {
|
||||
caseSensitive: element.props.caseSensitive,
|
||||
element: element.props.element,
|
||||
index: element.props.index,
|
||||
path: element.props.path
|
||||
};
|
||||
|
||||
if (element.props.children) {
|
||||
route.children = createRoutesFromChildren(element.props.children);
|
||||
}
|
||||
|
||||
routes.push(route);
|
||||
});
|
||||
return routes;
|
||||
}
|
||||
/**
|
||||
* Renders the result of `matchRoutes()` into a React element.
|
||||
*/
|
||||
|
||||
function renderMatches(matches) {
|
||||
return _renderMatches(matches);
|
||||
}
|
||||
|
||||
Object.defineProperty(exports, 'NavigationType', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return history.Action;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'createPath', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return history.createPath;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'parsePath', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return history.parsePath;
|
||||
}
|
||||
});
|
||||
exports.MemoryRouter = MemoryRouter;
|
||||
exports.Navigate = Navigate;
|
||||
exports.Outlet = Outlet;
|
||||
exports.Route = Route;
|
||||
exports.Router = Router;
|
||||
exports.Routes = Routes;
|
||||
exports.UNSAFE_LocationContext = LocationContext;
|
||||
exports.UNSAFE_NavigationContext = NavigationContext;
|
||||
exports.UNSAFE_RouteContext = RouteContext;
|
||||
exports.createRoutesFromChildren = createRoutesFromChildren;
|
||||
exports.generatePath = generatePath;
|
||||
exports.matchPath = matchPath;
|
||||
exports.matchRoutes = matchRoutes;
|
||||
exports.renderMatches = renderMatches;
|
||||
exports.resolvePath = resolvePath;
|
||||
exports.useHref = useHref;
|
||||
exports.useInRouterContext = useInRouterContext;
|
||||
exports.useLocation = useLocation;
|
||||
exports.useMatch = useMatch;
|
||||
exports.useNavigate = useNavigate;
|
||||
exports.useNavigationType = useNavigationType;
|
||||
exports.useOutlet = useOutlet;
|
||||
exports.useOutletContext = useOutletContext;
|
||||
exports.useParams = useParams;
|
||||
exports.useResolvedPath = useResolvedPath;
|
||||
exports.useRoutes = useRoutes;
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
})));
|
||||
//# sourceMappingURL=react-router.development.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"react-router.development.js","sources":["../../../../packages/react-router/lib/context.ts","../../../../packages/react-router/lib/router.ts","../../../../packages/react-router/lib/hooks.tsx","../../../../packages/react-router/lib/components.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { History, Location } from \"history\";\nimport { Action as NavigationType } from \"history\";\n\nimport type { RouteMatch } from \"./router\";\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level <Router> API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport type Navigator = Pick<History, \"go\" | \"push\" | \"replace\" | \"createHref\">;\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n}\n\nexport const NavigationContext = React.createContext<NavigationContextObject>(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext<LocationContextObject>(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\ninterface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n}\n\nexport const RouteContext = React.createContext<RouteContextObject>({\n outlet: null,\n matches: [],\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n","import type { Location, Path, To } from \"history\";\nimport { parsePath } from \"history\";\n\nexport function invariant(cond: any, message: string): asserts cond {\n if (!cond) throw new Error(message);\n}\n\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nconst alreadyWarned: Record<string, boolean> = {};\nexport function warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n\ntype ParamParseFailed = { failed: true };\n\ntype ParamParseSegment<Segment extends string> =\n // Check here if there exists a forward slash in the string.\n Segment extends `${infer LeftSegment}/${infer RightSegment}`\n ? // If there is a forward slash, then attempt to parse each side of the\n // forward slash.\n ParamParseSegment<LeftSegment> extends infer LeftResult\n ? ParamParseSegment<RightSegment> extends infer RightResult\n ? LeftResult extends string\n ? // If the left side is successfully parsed as a param, then check if\n // the right side can be successfully parsed as well. If both sides\n // can be parsed, then the result is a union of the two sides\n // (read: \"foo\" | \"bar\").\n RightResult extends string\n ? LeftResult | RightResult\n : LeftResult\n : // If the left side is not successfully parsed as a param, then check\n // if only the right side can be successfully parse as a param. If it\n // can, then the result is just right, else it's a failure.\n RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If the left side didn't parse into a param, then just check the right\n // side.\n ParamParseSegment<RightSegment> extends infer RightResult\n ? RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If there's no forward slash, then check if this segment starts with a\n // colon. If it does, then this is a dynamic segment, so the result is\n // just the remainder of the string. Otherwise, it's a failure.\n Segment extends `:${infer Remaining}`\n ? Remaining\n : ParamParseFailed;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey<Segment extends sLine truncated
|
||||
Generated
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("history"),require("react")):"function"==typeof define&&define.amd?define(["exports","history","react"],t):t((e=e||self).ReactRouter={},e.HistoryLibrary,e.React)}(this,(function(e,t,n){"use strict";const a=n.createContext(null),r=n.createContext(null),i=n.createContext({outlet:null,matches:[]});function l(e,t){if(!e)throw new Error(t)}function o(e,n,a){void 0===a&&(a="/");let r=g(("string"==typeof n?t.parsePath(n):n).pathname||"/",a);if(null==r)return null;let i=s(e);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,n)=>e===t[n]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(i);let l=null;for(let e=0;null==l&&e<i.length;++e)l=p(i[e],r);return l}function s(e,t,n,a){return void 0===t&&(t=[]),void 0===n&&(n=[]),void 0===a&&(a=""),e.forEach(((e,r)=>{let i={relativePath:e.path||"",caseSensitive:!0===e.caseSensitive,childrenIndex:r,route:e};i.relativePath.startsWith("/")&&(i.relativePath.startsWith(a)||l(!1),i.relativePath=i.relativePath.slice(a.length));let o=v([a,i.relativePath]),u=n.concat(i);e.children&&e.children.length>0&&(!0===e.index&&l(!1),s(e.children,t,u,o)),(null!=e.path||e.index)&&t.push({path:o,score:h(o,e.index),routesMeta:u})})),t}const u=/^:\w+$/,c=e=>"*"===e;function h(e,t){let n=e.split("/"),a=n.length;return n.some(c)&&(a+=-2),t&&(a+=2),n.filter((e=>!c(e))).reduce(((e,t)=>e+(u.test(t)?3:""===t?1:10)),a)}function p(e,t){let{routesMeta:n}=e,a={},r="/",i=[];for(let e=0;e<n.length;++e){let l=n[e],o=e===n.length-1,s="/"===r?t:t.slice(r.length)||"/",u=f({path:l.relativePath,caseSensitive:l.caseSensitive,end:o},s);if(!u)return null;Object.assign(a,u.params);let c=l.route;i.push({params:a,pathname:v([r,u.pathname]),pathnameBase:y(v([r,u.pathnameBase])),route:c}),"/"!==u.pathnameBase&&(r=v([r,u.pathnameBase]))}return i}function f(e,t){"string"==typeof e&&(e={path:e,caseSensitive:!1,end:!0});let[n,a]=function(e,t,n){void 0===t&&(t=!1);void 0===n&&(n=!0);let a=[],r="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/:(\w+)/g,((e,t)=>(a.push(t),"([^\\/]+)")));e.endsWith("*")?(a.push("*"),r+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r+=n?"\\/*$":"(?:(?=[.~-]|%[0-9A-F]{2})|\\b|\\/|$)";return[new RegExp(r,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),r=t.match(n);if(!r)return null;let i=r[0],l=i.replace(/(.)\/+$/,"$1"),o=r.slice(1);return{params:a.reduce(((e,t,n)=>{if("*"===t){let e=o[n]||"";l=i.slice(0,i.length-e.length).replace(/(.)\/+$/,"$1")}return e[t]=function(e,t){try{return decodeURIComponent(e)}catch(t){return e}}(o[n]||""),e}),{}),pathname:i,pathnameBase:l,pattern:e}}function m(e,n){void 0===n&&(n="/");let{pathname:a,search:r="",hash:i=""}="string"==typeof e?t.parsePath(e):e,l=a?a.startsWith("/")?a:function(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?n.length>1&&n.pop():"."!==e&&n.push(e)})),n.length>1?n.join("/"):"/"}(a,n):n;return{pathname:l,search:x(r),hash:P(i)}}function d(e,n,a){let r,i="string"==typeof e?t.parsePath(e):e,l=""===e||""===i.pathname?"/":i.pathname;if(null==l)r=a;else{let e=n.length-1;if(l.startsWith("..")){let t=l.split("/");for(;".."===t[0];)t.shift(),e-=1;i.pathname=t.join("/")}r=e>=0?n[e]:"/"}let o=m(i,r);return l&&"/"!==l&&l.endsWith("/")&&!o.pathname.endsWith("/")&&(o.pathname+="/"),o}function g(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=e.charAt(t.length);return n&&"/"!==n?null:e.slice(t.length)||"/"}const v=e=>e.join("/").replace(/\/\/+/g,"/"),y=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),x=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",P=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";function C(){return null!=n.useContext(r)}function b(){return C()||l(!1),n.useContext(r).location}function E(){C()||l(!1);let{basename:e,navigator:t}=n.useContext(a),{matches:r}=n.useContext(i),{pathname:o}=b(),s=JSON.stringify(r.map((e=>e.pathnameBase))),u=n.useRef(!1);return n.useEffect((()=>{u.current=!0})),n.useCallback((function(n,a){if(void 0===a&&(a={}),!u.current)return;if("number"==typeof n)return void t.go(n);let r=d(n,JSON.parse(s),o);"/"!==e&&(r.pathname=v([e,r.pathname])),(a.replace?t.replace:t.push)(r,a.state)}),[e,t,s,o])}const R=n.createContext(null);function S(e){let t=n.useContext(i).outlet;return t?n.createElement(R.Provider,{value:e},t):t}function $(e){let{matches:t}=n.useContext(i),{pathname:a}=b(),r=JSON.stringify(t.map((e=>e.pathnameBase)));return n.useMemo((()=>d(e,JSON.parse(r),a)),[e,r,a])}function O(e,a){C()||l(!1);let r,{matches:s}=n.useContext(i),u=s[s.length-1],c=u?u.params:{},h=(u&&u.pathname,u?u.pathnameBase:"/"),p=(u&&u.route,b());if(a){var f;let e="string"==typeof a?t.parsePath(a):a;"/"===h||(null==(f=e.pathname)?void 0:f.startsWith(h))||l(!1),r=e}else r=p;let m=r.pathname||"/",d=o(e,{pathname:"/"===hLine truncated
|
||||
//# sourceMappingURL=react-router.production.min.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"react-router.production.min.js","sources":["../../../../packages/react-router/lib/context.ts","../../../../packages/react-router/lib/router.ts","../../../../packages/react-router/lib/hooks.tsx","../../../../packages/react-router/lib/components.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { History, Location } from \"history\";\nimport { Action as NavigationType } from \"history\";\n\nimport type { RouteMatch } from \"./router\";\n\n/**\n * A Navigator is a \"location changer\"; it's how you get to different locations.\n *\n * Every history instance conforms to the Navigator interface, but the\n * distinction is useful primarily when it comes to the low-level <Router> API\n * where both the location and a navigator must be provided separately in order\n * to avoid \"tearing\" that may occur in a suspense-enabled app if the action\n * and/or location were to be read directly from the history instance.\n */\nexport type Navigator = Pick<History, \"go\" | \"push\" | \"replace\" | \"createHref\">;\n\ninterface NavigationContextObject {\n basename: string;\n navigator: Navigator;\n static: boolean;\n}\n\nexport const NavigationContext = React.createContext<NavigationContextObject>(\n null!\n);\n\nif (__DEV__) {\n NavigationContext.displayName = \"Navigation\";\n}\n\ninterface LocationContextObject {\n location: Location;\n navigationType: NavigationType;\n}\n\nexport const LocationContext = React.createContext<LocationContextObject>(\n null!\n);\n\nif (__DEV__) {\n LocationContext.displayName = \"Location\";\n}\n\ninterface RouteContextObject {\n outlet: React.ReactElement | null;\n matches: RouteMatch[];\n}\n\nexport const RouteContext = React.createContext<RouteContextObject>({\n outlet: null,\n matches: [],\n});\n\nif (__DEV__) {\n RouteContext.displayName = \"Route\";\n}\n","import type { Location, Path, To } from \"history\";\nimport { parsePath } from \"history\";\n\nexport function invariant(cond: any, message: string): asserts cond {\n if (!cond) throw new Error(message);\n}\n\nexport function warning(cond: any, message: string): void {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging React Router!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nconst alreadyWarned: Record<string, boolean> = {};\nexport function warningOnce(key: string, cond: boolean, message: string) {\n if (!cond && !alreadyWarned[key]) {\n alreadyWarned[key] = true;\n warning(false, message);\n }\n}\n\ntype ParamParseFailed = { failed: true };\n\ntype ParamParseSegment<Segment extends string> =\n // Check here if there exists a forward slash in the string.\n Segment extends `${infer LeftSegment}/${infer RightSegment}`\n ? // If there is a forward slash, then attempt to parse each side of the\n // forward slash.\n ParamParseSegment<LeftSegment> extends infer LeftResult\n ? ParamParseSegment<RightSegment> extends infer RightResult\n ? LeftResult extends string\n ? // If the left side is successfully parsed as a param, then check if\n // the right side can be successfully parsed as well. If both sides\n // can be parsed, then the result is a union of the two sides\n // (read: \"foo\" | \"bar\").\n RightResult extends string\n ? LeftResult | RightResult\n : LeftResult\n : // If the left side is not successfully parsed as a param, then check\n // if only the right side can be successfully parse as a param. If it\n // can, then the result is just right, else it's a failure.\n RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If the left side didn't parse into a param, then just check the right\n // side.\n ParamParseSegment<RightSegment> extends infer RightResult\n ? RightResult extends string\n ? RightResult\n : ParamParseFailed\n : ParamParseFailed\n : // If there's no forward slash, then check if this segment starts with a\n // colon. If it does, then this is a dynamic segment, so the result is\n // just the remainder of the string. Otherwise, it's a failure.\n Segment extends `:${infer Remaining}`\n ? Remaining\n : ParamParseFailed;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey<Segment extendLine truncated
|
||||
Reference in new issue
Block a user