react-router 6.0.0-beta.5 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{LICENSE → LICENSE.md} +0 -0
- package/index.d.ts +45 -22
- package/index.js +223 -160
- package/index.js.map +1 -1
- package/main.js +10 -0
- package/package.json +8 -6
- package/react-router.development.js +217 -138
- package/react-router.development.js.map +1 -1
- package/react-router.production.min.js +11 -1
- package/react-router.production.min.js.map +1 -1
- package/umd/react-router.development.js +223 -160
- package/umd/react-router.development.js.map +1 -1
- package/umd/react-router.production.min.js +11 -1
- package/umd/react-router.production.min.js.map +1 -1
- package/umd/index.d.ts +0 -303
package/index.js
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Router v6.0.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
1
11
|
import { createContext, useRef, useState, useLayoutEffect, createElement, useContext, useEffect, useMemo, useCallback, Children, isValidElement, Fragment } from 'react';
|
|
2
12
|
import { createMemoryHistory, Action, parsePath } from 'history';
|
|
3
13
|
|
|
4
|
-
function _extends() {
|
|
5
|
-
_extends = Object.assign || function (target) {
|
|
6
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
7
|
-
var source = arguments[i];
|
|
8
|
-
|
|
9
|
-
for (var key in source) {
|
|
10
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
11
|
-
target[key] = source[key];
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return target;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return _extends.apply(this, arguments);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
14
|
function invariant(cond, message) {
|
|
23
15
|
if (!cond) throw new Error(message);
|
|
24
16
|
}
|
|
@@ -46,7 +38,20 @@ function warningOnce(key, cond, message) {
|
|
|
46
38
|
alreadyWarned[key] = true;
|
|
47
39
|
process.env.NODE_ENV !== "production" ? warning(false, message) : void 0;
|
|
48
40
|
}
|
|
49
|
-
}
|
|
41
|
+
} ///////////////////////////////////////////////////////////////////////////////
|
|
42
|
+
// CONTEXT
|
|
43
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A Navigator is a "location changer"; it's how you get to different locations.
|
|
47
|
+
*
|
|
48
|
+
* Every history instance conforms to the Navigator interface, but the
|
|
49
|
+
* distinction is useful primarily when it comes to the low-level <Router> API
|
|
50
|
+
* where both the location and a navigator must be provided separately in order
|
|
51
|
+
* to avoid "tearing" that may occur in a suspense-enabled app if the action
|
|
52
|
+
* and/or location were to be read directly from the history instance.
|
|
53
|
+
*/
|
|
54
|
+
|
|
50
55
|
|
|
51
56
|
const NavigationContext = /*#__PURE__*/createContext(null);
|
|
52
57
|
|
|
@@ -62,21 +67,21 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
62
67
|
|
|
63
68
|
const RouteContext = /*#__PURE__*/createContext({
|
|
64
69
|
outlet: null,
|
|
65
|
-
|
|
66
|
-
pathname: "/",
|
|
67
|
-
route: null
|
|
70
|
+
matches: []
|
|
68
71
|
});
|
|
69
72
|
|
|
70
73
|
if (process.env.NODE_ENV !== "production") {
|
|
71
74
|
RouteContext.displayName = "Route";
|
|
72
|
-
}
|
|
75
|
+
} ///////////////////////////////////////////////////////////////////////////////
|
|
76
|
+
// COMPONENTS
|
|
77
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
78
|
+
|
|
79
|
+
|
|
73
80
|
/**
|
|
74
81
|
* A <Router> that stores all entries in memory.
|
|
75
82
|
*
|
|
76
83
|
* @see https://reactrouter.com/api/MemoryRouter
|
|
77
84
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
85
|
function MemoryRouter(_ref) {
|
|
81
86
|
let {
|
|
82
87
|
basename,
|
|
@@ -102,11 +107,12 @@ function MemoryRouter(_ref) {
|
|
|
102
107
|
return /*#__PURE__*/createElement(Router, {
|
|
103
108
|
basename: basename,
|
|
104
109
|
children: children,
|
|
105
|
-
action: state.action,
|
|
106
110
|
location: state.location,
|
|
111
|
+
navigationType: state.action,
|
|
107
112
|
navigator: history
|
|
108
113
|
});
|
|
109
114
|
}
|
|
115
|
+
|
|
110
116
|
/**
|
|
111
117
|
* Changes the current location.
|
|
112
118
|
*
|
|
@@ -116,7 +122,6 @@ function MemoryRouter(_ref) {
|
|
|
116
122
|
*
|
|
117
123
|
* @see https://reactrouter.com/api/Navigate
|
|
118
124
|
*/
|
|
119
|
-
|
|
120
125
|
function Navigate(_ref2) {
|
|
121
126
|
let {
|
|
122
127
|
to,
|
|
@@ -136,24 +141,25 @@ function Navigate(_ref2) {
|
|
|
136
141
|
});
|
|
137
142
|
return null;
|
|
138
143
|
}
|
|
144
|
+
|
|
139
145
|
/**
|
|
140
146
|
* Renders the child route's element, if there is one.
|
|
141
147
|
*
|
|
142
148
|
* @see https://reactrouter.com/api/Outlet
|
|
143
149
|
*/
|
|
144
|
-
|
|
145
150
|
function Outlet(_props) {
|
|
146
151
|
return useOutlet();
|
|
147
152
|
}
|
|
153
|
+
|
|
148
154
|
/**
|
|
149
155
|
* Declares an element that should be rendered at a certain URL path.
|
|
150
156
|
*
|
|
151
157
|
* @see https://reactrouter.com/api/Route
|
|
152
158
|
*/
|
|
153
|
-
|
|
154
159
|
function Route(_props) {
|
|
155
160
|
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) ;
|
|
156
161
|
}
|
|
162
|
+
|
|
157
163
|
/**
|
|
158
164
|
* Provides location context for the rest of the app.
|
|
159
165
|
*
|
|
@@ -163,13 +169,12 @@ function Route(_props) {
|
|
|
163
169
|
*
|
|
164
170
|
* @see https://reactrouter.com/api/Router
|
|
165
171
|
*/
|
|
166
|
-
|
|
167
172
|
function Router(_ref3) {
|
|
168
173
|
let {
|
|
169
|
-
action = Action.Pop,
|
|
170
174
|
basename: basenameProp = "/",
|
|
171
175
|
children = null,
|
|
172
176
|
location: locationProp,
|
|
177
|
+
navigationType = Action.Pop,
|
|
173
178
|
navigator,
|
|
174
179
|
static: staticProp = false
|
|
175
180
|
} = _ref3;
|
|
@@ -218,18 +223,18 @@ function Router(_ref3) {
|
|
|
218
223
|
}, /*#__PURE__*/createElement(LocationContext.Provider, {
|
|
219
224
|
children: children,
|
|
220
225
|
value: {
|
|
221
|
-
|
|
222
|
-
|
|
226
|
+
location,
|
|
227
|
+
navigationType
|
|
223
228
|
}
|
|
224
229
|
}));
|
|
225
230
|
}
|
|
231
|
+
|
|
226
232
|
/**
|
|
227
233
|
* A container for a nested tree of <Route> elements that renders the branch
|
|
228
234
|
* that best matches the current location.
|
|
229
235
|
*
|
|
230
236
|
* @see https://reactrouter.com/api/Routes
|
|
231
237
|
*/
|
|
232
|
-
|
|
233
238
|
function Routes(_ref4) {
|
|
234
239
|
let {
|
|
235
240
|
children,
|
|
@@ -240,43 +245,6 @@ function Routes(_ref4) {
|
|
|
240
245
|
// HOOKS
|
|
241
246
|
///////////////////////////////////////////////////////////////////////////////
|
|
242
247
|
|
|
243
|
-
/**
|
|
244
|
-
* Blocks all navigation attempts. This is useful for preventing the page from
|
|
245
|
-
* changing until some condition is met, like saving form data.
|
|
246
|
-
*
|
|
247
|
-
* @see https://reactrouter.com/api/useBlocker
|
|
248
|
-
*/
|
|
249
|
-
|
|
250
|
-
function useBlocker(blocker, when) {
|
|
251
|
-
if (when === void 0) {
|
|
252
|
-
when = true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
|
256
|
-
// router loaded. We can help them understand how to avoid that.
|
|
257
|
-
"useBlocker() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
|
258
|
-
let {
|
|
259
|
-
navigator
|
|
260
|
-
} = useContext(NavigationContext);
|
|
261
|
-
useEffect(() => {
|
|
262
|
-
if (!when) return;
|
|
263
|
-
let unblock = navigator.block(tx => {
|
|
264
|
-
let autoUnblockingTx = _extends({}, tx, {
|
|
265
|
-
retry() {
|
|
266
|
-
// Automatically unblock the transition so it can play all the way
|
|
267
|
-
// through before retrying it. TODO: Figure out how to re-enable
|
|
268
|
-
// this block if the transition is cancelled for some reason.
|
|
269
|
-
unblock();
|
|
270
|
-
tx.retry();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
blocker(autoUnblockingTx);
|
|
276
|
-
});
|
|
277
|
-
return unblock;
|
|
278
|
-
}, [navigator, blocker, when]);
|
|
279
|
-
}
|
|
280
248
|
/**
|
|
281
249
|
* Returns the full href for the given "to" value. This is useful for building
|
|
282
250
|
* custom links that are also accessible and preserve right-click behavior.
|
|
@@ -292,15 +260,24 @@ function useHref(to) {
|
|
|
292
260
|
basename,
|
|
293
261
|
navigator
|
|
294
262
|
} = useContext(NavigationContext);
|
|
295
|
-
let
|
|
263
|
+
let {
|
|
264
|
+
hash,
|
|
265
|
+
pathname,
|
|
266
|
+
search
|
|
267
|
+
} = useResolvedPath(to);
|
|
268
|
+
let joinedPathname = pathname;
|
|
296
269
|
|
|
297
270
|
if (basename !== "/") {
|
|
298
271
|
let toPathname = getToPathname(to);
|
|
299
272
|
let endsWithSlash = toPathname != null && toPathname.endsWith("/");
|
|
300
|
-
|
|
273
|
+
joinedPathname = pathname === "/" ? basename + (endsWithSlash ? "/" : "") : joinPaths([basename, pathname]);
|
|
301
274
|
}
|
|
302
275
|
|
|
303
|
-
return navigator.createHref(
|
|
276
|
+
return navigator.createHref({
|
|
277
|
+
pathname: joinedPathname,
|
|
278
|
+
search,
|
|
279
|
+
hash
|
|
280
|
+
});
|
|
304
281
|
}
|
|
305
282
|
/**
|
|
306
283
|
* Returns true if this component is a descendant of a <Router>.
|
|
@@ -328,6 +305,16 @@ function useLocation() {
|
|
|
328
305
|
"useLocation() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
|
329
306
|
return useContext(LocationContext).location;
|
|
330
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Returns the current navigation action which describes how the router came to
|
|
310
|
+
* the current location, either by a pop, push, or replace on the history stack.
|
|
311
|
+
*
|
|
312
|
+
* @see https://reactrouter.com/api/useNavigationType
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
function useNavigationType() {
|
|
316
|
+
return useContext(LocationContext).navigationType;
|
|
317
|
+
}
|
|
331
318
|
/**
|
|
332
319
|
* Returns true if the URL for the given "to" value matches the current URL.
|
|
333
320
|
* This is useful for components that need to know "active" state, e.g.
|
|
@@ -342,13 +329,16 @@ function useMatch(pattern) {
|
|
|
342
329
|
"useMatch() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
|
343
330
|
return matchPath(pattern, useLocation().pathname);
|
|
344
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* The interface for the navigate() function returned from useNavigate().
|
|
334
|
+
*/
|
|
335
|
+
|
|
345
336
|
/**
|
|
346
337
|
* Returns an imperative method for changing the location. Used by <Link>s, but
|
|
347
338
|
* may also be used by other elements to change the location.
|
|
348
339
|
*
|
|
349
340
|
* @see https://reactrouter.com/api/useNavigate
|
|
350
341
|
*/
|
|
351
|
-
|
|
352
342
|
function useNavigate() {
|
|
353
343
|
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
|
354
344
|
// router loaded. We can help them understand how to avoid that.
|
|
@@ -358,11 +348,12 @@ function useNavigate() {
|
|
|
358
348
|
navigator
|
|
359
349
|
} = useContext(NavigationContext);
|
|
360
350
|
let {
|
|
361
|
-
|
|
351
|
+
matches
|
|
362
352
|
} = useContext(RouteContext);
|
|
363
353
|
let {
|
|
364
354
|
pathname: locationPathname
|
|
365
355
|
} = useLocation();
|
|
356
|
+
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
|
366
357
|
let activeRef = useRef(false);
|
|
367
358
|
useEffect(() => {
|
|
368
359
|
activeRef.current = true;
|
|
@@ -380,14 +371,14 @@ function useNavigate() {
|
|
|
380
371
|
return;
|
|
381
372
|
}
|
|
382
373
|
|
|
383
|
-
let path = resolveTo(to,
|
|
374
|
+
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname);
|
|
384
375
|
|
|
385
376
|
if (basename !== "/") {
|
|
386
377
|
path.pathname = joinPaths([basename, path.pathname]);
|
|
387
378
|
}
|
|
388
379
|
|
|
389
380
|
(!!options.replace ? navigator.replace : navigator.push)(path, options.state);
|
|
390
|
-
}, [basename, navigator,
|
|
381
|
+
}, [basename, navigator, routePathnamesJson, locationPathname]);
|
|
391
382
|
return navigate;
|
|
392
383
|
}
|
|
393
384
|
/**
|
|
@@ -408,7 +399,11 @@ function useOutlet() {
|
|
|
408
399
|
*/
|
|
409
400
|
|
|
410
401
|
function useParams() {
|
|
411
|
-
|
|
402
|
+
let {
|
|
403
|
+
matches
|
|
404
|
+
} = useContext(RouteContext);
|
|
405
|
+
let routeMatch = matches[matches.length - 1];
|
|
406
|
+
return routeMatch ? routeMatch.params : {};
|
|
412
407
|
}
|
|
413
408
|
/**
|
|
414
409
|
* Resolves the pathname of the given `to` value against the current location.
|
|
@@ -417,13 +412,14 @@ function useParams() {
|
|
|
417
412
|
*/
|
|
418
413
|
|
|
419
414
|
function useResolvedPath(to) {
|
|
415
|
+
let {
|
|
416
|
+
matches
|
|
417
|
+
} = useContext(RouteContext);
|
|
420
418
|
let {
|
|
421
419
|
pathname: locationPathname
|
|
422
420
|
} = useLocation();
|
|
423
|
-
let
|
|
424
|
-
|
|
425
|
-
} = useContext(RouteContext);
|
|
426
|
-
return useMemo(() => resolveTo(to, routePathname, locationPathname), [to, routePathname, locationPathname]);
|
|
421
|
+
let routePathnamesJson = JSON.stringify(matches.map(match => match.pathnameBase));
|
|
422
|
+
return useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname), [to, routePathnamesJson, locationPathname]);
|
|
427
423
|
}
|
|
428
424
|
/**
|
|
429
425
|
* Returns the element of the route that matched the current location, prepared
|
|
@@ -439,10 +435,13 @@ function useRoutes(routes, locationArg) {
|
|
|
439
435
|
// router loaded. We can help them understand how to avoid that.
|
|
440
436
|
"useRoutes() may be used only in the context of a <Router> component.") : invariant(false) : void 0;
|
|
441
437
|
let {
|
|
442
|
-
|
|
443
|
-
pathname: parentPathname,
|
|
444
|
-
route: parentRoute
|
|
438
|
+
matches: parentMatches
|
|
445
439
|
} = useContext(RouteContext);
|
|
440
|
+
let routeMatch = parentMatches[parentMatches.length - 1];
|
|
441
|
+
let parentParams = routeMatch ? routeMatch.params : {};
|
|
442
|
+
let parentPathname = routeMatch ? routeMatch.pathname : "/";
|
|
443
|
+
let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
|
|
444
|
+
let parentRoute = routeMatch && routeMatch.route;
|
|
446
445
|
|
|
447
446
|
if (process.env.NODE_ENV !== "production") {
|
|
448
447
|
// You won't get a warning about 2 different <Routes> under a <Route>
|
|
@@ -470,21 +469,34 @@ function useRoutes(routes, locationArg) {
|
|
|
470
469
|
}
|
|
471
470
|
|
|
472
471
|
let locationFromContext = useLocation();
|
|
473
|
-
let location
|
|
472
|
+
let location;
|
|
473
|
+
|
|
474
|
+
if (locationArg) {
|
|
475
|
+
var _parsedLocationArg$pa;
|
|
476
|
+
|
|
477
|
+
let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
|
478
|
+
!(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;
|
|
479
|
+
location = parsedLocationArg;
|
|
480
|
+
} else {
|
|
481
|
+
location = locationFromContext;
|
|
482
|
+
}
|
|
483
|
+
|
|
474
484
|
let pathname = location.pathname || "/";
|
|
475
|
-
let
|
|
476
|
-
let remainingPathname = parentPathnameStart === "/" ? pathname : pathname.slice(parentPathnameStart.length);
|
|
485
|
+
let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
|
|
477
486
|
let matches = matchRoutes(routes, {
|
|
478
487
|
pathname: remainingPathname
|
|
479
488
|
});
|
|
480
489
|
|
|
481
490
|
if (process.env.NODE_ENV !== "production") {
|
|
482
491
|
process.env.NODE_ENV !== "production" ? warning(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") : void 0;
|
|
492
|
+
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;
|
|
483
493
|
}
|
|
484
494
|
|
|
485
|
-
return
|
|
486
|
-
|
|
487
|
-
|
|
495
|
+
return _renderMatches(matches && matches.map(match => Object.assign({}, match, {
|
|
496
|
+
params: Object.assign({}, parentParams, match.params),
|
|
497
|
+
pathname: joinPaths([parentPathnameBase, match.pathname]),
|
|
498
|
+
pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase, match.pathnameBase])
|
|
499
|
+
})), parentMatches);
|
|
488
500
|
} ///////////////////////////////////////////////////////////////////////////////
|
|
489
501
|
// UTILS
|
|
490
502
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -513,10 +525,10 @@ function createRoutesFromChildren(children) {
|
|
|
513
525
|
}
|
|
514
526
|
|
|
515
527
|
let route = {
|
|
516
|
-
path: element.props.path,
|
|
517
528
|
caseSensitive: element.props.caseSensitive,
|
|
529
|
+
element: element.props.element,
|
|
518
530
|
index: element.props.index,
|
|
519
|
-
|
|
531
|
+
path: element.props.path
|
|
520
532
|
};
|
|
521
533
|
|
|
522
534
|
if (element.props.children) {
|
|
@@ -527,12 +539,15 @@ function createRoutesFromChildren(children) {
|
|
|
527
539
|
});
|
|
528
540
|
return routes;
|
|
529
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* The parameters that were parsed from the URL path.
|
|
544
|
+
*/
|
|
545
|
+
|
|
530
546
|
/**
|
|
531
547
|
* Returns a path with params interpolated.
|
|
532
548
|
*
|
|
533
549
|
* @see https://reactrouter.com/api/generatePath
|
|
534
550
|
*/
|
|
535
|
-
|
|
536
551
|
function generatePath(path, params) {
|
|
537
552
|
if (params === void 0) {
|
|
538
553
|
params = {};
|
|
@@ -543,12 +558,15 @@ function generatePath(path, params) {
|
|
|
543
558
|
return params[key];
|
|
544
559
|
}).replace(/\/*\*$/, _ => params["*"] == null ? "" : params["*"].replace(/^\/*/, "/"));
|
|
545
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* A RouteMatch contains info about how a route matched a URL.
|
|
563
|
+
*/
|
|
564
|
+
|
|
546
565
|
/**
|
|
547
566
|
* Matches the given routes to a location and returns the match data.
|
|
548
567
|
*
|
|
549
568
|
* @see https://reactrouter.com/api/matchRoutes
|
|
550
569
|
*/
|
|
551
|
-
|
|
552
570
|
function matchRoutes(routes, locationArg, basename) {
|
|
553
571
|
if (basename === void 0) {
|
|
554
572
|
basename = "/";
|
|
@@ -605,11 +623,17 @@ function flattenRoutes(routes, branches, parentsMeta, parentPath) {
|
|
|
605
623
|
if (route.children && route.children.length > 0) {
|
|
606
624
|
!(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;
|
|
607
625
|
flattenRoutes(route.children, branches, routesMeta, path);
|
|
626
|
+
} // Routes without a path shouldn't ever match by themselves unless they are
|
|
627
|
+
// index routes, so don't add them to the list of possible branches.
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
if (route.path == null && !route.index) {
|
|
631
|
+
return;
|
|
608
632
|
}
|
|
609
633
|
|
|
610
634
|
branches.push({
|
|
611
635
|
path,
|
|
612
|
-
score: computeScore(path),
|
|
636
|
+
score: computeScore(path, route.index),
|
|
613
637
|
routesMeta
|
|
614
638
|
});
|
|
615
639
|
});
|
|
@@ -622,14 +646,15 @@ function rankRouteBranches(branches) {
|
|
|
622
646
|
}
|
|
623
647
|
|
|
624
648
|
const paramRe = /^:\w+$/;
|
|
625
|
-
const dynamicSegmentValue =
|
|
649
|
+
const dynamicSegmentValue = 3;
|
|
650
|
+
const indexRouteValue = 2;
|
|
626
651
|
const emptySegmentValue = 1;
|
|
627
652
|
const staticSegmentValue = 10;
|
|
628
653
|
const splatPenalty = -2;
|
|
629
654
|
|
|
630
655
|
const isSplat = s => s === "*";
|
|
631
656
|
|
|
632
|
-
function computeScore(path) {
|
|
657
|
+
function computeScore(path, index) {
|
|
633
658
|
let segments = path.split("/");
|
|
634
659
|
let initialScore = segments.length;
|
|
635
660
|
|
|
@@ -637,6 +662,10 @@ function computeScore(path) {
|
|
|
637
662
|
initialScore += splatPenalty;
|
|
638
663
|
}
|
|
639
664
|
|
|
665
|
+
if (index) {
|
|
666
|
+
initialScore += indexRouteValue;
|
|
667
|
+
}
|
|
668
|
+
|
|
640
669
|
return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
641
670
|
}
|
|
642
671
|
|
|
@@ -651,7 +680,8 @@ function compareIndexes(a, b) {
|
|
|
651
680
|
0;
|
|
652
681
|
}
|
|
653
682
|
|
|
654
|
-
function matchRouteBranch(branch,
|
|
683
|
+
function matchRouteBranch(branch, // TODO: attach original route object inside routesMeta so we don't need this arg
|
|
684
|
+
routesArg, pathname) {
|
|
655
685
|
let routes = routesArg;
|
|
656
686
|
let {
|
|
657
687
|
routesMeta
|
|
@@ -662,27 +692,25 @@ function matchRouteBranch(branch, routesArg, pathname) {
|
|
|
662
692
|
|
|
663
693
|
for (let i = 0; i < routesMeta.length; ++i) {
|
|
664
694
|
let meta = routesMeta[i];
|
|
665
|
-
let
|
|
695
|
+
let end = i === routesMeta.length - 1;
|
|
696
|
+
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
|
666
697
|
let match = matchPath({
|
|
667
698
|
path: meta.relativePath,
|
|
668
699
|
caseSensitive: meta.caseSensitive,
|
|
669
|
-
end
|
|
670
|
-
},
|
|
700
|
+
end
|
|
701
|
+
}, remainingPathname);
|
|
671
702
|
if (!match) return null;
|
|
672
703
|
Object.assign(matchedParams, match.params);
|
|
673
704
|
let route = routes[meta.childrenIndex];
|
|
674
705
|
matches.push({
|
|
675
706
|
params: matchedParams,
|
|
676
|
-
pathname:
|
|
707
|
+
pathname: joinPaths([matchedPathname, match.pathname]),
|
|
708
|
+
pathnameBase: joinPaths([matchedPathname, match.pathnameBase]),
|
|
677
709
|
route
|
|
678
710
|
});
|
|
679
|
-
let pathnameStart = getPathnameStart(match.pathname, match.params);
|
|
680
711
|
|
|
681
|
-
if (
|
|
682
|
-
|
|
683
|
-
// the matchedPathname. This allows child routes to match against the
|
|
684
|
-
// portion of the pathname that was matched by the *.
|
|
685
|
-
matchedPathname = joinPaths([matchedPathname, pathnameStart]);
|
|
712
|
+
if (match.pathnameBase !== "/") {
|
|
713
|
+
matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
|
|
686
714
|
}
|
|
687
715
|
|
|
688
716
|
routes = route.children;
|
|
@@ -696,26 +724,36 @@ function matchRouteBranch(branch, routesArg, pathname) {
|
|
|
696
724
|
|
|
697
725
|
|
|
698
726
|
function renderMatches(matches) {
|
|
727
|
+
return _renderMatches(matches);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function _renderMatches(matches, parentMatches) {
|
|
731
|
+
if (parentMatches === void 0) {
|
|
732
|
+
parentMatches = [];
|
|
733
|
+
}
|
|
734
|
+
|
|
699
735
|
if (matches == null) return null;
|
|
700
|
-
return matches.reduceRight((outlet, match) => {
|
|
736
|
+
return matches.reduceRight((outlet, match, index) => {
|
|
701
737
|
return /*#__PURE__*/createElement(RouteContext.Provider, {
|
|
702
|
-
children: match.route.element
|
|
738
|
+
children: match.route.element !== undefined ? match.route.element : /*#__PURE__*/createElement(Outlet, null),
|
|
703
739
|
value: {
|
|
704
740
|
outlet,
|
|
705
|
-
|
|
706
|
-
pathname: match.pathname,
|
|
707
|
-
route: match.route
|
|
741
|
+
matches: parentMatches.concat(matches.slice(0, index + 1))
|
|
708
742
|
}
|
|
709
743
|
});
|
|
710
744
|
}, null);
|
|
711
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* A PathPattern is used to match on some portion of a URL pathname.
|
|
748
|
+
*/
|
|
749
|
+
|
|
750
|
+
|
|
712
751
|
/**
|
|
713
752
|
* Performs pattern matching on a URL pathname and returns information about
|
|
714
753
|
* the match.
|
|
715
754
|
*
|
|
716
755
|
* @see https://reactrouter.com/api/matchPath
|
|
717
756
|
*/
|
|
718
|
-
|
|
719
757
|
function matchPath(pattern, pathname) {
|
|
720
758
|
if (typeof pattern === "string") {
|
|
721
759
|
pattern = {
|
|
@@ -729,14 +767,23 @@ function matchPath(pattern, pathname) {
|
|
|
729
767
|
let match = pathname.match(matcher);
|
|
730
768
|
if (!match) return null;
|
|
731
769
|
let matchedPathname = match[0];
|
|
732
|
-
let
|
|
770
|
+
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
771
|
+
let captureGroups = match.slice(1);
|
|
733
772
|
let params = paramNames.reduce((memo, paramName, index) => {
|
|
734
|
-
|
|
773
|
+
// We need to compute the pathnameBase here using the raw splat value
|
|
774
|
+
// instead of using params["*"] later because it will be decoded then
|
|
775
|
+
if (paramName === "*") {
|
|
776
|
+
let splatValue = captureGroups[index] || "";
|
|
777
|
+
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
|
|
735
781
|
return memo;
|
|
736
782
|
}, {});
|
|
737
783
|
return {
|
|
738
784
|
params,
|
|
739
785
|
pathname: matchedPathname,
|
|
786
|
+
pathnameBase,
|
|
740
787
|
pattern
|
|
741
788
|
};
|
|
742
789
|
}
|
|
@@ -750,35 +797,30 @@ function compilePath(path, caseSensitive, end) {
|
|
|
750
797
|
end = true;
|
|
751
798
|
}
|
|
752
799
|
|
|
753
|
-
|
|
754
|
-
let
|
|
800
|
+
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;
|
|
801
|
+
let paramNames = [];
|
|
802
|
+
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
|
755
803
|
.replace(/^\/*/, "/") // Make sure it has a leading /
|
|
756
804
|
.replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
|
|
757
|
-
.replace(/:(\w+)/g, (_,
|
|
758
|
-
|
|
805
|
+
.replace(/:(\w+)/g, (_, paramName) => {
|
|
806
|
+
paramNames.push(paramName);
|
|
759
807
|
return "([^\\/]+)";
|
|
760
808
|
});
|
|
761
809
|
|
|
762
810
|
if (path.endsWith("*")) {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
source += "(.*)$";
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
keys.push("*");
|
|
770
|
-
} else if (end) {
|
|
771
|
-
// When matching to the end, ignore trailing slashes.
|
|
772
|
-
source += "\\/?$";
|
|
811
|
+
paramNames.push("*");
|
|
812
|
+
regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
|
|
813
|
+
: "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
|
|
773
814
|
} else {
|
|
774
|
-
//
|
|
775
|
-
//
|
|
776
|
-
// and nothing more, e.g. parent
|
|
777
|
-
|
|
815
|
+
regexpSource += end ? "\\/*$" // When matching to the end, ignore trailing slashes
|
|
816
|
+
: // Otherwise, at least match a word boundary. This restricts parent
|
|
817
|
+
// routes to matching only their own words and nothing more, e.g. parent
|
|
818
|
+
// route "/home" should not match "/home2".
|
|
819
|
+
"(?:\\b|$)";
|
|
778
820
|
}
|
|
779
821
|
|
|
780
|
-
let matcher = new RegExp(
|
|
781
|
-
return [matcher,
|
|
822
|
+
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
|
823
|
+
return [matcher, paramNames];
|
|
782
824
|
}
|
|
783
825
|
|
|
784
826
|
function safelyDecodeURIComponent(value, paramName) {
|
|
@@ -828,17 +870,48 @@ function resolvePathname(relativePath, fromPathname) {
|
|
|
828
870
|
return segments.length > 1 ? segments.join("/") : "/";
|
|
829
871
|
}
|
|
830
872
|
|
|
831
|
-
function resolveTo(
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
// `<Link to>` values` in our
|
|
835
|
-
// disambiguation between `to` values
|
|
836
|
-
// that do not. However, this is problematic for
|
|
837
|
-
// not provide a pathname. `to` can simply be a search or
|
|
838
|
-
// string, in which case we should assume that the navigation is
|
|
839
|
-
//
|
|
840
|
-
|
|
841
|
-
|
|
873
|
+
function resolveTo(toArg, routePathnames, locationPathname) {
|
|
874
|
+
let to = typeof toArg === "string" ? parsePath(toArg) : toArg;
|
|
875
|
+
let toPathname = toArg === "" || to.pathname === "" ? "/" : to.pathname; // If a pathname is explicitly provided in `to`, it should be relative to the
|
|
876
|
+
// route context. This is explained in `Note on `<Link to>` values` in our
|
|
877
|
+
// migration guide from v5 as a means of disambiguation between `to` values
|
|
878
|
+
// that begin with `/` and those that do not. However, this is problematic for
|
|
879
|
+
// `to` values that do not provide a pathname. `to` can simply be a search or
|
|
880
|
+
// hash string, in which case we should assume that the navigation is relative
|
|
881
|
+
// to the current location's pathname and *not* the route pathname.
|
|
882
|
+
|
|
883
|
+
let from;
|
|
884
|
+
|
|
885
|
+
if (toPathname == null) {
|
|
886
|
+
from = locationPathname;
|
|
887
|
+
} else {
|
|
888
|
+
let routePathnameIndex = routePathnames.length - 1;
|
|
889
|
+
|
|
890
|
+
if (toPathname.startsWith("..")) {
|
|
891
|
+
let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
|
|
892
|
+
// URL segment". This is a key difference from how <a href> works and a
|
|
893
|
+
// major reason we call this a "to" value instead of a "href".
|
|
894
|
+
|
|
895
|
+
while (toSegments[0] === "..") {
|
|
896
|
+
toSegments.shift();
|
|
897
|
+
routePathnameIndex -= 1;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
to.pathname = toSegments.join("/");
|
|
901
|
+
} // If there are more ".." segments than parent routes, resolve relative to
|
|
902
|
+
// the root / URL.
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original to value had one.
|
|
909
|
+
|
|
910
|
+
if (toPathname && toPathname !== "/" && toPathname.endsWith("/") && !path.pathname.endsWith("/")) {
|
|
911
|
+
path.pathname += "/";
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return path;
|
|
842
915
|
}
|
|
843
916
|
|
|
844
917
|
function getToPathname(to) {
|
|
@@ -846,16 +919,6 @@ function getToPathname(to) {
|
|
|
846
919
|
return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
|
|
847
920
|
}
|
|
848
921
|
|
|
849
|
-
function getPathnameStart(pathname, params) {
|
|
850
|
-
let splat = params["*"];
|
|
851
|
-
if (!splat) return pathname;
|
|
852
|
-
let pathnameStart = pathname.slice(0, -splat.length);
|
|
853
|
-
if (splat.startsWith("/")) return pathnameStart;
|
|
854
|
-
let index = pathnameStart.lastIndexOf("/");
|
|
855
|
-
if (index > 0) return pathnameStart.slice(0, index);
|
|
856
|
-
return "/";
|
|
857
|
-
}
|
|
858
|
-
|
|
859
922
|
function stripBasename(pathname, basename) {
|
|
860
923
|
if (basename === "/") return pathname;
|
|
861
924
|
|
|
@@ -881,5 +944,5 @@ const normalizeSearch = search => !search || search === "?" ? "" : search.starts
|
|
|
881
944
|
|
|
882
945
|
const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; ///////////////////////////////////////////////////////////////////////////////
|
|
883
946
|
|
|
884
|
-
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,
|
|
947
|
+
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, useParams, useResolvedPath, useRoutes };
|
|
885
948
|
//# sourceMappingURL=index.js.map
|