@tanstack/react-router 0.0.1-beta.24 → 0.0.1-beta.240
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 +21 -0
- package/build/cjs/CatchBoundary.js +123 -0
- package/build/cjs/CatchBoundary.js.map +1 -0
- package/build/cjs/Matches.js +232 -0
- package/build/cjs/Matches.js.map +1 -0
- package/build/cjs/RouterProvider.js +159 -0
- package/build/cjs/RouterProvider.js.map +1 -0
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +2 -22
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
- package/build/cjs/awaited.js +43 -0
- package/build/cjs/awaited.js.map +1 -0
- package/build/cjs/defer.js +37 -0
- package/build/cjs/defer.js.map +1 -0
- package/build/cjs/fileRoute.js +27 -0
- package/build/cjs/fileRoute.js.map +1 -0
- package/build/cjs/index.js +123 -0
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/lazyRouteComponent.js +54 -0
- package/build/cjs/lazyRouteComponent.js.map +1 -0
- package/build/cjs/link.js +148 -0
- package/build/cjs/link.js.map +1 -0
- package/build/cjs/path.js +209 -0
- package/build/cjs/path.js.map +1 -0
- package/build/cjs/qss.js +63 -0
- package/build/cjs/qss.js.map +1 -0
- package/build/cjs/redirects.js +25 -0
- package/build/cjs/redirects.js.map +1 -0
- package/build/cjs/route.js +134 -0
- package/build/cjs/route.js.map +1 -0
- package/build/cjs/router.js +1113 -0
- package/build/cjs/router.js.map +1 -0
- package/build/cjs/scroll-restoration.js +202 -0
- package/build/cjs/scroll-restoration.js.map +1 -0
- package/build/cjs/searchParams.js +81 -0
- package/build/cjs/searchParams.js.map +1 -0
- package/build/cjs/useBlocker.js +61 -0
- package/build/cjs/useBlocker.js.map +1 -0
- package/build/cjs/useNavigate.js +75 -0
- package/build/cjs/useNavigate.js.map +1 -0
- package/build/cjs/useParams.js +26 -0
- package/build/cjs/useParams.js.map +1 -0
- package/build/cjs/useSearch.js +25 -0
- package/build/cjs/useSearch.js.map +1 -0
- package/build/cjs/utils.js +239 -0
- package/build/cjs/utils.js.map +1 -0
- package/build/esm/index.js +2159 -2534
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +3498 -2694
- package/build/stats-react.json +1210 -44
- package/build/types/CatchBoundary.d.ts +33 -0
- package/build/types/Matches.d.ts +57 -0
- package/build/types/RouterProvider.d.ts +36 -0
- package/build/types/awaited.d.ts +9 -0
- package/build/types/defer.d.ts +19 -0
- package/build/types/fileRoute.d.ts +35 -0
- package/build/types/history.d.ts +7 -0
- package/build/types/index.d.ts +27 -108
- package/build/types/injectHtml.d.ts +0 -0
- package/build/types/lazyRouteComponent.d.ts +2 -0
- package/build/types/link.d.ts +105 -0
- package/build/types/location.d.ts +14 -0
- package/build/types/path.d.ts +16 -0
- package/build/types/qss.d.ts +2 -0
- package/build/types/redirects.d.ts +10 -0
- package/build/types/route.d.ts +278 -0
- package/build/types/routeInfo.d.ts +22 -0
- package/build/types/router.d.ts +182 -0
- package/build/types/scroll-restoration.d.ts +18 -0
- package/build/types/searchParams.d.ts +7 -0
- package/build/types/useBlocker.d.ts +8 -0
- package/build/types/useNavigate.d.ts +20 -0
- package/build/types/useParams.d.ts +7 -0
- package/build/types/useSearch.d.ts +7 -0
- package/build/types/utils.d.ts +66 -0
- package/build/umd/index.development.js +2714 -2485
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +4 -4
- package/build/umd/index.production.js.map +1 -1
- package/package.json +11 -10
- package/src/CatchBoundary.tsx +98 -0
- package/src/Matches.tsx +401 -0
- package/src/RouterProvider.tsx +241 -0
- package/src/awaited.tsx +40 -0
- package/src/defer.ts +55 -0
- package/src/fileRoute.ts +154 -0
- package/src/history.ts +8 -0
- package/src/index.tsx +28 -708
- package/src/injectHtml.ts +28 -0
- package/src/lazyRouteComponent.tsx +33 -0
- package/src/link.tsx +508 -0
- package/src/location.ts +15 -0
- package/src/path.ts +256 -0
- package/src/qss.ts +53 -0
- package/src/redirects.ts +31 -0
- package/src/route.ts +861 -0
- package/src/routeInfo.ts +68 -0
- package/src/router.ts +1700 -0
- package/src/scroll-restoration.tsx +230 -0
- package/src/searchParams.ts +79 -0
- package/src/useBlocker.tsx +34 -0
- package/src/useNavigate.tsx +109 -0
- package/src/useParams.tsx +25 -0
- package/src/useSearch.tsx +25 -0
- package/src/utils.ts +350 -0
- package/build/cjs/react-router/src/index.js +0 -473
- package/build/cjs/react-router/src/index.js.map +0 -1
- package/build/cjs/router-core/build/esm/index.js +0 -2528
- package/build/cjs/router-core/build/esm/index.js.map +0 -1
package/build/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router
|
|
2
|
+
* @tanstack/react-router/src/index.tsx
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) TanStack
|
|
5
5
|
*
|
|
@@ -8,972 +8,292 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
+
import { createBrowserHistory, createMemoryHistory } from '@tanstack/history';
|
|
12
|
+
export * from '@tanstack/history';
|
|
13
|
+
import invariant from 'tiny-invariant';
|
|
14
|
+
export { default as invariant } from 'tiny-invariant';
|
|
15
|
+
import warning from 'tiny-warning';
|
|
16
|
+
export { default as warning } from 'tiny-warning';
|
|
11
17
|
import * as React from 'react';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
import { useStore } from '@tanstack/react-store';
|
|
19
|
+
import { Store } from '@tanstack/store';
|
|
20
|
+
|
|
21
|
+
function CatchBoundary(props) {
|
|
22
|
+
const errorComponent = props.errorComponent ?? ErrorComponent;
|
|
23
|
+
return /*#__PURE__*/React.createElement(CatchBoundaryImpl, {
|
|
24
|
+
resetKey: props.resetKey,
|
|
25
|
+
onCatch: props.onCatch,
|
|
26
|
+
children: ({
|
|
27
|
+
error
|
|
28
|
+
}) => {
|
|
29
|
+
if (error) {
|
|
30
|
+
return /*#__PURE__*/React.createElement(errorComponent, {
|
|
31
|
+
error
|
|
32
|
+
});
|
|
23
33
|
}
|
|
34
|
+
return props.children;
|
|
24
35
|
}
|
|
25
|
-
|
|
26
|
-
return target;
|
|
27
|
-
};
|
|
28
|
-
return _extends$2.apply(this, arguments);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
32
|
-
if (source == null) return {};
|
|
33
|
-
var target = {};
|
|
34
|
-
var sourceKeys = Object.keys(source);
|
|
35
|
-
var key, i;
|
|
36
|
-
|
|
37
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
38
|
-
key = sourceKeys[i];
|
|
39
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
40
|
-
target[key] = source[key];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return target;
|
|
36
|
+
});
|
|
44
37
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
* Copyright (c) TanStack
|
|
50
|
-
*
|
|
51
|
-
* This source code is licensed under the MIT license found in the
|
|
52
|
-
* LICENSE.md file in the root directory of this source tree.
|
|
53
|
-
*
|
|
54
|
-
* @license MIT
|
|
55
|
-
*/
|
|
56
|
-
function _extends$1() {
|
|
57
|
-
_extends$1 = Object.assign ? Object.assign.bind() : function (target) {
|
|
58
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
59
|
-
var source = arguments[i];
|
|
60
|
-
|
|
61
|
-
for (var key in source) {
|
|
62
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
63
|
-
target[key] = source[key];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return target;
|
|
38
|
+
class CatchBoundaryImpl extends React.Component {
|
|
39
|
+
state = {
|
|
40
|
+
error: null
|
|
69
41
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* Actions represent the type of change to a location value.
|
|
75
|
-
*
|
|
76
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#action
|
|
77
|
-
*/
|
|
78
|
-
var Action;
|
|
79
|
-
|
|
80
|
-
(function (Action) {
|
|
81
|
-
/**
|
|
82
|
-
* A POP indicates a change to an arbitrary index in the history stack, such
|
|
83
|
-
* as a back or forward navigation. It does not describe the direction of the
|
|
84
|
-
* navigation, only that the current index changed.
|
|
85
|
-
*
|
|
86
|
-
* Note: This is the default action for newly created history objects.
|
|
87
|
-
*/
|
|
88
|
-
Action["Pop"] = "POP";
|
|
89
|
-
/**
|
|
90
|
-
* A PUSH indicates a new entry being added to the history stack, such as when
|
|
91
|
-
* a link is clicked and a new page loads. When this happens, all subsequent
|
|
92
|
-
* entries in the stack are lost.
|
|
93
|
-
*/
|
|
94
|
-
|
|
95
|
-
Action["Push"] = "PUSH";
|
|
96
|
-
/**
|
|
97
|
-
* A REPLACE indicates the entry at the current index in the history stack
|
|
98
|
-
* being replaced by a new one.
|
|
99
|
-
*/
|
|
100
|
-
|
|
101
|
-
Action["Replace"] = "REPLACE";
|
|
102
|
-
})(Action || (Action = {}));
|
|
103
|
-
|
|
104
|
-
var readOnly = process.env.NODE_ENV !== "production" ? function (obj) {
|
|
105
|
-
return Object.freeze(obj);
|
|
106
|
-
} : function (obj) {
|
|
107
|
-
return obj;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
function warning$1(cond, message) {
|
|
111
|
-
if (!cond) {
|
|
112
|
-
// eslint-disable-next-line no-console
|
|
113
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
// Welcome to debugging history!
|
|
117
|
-
//
|
|
118
|
-
// This error is thrown as a convenience so you can more easily
|
|
119
|
-
// find the source for a warning that appears in the console by
|
|
120
|
-
// enabling "pause on exceptions" in your JavaScript debugger.
|
|
121
|
-
throw new Error(message); // eslint-disable-next-line no-empty
|
|
122
|
-
} catch (e) {}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
var BeforeUnloadEventType = 'beforeunload';
|
|
127
|
-
var HashChangeEventType = 'hashchange';
|
|
128
|
-
var PopStateEventType = 'popstate';
|
|
129
|
-
/**
|
|
130
|
-
* Browser history stores the location in regular URLs. This is the standard for
|
|
131
|
-
* most web apps, but it requires some configuration on the server to ensure you
|
|
132
|
-
* serve the same app at multiple URLs.
|
|
133
|
-
*
|
|
134
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
function createBrowserHistory(options) {
|
|
138
|
-
if (options === void 0) {
|
|
139
|
-
options = {};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
var _options = options,
|
|
143
|
-
_options$window = _options.window,
|
|
144
|
-
window = _options$window === void 0 ? document.defaultView : _options$window;
|
|
145
|
-
var globalHistory = window.history;
|
|
146
|
-
|
|
147
|
-
function getIndexAndLocation() {
|
|
148
|
-
var _window$location = window.location,
|
|
149
|
-
pathname = _window$location.pathname,
|
|
150
|
-
search = _window$location.search,
|
|
151
|
-
hash = _window$location.hash;
|
|
152
|
-
var state = globalHistory.state || {};
|
|
153
|
-
return [state.idx, readOnly({
|
|
154
|
-
pathname: pathname,
|
|
155
|
-
search: search,
|
|
156
|
-
hash: hash,
|
|
157
|
-
state: state.usr || null,
|
|
158
|
-
key: state.key || 'default'
|
|
159
|
-
})];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
var blockedPopTx = null;
|
|
163
|
-
|
|
164
|
-
function handlePop() {
|
|
165
|
-
if (blockedPopTx) {
|
|
166
|
-
blockers.call(blockedPopTx);
|
|
167
|
-
blockedPopTx = null;
|
|
168
|
-
} else {
|
|
169
|
-
var nextAction = Action.Pop;
|
|
170
|
-
|
|
171
|
-
var _getIndexAndLocation = getIndexAndLocation(),
|
|
172
|
-
nextIndex = _getIndexAndLocation[0],
|
|
173
|
-
nextLocation = _getIndexAndLocation[1];
|
|
174
|
-
|
|
175
|
-
if (blockers.length) {
|
|
176
|
-
if (nextIndex != null) {
|
|
177
|
-
var delta = index - nextIndex;
|
|
178
|
-
|
|
179
|
-
if (delta) {
|
|
180
|
-
// Revert the POP
|
|
181
|
-
blockedPopTx = {
|
|
182
|
-
action: nextAction,
|
|
183
|
-
location: nextLocation,
|
|
184
|
-
retry: function retry() {
|
|
185
|
-
go(delta * -1);
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
go(delta);
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
// Trying to POP to a location with no index. We did not create
|
|
192
|
-
// this location, so we can't effectively block the navigation.
|
|
193
|
-
process.env.NODE_ENV !== "production" ? warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
|
|
194
|
-
// detail and link to it here so people can understand better what
|
|
195
|
-
// is going on and how to avoid it.
|
|
196
|
-
"You are trying to block a POP navigation to a location that was not " + "created by the history library. The block will fail silently in " + "production, but in general you should do all navigation with the " + "history library (instead of using window.history.pushState directly) " + "to avoid this situation.") : void 0;
|
|
197
|
-
}
|
|
198
|
-
} else {
|
|
199
|
-
applyTx(nextAction);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
window.addEventListener(PopStateEventType, handlePop);
|
|
205
|
-
var action = Action.Pop;
|
|
206
|
-
|
|
207
|
-
var _getIndexAndLocation2 = getIndexAndLocation(),
|
|
208
|
-
index = _getIndexAndLocation2[0],
|
|
209
|
-
location = _getIndexAndLocation2[1];
|
|
210
|
-
|
|
211
|
-
var listeners = createEvents();
|
|
212
|
-
var blockers = createEvents();
|
|
213
|
-
|
|
214
|
-
if (index == null) {
|
|
215
|
-
index = 0;
|
|
216
|
-
globalHistory.replaceState(_extends$1({}, globalHistory.state, {
|
|
217
|
-
idx: index
|
|
218
|
-
}), '');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function createHref(to) {
|
|
222
|
-
return typeof to === 'string' ? to : createPath(to);
|
|
223
|
-
} // state defaults to `null` because `window.history.state` does
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
function getNextLocation(to, state) {
|
|
227
|
-
if (state === void 0) {
|
|
228
|
-
state = null;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return readOnly(_extends$1({
|
|
232
|
-
pathname: location.pathname,
|
|
233
|
-
hash: '',
|
|
234
|
-
search: ''
|
|
235
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
236
|
-
state: state,
|
|
237
|
-
key: createKey()
|
|
238
|
-
}));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function getHistoryStateAndUrl(nextLocation, index) {
|
|
242
|
-
return [{
|
|
243
|
-
usr: nextLocation.state,
|
|
244
|
-
key: nextLocation.key,
|
|
245
|
-
idx: index
|
|
246
|
-
}, createHref(nextLocation)];
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function allowTx(action, location, retry) {
|
|
250
|
-
return !blockers.length || (blockers.call({
|
|
251
|
-
action: action,
|
|
252
|
-
location: location,
|
|
253
|
-
retry: retry
|
|
254
|
-
}), false);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function applyTx(nextAction) {
|
|
258
|
-
action = nextAction;
|
|
259
|
-
|
|
260
|
-
var _getIndexAndLocation3 = getIndexAndLocation();
|
|
261
|
-
|
|
262
|
-
index = _getIndexAndLocation3[0];
|
|
263
|
-
location = _getIndexAndLocation3[1];
|
|
264
|
-
listeners.call({
|
|
265
|
-
action: action,
|
|
266
|
-
location: location
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function push(to, state) {
|
|
271
|
-
var nextAction = Action.Push;
|
|
272
|
-
var nextLocation = getNextLocation(to, state);
|
|
273
|
-
|
|
274
|
-
function retry() {
|
|
275
|
-
push(to, state);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
279
|
-
var _getHistoryStateAndUr = getHistoryStateAndUrl(nextLocation, index + 1),
|
|
280
|
-
historyState = _getHistoryStateAndUr[0],
|
|
281
|
-
url = _getHistoryStateAndUr[1]; // TODO: Support forced reloading
|
|
282
|
-
// try...catch because iOS limits us to 100 pushState calls :/
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
globalHistory.pushState(historyState, '', url);
|
|
287
|
-
} catch (error) {
|
|
288
|
-
// They are going to lose state here, but there is no real
|
|
289
|
-
// way to warn them about it since the page will refresh...
|
|
290
|
-
window.location.assign(url);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
applyTx(nextAction);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function replace(to, state) {
|
|
298
|
-
var nextAction = Action.Replace;
|
|
299
|
-
var nextLocation = getNextLocation(to, state);
|
|
300
|
-
|
|
301
|
-
function retry() {
|
|
302
|
-
replace(to, state);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
306
|
-
var _getHistoryStateAndUr2 = getHistoryStateAndUrl(nextLocation, index),
|
|
307
|
-
historyState = _getHistoryStateAndUr2[0],
|
|
308
|
-
url = _getHistoryStateAndUr2[1]; // TODO: Support forced reloading
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
globalHistory.replaceState(historyState, '', url);
|
|
312
|
-
applyTx(nextAction);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function go(delta) {
|
|
317
|
-
globalHistory.go(delta);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
var history = {
|
|
321
|
-
get action() {
|
|
322
|
-
return action;
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
get location() {
|
|
326
|
-
return location;
|
|
327
|
-
},
|
|
328
|
-
|
|
329
|
-
createHref: createHref,
|
|
330
|
-
push: push,
|
|
331
|
-
replace: replace,
|
|
332
|
-
go: go,
|
|
333
|
-
back: function back() {
|
|
334
|
-
go(-1);
|
|
335
|
-
},
|
|
336
|
-
forward: function forward() {
|
|
337
|
-
go(1);
|
|
338
|
-
},
|
|
339
|
-
listen: function listen(listener) {
|
|
340
|
-
return listeners.push(listener);
|
|
341
|
-
},
|
|
342
|
-
block: function block(blocker) {
|
|
343
|
-
var unblock = blockers.push(blocker);
|
|
344
|
-
|
|
345
|
-
if (blockers.length === 1) {
|
|
346
|
-
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return function () {
|
|
350
|
-
unblock(); // Remove the beforeunload listener so the document may
|
|
351
|
-
// still be salvageable in the pagehide event.
|
|
352
|
-
// See https://html.spec.whatwg.org/#unloading-documents
|
|
353
|
-
|
|
354
|
-
if (!blockers.length) {
|
|
355
|
-
window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
return history;
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* Hash history stores the location in window.location.hash. This makes it ideal
|
|
364
|
-
* for situations where you don't want to send the location to the server for
|
|
365
|
-
* some reason, either because you do cannot configure it or the URL space is
|
|
366
|
-
* reserved for something else.
|
|
367
|
-
*
|
|
368
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
|
|
369
|
-
*/
|
|
370
|
-
|
|
371
|
-
function createHashHistory(options) {
|
|
372
|
-
if (options === void 0) {
|
|
373
|
-
options = {};
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
var _options2 = options,
|
|
377
|
-
_options2$window = _options2.window,
|
|
378
|
-
window = _options2$window === void 0 ? document.defaultView : _options2$window;
|
|
379
|
-
var globalHistory = window.history;
|
|
380
|
-
|
|
381
|
-
function getIndexAndLocation() {
|
|
382
|
-
var _parsePath = parsePath(window.location.hash.substr(1)),
|
|
383
|
-
_parsePath$pathname = _parsePath.pathname,
|
|
384
|
-
pathname = _parsePath$pathname === void 0 ? '/' : _parsePath$pathname,
|
|
385
|
-
_parsePath$search = _parsePath.search,
|
|
386
|
-
search = _parsePath$search === void 0 ? '' : _parsePath$search,
|
|
387
|
-
_parsePath$hash = _parsePath.hash,
|
|
388
|
-
hash = _parsePath$hash === void 0 ? '' : _parsePath$hash;
|
|
389
|
-
|
|
390
|
-
var state = globalHistory.state || {};
|
|
391
|
-
return [state.idx, readOnly({
|
|
392
|
-
pathname: pathname,
|
|
393
|
-
search: search,
|
|
394
|
-
hash: hash,
|
|
395
|
-
state: state.usr || null,
|
|
396
|
-
key: state.key || 'default'
|
|
397
|
-
})];
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
var blockedPopTx = null;
|
|
401
|
-
|
|
402
|
-
function handlePop() {
|
|
403
|
-
if (blockedPopTx) {
|
|
404
|
-
blockers.call(blockedPopTx);
|
|
405
|
-
blockedPopTx = null;
|
|
406
|
-
} else {
|
|
407
|
-
var nextAction = Action.Pop;
|
|
408
|
-
|
|
409
|
-
var _getIndexAndLocation4 = getIndexAndLocation(),
|
|
410
|
-
nextIndex = _getIndexAndLocation4[0],
|
|
411
|
-
nextLocation = _getIndexAndLocation4[1];
|
|
412
|
-
|
|
413
|
-
if (blockers.length) {
|
|
414
|
-
if (nextIndex != null) {
|
|
415
|
-
var delta = index - nextIndex;
|
|
416
|
-
|
|
417
|
-
if (delta) {
|
|
418
|
-
// Revert the POP
|
|
419
|
-
blockedPopTx = {
|
|
420
|
-
action: nextAction,
|
|
421
|
-
location: nextLocation,
|
|
422
|
-
retry: function retry() {
|
|
423
|
-
go(delta * -1);
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
go(delta);
|
|
427
|
-
}
|
|
428
|
-
} else {
|
|
429
|
-
// Trying to POP to a location with no index. We did not create
|
|
430
|
-
// this location, so we can't effectively block the navigation.
|
|
431
|
-
process.env.NODE_ENV !== "production" ? warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
|
|
432
|
-
// detail and link to it here so people can understand better
|
|
433
|
-
// what is going on and how to avoid it.
|
|
434
|
-
"You are trying to block a POP navigation to a location that was not " + "created by the history library. The block will fail silently in " + "production, but in general you should do all navigation with the " + "history library (instead of using window.history.pushState directly) " + "to avoid this situation.") : void 0;
|
|
435
|
-
}
|
|
436
|
-
} else {
|
|
437
|
-
applyTx(nextAction);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
window.addEventListener(PopStateEventType, handlePop); // popstate does not fire on hashchange in IE 11 and old (trident) Edge
|
|
443
|
-
// https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
|
|
444
|
-
|
|
445
|
-
window.addEventListener(HashChangeEventType, function () {
|
|
446
|
-
var _getIndexAndLocation5 = getIndexAndLocation(),
|
|
447
|
-
nextLocation = _getIndexAndLocation5[1]; // Ignore extraneous hashchange events.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (createPath(nextLocation) !== createPath(location)) {
|
|
451
|
-
handlePop();
|
|
452
|
-
}
|
|
453
|
-
});
|
|
454
|
-
var action = Action.Pop;
|
|
455
|
-
|
|
456
|
-
var _getIndexAndLocation6 = getIndexAndLocation(),
|
|
457
|
-
index = _getIndexAndLocation6[0],
|
|
458
|
-
location = _getIndexAndLocation6[1];
|
|
459
|
-
|
|
460
|
-
var listeners = createEvents();
|
|
461
|
-
var blockers = createEvents();
|
|
462
|
-
|
|
463
|
-
if (index == null) {
|
|
464
|
-
index = 0;
|
|
465
|
-
globalHistory.replaceState(_extends$1({}, globalHistory.state, {
|
|
466
|
-
idx: index
|
|
467
|
-
}), '');
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function getBaseHref() {
|
|
471
|
-
var base = document.querySelector('base');
|
|
472
|
-
var href = '';
|
|
473
|
-
|
|
474
|
-
if (base && base.getAttribute('href')) {
|
|
475
|
-
var url = window.location.href;
|
|
476
|
-
var hashIndex = url.indexOf('#');
|
|
477
|
-
href = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
return href;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
function createHref(to) {
|
|
484
|
-
return getBaseHref() + '#' + (typeof to === 'string' ? to : createPath(to));
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function getNextLocation(to, state) {
|
|
488
|
-
if (state === void 0) {
|
|
489
|
-
state = null;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
return readOnly(_extends$1({
|
|
493
|
-
pathname: location.pathname,
|
|
494
|
-
hash: '',
|
|
495
|
-
search: ''
|
|
496
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
497
|
-
state: state,
|
|
498
|
-
key: createKey()
|
|
499
|
-
}));
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
function getHistoryStateAndUrl(nextLocation, index) {
|
|
503
|
-
return [{
|
|
504
|
-
usr: nextLocation.state,
|
|
505
|
-
key: nextLocation.key,
|
|
506
|
-
idx: index
|
|
507
|
-
}, createHref(nextLocation)];
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function allowTx(action, location, retry) {
|
|
511
|
-
return !blockers.length || (blockers.call({
|
|
512
|
-
action: action,
|
|
513
|
-
location: location,
|
|
514
|
-
retry: retry
|
|
515
|
-
}), false);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
function applyTx(nextAction) {
|
|
519
|
-
action = nextAction;
|
|
520
|
-
|
|
521
|
-
var _getIndexAndLocation7 = getIndexAndLocation();
|
|
522
|
-
|
|
523
|
-
index = _getIndexAndLocation7[0];
|
|
524
|
-
location = _getIndexAndLocation7[1];
|
|
525
|
-
listeners.call({
|
|
526
|
-
action: action,
|
|
527
|
-
location: location
|
|
528
|
-
});
|
|
42
|
+
static getDerivedStateFromError(error) {
|
|
43
|
+
return {
|
|
44
|
+
error
|
|
45
|
+
};
|
|
529
46
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
function retry() {
|
|
536
|
-
push(to, state);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
process.env.NODE_ENV !== "production" ? warning$1(nextLocation.pathname.charAt(0) === '/', "Relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")") : void 0;
|
|
540
|
-
|
|
541
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
542
|
-
var _getHistoryStateAndUr3 = getHistoryStateAndUrl(nextLocation, index + 1),
|
|
543
|
-
historyState = _getHistoryStateAndUr3[0],
|
|
544
|
-
url = _getHistoryStateAndUr3[1]; // TODO: Support forced reloading
|
|
545
|
-
// try...catch because iOS limits us to 100 pushState calls :/
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
try {
|
|
549
|
-
globalHistory.pushState(historyState, '', url);
|
|
550
|
-
} catch (error) {
|
|
551
|
-
// They are going to lose state here, but there is no real
|
|
552
|
-
// way to warn them about it since the page will refresh...
|
|
553
|
-
window.location.assign(url);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
applyTx(nextAction);
|
|
47
|
+
componentDidUpdate(prevProps, prevState) {
|
|
48
|
+
if (prevState.error && prevProps.resetKey !== this.props.resetKey) {
|
|
49
|
+
this.setState({
|
|
50
|
+
error: null
|
|
51
|
+
});
|
|
557
52
|
}
|
|
558
53
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
var nextLocation = getNextLocation(to, state);
|
|
563
|
-
|
|
564
|
-
function retry() {
|
|
565
|
-
replace(to, state);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
process.env.NODE_ENV !== "production" ? warning$1(nextLocation.pathname.charAt(0) === '/', "Relative pathnames are not supported in hash history.replace(" + JSON.stringify(to) + ")") : void 0;
|
|
569
|
-
|
|
570
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
571
|
-
var _getHistoryStateAndUr4 = getHistoryStateAndUrl(nextLocation, index),
|
|
572
|
-
historyState = _getHistoryStateAndUr4[0],
|
|
573
|
-
url = _getHistoryStateAndUr4[1]; // TODO: Support forced reloading
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
globalHistory.replaceState(historyState, '', url);
|
|
577
|
-
applyTx(nextAction);
|
|
578
|
-
}
|
|
54
|
+
componentDidCatch(error) {
|
|
55
|
+
console.error(error);
|
|
56
|
+
this.props.onCatch?.(error);
|
|
579
57
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
globalHistory.go(delta);
|
|
58
|
+
render() {
|
|
59
|
+
return this.props.children(this.state);
|
|
583
60
|
}
|
|
584
|
-
|
|
585
|
-
var history = {
|
|
586
|
-
get action() {
|
|
587
|
-
return action;
|
|
588
|
-
},
|
|
589
|
-
|
|
590
|
-
get location() {
|
|
591
|
-
return location;
|
|
592
|
-
},
|
|
593
|
-
|
|
594
|
-
createHref: createHref,
|
|
595
|
-
push: push,
|
|
596
|
-
replace: replace,
|
|
597
|
-
go: go,
|
|
598
|
-
back: function back() {
|
|
599
|
-
go(-1);
|
|
600
|
-
},
|
|
601
|
-
forward: function forward() {
|
|
602
|
-
go(1);
|
|
603
|
-
},
|
|
604
|
-
listen: function listen(listener) {
|
|
605
|
-
return listeners.push(listener);
|
|
606
|
-
},
|
|
607
|
-
block: function block(blocker) {
|
|
608
|
-
var unblock = blockers.push(blocker);
|
|
609
|
-
|
|
610
|
-
if (blockers.length === 1) {
|
|
611
|
-
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
return function () {
|
|
615
|
-
unblock(); // Remove the beforeunload listener so the document may
|
|
616
|
-
// still be salvageable in the pagehide event.
|
|
617
|
-
// See https://html.spec.whatwg.org/#unloading-documents
|
|
618
|
-
|
|
619
|
-
if (!blockers.length) {
|
|
620
|
-
window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
};
|
|
625
|
-
return history;
|
|
626
61
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (options === void 0) {
|
|
636
|
-
options = {};
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
var _options3 = options,
|
|
640
|
-
_options3$initialEntr = _options3.initialEntries,
|
|
641
|
-
initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
|
|
642
|
-
initialIndex = _options3.initialIndex;
|
|
643
|
-
var entries = initialEntries.map(function (entry) {
|
|
644
|
-
var location = readOnly(_extends$1({
|
|
645
|
-
pathname: '/',
|
|
646
|
-
search: '',
|
|
647
|
-
hash: '',
|
|
648
|
-
state: null,
|
|
649
|
-
key: createKey()
|
|
650
|
-
}, typeof entry === 'string' ? parsePath(entry) : entry));
|
|
651
|
-
process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: " + JSON.stringify(entry) + ")") : void 0;
|
|
652
|
-
return location;
|
|
653
|
-
});
|
|
654
|
-
var index = clamp(initialIndex == null ? entries.length - 1 : initialIndex, 0, entries.length - 1);
|
|
655
|
-
var action = Action.Pop;
|
|
656
|
-
var location = entries[index];
|
|
657
|
-
var listeners = createEvents();
|
|
658
|
-
var blockers = createEvents();
|
|
659
|
-
|
|
660
|
-
function createHref(to) {
|
|
661
|
-
return typeof to === 'string' ? to : createPath(to);
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
function getNextLocation(to, state) {
|
|
665
|
-
if (state === void 0) {
|
|
666
|
-
state = null;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
return readOnly(_extends$1({
|
|
670
|
-
pathname: location.pathname,
|
|
671
|
-
search: '',
|
|
672
|
-
hash: ''
|
|
673
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
674
|
-
state: state,
|
|
675
|
-
key: createKey()
|
|
676
|
-
}));
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
function allowTx(action, location, retry) {
|
|
680
|
-
return !blockers.length || (blockers.call({
|
|
681
|
-
action: action,
|
|
682
|
-
location: location,
|
|
683
|
-
retry: retry
|
|
684
|
-
}), false);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
function applyTx(nextAction, nextLocation) {
|
|
688
|
-
action = nextAction;
|
|
689
|
-
location = nextLocation;
|
|
690
|
-
listeners.call({
|
|
691
|
-
action: action,
|
|
692
|
-
location: location
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
function push(to, state) {
|
|
697
|
-
var nextAction = Action.Push;
|
|
698
|
-
var nextLocation = getNextLocation(to, state);
|
|
699
|
-
|
|
700
|
-
function retry() {
|
|
701
|
-
push(to, state);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.push(" + JSON.stringify(to) + ")") : void 0;
|
|
705
|
-
|
|
706
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
707
|
-
index += 1;
|
|
708
|
-
entries.splice(index, entries.length, nextLocation);
|
|
709
|
-
applyTx(nextAction, nextLocation);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
function replace(to, state) {
|
|
714
|
-
var nextAction = Action.Replace;
|
|
715
|
-
var nextLocation = getNextLocation(to, state);
|
|
716
|
-
|
|
717
|
-
function retry() {
|
|
718
|
-
replace(to, state);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.replace(" + JSON.stringify(to) + ")") : void 0;
|
|
722
|
-
|
|
723
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
724
|
-
entries[index] = nextLocation;
|
|
725
|
-
applyTx(nextAction, nextLocation);
|
|
62
|
+
function ErrorComponent({
|
|
63
|
+
error
|
|
64
|
+
}) {
|
|
65
|
+
const [show, setShow] = React.useState(process.env.NODE_ENV !== 'production');
|
|
66
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
67
|
+
style: {
|
|
68
|
+
padding: '.5rem',
|
|
69
|
+
maxWidth: '100%'
|
|
726
70
|
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
var nextLocation = entries[nextIndex];
|
|
733
|
-
|
|
734
|
-
function retry() {
|
|
735
|
-
go(delta);
|
|
71
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
72
|
+
style: {
|
|
73
|
+
display: 'flex',
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
gap: '.5rem'
|
|
736
76
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
applyTx(nextAction, nextLocation);
|
|
77
|
+
}, /*#__PURE__*/React.createElement("strong", {
|
|
78
|
+
style: {
|
|
79
|
+
fontSize: '1rem'
|
|
741
80
|
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
return action;
|
|
751
|
-
},
|
|
752
|
-
|
|
753
|
-
get location() {
|
|
754
|
-
return location;
|
|
755
|
-
},
|
|
756
|
-
|
|
757
|
-
createHref: createHref,
|
|
758
|
-
push: push,
|
|
759
|
-
replace: replace,
|
|
760
|
-
go: go,
|
|
761
|
-
back: function back() {
|
|
762
|
-
go(-1);
|
|
763
|
-
},
|
|
764
|
-
forward: function forward() {
|
|
765
|
-
go(1);
|
|
766
|
-
},
|
|
767
|
-
listen: function listen(listener) {
|
|
768
|
-
return listeners.push(listener);
|
|
81
|
+
}, "Something went wrong!"), /*#__PURE__*/React.createElement("button", {
|
|
82
|
+
style: {
|
|
83
|
+
appearance: 'none',
|
|
84
|
+
fontSize: '.6em',
|
|
85
|
+
border: '1px solid currentColor',
|
|
86
|
+
padding: '.1rem .2rem',
|
|
87
|
+
fontWeight: 'bold',
|
|
88
|
+
borderRadius: '.25rem'
|
|
769
89
|
},
|
|
770
|
-
|
|
771
|
-
|
|
90
|
+
onClick: () => setShow(d => !d)
|
|
91
|
+
}, show ? 'Hide Error' : 'Show Error')), /*#__PURE__*/React.createElement("div", {
|
|
92
|
+
style: {
|
|
93
|
+
height: '.25rem'
|
|
772
94
|
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
95
|
+
}), show ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("pre", {
|
|
96
|
+
style: {
|
|
97
|
+
fontSize: '.7em',
|
|
98
|
+
border: '1px solid red',
|
|
99
|
+
borderRadius: '.25rem',
|
|
100
|
+
padding: '.3rem',
|
|
101
|
+
color: 'red',
|
|
102
|
+
overflow: 'auto'
|
|
103
|
+
}
|
|
104
|
+
}, error.message ? /*#__PURE__*/React.createElement("code", null, error.message) : null)) : null);
|
|
781
105
|
}
|
|
782
106
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
107
|
+
// export type Expand<T> = T
|
|
108
|
+
|
|
109
|
+
// type Compute<T> = { [K in keyof T]: T[K] } | never
|
|
110
|
+
|
|
111
|
+
// type AllKeys<T> = T extends any ? keyof T : never
|
|
112
|
+
|
|
113
|
+
// export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<
|
|
114
|
+
// {
|
|
115
|
+
// [K in Keys]: T[Keys]
|
|
116
|
+
// } & {
|
|
117
|
+
// [K in AllKeys<T>]?: T extends any
|
|
118
|
+
// ? K extends keyof T
|
|
119
|
+
// ? T[K]
|
|
120
|
+
// : never
|
|
121
|
+
// : never
|
|
122
|
+
// }
|
|
123
|
+
// >
|
|
124
|
+
|
|
125
|
+
// // Sample types to merge
|
|
126
|
+
// type TypeA = {
|
|
127
|
+
// shared: string
|
|
128
|
+
// onlyInA: string
|
|
129
|
+
// nested: {
|
|
130
|
+
// shared: string
|
|
131
|
+
// aProp: string
|
|
132
|
+
// }
|
|
133
|
+
// array: string[]
|
|
134
|
+
// }
|
|
135
|
+
|
|
136
|
+
// type TypeB = {
|
|
137
|
+
// shared: number
|
|
138
|
+
// onlyInB: number
|
|
139
|
+
// nested: {
|
|
140
|
+
// shared: number
|
|
141
|
+
// bProp: number
|
|
142
|
+
// }
|
|
143
|
+
// array: number[]
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// type TypeC = {
|
|
147
|
+
// shared: boolean
|
|
148
|
+
// onlyInC: boolean
|
|
149
|
+
// nested: {
|
|
150
|
+
// shared: boolean
|
|
151
|
+
// cProp: boolean
|
|
152
|
+
// }
|
|
153
|
+
// array: boolean[]
|
|
154
|
+
// }
|
|
155
|
+
|
|
156
|
+
// type Test = Expand<Assign<TypeA, TypeB>>
|
|
157
|
+
|
|
158
|
+
// // Using DeepMerge to merge TypeA and TypeB
|
|
159
|
+
// type MergedType = Expand<AssignAll<[TypeA, TypeB, TypeC]>>
|
|
786
160
|
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
function createEvents() {
|
|
791
|
-
var handlers = [];
|
|
792
|
-
return {
|
|
793
|
-
get length() {
|
|
794
|
-
return handlers.length;
|
|
795
|
-
},
|
|
161
|
+
//
|
|
796
162
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
handlers = handlers.filter(function (handler) {
|
|
801
|
-
return handler !== fn;
|
|
802
|
-
});
|
|
803
|
-
};
|
|
804
|
-
},
|
|
805
|
-
call: function call(arg) {
|
|
806
|
-
handlers.forEach(function (fn) {
|
|
807
|
-
return fn && fn(arg);
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
};
|
|
163
|
+
const isServer = typeof document === 'undefined';
|
|
164
|
+
function last(arr) {
|
|
165
|
+
return arr[arr.length - 1];
|
|
811
166
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
return Math.random().toString(36).substr(2, 8);
|
|
167
|
+
function isFunction(d) {
|
|
168
|
+
return typeof d === 'function';
|
|
815
169
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createpath
|
|
820
|
-
*/
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
function createPath(_ref) {
|
|
824
|
-
var _ref$pathname = _ref.pathname,
|
|
825
|
-
pathname = _ref$pathname === void 0 ? '/' : _ref$pathname,
|
|
826
|
-
_ref$search = _ref.search,
|
|
827
|
-
search = _ref$search === void 0 ? '' : _ref$search,
|
|
828
|
-
_ref$hash = _ref.hash,
|
|
829
|
-
hash = _ref$hash === void 0 ? '' : _ref$hash;
|
|
830
|
-
if (search && search !== '?') pathname += search.charAt(0) === '?' ? search : '?' + search;
|
|
831
|
-
if (hash && hash !== '#') pathname += hash.charAt(0) === '#' ? hash : '#' + hash;
|
|
832
|
-
return pathname;
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* Parses a string URL path into its separate pathname, search, and hash components.
|
|
836
|
-
*
|
|
837
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
|
|
838
|
-
*/
|
|
839
|
-
|
|
840
|
-
function parsePath(path) {
|
|
841
|
-
var parsedPath = {};
|
|
842
|
-
|
|
843
|
-
if (path) {
|
|
844
|
-
var hashIndex = path.indexOf('#');
|
|
845
|
-
|
|
846
|
-
if (hashIndex >= 0) {
|
|
847
|
-
parsedPath.hash = path.substr(hashIndex);
|
|
848
|
-
path = path.substr(0, hashIndex);
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
var searchIndex = path.indexOf('?');
|
|
852
|
-
|
|
853
|
-
if (searchIndex >= 0) {
|
|
854
|
-
parsedPath.search = path.substr(searchIndex);
|
|
855
|
-
path = path.substr(0, searchIndex);
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
if (path) {
|
|
859
|
-
parsedPath.pathname = path;
|
|
860
|
-
}
|
|
170
|
+
function functionalUpdate(updater, previous) {
|
|
171
|
+
if (isFunction(updater)) {
|
|
172
|
+
return updater(previous);
|
|
861
173
|
}
|
|
862
|
-
|
|
863
|
-
return parsedPath;
|
|
174
|
+
return updater;
|
|
864
175
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
return;
|
|
871
|
-
}
|
|
872
|
-
if (isProduction) {
|
|
873
|
-
throw new Error(prefix);
|
|
874
|
-
}
|
|
875
|
-
var provided = typeof message === 'function' ? message() : message;
|
|
876
|
-
var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
|
|
877
|
-
throw new Error(value);
|
|
176
|
+
function pick(parent, keys) {
|
|
177
|
+
return keys.reduce((obj, key) => {
|
|
178
|
+
obj[key] = parent[key];
|
|
179
|
+
return obj;
|
|
180
|
+
}, {});
|
|
878
181
|
}
|
|
879
182
|
|
|
880
183
|
/**
|
|
881
184
|
* This function returns `a` if `b` is deeply equal.
|
|
882
185
|
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
883
|
-
* This can be used for structural sharing between JSON values for example.
|
|
186
|
+
* This can be used for structural sharing between immutable JSON values for example.
|
|
187
|
+
* Do not use this with signals
|
|
884
188
|
*/
|
|
885
|
-
function replaceEqualDeep(prev,
|
|
886
|
-
if (prev ===
|
|
189
|
+
function replaceEqualDeep(prev, _next) {
|
|
190
|
+
if (prev === _next) {
|
|
887
191
|
return prev;
|
|
888
192
|
}
|
|
889
|
-
|
|
193
|
+
const next = _next;
|
|
890
194
|
const array = Array.isArray(prev) && Array.isArray(next);
|
|
891
|
-
|
|
892
195
|
if (array || isPlainObject(prev) && isPlainObject(next)) {
|
|
893
|
-
const
|
|
894
|
-
const
|
|
895
|
-
const
|
|
196
|
+
const prevSize = array ? prev.length : Object.keys(prev).length;
|
|
197
|
+
const nextItems = array ? next : Object.keys(next);
|
|
198
|
+
const nextSize = nextItems.length;
|
|
896
199
|
const copy = array ? [] : {};
|
|
897
200
|
let equalItems = 0;
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
const key = array ? i : bItems[i];
|
|
201
|
+
for (let i = 0; i < nextSize; i++) {
|
|
202
|
+
const key = array ? i : nextItems[i];
|
|
901
203
|
copy[key] = replaceEqualDeep(prev[key], next[key]);
|
|
902
|
-
|
|
903
204
|
if (copy[key] === prev[key]) {
|
|
904
205
|
equalItems++;
|
|
905
206
|
}
|
|
906
207
|
}
|
|
907
|
-
|
|
908
|
-
return aSize === bSize && equalItems === aSize ? prev : copy;
|
|
208
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy;
|
|
909
209
|
}
|
|
910
|
-
|
|
911
210
|
return next;
|
|
912
|
-
}
|
|
211
|
+
}
|
|
913
212
|
|
|
213
|
+
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
914
214
|
function isPlainObject(o) {
|
|
915
215
|
if (!hasObjectPrototype(o)) {
|
|
916
216
|
return false;
|
|
917
|
-
}
|
|
918
|
-
|
|
217
|
+
}
|
|
919
218
|
|
|
219
|
+
// If has modified constructor
|
|
920
220
|
const ctor = o.constructor;
|
|
921
|
-
|
|
922
221
|
if (typeof ctor === 'undefined') {
|
|
923
222
|
return true;
|
|
924
|
-
}
|
|
925
|
-
|
|
223
|
+
}
|
|
926
224
|
|
|
225
|
+
// If has modified prototype
|
|
927
226
|
const prot = ctor.prototype;
|
|
928
|
-
|
|
929
227
|
if (!hasObjectPrototype(prot)) {
|
|
930
228
|
return false;
|
|
931
|
-
}
|
|
932
|
-
|
|
229
|
+
}
|
|
933
230
|
|
|
231
|
+
// If constructor does not have an Object-specific method
|
|
934
232
|
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
935
233
|
return false;
|
|
936
|
-
} // Most likely a plain Object
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
return true;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
function hasObjectPrototype(o) {
|
|
943
|
-
return Object.prototype.toString.call(o) === '[object Object]';
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
function last(arr) {
|
|
947
|
-
return arr[arr.length - 1];
|
|
948
|
-
}
|
|
949
|
-
function warning(cond, message) {
|
|
950
|
-
if (cond) {
|
|
951
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
952
|
-
|
|
953
|
-
try {
|
|
954
|
-
throw new Error(message);
|
|
955
|
-
} catch (_unused) {}
|
|
956
234
|
}
|
|
957
235
|
|
|
236
|
+
// Most likely a plain Object
|
|
958
237
|
return true;
|
|
959
238
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
return typeof d === 'function';
|
|
239
|
+
function hasObjectPrototype(o) {
|
|
240
|
+
return Object.prototype.toString.call(o) === '[object Object]';
|
|
963
241
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
return updater(previous);
|
|
242
|
+
function deepEqual(a, b, partial = false) {
|
|
243
|
+
if (a === b) {
|
|
244
|
+
return true;
|
|
968
245
|
}
|
|
969
|
-
|
|
970
|
-
|
|
246
|
+
if (typeof a !== typeof b) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
250
|
+
const aKeys = Object.keys(a);
|
|
251
|
+
const bKeys = Object.keys(b);
|
|
252
|
+
if (!partial && aKeys.length !== bKeys.length) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
return !bKeys.some(key => !(key in a) || !deepEqual(a[key], b[key], partial));
|
|
256
|
+
}
|
|
257
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
258
|
+
return !a.some((item, index) => !deepEqual(item, b[index], partial));
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
971
261
|
}
|
|
972
|
-
function
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
262
|
+
function useStableCallback(fn) {
|
|
263
|
+
const fnRef = React.useRef(fn);
|
|
264
|
+
fnRef.current = fn;
|
|
265
|
+
const ref = React.useRef((...args) => fnRef.current(...args));
|
|
266
|
+
return ref.current;
|
|
267
|
+
}
|
|
268
|
+
function shallow(objA, objB) {
|
|
269
|
+
if (Object.is(objA, objB)) {
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
const keysA = Object.keys(objA);
|
|
276
|
+
if (keysA.length !== Object.keys(objB).length) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
280
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
function useRouteContext(opts) {
|
|
287
|
+
return useMatch({
|
|
288
|
+
...opts,
|
|
289
|
+
select: match => opts?.select ? opts.select(match.context) : match.context
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const useLayoutEffect$1 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
293
|
+
function escapeJSON(jsonString) {
|
|
294
|
+
return jsonString.replace(/\\/g, '\\\\') // Escape backslashes
|
|
295
|
+
.replace(/'/g, "\\'") // Escape single quotes
|
|
296
|
+
.replace(/"/g, '\\"'); // Escape double quotes
|
|
977
297
|
}
|
|
978
298
|
|
|
979
299
|
function joinPaths(paths) {
|
|
@@ -993,8 +313,8 @@ function trimPath(path) {
|
|
|
993
313
|
return trimPathRight(trimPathLeft(path));
|
|
994
314
|
}
|
|
995
315
|
function resolvePath(basepath, base, to) {
|
|
996
|
-
base = base.replace(new RegExp(
|
|
997
|
-
to = to.replace(new RegExp(
|
|
316
|
+
base = base.replace(new RegExp(`^${basepath}`), '/');
|
|
317
|
+
to = to.replace(new RegExp(`^${basepath}`), '/');
|
|
998
318
|
let baseSegments = parsePathname(base);
|
|
999
319
|
const toSegments = parsePathname(to);
|
|
1000
320
|
toSegments.forEach((toSegment, index) => {
|
|
@@ -1007,13 +327,10 @@ function resolvePath(basepath, base, to) {
|
|
|
1007
327
|
baseSegments.push(toSegment);
|
|
1008
328
|
} else ;
|
|
1009
329
|
} else if (toSegment.value === '..') {
|
|
1010
|
-
var _last;
|
|
1011
|
-
|
|
1012
330
|
// Extra trailing slash? pop it off
|
|
1013
|
-
if (baseSegments.length > 1 &&
|
|
331
|
+
if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
|
|
1014
332
|
baseSegments.pop();
|
|
1015
333
|
}
|
|
1016
|
-
|
|
1017
334
|
baseSegments.pop();
|
|
1018
335
|
} else if (toSegment.value === '.') {
|
|
1019
336
|
return;
|
|
@@ -1028,10 +345,8 @@ function parsePathname(pathname) {
|
|
|
1028
345
|
if (!pathname) {
|
|
1029
346
|
return [];
|
|
1030
347
|
}
|
|
1031
|
-
|
|
1032
348
|
pathname = cleanPath(pathname);
|
|
1033
349
|
const segments = [];
|
|
1034
|
-
|
|
1035
350
|
if (pathname.slice(0, 1) === '/') {
|
|
1036
351
|
pathname = pathname.substring(1);
|
|
1037
352
|
segments.push({
|
|
@@ -1039,34 +354,30 @@ function parsePathname(pathname) {
|
|
|
1039
354
|
value: '/'
|
|
1040
355
|
});
|
|
1041
356
|
}
|
|
1042
|
-
|
|
1043
357
|
if (!pathname) {
|
|
1044
358
|
return segments;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
359
|
+
}
|
|
1047
360
|
|
|
361
|
+
// Remove empty segments and '.' segments
|
|
1048
362
|
const split = pathname.split('/').filter(Boolean);
|
|
1049
363
|
segments.push(...split.map(part => {
|
|
1050
|
-
if (part
|
|
364
|
+
if (part === '$' || part === '*') {
|
|
1051
365
|
return {
|
|
1052
366
|
type: 'wildcard',
|
|
1053
367
|
value: part
|
|
1054
368
|
};
|
|
1055
369
|
}
|
|
1056
|
-
|
|
1057
|
-
if (part.charAt(0) === ':') {
|
|
370
|
+
if (part.charAt(0) === '$') {
|
|
1058
371
|
return {
|
|
1059
372
|
type: 'param',
|
|
1060
373
|
value: part
|
|
1061
374
|
};
|
|
1062
375
|
}
|
|
1063
|
-
|
|
1064
376
|
return {
|
|
1065
377
|
type: 'pathname',
|
|
1066
378
|
value: part
|
|
1067
379
|
};
|
|
1068
380
|
}));
|
|
1069
|
-
|
|
1070
381
|
if (pathname.slice(-1) === '/') {
|
|
1071
382
|
pathname = pathname.substring(1);
|
|
1072
383
|
segments.push({
|
|
@@ -1074,63 +385,70 @@ function parsePathname(pathname) {
|
|
|
1074
385
|
value: '/'
|
|
1075
386
|
});
|
|
1076
387
|
}
|
|
1077
|
-
|
|
1078
388
|
return segments;
|
|
1079
389
|
}
|
|
1080
|
-
function interpolatePath(path, params,
|
|
390
|
+
function interpolatePath(path, params, leaveWildcards = false) {
|
|
1081
391
|
const interpolatedPathSegments = parsePathname(path);
|
|
1082
392
|
return joinPaths(interpolatedPathSegments.map(segment => {
|
|
1083
|
-
if (segment.
|
|
1084
|
-
|
|
393
|
+
if (segment.type === 'wildcard') {
|
|
394
|
+
const value = params[segment.value];
|
|
395
|
+
if (leaveWildcards) return `${segment.value}${value ?? ''}`;
|
|
396
|
+
return value;
|
|
1085
397
|
}
|
|
1086
|
-
|
|
1087
398
|
if (segment.type === 'param') {
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
|
|
399
|
+
return params[segment.value.substring(1)] ?? '';
|
|
1091
400
|
}
|
|
1092
|
-
|
|
1093
401
|
return segment.value;
|
|
1094
402
|
}));
|
|
1095
403
|
}
|
|
1096
|
-
function matchPathname(currentPathname, matchLocation) {
|
|
1097
|
-
const pathParams = matchByPath(currentPathname, matchLocation);
|
|
404
|
+
function matchPathname(basepath, currentPathname, matchLocation) {
|
|
405
|
+
const pathParams = matchByPath(basepath, currentPathname, matchLocation);
|
|
406
|
+
// const searchMatched = matchBySearch(location.search, matchLocation)
|
|
1098
407
|
|
|
1099
408
|
if (matchLocation.to && !pathParams) {
|
|
1100
409
|
return;
|
|
1101
410
|
}
|
|
1102
|
-
|
|
1103
|
-
return pathParams != null ? pathParams : {};
|
|
411
|
+
return pathParams ?? {};
|
|
1104
412
|
}
|
|
1105
|
-
function matchByPath(from, matchLocation) {
|
|
1106
|
-
|
|
1107
|
-
|
|
413
|
+
function matchByPath(basepath, from, matchLocation) {
|
|
414
|
+
// Remove the base path from the pathname
|
|
415
|
+
from = basepath != '/' ? from.substring(basepath.length) : from;
|
|
416
|
+
// Default to to $ (wildcard)
|
|
417
|
+
const to = `${matchLocation.to ?? '$'}`;
|
|
418
|
+
// Parse the from and to
|
|
1108
419
|
const baseSegments = parsePathname(from);
|
|
1109
|
-
const routeSegments = parsePathname(
|
|
420
|
+
const routeSegments = parsePathname(to);
|
|
421
|
+
if (!from.startsWith('/')) {
|
|
422
|
+
baseSegments.unshift({
|
|
423
|
+
type: 'pathname',
|
|
424
|
+
value: '/'
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (!to.startsWith('/')) {
|
|
428
|
+
routeSegments.unshift({
|
|
429
|
+
type: 'pathname',
|
|
430
|
+
value: '/'
|
|
431
|
+
});
|
|
432
|
+
}
|
|
1110
433
|
const params = {};
|
|
1111
|
-
|
|
1112
434
|
let isMatch = (() => {
|
|
1113
435
|
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
1114
436
|
const baseSegment = baseSegments[i];
|
|
1115
437
|
const routeSegment = routeSegments[i];
|
|
1116
|
-
const
|
|
1117
|
-
const
|
|
1118
|
-
|
|
438
|
+
const isLastBaseSegment = i >= baseSegments.length - 1;
|
|
439
|
+
const isLastRouteSegment = i >= routeSegments.length - 1;
|
|
1119
440
|
if (routeSegment) {
|
|
1120
441
|
if (routeSegment.type === 'wildcard') {
|
|
1121
|
-
if (baseSegment
|
|
442
|
+
if (baseSegment?.value) {
|
|
1122
443
|
params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
|
|
1123
444
|
return true;
|
|
1124
445
|
}
|
|
1125
|
-
|
|
1126
446
|
return false;
|
|
1127
447
|
}
|
|
1128
|
-
|
|
1129
448
|
if (routeSegment.type === 'pathname') {
|
|
1130
|
-
if (routeSegment.value === '/' && !
|
|
449
|
+
if (routeSegment.value === '/' && !baseSegment?.value) {
|
|
1131
450
|
return true;
|
|
1132
451
|
}
|
|
1133
|
-
|
|
1134
452
|
if (baseSegment) {
|
|
1135
453
|
if (matchLocation.caseSensitive) {
|
|
1136
454
|
if (routeSegment.value !== baseSegment.value) {
|
|
@@ -1141,41 +459,664 @@ function matchByPath(from, matchLocation) {
|
|
|
1141
459
|
}
|
|
1142
460
|
}
|
|
1143
461
|
}
|
|
1144
|
-
|
|
1145
462
|
if (!baseSegment) {
|
|
1146
463
|
return false;
|
|
1147
464
|
}
|
|
1148
|
-
|
|
1149
465
|
if (routeSegment.type === 'param') {
|
|
1150
|
-
if (
|
|
466
|
+
if (baseSegment?.value === '/') {
|
|
1151
467
|
return false;
|
|
1152
468
|
}
|
|
1153
|
-
|
|
1154
|
-
if (!baseSegment.value.startsWith(':')) {
|
|
469
|
+
if (baseSegment.value.charAt(0) !== '$') {
|
|
1155
470
|
params[routeSegment.value.substring(1)] = baseSegment.value;
|
|
1156
471
|
}
|
|
1157
472
|
}
|
|
1158
473
|
}
|
|
1159
|
-
|
|
1160
|
-
if (isLastRouteSegment && !isLastBaseSegment) {
|
|
474
|
+
if (!isLastBaseSegment && isLastRouteSegment) {
|
|
1161
475
|
return !!matchLocation.fuzzy;
|
|
1162
476
|
}
|
|
1163
477
|
}
|
|
1164
|
-
|
|
1165
478
|
return true;
|
|
1166
479
|
})();
|
|
1167
|
-
|
|
1168
480
|
return isMatch ? params : undefined;
|
|
1169
481
|
}
|
|
1170
482
|
|
|
483
|
+
function useParams(opts) {
|
|
484
|
+
return useRouterState({
|
|
485
|
+
select: state => {
|
|
486
|
+
const params = last(state.matches)?.params;
|
|
487
|
+
return opts?.select ? opts.select(params) : params;
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function useSearch(opts) {
|
|
493
|
+
return useMatch({
|
|
494
|
+
...opts,
|
|
495
|
+
select: match => {
|
|
496
|
+
return opts?.select ? opts.select(match.search) : match.search;
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const rootRouteId = '__root__';
|
|
502
|
+
|
|
503
|
+
// The parse type here allows a zod schema to be passed directly to the validator
|
|
504
|
+
|
|
505
|
+
class Route {
|
|
506
|
+
// Set up in this.init()
|
|
507
|
+
|
|
508
|
+
// customId!: TCustomId
|
|
509
|
+
|
|
510
|
+
// Optional
|
|
511
|
+
|
|
512
|
+
constructor(options) {
|
|
513
|
+
this.options = options || {};
|
|
514
|
+
this.isRoot = !options?.getParentRoute;
|
|
515
|
+
Route.__onInit(this);
|
|
516
|
+
this.$$typeof = Symbol.for('react.memo');
|
|
517
|
+
}
|
|
518
|
+
init = opts => {
|
|
519
|
+
this.originalIndex = opts.originalIndex;
|
|
520
|
+
const options = this.options;
|
|
521
|
+
const isRoot = !options?.path && !options?.id;
|
|
522
|
+
this.parentRoute = this.options?.getParentRoute?.();
|
|
523
|
+
if (isRoot) {
|
|
524
|
+
this.path = rootRouteId;
|
|
525
|
+
} else {
|
|
526
|
+
invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
|
|
527
|
+
}
|
|
528
|
+
let path = isRoot ? rootRouteId : options.path;
|
|
529
|
+
|
|
530
|
+
// If the path is anything other than an index path, trim it up
|
|
531
|
+
if (path && path !== '/') {
|
|
532
|
+
path = trimPath(path);
|
|
533
|
+
}
|
|
534
|
+
const customId = options?.id || path;
|
|
535
|
+
|
|
536
|
+
// Strip the parentId prefix from the first level of children
|
|
537
|
+
let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
|
|
538
|
+
if (path === rootRouteId) {
|
|
539
|
+
path = '/';
|
|
540
|
+
}
|
|
541
|
+
if (id !== rootRouteId) {
|
|
542
|
+
id = joinPaths(['/', id]);
|
|
543
|
+
}
|
|
544
|
+
const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
|
|
545
|
+
this.path = path;
|
|
546
|
+
this.id = id;
|
|
547
|
+
// this.customId = customId as TCustomId
|
|
548
|
+
this.fullPath = fullPath;
|
|
549
|
+
this.to = fullPath;
|
|
550
|
+
};
|
|
551
|
+
addChildren = children => {
|
|
552
|
+
this.children = children;
|
|
553
|
+
return this;
|
|
554
|
+
};
|
|
555
|
+
update = options => {
|
|
556
|
+
Object.assign(this.options, options);
|
|
557
|
+
return this;
|
|
558
|
+
};
|
|
559
|
+
static __onInit = route => {
|
|
560
|
+
// This is a dummy static method that should get
|
|
561
|
+
// replaced by a framework specific implementation if necessary
|
|
562
|
+
};
|
|
563
|
+
useMatch = opts => {
|
|
564
|
+
return useMatch({
|
|
565
|
+
...opts,
|
|
566
|
+
from: this.id
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
useRouteContext = opts => {
|
|
570
|
+
return useMatch({
|
|
571
|
+
...opts,
|
|
572
|
+
from: this.id,
|
|
573
|
+
select: d => opts?.select ? opts.select(d.context) : d.context
|
|
574
|
+
});
|
|
575
|
+
};
|
|
576
|
+
useSearch = opts => {
|
|
577
|
+
return useSearch({
|
|
578
|
+
...opts,
|
|
579
|
+
from: this.id
|
|
580
|
+
});
|
|
581
|
+
};
|
|
582
|
+
useParams = opts => {
|
|
583
|
+
return useParams({
|
|
584
|
+
...opts,
|
|
585
|
+
from: this.id
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
useLoaderData = opts => {
|
|
589
|
+
return useLoaderData({
|
|
590
|
+
...opts,
|
|
591
|
+
from: this.id
|
|
592
|
+
});
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
function rootRouteWithContext() {
|
|
596
|
+
return options => {
|
|
597
|
+
return new RootRoute(options);
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
class RootRoute extends Route {
|
|
601
|
+
constructor(options) {
|
|
602
|
+
super(options);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function createRouteMask(opts) {
|
|
606
|
+
return opts;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
//
|
|
610
|
+
|
|
611
|
+
function Matches() {
|
|
612
|
+
const router = useRouter();
|
|
613
|
+
const routerState = useRouterState();
|
|
614
|
+
const matches = routerState.pendingMatches?.some(d => d.showPending) ? routerState.pendingMatches : routerState.matches;
|
|
615
|
+
const locationKey = routerState.resolvedLocation.state.key;
|
|
616
|
+
const route = router.routesById[rootRouteId];
|
|
617
|
+
const errorComponent = React.useCallback(props => {
|
|
618
|
+
return /*#__PURE__*/React.createElement(ErrorComponent, {
|
|
619
|
+
...props,
|
|
620
|
+
useMatch: route.useMatch,
|
|
621
|
+
useRouteContext: route.useRouteContext,
|
|
622
|
+
useSearch: route.useSearch,
|
|
623
|
+
useParams: route.useParams
|
|
624
|
+
});
|
|
625
|
+
}, [route]);
|
|
626
|
+
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
627
|
+
value: matches
|
|
628
|
+
}, /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
629
|
+
resetKey: locationKey,
|
|
630
|
+
errorComponent: errorComponent,
|
|
631
|
+
onCatch: () => {
|
|
632
|
+
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
633
|
+
}
|
|
634
|
+
}, matches.length ? /*#__PURE__*/React.createElement(Match, {
|
|
635
|
+
matches: matches
|
|
636
|
+
}) : null));
|
|
637
|
+
}
|
|
638
|
+
function SafeFragment(props) {
|
|
639
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
640
|
+
}
|
|
641
|
+
function Match({
|
|
642
|
+
matches
|
|
643
|
+
}) {
|
|
644
|
+
const {
|
|
645
|
+
options,
|
|
646
|
+
routesById
|
|
647
|
+
} = useRouter();
|
|
648
|
+
const match = matches[0];
|
|
649
|
+
const routeId = match?.routeId;
|
|
650
|
+
const route = routesById[routeId];
|
|
651
|
+
useRouter();
|
|
652
|
+
const locationKey = useRouterState().resolvedLocation.state?.key;
|
|
653
|
+
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent;
|
|
654
|
+
const pendingElement = PendingComponent ? /*#__PURE__*/React.createElement(PendingComponent, {
|
|
655
|
+
useMatch: route.useMatch,
|
|
656
|
+
useRouteContext: route.useRouteContext,
|
|
657
|
+
useSearch: route.useSearch,
|
|
658
|
+
useParams: route.useParams
|
|
659
|
+
}) : undefined;
|
|
660
|
+
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
661
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? pendingElement ? React.Suspense : SafeFragment;
|
|
662
|
+
const errorComponent = routeErrorComponent ? React.useCallback(props => {
|
|
663
|
+
return /*#__PURE__*/React.createElement(routeErrorComponent, {
|
|
664
|
+
...props,
|
|
665
|
+
useMatch: route.useMatch,
|
|
666
|
+
useRouteContext: route.useRouteContext,
|
|
667
|
+
useSearch: route.useSearch,
|
|
668
|
+
useParams: route.useParams
|
|
669
|
+
});
|
|
670
|
+
}, [route]) : undefined;
|
|
671
|
+
const ResolvedCatchBoundary = errorComponent ? CatchBoundary : SafeFragment;
|
|
672
|
+
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
673
|
+
value: matches
|
|
674
|
+
}, /*#__PURE__*/React.createElement(ResolvedSuspenseBoundary, {
|
|
675
|
+
fallback: pendingElement
|
|
676
|
+
}, /*#__PURE__*/React.createElement(ResolvedCatchBoundary, {
|
|
677
|
+
resetKey: locationKey,
|
|
678
|
+
errorComponent: errorComponent,
|
|
679
|
+
onCatch: () => {
|
|
680
|
+
warning(false, `Error in route match: ${match.id}`);
|
|
681
|
+
}
|
|
682
|
+
}, /*#__PURE__*/React.createElement(MatchInner, {
|
|
683
|
+
match: match,
|
|
684
|
+
pendingElement: pendingElement
|
|
685
|
+
}))));
|
|
686
|
+
}
|
|
687
|
+
function MatchInner({
|
|
688
|
+
match,
|
|
689
|
+
pendingElement
|
|
690
|
+
}) {
|
|
691
|
+
const {
|
|
692
|
+
options,
|
|
693
|
+
routesById
|
|
694
|
+
} = useRouter();
|
|
695
|
+
const route = routesById[match.routeId];
|
|
696
|
+
if (match.status === 'error') {
|
|
697
|
+
throw match.error;
|
|
698
|
+
}
|
|
699
|
+
if (match.status === 'pending') {
|
|
700
|
+
if (match.showPending) {
|
|
701
|
+
return pendingElement || null;
|
|
702
|
+
}
|
|
703
|
+
throw match.loadPromise;
|
|
704
|
+
}
|
|
705
|
+
if (match.status === 'success') {
|
|
706
|
+
let comp = route.options.component ?? options.defaultComponent;
|
|
707
|
+
if (comp) {
|
|
708
|
+
return /*#__PURE__*/React.createElement(comp, {
|
|
709
|
+
useMatch: route.useMatch,
|
|
710
|
+
useRouteContext: route.useRouteContext,
|
|
711
|
+
useSearch: route.useSearch,
|
|
712
|
+
useParams: route.useParams,
|
|
713
|
+
useLoaderData: route.useLoaderData
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
return /*#__PURE__*/React.createElement(Outlet, null);
|
|
717
|
+
}
|
|
718
|
+
invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
|
|
719
|
+
}
|
|
720
|
+
function Outlet() {
|
|
721
|
+
const matches = React.useContext(matchesContext).slice(1);
|
|
722
|
+
if (!matches[0]) {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
return /*#__PURE__*/React.createElement(Match, {
|
|
726
|
+
matches: matches
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
function useMatchRoute() {
|
|
730
|
+
const {
|
|
731
|
+
matchRoute
|
|
732
|
+
} = useRouter();
|
|
733
|
+
return React.useCallback(opts => {
|
|
734
|
+
const {
|
|
735
|
+
pending,
|
|
736
|
+
caseSensitive,
|
|
737
|
+
...rest
|
|
738
|
+
} = opts;
|
|
739
|
+
return matchRoute(rest, {
|
|
740
|
+
pending,
|
|
741
|
+
caseSensitive
|
|
742
|
+
});
|
|
743
|
+
}, []);
|
|
744
|
+
}
|
|
745
|
+
function MatchRoute(props) {
|
|
746
|
+
const matchRoute = useMatchRoute();
|
|
747
|
+
const params = matchRoute(props);
|
|
748
|
+
if (typeof props.children === 'function') {
|
|
749
|
+
return props.children(params);
|
|
750
|
+
}
|
|
751
|
+
return !!params ? props.children : null;
|
|
752
|
+
}
|
|
753
|
+
function useMatch(opts) {
|
|
754
|
+
const nearestMatch = React.useContext(matchesContext)[0];
|
|
755
|
+
const nearestMatchRouteId = nearestMatch?.routeId;
|
|
756
|
+
const matchRouteId = useRouterState({
|
|
757
|
+
select: state => {
|
|
758
|
+
const matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
759
|
+
const match = opts?.from ? matches.find(d => d.routeId === opts?.from) : matches.find(d => d.id === nearestMatch.id);
|
|
760
|
+
return match.routeId;
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
if (opts?.strict ?? true) {
|
|
764
|
+
invariant(nearestMatchRouteId == matchRouteId, `useMatch("${matchRouteId}") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${matchRouteId}", { strict: false })' or 'useRoute("${matchRouteId}")' instead?`);
|
|
765
|
+
}
|
|
766
|
+
const matchSelection = useRouterState({
|
|
767
|
+
select: state => {
|
|
768
|
+
const matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
769
|
+
const match = opts?.from ? matches.find(d => d.routeId === opts?.from) : matches.find(d => d.id === nearestMatch.id);
|
|
770
|
+
invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
|
|
771
|
+
return opts?.select ? opts.select(match) : match;
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
return matchSelection;
|
|
775
|
+
}
|
|
776
|
+
const matchesContext = /*#__PURE__*/React.createContext(null);
|
|
777
|
+
function useMatches(opts) {
|
|
778
|
+
const contextMatches = React.useContext(matchesContext);
|
|
779
|
+
return useRouterState({
|
|
780
|
+
select: state => {
|
|
781
|
+
let matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
782
|
+
matches = matches.slice(matches.findIndex(d => d.id === contextMatches[0]?.id));
|
|
783
|
+
return opts?.select ? opts.select(matches) : matches;
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
function useLoaderData(opts) {
|
|
788
|
+
const match = useMatch({
|
|
789
|
+
...opts,
|
|
790
|
+
select: undefined
|
|
791
|
+
});
|
|
792
|
+
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const routerContext = /*#__PURE__*/React.createContext(null);
|
|
796
|
+
if (typeof document !== 'undefined') {
|
|
797
|
+
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
798
|
+
}
|
|
799
|
+
function RouterProvider({
|
|
800
|
+
router,
|
|
801
|
+
...rest
|
|
802
|
+
}) {
|
|
803
|
+
// Allow the router to update options on the router instance
|
|
804
|
+
router.update({
|
|
805
|
+
...router.options,
|
|
806
|
+
...rest,
|
|
807
|
+
context: {
|
|
808
|
+
...router.options.context,
|
|
809
|
+
...rest?.context
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
const inner = /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
813
|
+
value: router
|
|
814
|
+
}, /*#__PURE__*/React.createElement(Matches, null), /*#__PURE__*/React.createElement(Transitioner, null));
|
|
815
|
+
if (router.options.Wrap) {
|
|
816
|
+
return /*#__PURE__*/React.createElement(router.options.Wrap, null, inner);
|
|
817
|
+
}
|
|
818
|
+
return inner;
|
|
819
|
+
}
|
|
820
|
+
function Transitioner() {
|
|
821
|
+
const router = useRouter();
|
|
822
|
+
const routerState = useRouterState({
|
|
823
|
+
select: s => pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning'])
|
|
824
|
+
});
|
|
825
|
+
const [isTransitioning, startReactTransition] = React.useTransition();
|
|
826
|
+
router.startReactTransition = startReactTransition;
|
|
827
|
+
React.useEffect(() => {
|
|
828
|
+
if (isTransitioning) {
|
|
829
|
+
router.__store.setState(s => ({
|
|
830
|
+
...s,
|
|
831
|
+
isTransitioning
|
|
832
|
+
}));
|
|
833
|
+
}
|
|
834
|
+
}, [isTransitioning]);
|
|
835
|
+
const tryLoad = () => {
|
|
836
|
+
const apply = cb => {
|
|
837
|
+
if (!routerState.isTransitioning) {
|
|
838
|
+
startReactTransition(() => cb());
|
|
839
|
+
} else {
|
|
840
|
+
cb();
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
apply(() => {
|
|
844
|
+
try {
|
|
845
|
+
router.load();
|
|
846
|
+
} catch (err) {
|
|
847
|
+
console.error(err);
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
};
|
|
851
|
+
useLayoutEffect$1(() => {
|
|
852
|
+
const unsub = router.history.subscribe(() => {
|
|
853
|
+
router.latestLocation = router.parseLocation(router.latestLocation);
|
|
854
|
+
if (routerState.location !== router.latestLocation) {
|
|
855
|
+
tryLoad();
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
const nextLocation = router.buildLocation({
|
|
859
|
+
search: true,
|
|
860
|
+
params: true,
|
|
861
|
+
hash: true,
|
|
862
|
+
state: true
|
|
863
|
+
});
|
|
864
|
+
if (routerState.location.href !== nextLocation.href) {
|
|
865
|
+
router.commitLocation({
|
|
866
|
+
...nextLocation,
|
|
867
|
+
replace: true
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
return () => {
|
|
871
|
+
unsub();
|
|
872
|
+
};
|
|
873
|
+
}, [router.history]);
|
|
874
|
+
useLayoutEffect$1(() => {
|
|
875
|
+
if (routerState.isTransitioning && !isTransitioning && !routerState.isLoading && routerState.resolvedLocation !== routerState.location) {
|
|
876
|
+
router.emit({
|
|
877
|
+
type: 'onResolved',
|
|
878
|
+
fromLocation: routerState.resolvedLocation,
|
|
879
|
+
toLocation: routerState.location,
|
|
880
|
+
pathChanged: routerState.location.href !== routerState.resolvedLocation?.href
|
|
881
|
+
});
|
|
882
|
+
router.pendingMatches = [];
|
|
883
|
+
router.__store.setState(s => ({
|
|
884
|
+
...s,
|
|
885
|
+
isTransitioning: false,
|
|
886
|
+
resolvedLocation: s.location
|
|
887
|
+
}));
|
|
888
|
+
}
|
|
889
|
+
}, [routerState.isTransitioning, isTransitioning, routerState.isLoading, routerState.resolvedLocation, routerState.location]);
|
|
890
|
+
useLayoutEffect$1(() => {
|
|
891
|
+
if (!window.__TSR_DEHYDRATED__) {
|
|
892
|
+
tryLoad();
|
|
893
|
+
}
|
|
894
|
+
}, []);
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
function getRouteMatch(state, id) {
|
|
898
|
+
return [...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
|
|
899
|
+
}
|
|
900
|
+
function useRouterState(opts) {
|
|
901
|
+
const router = useRouter();
|
|
902
|
+
return useStore(router.__store, opts?.select);
|
|
903
|
+
}
|
|
904
|
+
function useRouter() {
|
|
905
|
+
const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || routerContext : routerContext;
|
|
906
|
+
const value = React.useContext(resolvedContext);
|
|
907
|
+
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
908
|
+
return value;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function defer(_promise) {
|
|
912
|
+
const promise = _promise;
|
|
913
|
+
if (!promise.__deferredState) {
|
|
914
|
+
promise.__deferredState = {
|
|
915
|
+
uid: Math.random().toString(36).slice(2),
|
|
916
|
+
status: 'pending'
|
|
917
|
+
};
|
|
918
|
+
const state = promise.__deferredState;
|
|
919
|
+
promise.then(data => {
|
|
920
|
+
state.status = 'success';
|
|
921
|
+
state.data = data;
|
|
922
|
+
}).catch(error => {
|
|
923
|
+
state.status = 'error';
|
|
924
|
+
state.error = error;
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
return promise;
|
|
928
|
+
}
|
|
929
|
+
function isDehydratedDeferred(obj) {
|
|
930
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
function useAwaited({
|
|
934
|
+
promise
|
|
935
|
+
}) {
|
|
936
|
+
const router = useRouter();
|
|
937
|
+
let state = promise.__deferredState;
|
|
938
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
939
|
+
if (isDehydratedDeferred(promise)) {
|
|
940
|
+
state = router.hydrateData(key);
|
|
941
|
+
promise = Promise.resolve(state.data);
|
|
942
|
+
promise.__deferredState = state;
|
|
943
|
+
}
|
|
944
|
+
if (state.status === 'pending') {
|
|
945
|
+
throw new Promise(r => setTimeout(r, 1)).then(() => promise);
|
|
946
|
+
}
|
|
947
|
+
if (state.status === 'error') {
|
|
948
|
+
throw state.error;
|
|
949
|
+
}
|
|
950
|
+
router.dehydrateData(key, state);
|
|
951
|
+
return [state.data];
|
|
952
|
+
}
|
|
953
|
+
function Await(props) {
|
|
954
|
+
const awaited = useAwaited(props);
|
|
955
|
+
return props.children(...awaited);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
class FileRoute {
|
|
959
|
+
constructor(path) {
|
|
960
|
+
this.path = path;
|
|
961
|
+
}
|
|
962
|
+
createRoute = options => {
|
|
963
|
+
const route = new Route(options);
|
|
964
|
+
route.isRoot = false;
|
|
965
|
+
return route;
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
function lazyRouteComponent(importer, exportName) {
|
|
970
|
+
let loadPromise;
|
|
971
|
+
const load = () => {
|
|
972
|
+
if (!loadPromise) {
|
|
973
|
+
loadPromise = importer();
|
|
974
|
+
}
|
|
975
|
+
return loadPromise;
|
|
976
|
+
};
|
|
977
|
+
const lazyComp = /*#__PURE__*/React.lazy(async () => {
|
|
978
|
+
const moduleExports = await load();
|
|
979
|
+
const comp = moduleExports[exportName ?? 'default'];
|
|
980
|
+
return {
|
|
981
|
+
default: comp
|
|
982
|
+
};
|
|
983
|
+
});
|
|
984
|
+
lazyComp.preload = load;
|
|
985
|
+
return lazyComp;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function _extends() {
|
|
989
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
990
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
991
|
+
var source = arguments[i];
|
|
992
|
+
for (var key in source) {
|
|
993
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
994
|
+
target[key] = source[key];
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return target;
|
|
999
|
+
};
|
|
1000
|
+
return _extends.apply(this, arguments);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
function useLinkProps(options) {
|
|
1004
|
+
const {
|
|
1005
|
+
buildLink
|
|
1006
|
+
} = useRouter();
|
|
1007
|
+
const match = useMatch({
|
|
1008
|
+
strict: false
|
|
1009
|
+
});
|
|
1010
|
+
const {
|
|
1011
|
+
// custom props
|
|
1012
|
+
type,
|
|
1013
|
+
children,
|
|
1014
|
+
target,
|
|
1015
|
+
activeProps = () => ({
|
|
1016
|
+
className: 'active'
|
|
1017
|
+
}),
|
|
1018
|
+
inactiveProps = () => ({}),
|
|
1019
|
+
activeOptions,
|
|
1020
|
+
disabled,
|
|
1021
|
+
hash,
|
|
1022
|
+
search,
|
|
1023
|
+
params,
|
|
1024
|
+
to,
|
|
1025
|
+
state,
|
|
1026
|
+
mask,
|
|
1027
|
+
preload,
|
|
1028
|
+
preloadDelay,
|
|
1029
|
+
replace,
|
|
1030
|
+
startTransition,
|
|
1031
|
+
resetScroll,
|
|
1032
|
+
// element props
|
|
1033
|
+
style,
|
|
1034
|
+
className,
|
|
1035
|
+
onClick,
|
|
1036
|
+
onFocus,
|
|
1037
|
+
onMouseEnter,
|
|
1038
|
+
onMouseLeave,
|
|
1039
|
+
onTouchStart,
|
|
1040
|
+
...rest
|
|
1041
|
+
} = options;
|
|
1042
|
+
const linkInfo = buildLink({
|
|
1043
|
+
from: options.to ? match.pathname : undefined,
|
|
1044
|
+
...options
|
|
1045
|
+
});
|
|
1046
|
+
if (linkInfo.type === 'external') {
|
|
1047
|
+
const {
|
|
1048
|
+
href
|
|
1049
|
+
} = linkInfo;
|
|
1050
|
+
return {
|
|
1051
|
+
href
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
const {
|
|
1055
|
+
handleClick,
|
|
1056
|
+
handleFocus,
|
|
1057
|
+
handleEnter,
|
|
1058
|
+
handleLeave,
|
|
1059
|
+
handleTouchStart,
|
|
1060
|
+
isActive,
|
|
1061
|
+
next
|
|
1062
|
+
} = linkInfo;
|
|
1063
|
+
const composeHandlers = handlers => e => {
|
|
1064
|
+
if (e.persist) e.persist();
|
|
1065
|
+
handlers.filter(Boolean).forEach(handler => {
|
|
1066
|
+
if (e.defaultPrevented) return;
|
|
1067
|
+
handler(e);
|
|
1068
|
+
});
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
// Get the active props
|
|
1072
|
+
const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
|
|
1073
|
+
|
|
1074
|
+
// Get the inactive props
|
|
1075
|
+
const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
|
|
1076
|
+
return {
|
|
1077
|
+
...resolvedActiveProps,
|
|
1078
|
+
...resolvedInactiveProps,
|
|
1079
|
+
...rest,
|
|
1080
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
1081
|
+
onClick: composeHandlers([onClick, handleClick]),
|
|
1082
|
+
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
1083
|
+
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
1084
|
+
onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
|
|
1085
|
+
onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
|
|
1086
|
+
target,
|
|
1087
|
+
style: {
|
|
1088
|
+
...style,
|
|
1089
|
+
...resolvedActiveProps.style,
|
|
1090
|
+
...resolvedInactiveProps.style
|
|
1091
|
+
},
|
|
1092
|
+
className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
|
|
1093
|
+
...(disabled ? {
|
|
1094
|
+
role: 'link',
|
|
1095
|
+
'aria-disabled': true
|
|
1096
|
+
} : undefined),
|
|
1097
|
+
['data-status']: isActive ? 'active' : undefined
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
const Link = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1101
|
+
const linkProps = useLinkProps(props);
|
|
1102
|
+
return /*#__PURE__*/React.createElement("a", _extends({
|
|
1103
|
+
ref: ref
|
|
1104
|
+
}, linkProps, {
|
|
1105
|
+
children: typeof props.children === 'function' ? props.children({
|
|
1106
|
+
isActive: linkProps['data-status'] === 'active'
|
|
1107
|
+
}) : props.children
|
|
1108
|
+
}));
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1171
1111
|
// @ts-nocheck
|
|
1112
|
+
|
|
1172
1113
|
// qss has been slightly modified and inlined here for our use cases (and compression's sake). We've included it as a hard dependency for MIT license attribution.
|
|
1114
|
+
|
|
1173
1115
|
function encode(obj, pfx) {
|
|
1174
1116
|
var k,
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1117
|
+
i,
|
|
1118
|
+
tmp,
|
|
1119
|
+
str = '';
|
|
1179
1120
|
for (k in obj) {
|
|
1180
1121
|
if ((tmp = obj[k]) !== void 0) {
|
|
1181
1122
|
if (Array.isArray(tmp)) {
|
|
@@ -1189,1726 +1130,1410 @@ function encode(obj, pfx) {
|
|
|
1189
1130
|
}
|
|
1190
1131
|
}
|
|
1191
1132
|
}
|
|
1192
|
-
|
|
1193
1133
|
return (pfx || '') + str;
|
|
1194
1134
|
}
|
|
1195
|
-
|
|
1196
1135
|
function toValue(mix) {
|
|
1197
1136
|
if (!mix) return '';
|
|
1198
1137
|
var str = decodeURIComponent(mix);
|
|
1199
1138
|
if (str === 'false') return false;
|
|
1200
1139
|
if (str === 'true') return true;
|
|
1201
|
-
|
|
1202
|
-
return +str * 0 === 0 ? +str : str;
|
|
1140
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
1203
1141
|
}
|
|
1204
|
-
|
|
1205
1142
|
function decode(str) {
|
|
1206
1143
|
var tmp,
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1144
|
+
k,
|
|
1145
|
+
out = {},
|
|
1146
|
+
arr = str.split('&');
|
|
1211
1147
|
while (tmp = arr.shift()) {
|
|
1212
1148
|
tmp = tmp.split('=');
|
|
1213
1149
|
k = tmp.shift();
|
|
1214
|
-
|
|
1215
1150
|
if (out[k] !== void 0) {
|
|
1216
1151
|
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1217
1152
|
} else {
|
|
1218
1153
|
out[k] = toValue(tmp.shift());
|
|
1219
1154
|
}
|
|
1220
1155
|
}
|
|
1221
|
-
|
|
1222
1156
|
return out;
|
|
1223
1157
|
}
|
|
1224
1158
|
|
|
1225
|
-
|
|
1226
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
1227
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
1228
|
-
var source = arguments[i];
|
|
1229
|
-
|
|
1230
|
-
for (var key in source) {
|
|
1231
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1232
|
-
target[key] = source[key];
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
return target;
|
|
1238
|
-
};
|
|
1239
|
-
return _extends.apply(this, arguments);
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
function createRoute(routeConfig, options, parent, router) {
|
|
1243
|
-
const {
|
|
1244
|
-
id,
|
|
1245
|
-
routeId,
|
|
1246
|
-
path: routePath,
|
|
1247
|
-
fullPath
|
|
1248
|
-
} = routeConfig;
|
|
1249
|
-
|
|
1250
|
-
const action = router.state.actions[id] || (() => {
|
|
1251
|
-
router.state.actions[id] = {
|
|
1252
|
-
submissions: [],
|
|
1253
|
-
submit: async (submission, actionOpts) => {
|
|
1254
|
-
var _actionOpts$invalidat;
|
|
1255
|
-
|
|
1256
|
-
if (!route) {
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
|
|
1261
|
-
|
|
1262
|
-
if (!(actionOpts != null && actionOpts.multi)) {
|
|
1263
|
-
action.submissions = action.submissions.filter(d => d.isMulti);
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
const actionState = {
|
|
1267
|
-
submittedAt: Date.now(),
|
|
1268
|
-
status: 'pending',
|
|
1269
|
-
submission,
|
|
1270
|
-
isMulti: !!(actionOpts != null && actionOpts.multi)
|
|
1271
|
-
};
|
|
1272
|
-
action.current = actionState;
|
|
1273
|
-
action.latest = actionState;
|
|
1274
|
-
action.submissions.push(actionState);
|
|
1275
|
-
router.notify();
|
|
1276
|
-
|
|
1277
|
-
try {
|
|
1278
|
-
const res = await (route.options.action == null ? void 0 : route.options.action(submission));
|
|
1279
|
-
actionState.data = res;
|
|
1280
|
-
|
|
1281
|
-
if (invalidate) {
|
|
1282
|
-
router.invalidateRoute({
|
|
1283
|
-
to: '.',
|
|
1284
|
-
fromCurrent: true
|
|
1285
|
-
});
|
|
1286
|
-
await router.reload();
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
actionState.status = 'success';
|
|
1290
|
-
return res;
|
|
1291
|
-
} catch (err) {
|
|
1292
|
-
console.error(err);
|
|
1293
|
-
actionState.error = err;
|
|
1294
|
-
actionState.status = 'error';
|
|
1295
|
-
} finally {
|
|
1296
|
-
router.notify();
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
};
|
|
1300
|
-
return router.state.actions[id];
|
|
1301
|
-
})();
|
|
1302
|
-
|
|
1303
|
-
const loader = router.state.loaders[id] || (() => {
|
|
1304
|
-
router.state.loaders[id] = {
|
|
1305
|
-
pending: [],
|
|
1306
|
-
fetch: async loaderContext => {
|
|
1307
|
-
if (!route) {
|
|
1308
|
-
return;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
const loaderState = {
|
|
1312
|
-
loadedAt: Date.now(),
|
|
1313
|
-
loaderContext
|
|
1314
|
-
};
|
|
1315
|
-
loader.current = loaderState;
|
|
1316
|
-
loader.latest = loaderState;
|
|
1317
|
-
loader.pending.push(loaderState); // router.state = {
|
|
1318
|
-
// ...router.state,
|
|
1319
|
-
// currentAction: loaderState,
|
|
1320
|
-
// latestAction: loaderState,
|
|
1321
|
-
// }
|
|
1322
|
-
|
|
1323
|
-
router.notify();
|
|
1324
|
-
|
|
1325
|
-
try {
|
|
1326
|
-
return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
|
|
1327
|
-
} finally {
|
|
1328
|
-
loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
|
|
1329
|
-
|
|
1330
|
-
router.notify();
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
};
|
|
1334
|
-
return router.state.loaders[id];
|
|
1335
|
-
})();
|
|
1159
|
+
// Detect if we're in the DOM
|
|
1336
1160
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
routeRouteId: routeId,
|
|
1341
|
-
routePath,
|
|
1342
|
-
fullPath,
|
|
1343
|
-
options,
|
|
1344
|
-
router,
|
|
1345
|
-
childRoutes: undefined,
|
|
1346
|
-
parentRoute: parent,
|
|
1347
|
-
action,
|
|
1348
|
-
loader: loader,
|
|
1349
|
-
buildLink: options => {
|
|
1350
|
-
return router.buildLink(_extends({}, options, {
|
|
1351
|
-
from: fullPath
|
|
1352
|
-
}));
|
|
1353
|
-
},
|
|
1354
|
-
navigate: options => {
|
|
1355
|
-
return router.navigate(_extends({}, options, {
|
|
1356
|
-
from: fullPath
|
|
1357
|
-
}));
|
|
1358
|
-
},
|
|
1359
|
-
matchRoute: (matchLocation, opts) => {
|
|
1360
|
-
return router.matchRoute(_extends({}, matchLocation, {
|
|
1361
|
-
from: fullPath
|
|
1362
|
-
}), opts);
|
|
1363
|
-
}
|
|
1364
|
-
};
|
|
1365
|
-
router.options.createRoute == null ? void 0 : router.options.createRoute({
|
|
1366
|
-
router,
|
|
1367
|
-
route
|
|
1368
|
-
});
|
|
1369
|
-
return route;
|
|
1161
|
+
function redirect(opts) {
|
|
1162
|
+
opts.isRedirect = true;
|
|
1163
|
+
return opts;
|
|
1370
1164
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
|
|
1374
|
-
if (options === void 0) {
|
|
1375
|
-
options = {};
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
if (isRoot === void 0) {
|
|
1379
|
-
isRoot = true;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
if (isRoot) {
|
|
1383
|
-
options.path = rootRouteId;
|
|
1384
|
-
} // Strip the root from parentIds
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
if (parentId === rootRouteId) {
|
|
1388
|
-
parentId = '';
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
|
|
1392
|
-
|
|
1393
|
-
if (path && path !== '/') {
|
|
1394
|
-
path = trimPath(path);
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
const routeId = path || options.id;
|
|
1398
|
-
let id = joinPaths([parentId, routeId]);
|
|
1399
|
-
|
|
1400
|
-
if (path === rootRouteId) {
|
|
1401
|
-
path = '/';
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
if (id !== rootRouteId) {
|
|
1405
|
-
id = joinPaths(['/', id]);
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
|
|
1409
|
-
return {
|
|
1410
|
-
id: id,
|
|
1411
|
-
routeId: routeId,
|
|
1412
|
-
path: path,
|
|
1413
|
-
fullPath: fullPath,
|
|
1414
|
-
options: options,
|
|
1415
|
-
children,
|
|
1416
|
-
createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
|
|
1417
|
-
addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
|
|
1418
|
-
createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
|
|
1419
|
-
};
|
|
1420
|
-
};
|
|
1421
|
-
|
|
1422
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1423
|
-
function createRouteMatch(router, route, opts) {
|
|
1424
|
-
const routeMatch = _extends({}, route, opts, {
|
|
1425
|
-
router,
|
|
1426
|
-
routeSearch: {},
|
|
1427
|
-
search: {},
|
|
1428
|
-
childMatches: [],
|
|
1429
|
-
status: 'idle',
|
|
1430
|
-
routeLoaderData: {},
|
|
1431
|
-
loaderData: {},
|
|
1432
|
-
isFetching: false,
|
|
1433
|
-
isInvalid: false,
|
|
1434
|
-
invalidAt: Infinity,
|
|
1435
|
-
// pendingActions: [],
|
|
1436
|
-
getIsInvalid: () => {
|
|
1437
|
-
const now = Date.now();
|
|
1438
|
-
return routeMatch.isInvalid || routeMatch.invalidAt < now;
|
|
1439
|
-
},
|
|
1440
|
-
__: {
|
|
1441
|
-
abortController: new AbortController(),
|
|
1442
|
-
latestId: '',
|
|
1443
|
-
resolve: () => {},
|
|
1444
|
-
notify: () => {
|
|
1445
|
-
routeMatch.__.resolve();
|
|
1446
|
-
|
|
1447
|
-
routeMatch.router.notify();
|
|
1448
|
-
},
|
|
1449
|
-
validate: () => {
|
|
1450
|
-
var _routeMatch$parentMat, _routeMatch$parentMat2;
|
|
1451
|
-
|
|
1452
|
-
// Validate the search params and stabilize them
|
|
1453
|
-
const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
|
|
1454
|
-
|
|
1455
|
-
try {
|
|
1456
|
-
var _validator;
|
|
1457
|
-
|
|
1458
|
-
const prevSearch = routeMatch.routeSearch;
|
|
1459
|
-
const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
|
|
1460
|
-
let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {}); // Invalidate route matches when search param stability changes
|
|
1461
|
-
|
|
1462
|
-
if (prevSearch !== nextSearch) {
|
|
1463
|
-
routeMatch.isInvalid = true;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
routeMatch.routeSearch = nextSearch;
|
|
1467
|
-
routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
|
|
1468
|
-
componentTypes.map(async type => {
|
|
1469
|
-
const component = routeMatch.options[type];
|
|
1470
|
-
|
|
1471
|
-
if (typeof routeMatch.__[type] !== 'function') {
|
|
1472
|
-
routeMatch.__[type] = component;
|
|
1473
|
-
}
|
|
1474
|
-
});
|
|
1475
|
-
} catch (err) {
|
|
1476
|
-
console.error(err);
|
|
1477
|
-
const error = new Error('Invalid search params found', {
|
|
1478
|
-
cause: err
|
|
1479
|
-
});
|
|
1480
|
-
error.code = 'INVALID_SEARCH_PARAMS';
|
|
1481
|
-
routeMatch.status = 'error';
|
|
1482
|
-
routeMatch.error = error; // Do not proceed with loading the route
|
|
1483
|
-
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
},
|
|
1488
|
-
cancel: () => {
|
|
1489
|
-
var _routeMatch$__$abortC;
|
|
1490
|
-
|
|
1491
|
-
(_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
|
|
1492
|
-
},
|
|
1493
|
-
invalidate: () => {
|
|
1494
|
-
routeMatch.isInvalid = true;
|
|
1495
|
-
},
|
|
1496
|
-
hasLoaders: () => {
|
|
1497
|
-
return !!(route.options.loader || componentTypes.some(d => {
|
|
1498
|
-
var _route$options$d;
|
|
1499
|
-
|
|
1500
|
-
return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
|
|
1501
|
-
}));
|
|
1502
|
-
},
|
|
1503
|
-
load: async loaderOpts => {
|
|
1504
|
-
const now = Date.now();
|
|
1505
|
-
const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
|
|
1506
|
-
|
|
1507
|
-
if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
|
|
1508
|
-
// If the match is currently active, don't preload it
|
|
1509
|
-
if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
|
|
1510
|
-
return;
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
|
-
router.matchCache[routeMatch.matchId] = {
|
|
1514
|
-
gc: now + loaderOpts.gcMaxAge,
|
|
1515
|
-
match: routeMatch
|
|
1516
|
-
};
|
|
1517
|
-
} // If the match is invalid, errored or idle, trigger it to load
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
|
|
1521
|
-
const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
|
|
1522
|
-
await routeMatch.fetch({
|
|
1523
|
-
maxAge
|
|
1524
|
-
});
|
|
1525
|
-
}
|
|
1526
|
-
},
|
|
1527
|
-
fetch: async opts => {
|
|
1528
|
-
const loadId = '' + Date.now() + Math.random();
|
|
1529
|
-
routeMatch.__.latestId = loadId;
|
|
1530
|
-
|
|
1531
|
-
const checkLatest = async () => {
|
|
1532
|
-
if (loadId !== routeMatch.__.latestId) {
|
|
1533
|
-
// warning(true, 'Data loader is out of date!')
|
|
1534
|
-
return new Promise(() => {});
|
|
1535
|
-
}
|
|
1536
|
-
}; // If the match was in an error state, set it
|
|
1537
|
-
// to a loading state again. Otherwise, keep it
|
|
1538
|
-
// as loading or resolved
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if (routeMatch.status === 'idle') {
|
|
1542
|
-
routeMatch.status = 'loading';
|
|
1543
|
-
} // We started loading the route, so it's no longer invalid
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
routeMatch.isInvalid = false;
|
|
1547
|
-
routeMatch.__.loadPromise = new Promise(async resolve => {
|
|
1548
|
-
// We are now fetching, even if it's in the background of a
|
|
1549
|
-
// resolved state
|
|
1550
|
-
routeMatch.isFetching = true;
|
|
1551
|
-
routeMatch.__.resolve = resolve;
|
|
1552
|
-
|
|
1553
|
-
routeMatch.__.componentsPromise = (async () => {
|
|
1554
|
-
// then run all component and data loaders in parallel
|
|
1555
|
-
// For each component type, potentially load it asynchronously
|
|
1556
|
-
await Promise.all(componentTypes.map(async type => {
|
|
1557
|
-
var _routeMatch$__$type;
|
|
1558
|
-
|
|
1559
|
-
const component = routeMatch.options[type];
|
|
1560
|
-
|
|
1561
|
-
if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
|
|
1562
|
-
routeMatch.__[type] = await router.options.loadComponent(component);
|
|
1563
|
-
}
|
|
1564
|
-
}));
|
|
1565
|
-
})();
|
|
1566
|
-
|
|
1567
|
-
routeMatch.__.dataPromise = Promise.resolve().then(async () => {
|
|
1568
|
-
try {
|
|
1569
|
-
var _ref, _ref2, _opts$maxAge;
|
|
1570
|
-
|
|
1571
|
-
if (routeMatch.options.loader) {
|
|
1572
|
-
const data = await router.loadMatchData(routeMatch);
|
|
1573
|
-
await checkLatest();
|
|
1574
|
-
routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
routeMatch.error = undefined;
|
|
1578
|
-
routeMatch.status = 'success';
|
|
1579
|
-
routeMatch.updatedAt = Date.now();
|
|
1580
|
-
routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
|
|
1581
|
-
return routeMatch.routeLoaderData;
|
|
1582
|
-
} catch (err) {
|
|
1583
|
-
await checkLatest();
|
|
1584
|
-
|
|
1585
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
1586
|
-
console.error(err);
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
routeMatch.error = err;
|
|
1590
|
-
routeMatch.status = 'error';
|
|
1591
|
-
routeMatch.updatedAt = Date.now();
|
|
1592
|
-
throw err;
|
|
1593
|
-
}
|
|
1594
|
-
});
|
|
1595
|
-
|
|
1596
|
-
const after = async () => {
|
|
1597
|
-
await checkLatest();
|
|
1598
|
-
routeMatch.isFetching = false;
|
|
1599
|
-
delete routeMatch.__.loadPromise;
|
|
1600
|
-
|
|
1601
|
-
routeMatch.__.notify();
|
|
1602
|
-
};
|
|
1603
|
-
|
|
1604
|
-
try {
|
|
1605
|
-
await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise.catch(() => {})]);
|
|
1606
|
-
after();
|
|
1607
|
-
} catch (_unused) {
|
|
1608
|
-
after();
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
await routeMatch.__.loadPromise;
|
|
1612
|
-
await checkLatest();
|
|
1613
|
-
}
|
|
1614
|
-
});
|
|
1615
|
-
|
|
1616
|
-
if (!routeMatch.hasLoaders()) {
|
|
1617
|
-
routeMatch.status = 'success';
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
return routeMatch;
|
|
1165
|
+
function isRedirect(obj) {
|
|
1166
|
+
return !!obj?.isRedirect;
|
|
1621
1167
|
}
|
|
1622
1168
|
|
|
1623
1169
|
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1624
|
-
const defaultStringifySearch = stringifySearchWith(JSON.stringify);
|
|
1170
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
1625
1171
|
function parseSearchWith(parser) {
|
|
1626
1172
|
return searchStr => {
|
|
1627
1173
|
if (searchStr.substring(0, 1) === '?') {
|
|
1628
1174
|
searchStr = searchStr.substring(1);
|
|
1629
1175
|
}
|
|
1176
|
+
let query = decode(searchStr);
|
|
1630
1177
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1178
|
+
// Try to parse any query params that might be json
|
|
1633
1179
|
for (let key in query) {
|
|
1634
1180
|
const value = query[key];
|
|
1635
|
-
|
|
1636
1181
|
if (typeof value === 'string') {
|
|
1637
1182
|
try {
|
|
1638
1183
|
query[key] = parser(value);
|
|
1639
|
-
} catch (err) {
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
//
|
|
1640
1186
|
}
|
|
1641
1187
|
}
|
|
1642
1188
|
}
|
|
1643
|
-
|
|
1644
1189
|
return query;
|
|
1645
1190
|
};
|
|
1646
1191
|
}
|
|
1647
|
-
function stringifySearchWith(stringify) {
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
if (search) {
|
|
1652
|
-
Object.keys(search).forEach(key => {
|
|
1653
|
-
const val = search[key];
|
|
1654
|
-
|
|
1655
|
-
if (typeof val === 'undefined' || val === undefined) {
|
|
1656
|
-
delete search[key];
|
|
1657
|
-
} else if (val && typeof val === 'object' && val !== null) {
|
|
1658
|
-
try {
|
|
1659
|
-
search[key] = stringify(val);
|
|
1660
|
-
} catch (err) {// silent
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
});
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
const searchStr = encode(search).toString();
|
|
1667
|
-
return searchStr ? "?" + searchStr : '';
|
|
1668
|
-
};
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
var _window$document;
|
|
1672
|
-
// Detect if we're in the DOM
|
|
1673
|
-
const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
|
|
1674
|
-
|
|
1675
|
-
const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
|
|
1676
|
-
|
|
1677
|
-
function getInitialRouterState() {
|
|
1678
|
-
return {
|
|
1679
|
-
status: 'idle',
|
|
1680
|
-
location: null,
|
|
1681
|
-
matches: [],
|
|
1682
|
-
actions: {},
|
|
1683
|
-
loaders: {},
|
|
1684
|
-
lastUpdated: Date.now(),
|
|
1685
|
-
isFetching: false,
|
|
1686
|
-
isPreloading: false
|
|
1687
|
-
};
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
function createRouter(userOptions) {
|
|
1691
|
-
var _userOptions$stringif, _userOptions$parseSea;
|
|
1692
|
-
|
|
1693
|
-
const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
|
|
1694
|
-
|
|
1695
|
-
const originalOptions = _extends({
|
|
1696
|
-
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
1697
|
-
defaultLoaderMaxAge: 0,
|
|
1698
|
-
defaultPreloadMaxAge: 2000,
|
|
1699
|
-
defaultPreloadDelay: 50
|
|
1700
|
-
}, userOptions, {
|
|
1701
|
-
stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
|
|
1702
|
-
parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
let router = {
|
|
1706
|
-
types: undefined,
|
|
1707
|
-
// public api
|
|
1708
|
-
history,
|
|
1709
|
-
options: originalOptions,
|
|
1710
|
-
listeners: [],
|
|
1711
|
-
// Resolved after construction
|
|
1712
|
-
context: {},
|
|
1713
|
-
basepath: '',
|
|
1714
|
-
routeTree: undefined,
|
|
1715
|
-
routesById: {},
|
|
1716
|
-
location: undefined,
|
|
1717
|
-
//
|
|
1718
|
-
navigationPromise: Promise.resolve(),
|
|
1719
|
-
resolveNavigation: () => {},
|
|
1720
|
-
matchCache: {},
|
|
1721
|
-
state: getInitialRouterState(),
|
|
1722
|
-
reset: () => {
|
|
1723
|
-
router.state = getInitialRouterState();
|
|
1724
|
-
router.notify();
|
|
1725
|
-
},
|
|
1726
|
-
startedLoadingAt: Date.now(),
|
|
1727
|
-
subscribe: listener => {
|
|
1728
|
-
router.listeners.push(listener);
|
|
1729
|
-
return () => {
|
|
1730
|
-
router.listeners = router.listeners.filter(x => x !== listener);
|
|
1731
|
-
};
|
|
1732
|
-
},
|
|
1733
|
-
getRoute: id => {
|
|
1734
|
-
return router.routesById[id];
|
|
1735
|
-
},
|
|
1736
|
-
notify: () => {
|
|
1737
|
-
const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
|
|
1738
|
-
const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
|
|
1739
|
-
|
|
1740
|
-
if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
|
|
1741
|
-
router.state = _extends({}, router.state, {
|
|
1742
|
-
isFetching,
|
|
1743
|
-
isPreloading
|
|
1744
|
-
});
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
cascadeLoaderData(router.state.matches);
|
|
1748
|
-
router.listeners.forEach(listener => listener(router));
|
|
1749
|
-
},
|
|
1750
|
-
dehydrateState: () => {
|
|
1751
|
-
return _extends({}, pick(router.state, ['status', 'location', 'lastUpdated']), {
|
|
1752
|
-
matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
|
|
1753
|
-
});
|
|
1754
|
-
},
|
|
1755
|
-
hydrateState: dehydratedState => {
|
|
1756
|
-
// Match the routes
|
|
1757
|
-
const matches = router.matchRoutes(router.location.pathname, {
|
|
1758
|
-
strictParseParams: true
|
|
1759
|
-
});
|
|
1760
|
-
matches.forEach((match, index) => {
|
|
1761
|
-
const dehydratedMatch = dehydratedState.matches[index];
|
|
1762
|
-
invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
|
|
1763
|
-
Object.assign(match, dehydratedMatch);
|
|
1764
|
-
});
|
|
1765
|
-
matches.forEach(match => match.__.validate());
|
|
1766
|
-
router.state = _extends({}, router.state, dehydratedState, {
|
|
1767
|
-
matches
|
|
1768
|
-
});
|
|
1769
|
-
},
|
|
1770
|
-
mount: () => {
|
|
1771
|
-
const next = router.__.buildLocation({
|
|
1772
|
-
to: '.',
|
|
1773
|
-
search: true,
|
|
1774
|
-
hash: true
|
|
1775
|
-
}); // If the current location isn't updated, trigger a navigation
|
|
1776
|
-
// to the current location. Otherwise, load the current location.
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
if (next.href !== router.location.href) {
|
|
1780
|
-
router.__.commitLocation(next, true);
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
if (!router.state.matches.length) {
|
|
1784
|
-
router.load();
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
const unsub = router.history.listen(event => {
|
|
1788
|
-
router.load(router.__.parseLocation(event.location, router.location));
|
|
1789
|
-
}); // addEventListener does not exist in React Native, but window does
|
|
1790
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1791
|
-
|
|
1792
|
-
if (!isServer && window.addEventListener) {
|
|
1793
|
-
// Listen to visibillitychange and focus
|
|
1794
|
-
window.addEventListener('visibilitychange', router.onFocus, false);
|
|
1795
|
-
window.addEventListener('focus', router.onFocus, false);
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
return () => {
|
|
1799
|
-
unsub();
|
|
1800
|
-
|
|
1801
|
-
if (!isServer && window.removeEventListener) {
|
|
1802
|
-
// Be sure to unsubscribe if a new handler is set
|
|
1803
|
-
window.removeEventListener('visibilitychange', router.onFocus);
|
|
1804
|
-
window.removeEventListener('focus', router.onFocus);
|
|
1805
|
-
}
|
|
1806
|
-
};
|
|
1807
|
-
},
|
|
1808
|
-
onFocus: () => {
|
|
1809
|
-
router.load();
|
|
1810
|
-
},
|
|
1811
|
-
update: opts => {
|
|
1812
|
-
const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
|
|
1813
|
-
|
|
1814
|
-
if (!router.location || newHistory) {
|
|
1815
|
-
if (opts != null && opts.history) {
|
|
1816
|
-
router.history = opts.history;
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
|
-
router.location = router.__.parseLocation(router.history.location);
|
|
1820
|
-
router.state.location = router.location;
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
Object.assign(router.options, opts);
|
|
1824
|
-
const {
|
|
1825
|
-
basepath,
|
|
1826
|
-
routeConfig
|
|
1827
|
-
} = router.options;
|
|
1828
|
-
router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
|
|
1829
|
-
|
|
1830
|
-
if (routeConfig) {
|
|
1831
|
-
router.routesById = {};
|
|
1832
|
-
router.routeTree = router.__.buildRouteTree(routeConfig);
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
return router;
|
|
1836
|
-
},
|
|
1837
|
-
cancelMatches: () => {
|
|
1838
|
-
var _router$state$pending, _router$state$pending2;
|
|
1839
|
-
[...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
|
|
1840
|
-
match.cancel();
|
|
1841
|
-
});
|
|
1842
|
-
},
|
|
1843
|
-
load: async next => {
|
|
1844
|
-
const id = Math.random();
|
|
1845
|
-
router.startedLoadingAt = id;
|
|
1846
|
-
|
|
1847
|
-
if (next) {
|
|
1848
|
-
// Ingest the new location
|
|
1849
|
-
router.location = next;
|
|
1850
|
-
} // Cancel any pending matches
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
router.cancelMatches(); // Match the routes
|
|
1854
|
-
|
|
1855
|
-
const matches = router.matchRoutes(router.location.pathname, {
|
|
1856
|
-
strictParseParams: true
|
|
1857
|
-
}); // Check if each match middleware to see if the route can be accessed
|
|
1858
|
-
|
|
1192
|
+
function stringifySearchWith(stringify, parser) {
|
|
1193
|
+
function stringifyValue(val) {
|
|
1194
|
+
if (typeof val === 'object' && val !== null) {
|
|
1859
1195
|
try {
|
|
1860
|
-
|
|
1861
|
-
context: router.context
|
|
1862
|
-
})));
|
|
1196
|
+
return stringify(val);
|
|
1863
1197
|
} catch (err) {
|
|
1864
|
-
|
|
1865
|
-
await new Promise(() => {});
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
throw err;
|
|
1869
|
-
}
|
|
1870
|
-
|
|
1871
|
-
if (typeof document !== 'undefined') {
|
|
1872
|
-
router.state = _extends({}, router.state, {
|
|
1873
|
-
pending: {
|
|
1874
|
-
matches: matches,
|
|
1875
|
-
location: router.location
|
|
1876
|
-
},
|
|
1877
|
-
status: 'loading'
|
|
1878
|
-
});
|
|
1879
|
-
} else {
|
|
1880
|
-
router.state = _extends({}, router.state, {
|
|
1881
|
-
matches: matches,
|
|
1882
|
-
location: router.location,
|
|
1883
|
-
status: 'loading'
|
|
1884
|
-
});
|
|
1198
|
+
// silent
|
|
1885
1199
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1200
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
1201
|
+
try {
|
|
1202
|
+
// Check if it's a valid parseable string.
|
|
1203
|
+
// If it is, then stringify it again.
|
|
1204
|
+
parser(val);
|
|
1205
|
+
return stringify(val);
|
|
1206
|
+
} catch (err) {
|
|
1207
|
+
// silent
|
|
1894
1208
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1209
|
+
}
|
|
1210
|
+
return val;
|
|
1211
|
+
}
|
|
1212
|
+
return search => {
|
|
1213
|
+
search = {
|
|
1214
|
+
...search
|
|
1215
|
+
};
|
|
1216
|
+
if (search) {
|
|
1217
|
+
Object.keys(search).forEach(key => {
|
|
1218
|
+
const val = search[key];
|
|
1219
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
1220
|
+
delete search[key];
|
|
1902
1221
|
} else {
|
|
1903
|
-
|
|
1222
|
+
search[key] = stringifyValue(val);
|
|
1904
1223
|
}
|
|
1905
1224
|
});
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
|
|
1912
|
-
|
|
1913
|
-
d.__.onExit == null ? void 0 : d.__.onExit({
|
|
1914
|
-
params: d.params,
|
|
1915
|
-
search: d.routeSearch
|
|
1916
|
-
}); // Clear idle error states when match leaves
|
|
1917
|
-
|
|
1918
|
-
if (d.status === 'error' && !d.isFetching) {
|
|
1919
|
-
d.status = 'idle';
|
|
1920
|
-
d.error = undefined;
|
|
1921
|
-
}
|
|
1225
|
+
}
|
|
1226
|
+
const searchStr = encode(search).toString();
|
|
1227
|
+
return searchStr ? `?${searchStr}` : '';
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1922
1230
|
|
|
1923
|
-
|
|
1231
|
+
// import warning from 'tiny-warning'
|
|
1924
1232
|
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1233
|
+
//
|
|
1234
|
+
|
|
1235
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1236
|
+
const preloadWarning = 'Error preloading route! ☝️';
|
|
1237
|
+
class Router {
|
|
1238
|
+
// Option-independent properties
|
|
1239
|
+
tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
|
|
1240
|
+
resetNextScroll = true;
|
|
1241
|
+
navigateTimeout = null;
|
|
1242
|
+
latestLoadPromise = Promise.resolve();
|
|
1243
|
+
subscribers = new Set();
|
|
1244
|
+
pendingMatches = [];
|
|
1245
|
+
injectedHtml = [];
|
|
1246
|
+
|
|
1247
|
+
// Must build in constructor
|
|
1248
|
+
|
|
1249
|
+
constructor(options) {
|
|
1250
|
+
this.update({
|
|
1251
|
+
defaultPreloadDelay: 50,
|
|
1252
|
+
defaultPendingMs: 1000,
|
|
1253
|
+
defaultPendingMinMs: 500,
|
|
1254
|
+
context: undefined,
|
|
1255
|
+
...options,
|
|
1256
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
1257
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// These are default implementations that can optionally be overridden
|
|
1262
|
+
// by the router provider once rendered. We provide these so that the
|
|
1263
|
+
// router can be used in a non-react environment if necessary
|
|
1264
|
+
startReactTransition = fn => fn();
|
|
1265
|
+
update = newOptions => {
|
|
1266
|
+
this.options = {
|
|
1267
|
+
...this.options,
|
|
1268
|
+
...newOptions
|
|
1269
|
+
};
|
|
1270
|
+
this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
|
|
1271
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
1272
|
+
this.history = this.options.history ?? (typeof document !== 'undefined' ? createBrowserHistory() : createMemoryHistory());
|
|
1273
|
+
this.latestLocation = this.parseLocation();
|
|
1274
|
+
}
|
|
1275
|
+
if (this.options.routeTree !== this.routeTree) {
|
|
1276
|
+
this.routeTree = this.options.routeTree;
|
|
1277
|
+
this.buildRouteTree();
|
|
1278
|
+
}
|
|
1279
|
+
if (!this.__store) {
|
|
1280
|
+
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
1281
|
+
onUpdate: () => {
|
|
1282
|
+
this.__store.state = {
|
|
1283
|
+
...this.state,
|
|
1284
|
+
status: this.state.isTransitioning || this.state.isLoading ? 'pending' : 'idle'
|
|
1929
1285
|
};
|
|
1930
1286
|
}
|
|
1931
1287
|
});
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
get state() {
|
|
1291
|
+
return this.__store.state;
|
|
1292
|
+
}
|
|
1293
|
+
buildRouteTree = () => {
|
|
1294
|
+
this.routesById = {};
|
|
1295
|
+
this.routesByPath = {};
|
|
1296
|
+
const recurseRoutes = childRoutes => {
|
|
1297
|
+
childRoutes.forEach((childRoute, i) => {
|
|
1298
|
+
// if (typeof childRoute === 'function') {
|
|
1299
|
+
// childRoute = (childRoute as any)()
|
|
1300
|
+
// }
|
|
1301
|
+
childRoute.init({
|
|
1302
|
+
originalIndex: i
|
|
1942
1303
|
});
|
|
1943
|
-
|
|
1304
|
+
const existingRoute = this.routesById[childRoute.id];
|
|
1305
|
+
invariant(!existingRoute, `Duplicate routes found with id: ${String(childRoute.id)}`);
|
|
1306
|
+
this.routesById[childRoute.id] = childRoute;
|
|
1307
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
1308
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
1309
|
+
if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith('/')) {
|
|
1310
|
+
this.routesByPath[trimmedFullPath] = childRoute;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
const children = childRoute.children;
|
|
1314
|
+
if (children?.length) {
|
|
1315
|
+
recurseRoutes(children);
|
|
1316
|
+
}
|
|
1944
1317
|
});
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1318
|
+
};
|
|
1319
|
+
recurseRoutes([this.routeTree]);
|
|
1320
|
+
this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
|
|
1321
|
+
const trimmed = trimPath(d.fullPath);
|
|
1322
|
+
const parsed = parsePathname(trimmed);
|
|
1323
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1324
|
+
parsed.shift();
|
|
1949
1325
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
if (match.action) {
|
|
1954
|
-
match.action.current = undefined;
|
|
1955
|
-
match.action.submissions = [];
|
|
1326
|
+
const score = parsed.map(d => {
|
|
1327
|
+
if (d.type === 'param') {
|
|
1328
|
+
return 0.5;
|
|
1956
1329
|
}
|
|
1330
|
+
if (d.type === 'wildcard') {
|
|
1331
|
+
return 0.25;
|
|
1332
|
+
}
|
|
1333
|
+
return 1;
|
|
1957
1334
|
});
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
const
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
} // Do not remove successful matches that are still valid
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
if (entry.gc > 0 && entry.gc > now) {
|
|
1978
|
-
return;
|
|
1979
|
-
} // Everything else gets removed
|
|
1980
|
-
|
|
1335
|
+
return {
|
|
1336
|
+
child: d,
|
|
1337
|
+
trimmed,
|
|
1338
|
+
parsed,
|
|
1339
|
+
index: i,
|
|
1340
|
+
score
|
|
1341
|
+
};
|
|
1342
|
+
}).sort((a, b) => {
|
|
1343
|
+
let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
|
|
1344
|
+
if (isIndex !== 0) return isIndex;
|
|
1345
|
+
const length = Math.min(a.score.length, b.score.length);
|
|
1346
|
+
|
|
1347
|
+
// Sort by length of score
|
|
1348
|
+
if (a.score.length !== b.score.length) {
|
|
1349
|
+
return b.score.length - a.score.length;
|
|
1350
|
+
}
|
|
1981
1351
|
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
navigateOpts = router.location;
|
|
1352
|
+
// Sort by min available score
|
|
1353
|
+
for (let i = 0; i < length; i++) {
|
|
1354
|
+
if (a.score[i] !== b.score[i]) {
|
|
1355
|
+
return b.score[i] - a.score[i];
|
|
1356
|
+
}
|
|
1988
1357
|
}
|
|
1989
1358
|
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
},
|
|
1997
|
-
preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
|
|
1998
|
-
var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
|
|
1359
|
+
// Sort by min available parsed value
|
|
1360
|
+
for (let i = 0; i < length; i++) {
|
|
1361
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
1362
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1999
1365
|
|
|
2000
|
-
|
|
2001
|
-
|
|
1366
|
+
// Sort by length of trimmed full path
|
|
1367
|
+
if (a.trimmed !== b.trimmed) {
|
|
1368
|
+
return a.trimmed > b.trimmed ? 1 : -1;
|
|
2002
1369
|
}
|
|
2003
1370
|
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
1371
|
+
// Sort by original index
|
|
1372
|
+
return a.index - b.index;
|
|
1373
|
+
}).map((d, i) => {
|
|
1374
|
+
d.child.rank = i;
|
|
1375
|
+
return d.child;
|
|
1376
|
+
});
|
|
1377
|
+
};
|
|
1378
|
+
subscribe = (eventType, fn) => {
|
|
1379
|
+
const listener = {
|
|
1380
|
+
eventType,
|
|
1381
|
+
fn
|
|
1382
|
+
};
|
|
1383
|
+
this.subscribers.add(listener);
|
|
1384
|
+
return () => {
|
|
1385
|
+
this.subscribers.delete(listener);
|
|
1386
|
+
};
|
|
1387
|
+
};
|
|
1388
|
+
emit = routerEvent => {
|
|
1389
|
+
this.subscribers.forEach(listener => {
|
|
1390
|
+
if (listener.eventType === routerEvent.type) {
|
|
1391
|
+
listener.fn(routerEvent);
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
};
|
|
1395
|
+
checkLatest = promise => {
|
|
1396
|
+
return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
|
|
1397
|
+
};
|
|
1398
|
+
parseLocation = previousLocation => {
|
|
1399
|
+
const parse = ({
|
|
1400
|
+
pathname,
|
|
1401
|
+
search,
|
|
1402
|
+
hash,
|
|
1403
|
+
state
|
|
1404
|
+
}) => {
|
|
1405
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1406
|
+
return {
|
|
1407
|
+
pathname: pathname,
|
|
1408
|
+
searchStr: search,
|
|
1409
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1410
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1411
|
+
href: `${pathname}${search}${hash}`,
|
|
1412
|
+
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1413
|
+
};
|
|
1414
|
+
};
|
|
1415
|
+
const location = parse(this.history.location);
|
|
1416
|
+
let {
|
|
1417
|
+
__tempLocation,
|
|
1418
|
+
__tempKey
|
|
1419
|
+
} = location.state;
|
|
1420
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
1421
|
+
// Sync up the location keys
|
|
1422
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
1423
|
+
parsedTempLocation.state.key = location.state.key;
|
|
1424
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
1425
|
+
return {
|
|
1426
|
+
...parsedTempLocation,
|
|
1427
|
+
maskedLocation: location
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
return location;
|
|
1431
|
+
};
|
|
1432
|
+
resolvePathWithBase = (from, path) => {
|
|
1433
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1434
|
+
};
|
|
1435
|
+
get looseRoutesById() {
|
|
1436
|
+
return this.routesById;
|
|
1437
|
+
}
|
|
1438
|
+
matchRoutes = (pathname, locationSearch, opts) => {
|
|
1439
|
+
let routeParams = {};
|
|
1440
|
+
let foundRoute = this.flatRoutes.find(route => {
|
|
1441
|
+
const matchedParams = matchPathname(this.basepath, trimPathRight(pathname), {
|
|
1442
|
+
to: route.fullPath,
|
|
1443
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
|
|
1444
|
+
fuzzy: false
|
|
2012
1445
|
});
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
var _router$state$pending3, _router$state$pending4;
|
|
2017
|
-
|
|
2018
|
-
router.cleanMatchCache();
|
|
2019
|
-
const matches = [];
|
|
2020
|
-
|
|
2021
|
-
if (!router.routeTree) {
|
|
2022
|
-
return matches;
|
|
1446
|
+
if (matchedParams) {
|
|
1447
|
+
routeParams = matchedParams;
|
|
1448
|
+
return true;
|
|
2023
1449
|
}
|
|
1450
|
+
return false;
|
|
1451
|
+
});
|
|
1452
|
+
let routeCursor = foundRoute || this.routesById['__root__'];
|
|
1453
|
+
let matchedRoutes = [routeCursor];
|
|
1454
|
+
// let includingLayouts = true
|
|
1455
|
+
while (routeCursor?.parentRoute) {
|
|
1456
|
+
routeCursor = routeCursor.parentRoute;
|
|
1457
|
+
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1458
|
+
}
|
|
2024
1459
|
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
const recurse = async routes => {
|
|
2028
|
-
var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
|
|
2029
|
-
|
|
2030
|
-
const parentMatch = last(matches);
|
|
2031
|
-
let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
|
|
2032
|
-
const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
|
|
2033
|
-
let foundRoutes = [];
|
|
2034
|
-
|
|
2035
|
-
const findMatchInRoutes = (parentRoutes, routes) => {
|
|
2036
|
-
routes.some(route => {
|
|
2037
|
-
var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
|
|
2038
|
-
|
|
2039
|
-
if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
|
|
2040
|
-
return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
|
|
2044
|
-
const matchParams = matchPathname(pathname, {
|
|
2045
|
-
to: route.fullPath,
|
|
2046
|
-
fuzzy,
|
|
2047
|
-
caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
|
|
2048
|
-
});
|
|
2049
|
-
|
|
2050
|
-
if (matchParams) {
|
|
2051
|
-
let parsedParams;
|
|
2052
|
-
|
|
2053
|
-
try {
|
|
2054
|
-
var _route$options$parseP;
|
|
2055
|
-
|
|
2056
|
-
parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
|
|
2057
|
-
} catch (err) {
|
|
2058
|
-
if (opts != null && opts.strictParseParams) {
|
|
2059
|
-
throw err;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
params = _extends({}, params, parsedParams);
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
|
-
if (!!matchParams) {
|
|
2067
|
-
foundRoutes = [...parentRoutes, route];
|
|
2068
|
-
}
|
|
1460
|
+
// Existing matches are matches that are already loaded along with
|
|
1461
|
+
// pending matches that are still loading
|
|
2069
1462
|
|
|
2070
|
-
|
|
1463
|
+
const parseErrors = matchedRoutes.map(route => {
|
|
1464
|
+
let parsedParamsError;
|
|
1465
|
+
if (route.options.parseParams) {
|
|
1466
|
+
try {
|
|
1467
|
+
const parsedParams = route.options.parseParams(routeParams);
|
|
1468
|
+
// Add the parsed params to the accumulated params bag
|
|
1469
|
+
Object.assign(routeParams, parsedParams);
|
|
1470
|
+
} catch (err) {
|
|
1471
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1472
|
+
cause: err
|
|
2071
1473
|
});
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
if (!foundRoutes.length) {
|
|
2078
|
-
return;
|
|
1474
|
+
if (opts?.throwOnError) {
|
|
1475
|
+
throw parsedParamsError;
|
|
1476
|
+
}
|
|
1477
|
+
return parsedParamsError;
|
|
2079
1478
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
1479
|
+
}
|
|
1480
|
+
return;
|
|
1481
|
+
});
|
|
1482
|
+
const matches = [];
|
|
1483
|
+
matchedRoutes.forEach((route, index) => {
|
|
1484
|
+
// Take each matched route and resolve + validate its search params
|
|
1485
|
+
// This has to happen serially because each route's search params
|
|
1486
|
+
// can depend on the parent route's search params
|
|
1487
|
+
// It must also happen before we create the match so that we can
|
|
1488
|
+
// pass the search params to the route's potential key function
|
|
1489
|
+
// which is used to uniquely identify the route match in state
|
|
1490
|
+
|
|
1491
|
+
const parentMatch = matches[index - 1];
|
|
1492
|
+
const [preMatchSearch, searchError] = (() => {
|
|
1493
|
+
// Validate the search params and stabilize them
|
|
1494
|
+
const parentSearch = parentMatch?.search ?? locationSearch;
|
|
1495
|
+
try {
|
|
1496
|
+
const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
|
|
1497
|
+
let search = validator?.(parentSearch) ?? {};
|
|
1498
|
+
return [{
|
|
1499
|
+
...parentSearch,
|
|
1500
|
+
...search
|
|
1501
|
+
}, undefined];
|
|
1502
|
+
} catch (err) {
|
|
1503
|
+
const searchError = new SearchParamError(err.message, {
|
|
1504
|
+
cause: err
|
|
2091
1505
|
});
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
|
|
2097
|
-
recurse(foundRoute.childRoutes);
|
|
1506
|
+
if (opts?.throwOnError) {
|
|
1507
|
+
throw searchError;
|
|
1508
|
+
}
|
|
1509
|
+
return [parentSearch, searchError];
|
|
2098
1510
|
}
|
|
1511
|
+
})();
|
|
1512
|
+
const interpolatedPath = interpolatePath(route.path, routeParams);
|
|
1513
|
+
const matchId = interpolatePath(route.id, routeParams, true) + (route.options.key?.({
|
|
1514
|
+
search: preMatchSearch,
|
|
1515
|
+
location: this.state.location
|
|
1516
|
+
}) ?? '');
|
|
1517
|
+
|
|
1518
|
+
// Waste not, want not. If we already have a match for this route,
|
|
1519
|
+
// reuse it. This is important for layout routes, which might stick
|
|
1520
|
+
// around between navigation actions that only change leaf routes.
|
|
1521
|
+
const existingMatch = getRouteMatch(this.state, matchId);
|
|
1522
|
+
const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1523
|
+
|
|
1524
|
+
// Create a fresh route match
|
|
1525
|
+
const hasLoaders = !!(route.options.loader || componentTypes.some(d => route.options[d]?.preload));
|
|
1526
|
+
const match = existingMatch ? {
|
|
1527
|
+
...existingMatch,
|
|
1528
|
+
cause
|
|
1529
|
+
} : {
|
|
1530
|
+
id: matchId,
|
|
1531
|
+
routeId: route.id,
|
|
1532
|
+
params: routeParams,
|
|
1533
|
+
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1534
|
+
updatedAt: Date.now(),
|
|
1535
|
+
search: {},
|
|
1536
|
+
searchError: undefined,
|
|
1537
|
+
status: hasLoaders ? 'pending' : 'success',
|
|
1538
|
+
showPending: false,
|
|
1539
|
+
isFetching: false,
|
|
1540
|
+
invalid: false,
|
|
1541
|
+
error: undefined,
|
|
1542
|
+
paramsError: parseErrors[index],
|
|
1543
|
+
loadPromise: Promise.resolve(),
|
|
1544
|
+
context: undefined,
|
|
1545
|
+
abortController: new AbortController(),
|
|
1546
|
+
shouldReloadDeps: undefined,
|
|
1547
|
+
fetchedAt: 0,
|
|
1548
|
+
cause
|
|
2099
1549
|
};
|
|
2100
1550
|
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
} else {
|
|
2136
|
-
const next = router.buildNext({
|
|
2137
|
-
to: '.',
|
|
2138
|
-
search: d => _extends({}, d != null ? d : {}, {
|
|
2139
|
-
__data: {
|
|
2140
|
-
matchId: routeMatch.matchId
|
|
2141
|
-
}
|
|
2142
|
-
})
|
|
2143
|
-
});
|
|
2144
|
-
const res = await fetch(next.href, {
|
|
2145
|
-
method: 'GET' // signal: routeMatch.__.abortController.signal,
|
|
2146
|
-
|
|
1551
|
+
// Regardless of whether we're reusing an existing match or creating
|
|
1552
|
+
// a new one, we need to update the match's search params
|
|
1553
|
+
match.search = replaceEqualDeep(match.search, preMatchSearch);
|
|
1554
|
+
// And also update the searchError if there is one
|
|
1555
|
+
match.searchError = searchError;
|
|
1556
|
+
matches.push(match);
|
|
1557
|
+
});
|
|
1558
|
+
return matches;
|
|
1559
|
+
};
|
|
1560
|
+
cancelMatch = id => {
|
|
1561
|
+
getRouteMatch(this.state, id)?.abortController?.abort();
|
|
1562
|
+
};
|
|
1563
|
+
cancelMatches = () => {
|
|
1564
|
+
this.state.pendingMatches?.forEach(match => {
|
|
1565
|
+
this.cancelMatch(match.id);
|
|
1566
|
+
});
|
|
1567
|
+
};
|
|
1568
|
+
buildLocation = opts => {
|
|
1569
|
+
const build = (dest = {}, matches) => {
|
|
1570
|
+
const from = this.latestLocation;
|
|
1571
|
+
const fromPathname = dest.from ?? from.pathname;
|
|
1572
|
+
let pathname = this.resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1573
|
+
const fromMatches = this.matchRoutes(fromPathname, from.search);
|
|
1574
|
+
const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
|
|
1575
|
+
const prevParams = {
|
|
1576
|
+
...last(fromMatches)?.params
|
|
1577
|
+
};
|
|
1578
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1579
|
+
if (nextParams) {
|
|
1580
|
+
matches?.map(d => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1581
|
+
nextParams = {
|
|
1582
|
+
...nextParams,
|
|
1583
|
+
...fn(nextParams)
|
|
1584
|
+
};
|
|
2147
1585
|
});
|
|
2148
|
-
|
|
2149
|
-
if (res.ok) {
|
|
2150
|
-
return res.json();
|
|
2151
|
-
}
|
|
2152
|
-
|
|
2153
|
-
throw new Error('Failed to fetch match data');
|
|
2154
1586
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
const
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
search
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
1587
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1588
|
+
const preSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1589
|
+
const postSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1590
|
+
|
|
1591
|
+
// Pre filters first
|
|
1592
|
+
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
|
|
1593
|
+
|
|
1594
|
+
// Then the link/navigate function
|
|
1595
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1596
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1597
|
+
: preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1598
|
+
: {};
|
|
1599
|
+
|
|
1600
|
+
// Then post filters
|
|
1601
|
+
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1602
|
+
const search = replaceEqualDeep(from.search, postFilteredSearch);
|
|
1603
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1604
|
+
const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
|
|
1605
|
+
const hashStr = hash ? `#${hash}` : '';
|
|
1606
|
+
let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
|
|
1607
|
+
nextState = replaceEqualDeep(from.state, nextState);
|
|
1608
|
+
return {
|
|
1609
|
+
pathname,
|
|
1610
|
+
search,
|
|
1611
|
+
searchStr,
|
|
1612
|
+
state: nextState,
|
|
1613
|
+
hash,
|
|
1614
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1615
|
+
unmaskOnReload: dest.unmaskOnReload
|
|
1616
|
+
};
|
|
1617
|
+
};
|
|
1618
|
+
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
1619
|
+
let next = build(dest);
|
|
1620
|
+
let maskedNext = maskedDest ? build(maskedDest) : undefined;
|
|
1621
|
+
if (!maskedNext) {
|
|
1622
|
+
let params = {};
|
|
1623
|
+
let foundMask = this.options.routeMasks?.find(d => {
|
|
1624
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1625
|
+
to: d.from,
|
|
1626
|
+
caseSensitive: false,
|
|
1627
|
+
fuzzy: false
|
|
1628
|
+
});
|
|
1629
|
+
if (match) {
|
|
1630
|
+
params = match;
|
|
1631
|
+
return true;
|
|
1632
|
+
}
|
|
2188
1633
|
return false;
|
|
1634
|
+
});
|
|
1635
|
+
if (foundMask) {
|
|
1636
|
+
foundMask = {
|
|
1637
|
+
...foundMask,
|
|
1638
|
+
from: interpolatePath(foundMask.from, params)
|
|
1639
|
+
};
|
|
1640
|
+
maskedDest = foundMask;
|
|
1641
|
+
maskedNext = build(maskedDest);
|
|
2189
1642
|
}
|
|
2190
|
-
|
|
2191
|
-
return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
|
|
2192
|
-
to: next.pathname
|
|
2193
|
-
}));
|
|
2194
1643
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
} = _ref7;
|
|
2209
|
-
// If this link simply reloads the current route,
|
|
2210
|
-
// make sure it has a new key so it will trigger a data refresh
|
|
2211
|
-
// If this `to` is a valid external URL, return
|
|
2212
|
-
// null for LinkUtils
|
|
2213
|
-
const toString = String(to);
|
|
2214
|
-
const fromString = String(from);
|
|
2215
|
-
let isExternal;
|
|
2216
|
-
|
|
2217
|
-
try {
|
|
2218
|
-
new URL("" + toString);
|
|
2219
|
-
isExternal = true;
|
|
2220
|
-
} catch (e) {}
|
|
2221
|
-
|
|
2222
|
-
invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
|
|
2223
|
-
return router.__.navigate({
|
|
2224
|
-
from: fromString,
|
|
2225
|
-
to: toString,
|
|
2226
|
-
search,
|
|
2227
|
-
hash,
|
|
2228
|
-
replace,
|
|
2229
|
-
params
|
|
1644
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1645
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1646
|
+
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1647
|
+
const final = build(dest, nextMatches);
|
|
1648
|
+
if (maskedFinal) {
|
|
1649
|
+
final.maskedLocation = maskedFinal;
|
|
1650
|
+
}
|
|
1651
|
+
return final;
|
|
1652
|
+
};
|
|
1653
|
+
if (opts.mask) {
|
|
1654
|
+
return buildWithMatches(opts, {
|
|
1655
|
+
...pick(opts, ['from']),
|
|
1656
|
+
...opts.mask
|
|
2230
1657
|
});
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
1658
|
+
}
|
|
1659
|
+
return buildWithMatches(opts);
|
|
1660
|
+
};
|
|
1661
|
+
commitLocation = async ({
|
|
1662
|
+
startTransition,
|
|
1663
|
+
...next
|
|
1664
|
+
}) => {
|
|
1665
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1666
|
+
const isSameUrl = this.latestLocation.href === next.href;
|
|
1667
|
+
|
|
1668
|
+
// If the next urls are the same and we're not replacing,
|
|
1669
|
+
// do nothing
|
|
1670
|
+
if (!isSameUrl || !next.replace) {
|
|
2235
1671
|
let {
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
new URL("" + to);
|
|
2257
|
-
return {
|
|
2258
|
-
type: 'external',
|
|
2259
|
-
href: to
|
|
1672
|
+
maskedLocation,
|
|
1673
|
+
...nextHistory
|
|
1674
|
+
} = next;
|
|
1675
|
+
if (maskedLocation) {
|
|
1676
|
+
nextHistory = {
|
|
1677
|
+
...maskedLocation,
|
|
1678
|
+
state: {
|
|
1679
|
+
...maskedLocation.state,
|
|
1680
|
+
__tempKey: undefined,
|
|
1681
|
+
__tempLocation: {
|
|
1682
|
+
...nextHistory,
|
|
1683
|
+
search: nextHistory.searchStr,
|
|
1684
|
+
state: {
|
|
1685
|
+
...nextHistory.state,
|
|
1686
|
+
__tempKey: undefined,
|
|
1687
|
+
__tempLocation: undefined,
|
|
1688
|
+
key: undefined
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
2260
1692
|
};
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
const nextOpts = {
|
|
2264
|
-
from,
|
|
2265
|
-
to,
|
|
2266
|
-
search,
|
|
2267
|
-
params,
|
|
2268
|
-
hash,
|
|
2269
|
-
replace
|
|
2270
|
-
};
|
|
2271
|
-
const next = router.buildNext(nextOpts);
|
|
2272
|
-
preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
|
|
2273
|
-
const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0; // Compare path/hash for matches
|
|
2274
|
-
|
|
2275
|
-
const pathIsEqual = router.state.location.pathname === next.pathname;
|
|
2276
|
-
const currentPathSplit = router.state.location.pathname.split('/');
|
|
2277
|
-
const nextPathSplit = next.pathname.split('/');
|
|
2278
|
-
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2279
|
-
const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
|
|
2280
|
-
|
|
2281
|
-
const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
|
|
2282
|
-
const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
|
|
2283
|
-
|
|
2284
|
-
const isActive = pathTest && hashTest; // The click handler
|
|
2285
|
-
|
|
2286
|
-
const handleClick = e => {
|
|
2287
|
-
if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
|
|
2288
|
-
e.preventDefault();
|
|
2289
|
-
|
|
2290
|
-
if (pathIsEqual && !search && !hash) {
|
|
2291
|
-
router.invalidateRoute(nextOpts);
|
|
2292
|
-
} // All is well? Navigate!)
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
router.__.navigate(nextOpts);
|
|
2296
|
-
}
|
|
2297
|
-
}; // The click handler
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
const handleFocus = e => {
|
|
2301
|
-
if (preload) {
|
|
2302
|
-
router.preloadRoute(nextOpts, {
|
|
2303
|
-
maxAge: userPreloadMaxAge,
|
|
2304
|
-
gcMaxAge: userPreloadGcMaxAge
|
|
2305
|
-
});
|
|
1693
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
1694
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
2306
1695
|
}
|
|
1696
|
+
}
|
|
1697
|
+
const apply = () => {
|
|
1698
|
+
this.history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
2307
1699
|
};
|
|
1700
|
+
if (startTransition ?? true) {
|
|
1701
|
+
this.startReactTransition(apply);
|
|
1702
|
+
} else {
|
|
1703
|
+
apply();
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
1707
|
+
return this.latestLoadPromise;
|
|
1708
|
+
};
|
|
1709
|
+
buildAndCommitLocation = ({
|
|
1710
|
+
replace,
|
|
1711
|
+
resetScroll,
|
|
1712
|
+
startTransition,
|
|
1713
|
+
...rest
|
|
1714
|
+
} = {}) => {
|
|
1715
|
+
const location = this.buildLocation(rest);
|
|
1716
|
+
return this.commitLocation({
|
|
1717
|
+
...location,
|
|
1718
|
+
startTransition,
|
|
1719
|
+
replace,
|
|
1720
|
+
resetScroll
|
|
1721
|
+
});
|
|
1722
|
+
};
|
|
1723
|
+
navigate = ({
|
|
1724
|
+
from,
|
|
1725
|
+
to = '',
|
|
1726
|
+
...rest
|
|
1727
|
+
}) => {
|
|
1728
|
+
// If this link simply reloads the current route,
|
|
1729
|
+
// make sure it has a new key so it will trigger a data refresh
|
|
1730
|
+
|
|
1731
|
+
// If this `to` is a valid external URL, return
|
|
1732
|
+
// null for LinkUtils
|
|
1733
|
+
const toString = String(to);
|
|
1734
|
+
const fromString = typeof from === 'undefined' ? from : String(from);
|
|
1735
|
+
let isExternal;
|
|
1736
|
+
try {
|
|
1737
|
+
new URL(`${toString}`);
|
|
1738
|
+
isExternal = true;
|
|
1739
|
+
} catch (e) {}
|
|
1740
|
+
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1741
|
+
return this.buildAndCommitLocation({
|
|
1742
|
+
...rest,
|
|
1743
|
+
from: fromString,
|
|
1744
|
+
to: toString
|
|
1745
|
+
});
|
|
1746
|
+
};
|
|
1747
|
+
loadMatches = async ({
|
|
1748
|
+
checkLatest,
|
|
1749
|
+
matches,
|
|
1750
|
+
preload,
|
|
1751
|
+
invalidate
|
|
1752
|
+
}) => {
|
|
1753
|
+
let latestPromise;
|
|
1754
|
+
let firstBadMatchIndex;
|
|
1755
|
+
const updatePendingMatch = match => {
|
|
1756
|
+
this.__store.setState(s => ({
|
|
1757
|
+
...s,
|
|
1758
|
+
pendingMatches: s.pendingMatches?.map(d => d.id === match.id ? match : d)
|
|
1759
|
+
}));
|
|
1760
|
+
};
|
|
2308
1761
|
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
1762
|
+
// Check each match middleware to see if the route can be accessed
|
|
1763
|
+
try {
|
|
1764
|
+
for (let [index, match] of matches.entries()) {
|
|
1765
|
+
const parentMatch = matches[index - 1];
|
|
1766
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1767
|
+
const handleError = (err, code) => {
|
|
1768
|
+
err.routerCode = code;
|
|
1769
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
1770
|
+
if (isRedirect(err)) {
|
|
1771
|
+
throw err;
|
|
2315
1772
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
}
|
|
2323
|
-
}
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
1773
|
+
try {
|
|
1774
|
+
route.options.onError?.(err);
|
|
1775
|
+
} catch (errorHandlerErr) {
|
|
1776
|
+
err = errorHandlerErr;
|
|
1777
|
+
if (isRedirect(errorHandlerErr)) {
|
|
1778
|
+
throw errorHandlerErr;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
matches[index] = match = {
|
|
1782
|
+
...match,
|
|
1783
|
+
error: err,
|
|
1784
|
+
status: 'error',
|
|
1785
|
+
updatedAt: Date.now()
|
|
1786
|
+
};
|
|
1787
|
+
};
|
|
1788
|
+
try {
|
|
1789
|
+
if (match.paramsError) {
|
|
1790
|
+
handleError(match.paramsError, 'PARSE_PARAMS');
|
|
1791
|
+
}
|
|
1792
|
+
if (match.searchError) {
|
|
1793
|
+
handleError(match.searchError, 'VALIDATE_SEARCH');
|
|
1794
|
+
}
|
|
1795
|
+
const parentContext = parentMatch?.context ?? this.options.context ?? {};
|
|
1796
|
+
const beforeLoadContext = (await route.options.beforeLoad?.({
|
|
1797
|
+
search: match.search,
|
|
1798
|
+
abortController: match.abortController,
|
|
1799
|
+
params: match.params,
|
|
1800
|
+
preload: !!preload,
|
|
1801
|
+
context: parentContext,
|
|
1802
|
+
location: this.state.location,
|
|
1803
|
+
// TOOD: just expose state and router, etc
|
|
1804
|
+
navigate: opts => this.navigate({
|
|
1805
|
+
...opts,
|
|
1806
|
+
from: match.pathname
|
|
1807
|
+
}),
|
|
1808
|
+
buildLocation: this.buildLocation,
|
|
1809
|
+
cause: match.cause
|
|
1810
|
+
})) ?? {};
|
|
1811
|
+
const context = {
|
|
1812
|
+
...parentContext,
|
|
1813
|
+
...beforeLoadContext
|
|
1814
|
+
};
|
|
1815
|
+
matches[index] = match = {
|
|
1816
|
+
...match,
|
|
1817
|
+
context: replaceEqualDeep(match.context, context)
|
|
1818
|
+
};
|
|
1819
|
+
} catch (err) {
|
|
1820
|
+
handleError(err, 'BEFORE_LOAD');
|
|
1821
|
+
break;
|
|
2333
1822
|
}
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
const __preSearchFilters = matches.map(match => {
|
|
2353
|
-
var _match$options$preSea;
|
|
2354
|
-
|
|
2355
|
-
return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
|
|
2356
|
-
}).flat().filter(Boolean);
|
|
2357
|
-
|
|
2358
|
-
const __postSearchFilters = matches.map(match => {
|
|
2359
|
-
var _match$options$postSe;
|
|
2360
|
-
|
|
2361
|
-
return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
|
|
2362
|
-
}).flat().filter(Boolean);
|
|
2363
|
-
|
|
2364
|
-
return router.__.buildLocation(_extends({}, opts, {
|
|
2365
|
-
__preSearchFilters,
|
|
2366
|
-
__postSearchFilters
|
|
2367
|
-
}));
|
|
2368
|
-
},
|
|
2369
|
-
__: {
|
|
2370
|
-
buildRouteTree: rootRouteConfig => {
|
|
2371
|
-
const recurseRoutes = (routeConfigs, parent) => {
|
|
2372
|
-
return routeConfigs.map(routeConfig => {
|
|
2373
|
-
const routeOptions = routeConfig.options;
|
|
2374
|
-
const route = createRoute(routeConfig, routeOptions, parent, router);
|
|
2375
|
-
const existingRoute = router.routesById[route.routeId];
|
|
2376
|
-
|
|
2377
|
-
if (existingRoute) {
|
|
2378
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
2379
|
-
console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
|
|
2380
|
-
}
|
|
2381
|
-
|
|
2382
|
-
throw new Error();
|
|
1823
|
+
}
|
|
1824
|
+
} catch (err) {
|
|
1825
|
+
if (isRedirect(err)) {
|
|
1826
|
+
if (!preload) this.navigate(err);
|
|
1827
|
+
return matches;
|
|
1828
|
+
}
|
|
1829
|
+
throw err;
|
|
1830
|
+
}
|
|
1831
|
+
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
1832
|
+
const matchPromises = [];
|
|
1833
|
+
validResolvedMatches.forEach((match, index) => {
|
|
1834
|
+
matchPromises.push((async () => {
|
|
1835
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
1836
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1837
|
+
const handleIfRedirect = err => {
|
|
1838
|
+
if (isRedirect(err)) {
|
|
1839
|
+
if (!preload) {
|
|
1840
|
+
this.navigate(err);
|
|
2383
1841
|
}
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
return route;
|
|
2388
|
-
});
|
|
1842
|
+
return true;
|
|
1843
|
+
}
|
|
1844
|
+
return false;
|
|
2389
1845
|
};
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
const parsedSearch = router.options.parseSearch(location.search);
|
|
2398
|
-
return {
|
|
2399
|
-
pathname: location.pathname,
|
|
2400
|
-
searchStr: location.search,
|
|
2401
|
-
search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
|
|
2402
|
-
hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
|
|
2403
|
-
href: "" + location.pathname + location.search + location.hash,
|
|
2404
|
-
state: location.state,
|
|
2405
|
-
key: location.key
|
|
1846
|
+
let loadPromise;
|
|
1847
|
+
matches[index] = match = {
|
|
1848
|
+
...match,
|
|
1849
|
+
fetchedAt: Date.now(),
|
|
1850
|
+
invalid: false,
|
|
1851
|
+
showPending: false
|
|
2406
1852
|
};
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
},
|
|
2412
|
-
buildLocation: function buildLocation(dest) {
|
|
2413
|
-
var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
|
|
2414
|
-
|
|
2415
|
-
if (dest === void 0) {
|
|
2416
|
-
dest = {};
|
|
1853
|
+
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
1854
|
+
let pendingPromise;
|
|
1855
|
+
if (!preload && pendingMs && (route.options.pendingComponent ?? this.options.defaultPendingComponent)) {
|
|
1856
|
+
pendingPromise = new Promise(r => setTimeout(r, pendingMs));
|
|
2417
1857
|
}
|
|
1858
|
+
if (match.isFetching) {
|
|
1859
|
+
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
1860
|
+
} else {
|
|
1861
|
+
const loaderContext = {
|
|
1862
|
+
params: match.params,
|
|
1863
|
+
search: match.search,
|
|
1864
|
+
preload: !!preload,
|
|
1865
|
+
parentMatchPromise,
|
|
1866
|
+
abortController: match.abortController,
|
|
1867
|
+
context: match.context,
|
|
1868
|
+
location: this.state.location,
|
|
1869
|
+
navigate: opts => this.navigate({
|
|
1870
|
+
...opts,
|
|
1871
|
+
from: match.pathname
|
|
1872
|
+
}),
|
|
1873
|
+
cause: match.cause
|
|
1874
|
+
};
|
|
2418
1875
|
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
1876
|
+
// Default to reloading the route all the time
|
|
1877
|
+
let shouldReload = true;
|
|
1878
|
+
let shouldReloadDeps = typeof route.options.shouldReload === 'function' ? route.options.shouldReload?.(loaderContext) : !!(route.options.shouldReload ?? true);
|
|
1879
|
+
if (match.cause === 'enter' || invalidate) {
|
|
1880
|
+
match.shouldReloadDeps = shouldReloadDeps;
|
|
1881
|
+
} else if (match.cause === 'stay') {
|
|
1882
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
1883
|
+
// compare the deps to see if they've changed
|
|
1884
|
+
shouldReload = !deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
1885
|
+
match.shouldReloadDeps = shouldReloadDeps;
|
|
1886
|
+
} else {
|
|
1887
|
+
shouldReload = !!shouldReloadDeps;
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
2431
1890
|
|
|
2432
|
-
|
|
1891
|
+
// If the user doesn't want the route to reload, just
|
|
1892
|
+
// resolve with the existing loader data
|
|
2433
1893
|
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
1894
|
+
if (!shouldReload) {
|
|
1895
|
+
loadPromise = Promise.resolve(match.loaderData);
|
|
1896
|
+
} else {
|
|
1897
|
+
// Otherwise, load the route
|
|
1898
|
+
matches[index] = match = {
|
|
1899
|
+
...match,
|
|
1900
|
+
isFetching: true
|
|
1901
|
+
};
|
|
1902
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
1903
|
+
const component = route.options[type];
|
|
1904
|
+
if (component?.preload) {
|
|
1905
|
+
await component.preload();
|
|
1906
|
+
}
|
|
1907
|
+
}));
|
|
1908
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
1909
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
1910
|
+
}
|
|
2438
1911
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
|
|
2443
|
-
|
|
2444
|
-
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
2445
|
-
: dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
|
|
2446
|
-
: (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
2447
|
-
: {}; // Then post filters
|
|
2448
|
-
|
|
2449
|
-
const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
2450
|
-
const search = replaceEqualDeep(router.location.search, postFilteredSearch);
|
|
2451
|
-
const searchStr = router.options.stringifySearch(search);
|
|
2452
|
-
let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
|
|
2453
|
-
hash = hash ? "#" + hash : '';
|
|
2454
|
-
return {
|
|
2455
|
-
pathname,
|
|
2456
|
-
search,
|
|
2457
|
-
searchStr,
|
|
2458
|
-
state: router.location.state,
|
|
2459
|
-
hash,
|
|
2460
|
-
href: "" + pathname + searchStr + hash,
|
|
2461
|
-
key: dest.key
|
|
1912
|
+
matches[index] = match = {
|
|
1913
|
+
...match,
|
|
1914
|
+
loadPromise
|
|
2462
1915
|
};
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
const id = '' + Date.now() + Math.random();
|
|
2466
|
-
if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
|
|
2467
|
-
let nextAction = 'replace';
|
|
2468
|
-
|
|
2469
|
-
if (!replace) {
|
|
2470
|
-
nextAction = 'push';
|
|
1916
|
+
if (!preload) {
|
|
1917
|
+
updatePendingMatch(match);
|
|
2471
1918
|
}
|
|
1919
|
+
let didShowPending = false;
|
|
1920
|
+
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
1921
|
+
await new Promise(async resolve => {
|
|
1922
|
+
// If the route has a pending component and a pendingMs option,
|
|
1923
|
+
// forcefully show the pending component
|
|
1924
|
+
if (pendingPromise) {
|
|
1925
|
+
pendingPromise.then(() => {
|
|
1926
|
+
if (latestPromise = checkLatest()) return;
|
|
1927
|
+
didShowPending = true;
|
|
1928
|
+
matches[index] = match = {
|
|
1929
|
+
...match,
|
|
1930
|
+
showPending: true
|
|
1931
|
+
};
|
|
1932
|
+
updatePendingMatch(match);
|
|
1933
|
+
resolve();
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
try {
|
|
1937
|
+
const loaderData = await loadPromise;
|
|
1938
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1939
|
+
if (didShowPending && pendingMinMs) {
|
|
1940
|
+
await new Promise(r => setTimeout(r, pendingMinMs));
|
|
1941
|
+
}
|
|
1942
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1943
|
+
matches[index] = match = {
|
|
1944
|
+
...match,
|
|
1945
|
+
error: undefined,
|
|
1946
|
+
status: 'success',
|
|
1947
|
+
isFetching: false,
|
|
1948
|
+
updatedAt: Date.now(),
|
|
1949
|
+
loaderData,
|
|
1950
|
+
loadPromise: undefined
|
|
1951
|
+
};
|
|
1952
|
+
} catch (error) {
|
|
1953
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1954
|
+
if (handleIfRedirect(error)) return;
|
|
1955
|
+
try {
|
|
1956
|
+
route.options.onError?.(error);
|
|
1957
|
+
} catch (onErrorError) {
|
|
1958
|
+
error = onErrorError;
|
|
1959
|
+
if (handleIfRedirect(onErrorError)) return;
|
|
1960
|
+
}
|
|
1961
|
+
matches[index] = match = {
|
|
1962
|
+
...match,
|
|
1963
|
+
error,
|
|
1964
|
+
status: 'error',
|
|
1965
|
+
isFetching: false,
|
|
1966
|
+
updatedAt: Date.now()
|
|
1967
|
+
};
|
|
1968
|
+
} finally {
|
|
1969
|
+
// If we showed the pending component, that means
|
|
1970
|
+
// we already moved the pendingMatches to the matches
|
|
1971
|
+
// state, so we need to update that specific match
|
|
1972
|
+
if (didShowPending && pendingMinMs && match.showPending) {
|
|
1973
|
+
this.__store.setState(s => ({
|
|
1974
|
+
...s,
|
|
1975
|
+
matches: s.matches?.map(d => d.id === match.id ? match : d)
|
|
1976
|
+
}));
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
if (!preload) {
|
|
1980
|
+
updatePendingMatch(match);
|
|
1981
|
+
}
|
|
1982
|
+
resolve();
|
|
1983
|
+
});
|
|
1984
|
+
})());
|
|
1985
|
+
});
|
|
1986
|
+
await Promise.all(matchPromises);
|
|
1987
|
+
return matches;
|
|
1988
|
+
};
|
|
1989
|
+
invalidate = () => this.load({
|
|
1990
|
+
invalidate: true
|
|
1991
|
+
});
|
|
1992
|
+
load = async opts => {
|
|
1993
|
+
const promise = new Promise(async (resolve, reject) => {
|
|
1994
|
+
const next = this.latestLocation;
|
|
1995
|
+
const prevLocation = this.state.resolvedLocation;
|
|
1996
|
+
const pathDidChange = prevLocation.href !== next.href;
|
|
1997
|
+
let latestPromise;
|
|
1998
|
+
|
|
1999
|
+
// Cancel any pending matches
|
|
2000
|
+
this.cancelMatches();
|
|
2001
|
+
this.emit({
|
|
2002
|
+
type: 'onBeforeLoad',
|
|
2003
|
+
fromLocation: prevLocation,
|
|
2004
|
+
toLocation: next,
|
|
2005
|
+
pathChanged: pathDidChange
|
|
2006
|
+
});
|
|
2472
2007
|
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2008
|
+
// Match the routes
|
|
2009
|
+
let pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
2010
|
+
debug: true
|
|
2011
|
+
});
|
|
2012
|
+
const previousMatches = this.state.matches;
|
|
2013
|
+
|
|
2014
|
+
// Ingest the new matches
|
|
2015
|
+
this.__store.setState(s => ({
|
|
2016
|
+
...s,
|
|
2017
|
+
isLoading: true,
|
|
2018
|
+
location: next,
|
|
2019
|
+
pendingMatches
|
|
2020
|
+
}));
|
|
2021
|
+
try {
|
|
2022
|
+
try {
|
|
2023
|
+
// Load the matches
|
|
2024
|
+
await this.loadMatches({
|
|
2025
|
+
matches: pendingMatches,
|
|
2026
|
+
checkLatest: () => this.checkLatest(promise),
|
|
2027
|
+
invalidate: opts?.invalidate
|
|
2028
|
+
});
|
|
2029
|
+
} catch (err) {
|
|
2030
|
+
// swallow this error, since we'll display the
|
|
2031
|
+
// errors on the route components
|
|
2477
2032
|
}
|
|
2478
2033
|
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2034
|
+
// Only apply the latest transition
|
|
2035
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2036
|
+
return latestPromise;
|
|
2037
|
+
}
|
|
2038
|
+
const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
|
|
2039
|
+
const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
|
|
2040
|
+
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id));
|
|
2041
|
+
this.__store.setState(s => ({
|
|
2042
|
+
...s,
|
|
2043
|
+
isLoading: false,
|
|
2044
|
+
matches: pendingMatches,
|
|
2045
|
+
pendingMatches: undefined
|
|
2046
|
+
}))
|
|
2047
|
+
|
|
2048
|
+
//
|
|
2049
|
+
;
|
|
2050
|
+
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matches, hook]) => {
|
|
2051
|
+
matches.forEach(match => {
|
|
2052
|
+
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2494
2053
|
});
|
|
2054
|
+
});
|
|
2055
|
+
this.emit({
|
|
2056
|
+
type: 'onLoad',
|
|
2057
|
+
fromLocation: prevLocation,
|
|
2058
|
+
toLocation: next,
|
|
2059
|
+
pathChanged: pathDidChange
|
|
2060
|
+
});
|
|
2061
|
+
resolve();
|
|
2062
|
+
} catch (err) {
|
|
2063
|
+
// Only apply the latest transition
|
|
2064
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2065
|
+
return latestPromise;
|
|
2495
2066
|
}
|
|
2067
|
+
reject(err);
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
this.latestLoadPromise = promise;
|
|
2071
|
+
return this.latestLoadPromise;
|
|
2072
|
+
};
|
|
2073
|
+
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
2074
|
+
let next = this.buildLocation(navigateOpts);
|
|
2075
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
2076
|
+
throwOnError: true
|
|
2077
|
+
});
|
|
2078
|
+
await this.loadMatches({
|
|
2079
|
+
matches,
|
|
2080
|
+
preload: true,
|
|
2081
|
+
checkLatest: () => undefined
|
|
2082
|
+
});
|
|
2083
|
+
return [last(matches), matches];
|
|
2084
|
+
};
|
|
2085
|
+
buildLink = dest => {
|
|
2086
|
+
// If this link simply reloads the current route,
|
|
2087
|
+
// make sure it has a new key so it will trigger a data refresh
|
|
2088
|
+
|
|
2089
|
+
// If this `to` is a valid external URL, return
|
|
2090
|
+
// null for LinkUtils
|
|
2091
|
+
|
|
2092
|
+
const {
|
|
2093
|
+
to,
|
|
2094
|
+
preload: userPreload,
|
|
2095
|
+
preloadDelay: userPreloadDelay,
|
|
2096
|
+
activeOptions,
|
|
2097
|
+
disabled,
|
|
2098
|
+
target,
|
|
2099
|
+
replace,
|
|
2100
|
+
resetScroll,
|
|
2101
|
+
startTransition
|
|
2102
|
+
} = dest;
|
|
2103
|
+
try {
|
|
2104
|
+
new URL(`${to}`);
|
|
2105
|
+
return {
|
|
2106
|
+
type: 'external',
|
|
2107
|
+
href: to
|
|
2108
|
+
};
|
|
2109
|
+
} catch (e) {}
|
|
2110
|
+
const nextOpts = dest;
|
|
2111
|
+
const next = this.buildLocation(nextOpts);
|
|
2112
|
+
const preload = userPreload ?? this.options.defaultPreload;
|
|
2113
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
2114
|
+
|
|
2115
|
+
// Compare path/hash for matches
|
|
2116
|
+
const currentPathSplit = this.latestLocation.pathname.split('/');
|
|
2117
|
+
const nextPathSplit = next.pathname.split('/');
|
|
2118
|
+
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2119
|
+
// Combine the matches based on user this.options
|
|
2120
|
+
const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
|
|
2121
|
+
const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
|
|
2122
|
+
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
|
|
2123
|
+
|
|
2124
|
+
// The final "active" test
|
|
2125
|
+
const isActive = pathTest && hashTest && searchTest;
|
|
2126
|
+
|
|
2127
|
+
// The click handler
|
|
2128
|
+
const handleClick = e => {
|
|
2129
|
+
if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
|
|
2130
|
+
e.preventDefault();
|
|
2131
|
+
|
|
2132
|
+
// All is well? Navigate!
|
|
2133
|
+
this.commitLocation({
|
|
2134
|
+
...next,
|
|
2135
|
+
replace,
|
|
2136
|
+
resetScroll,
|
|
2137
|
+
startTransition
|
|
2138
|
+
});
|
|
2139
|
+
}
|
|
2140
|
+
};
|
|
2496
2141
|
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
};
|
|
2142
|
+
// The click handler
|
|
2143
|
+
const handleFocus = e => {
|
|
2144
|
+
if (preload) {
|
|
2145
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2146
|
+
console.warn(err);
|
|
2147
|
+
console.warn(preloadWarning);
|
|
2504
2148
|
});
|
|
2505
|
-
return router.navigationPromise;
|
|
2506
2149
|
}
|
|
2150
|
+
};
|
|
2151
|
+
const handleTouchStart = e => {
|
|
2152
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2153
|
+
console.warn(err);
|
|
2154
|
+
console.warn(preloadWarning);
|
|
2155
|
+
});
|
|
2156
|
+
};
|
|
2157
|
+
const handleEnter = e => {
|
|
2158
|
+
const target = e.target || {};
|
|
2159
|
+
if (preload) {
|
|
2160
|
+
if (target.preloadTimeout) {
|
|
2161
|
+
return;
|
|
2162
|
+
}
|
|
2163
|
+
target.preloadTimeout = setTimeout(() => {
|
|
2164
|
+
target.preloadTimeout = null;
|
|
2165
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2166
|
+
console.warn(err);
|
|
2167
|
+
console.warn(preloadWarning);
|
|
2168
|
+
});
|
|
2169
|
+
}, preloadDelay);
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
const handleLeave = e => {
|
|
2173
|
+
const target = e.target || {};
|
|
2174
|
+
if (target.preloadTimeout) {
|
|
2175
|
+
clearTimeout(target.preloadTimeout);
|
|
2176
|
+
target.preloadTimeout = null;
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
return {
|
|
2180
|
+
type: 'internal',
|
|
2181
|
+
next,
|
|
2182
|
+
handleFocus,
|
|
2183
|
+
handleClick,
|
|
2184
|
+
handleEnter,
|
|
2185
|
+
handleLeave,
|
|
2186
|
+
handleTouchStart,
|
|
2187
|
+
isActive,
|
|
2188
|
+
disabled
|
|
2189
|
+
};
|
|
2190
|
+
};
|
|
2191
|
+
matchRoute = (location, opts) => {
|
|
2192
|
+
location = {
|
|
2193
|
+
...location,
|
|
2194
|
+
to: location.to ? this.resolvePathWithBase(location.from || '', location.to) : undefined
|
|
2195
|
+
};
|
|
2196
|
+
const next = this.buildLocation(location);
|
|
2197
|
+
if (opts?.pending && this.state.status !== 'pending') {
|
|
2198
|
+
return false;
|
|
2199
|
+
}
|
|
2200
|
+
const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
|
|
2201
|
+
if (!baseLocation) {
|
|
2202
|
+
return false;
|
|
2203
|
+
}
|
|
2204
|
+
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
2205
|
+
...opts,
|
|
2206
|
+
to: next.pathname
|
|
2207
|
+
});
|
|
2208
|
+
if (!match) {
|
|
2209
|
+
return false;
|
|
2210
|
+
}
|
|
2211
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
2212
|
+
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
2213
|
+
}
|
|
2214
|
+
return match;
|
|
2215
|
+
};
|
|
2216
|
+
injectHtml = async html => {
|
|
2217
|
+
this.injectedHtml.push(html);
|
|
2218
|
+
};
|
|
2219
|
+
dehydrateData = (key, getData) => {
|
|
2220
|
+
if (typeof document === 'undefined') {
|
|
2221
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2222
|
+
this.injectHtml(async () => {
|
|
2223
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2224
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2225
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2226
|
+
;(() => {
|
|
2227
|
+
var el = document.getElementById('${id}')
|
|
2228
|
+
el.parentElement.removeChild(el)
|
|
2229
|
+
})()
|
|
2230
|
+
</script>`;
|
|
2231
|
+
});
|
|
2232
|
+
return () => this.hydrateData(key);
|
|
2233
|
+
}
|
|
2234
|
+
return () => undefined;
|
|
2235
|
+
};
|
|
2236
|
+
hydrateData = key => {
|
|
2237
|
+
if (typeof document !== 'undefined') {
|
|
2238
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2239
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2240
|
+
}
|
|
2241
|
+
return undefined;
|
|
2242
|
+
};
|
|
2243
|
+
dehydrate = () => {
|
|
2244
|
+
return {
|
|
2245
|
+
state: {
|
|
2246
|
+
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt', 'loaderData']))
|
|
2247
|
+
}
|
|
2248
|
+
};
|
|
2249
|
+
};
|
|
2250
|
+
hydrate = async __do_not_use_server_ctx => {
|
|
2251
|
+
let _ctx = __do_not_use_server_ctx;
|
|
2252
|
+
// Client hydrates from window
|
|
2253
|
+
if (typeof document !== 'undefined') {
|
|
2254
|
+
_ctx = window.__TSR_DEHYDRATED__;
|
|
2507
2255
|
}
|
|
2256
|
+
invariant(_ctx, 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?');
|
|
2257
|
+
const ctx = _ctx;
|
|
2258
|
+
this.dehydratedData = ctx.payload;
|
|
2259
|
+
this.options.hydrate?.(ctx.payload);
|
|
2260
|
+
const dehydratedState = ctx.router.state;
|
|
2261
|
+
let matches = this.matchRoutes(this.state.location.pathname, this.state.location.search).map(match => {
|
|
2262
|
+
const dehydratedMatch = dehydratedState.dehydratedMatches.find(d => d.id === match.id);
|
|
2263
|
+
invariant(dehydratedMatch, `Could not find a client-side match for dehydrated match with id: ${match.id}!`);
|
|
2264
|
+
if (dehydratedMatch) {
|
|
2265
|
+
return {
|
|
2266
|
+
...match,
|
|
2267
|
+
...dehydratedMatch
|
|
2268
|
+
};
|
|
2269
|
+
}
|
|
2270
|
+
return match;
|
|
2271
|
+
});
|
|
2272
|
+
this.__store.setState(s => {
|
|
2273
|
+
return {
|
|
2274
|
+
...s,
|
|
2275
|
+
matches: matches
|
|
2276
|
+
};
|
|
2277
|
+
});
|
|
2508
2278
|
};
|
|
2509
|
-
router.update(userOptions); // Allow frameworks to hook into the router creation
|
|
2510
2279
|
|
|
2511
|
-
|
|
2512
|
-
|
|
2280
|
+
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
2281
|
+
// state.matches
|
|
2282
|
+
// .find((d) => d.id === matchId)
|
|
2283
|
+
// ?.__promisesByKey[key]?.resolve(value)
|
|
2284
|
+
// }
|
|
2513
2285
|
}
|
|
2514
2286
|
|
|
2287
|
+
// A function that takes an import() argument which is a function and returns a new function that will
|
|
2288
|
+
// proxy arguments from the caller to the imported function, retaining all type
|
|
2289
|
+
// information along the way
|
|
2290
|
+
function lazyFn(fn, key) {
|
|
2291
|
+
return async (...args) => {
|
|
2292
|
+
const imported = await fn();
|
|
2293
|
+
return imported[key || 'default'](...args);
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2515
2296
|
function isCtrlEvent(e) {
|
|
2516
2297
|
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
2517
2298
|
}
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2299
|
+
class SearchParamError extends Error {}
|
|
2300
|
+
class PathParamError extends Error {}
|
|
2301
|
+
function getInitialRouterState(location) {
|
|
2302
|
+
return {
|
|
2303
|
+
isLoading: false,
|
|
2304
|
+
isTransitioning: false,
|
|
2305
|
+
status: 'idle',
|
|
2306
|
+
resolvedLocation: {
|
|
2307
|
+
...location
|
|
2308
|
+
},
|
|
2309
|
+
location,
|
|
2310
|
+
matches: [],
|
|
2311
|
+
pendingMatches: [],
|
|
2312
|
+
lastUpdated: Date.now()
|
|
2313
|
+
};
|
|
2527
2314
|
}
|
|
2528
2315
|
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
const
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
if (!promise) {
|
|
2546
|
-
promise = importer().then(module => {
|
|
2547
|
-
resolvedComp = module.default;
|
|
2548
|
-
return resolvedComp;
|
|
2549
|
-
});
|
|
2316
|
+
const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
2317
|
+
const windowKey = 'window';
|
|
2318
|
+
const delimiter = '___';
|
|
2319
|
+
let weakScrolledElements = new WeakSet();
|
|
2320
|
+
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2321
|
+
let cache = sessionsStorage ? (() => {
|
|
2322
|
+
const storageKey = 'tsr-scroll-restoration-v2';
|
|
2323
|
+
const state = JSON.parse(window.sessionStorage.getItem(storageKey) || 'null') || {
|
|
2324
|
+
cached: {},
|
|
2325
|
+
next: {}
|
|
2326
|
+
};
|
|
2327
|
+
return {
|
|
2328
|
+
state,
|
|
2329
|
+
set: updater => {
|
|
2330
|
+
cache.state = functionalUpdate(updater, cache.state);
|
|
2331
|
+
window.sessionStorage.setItem(storageKey, JSON.stringify(cache.state));
|
|
2550
2332
|
}
|
|
2551
|
-
|
|
2552
|
-
return promise;
|
|
2553
2333
|
};
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
//
|
|
2558
|
-
function Link(props) {
|
|
2334
|
+
})() : undefined;
|
|
2335
|
+
const defaultGetKey = location => location.state.key;
|
|
2336
|
+
function useScrollRestoration(options) {
|
|
2559
2337
|
const router = useRouter();
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
const
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
if (
|
|
2577
|
-
|
|
2578
|
-
}
|
|
2579
|
-
|
|
2580
|
-
const resolvedRouteId = router.resolvePath(route.routeId, subRouteId);
|
|
2581
|
-
const resolvedRoute = router.getRoute(resolvedRouteId);
|
|
2582
|
-
useRouterSubscription(router);
|
|
2583
|
-
invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
|
|
2584
|
-
return resolvedRoute;
|
|
2585
|
-
},
|
|
2586
|
-
linkProps: options => {
|
|
2587
|
-
var _functionalUpdate, _functionalUpdate2;
|
|
2588
|
-
|
|
2589
|
-
const {
|
|
2590
|
-
// custom props
|
|
2591
|
-
target,
|
|
2592
|
-
activeProps = () => ({
|
|
2593
|
-
className: 'active'
|
|
2594
|
-
}),
|
|
2595
|
-
inactiveProps = () => ({}),
|
|
2596
|
-
disabled,
|
|
2597
|
-
// element props
|
|
2598
|
-
style,
|
|
2599
|
-
className,
|
|
2600
|
-
onClick,
|
|
2601
|
-
onFocus,
|
|
2602
|
-
onMouseEnter,
|
|
2603
|
-
onMouseLeave
|
|
2604
|
-
} = options,
|
|
2605
|
-
rest = _objectWithoutPropertiesLoose(options, _excluded);
|
|
2606
|
-
|
|
2607
|
-
const linkInfo = route.buildLink(options);
|
|
2608
|
-
|
|
2609
|
-
if (linkInfo.type === 'external') {
|
|
2610
|
-
const {
|
|
2611
|
-
href
|
|
2612
|
-
} = linkInfo;
|
|
2613
|
-
return {
|
|
2614
|
-
href
|
|
2615
|
-
};
|
|
2338
|
+
useLayoutEffect(() => {
|
|
2339
|
+
const getKey = options?.getKey || defaultGetKey;
|
|
2340
|
+
const {
|
|
2341
|
+
history
|
|
2342
|
+
} = window;
|
|
2343
|
+
if (history.scrollRestoration) {
|
|
2344
|
+
history.scrollRestoration = 'manual';
|
|
2345
|
+
}
|
|
2346
|
+
const onScroll = event => {
|
|
2347
|
+
if (weakScrolledElements.has(event.target)) return;
|
|
2348
|
+
weakScrolledElements.add(event.target);
|
|
2349
|
+
let elementSelector = '';
|
|
2350
|
+
if (event.target === document || event.target === window) {
|
|
2351
|
+
elementSelector = windowKey;
|
|
2352
|
+
} else {
|
|
2353
|
+
const attrId = event.target.getAttribute('data-scroll-restoration-id');
|
|
2354
|
+
if (attrId) {
|
|
2355
|
+
elementSelector = `[data-scroll-restoration-id="${attrId}"]`;
|
|
2356
|
+
} else {
|
|
2357
|
+
elementSelector = getCssSelector(event.target);
|
|
2616
2358
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
React.startTransition(() => {
|
|
2629
|
-
handleClick(e);
|
|
2630
|
-
});
|
|
2631
|
-
};
|
|
2632
|
-
|
|
2633
|
-
const composeHandlers = handlers => e => {
|
|
2634
|
-
e.persist();
|
|
2635
|
-
handlers.forEach(handler => {
|
|
2636
|
-
if (handler) handler(e);
|
|
2637
|
-
});
|
|
2638
|
-
}; // Get the active props
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps, {})) != null ? _functionalUpdate : {} : {}; // Get the inactive props
|
|
2642
|
-
|
|
2643
|
-
const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
|
|
2644
|
-
return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
|
|
2645
|
-
href: disabled ? undefined : next.href,
|
|
2646
|
-
onClick: composeHandlers([reactHandleClick, onClick]),
|
|
2647
|
-
onFocus: composeHandlers([handleFocus, onFocus]),
|
|
2648
|
-
onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
|
|
2649
|
-
onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
|
|
2650
|
-
target,
|
|
2651
|
-
style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
|
|
2652
|
-
className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
|
|
2653
|
-
}, disabled ? {
|
|
2654
|
-
role: 'link',
|
|
2655
|
-
'aria-disabled': true
|
|
2656
|
-
} : undefined, {
|
|
2657
|
-
['data-status']: isActive ? 'active' : undefined
|
|
2658
|
-
});
|
|
2659
|
-
},
|
|
2660
|
-
Link: /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
2661
|
-
const linkProps = route.linkProps(props);
|
|
2662
|
-
useRouterSubscription(router);
|
|
2663
|
-
return /*#__PURE__*/React.createElement("a", _extends$2({
|
|
2664
|
-
ref: ref
|
|
2665
|
-
}, linkProps, {
|
|
2666
|
-
children: typeof props.children === 'function' ? props.children({
|
|
2667
|
-
isActive: linkProps['data-status'] === 'active'
|
|
2668
|
-
}) : props.children
|
|
2359
|
+
}
|
|
2360
|
+
if (!cache.state.next[elementSelector]) {
|
|
2361
|
+
cache.set(c => ({
|
|
2362
|
+
...c,
|
|
2363
|
+
next: {
|
|
2364
|
+
...c.next,
|
|
2365
|
+
[elementSelector]: {
|
|
2366
|
+
scrollX: NaN,
|
|
2367
|
+
scrollY: NaN
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2669
2370
|
}));
|
|
2670
|
-
}),
|
|
2671
|
-
MatchRoute: opts => {
|
|
2672
|
-
const {
|
|
2673
|
-
pending,
|
|
2674
|
-
caseSensitive
|
|
2675
|
-
} = opts,
|
|
2676
|
-
rest = _objectWithoutPropertiesLoose(opts, _excluded2);
|
|
2677
|
-
|
|
2678
|
-
const params = route.matchRoute(rest, {
|
|
2679
|
-
pending,
|
|
2680
|
-
caseSensitive
|
|
2681
|
-
});
|
|
2682
|
-
|
|
2683
|
-
if (!params) {
|
|
2684
|
-
return null;
|
|
2685
|
-
}
|
|
2686
|
-
|
|
2687
|
-
return typeof opts.children === 'function' ? opts.children(params) : opts.children;
|
|
2688
2371
|
}
|
|
2689
2372
|
};
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
const match = router.state.matches.find(d => d.routeId === routeId);
|
|
2706
|
-
|
|
2707
|
-
if ((_opts$strict = opts == null ? void 0 : opts.strict) != null ? _opts$strict : true) {
|
|
2708
|
-
invariant(match, "Could not find an active match for \"" + routeId + "\"!");
|
|
2709
|
-
invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch(\"" + (match == null ? void 0 : match.routeId) + "\") is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useMatch(\"" + (match == null ? void 0 : match.routeId) + "\", { strict: false })' or 'useRoute(\"" + (match == null ? void 0 : match.routeId) + "\")' instead?");
|
|
2373
|
+
if (typeof document !== 'undefined') {
|
|
2374
|
+
document.addEventListener('scroll', onScroll, true);
|
|
2375
|
+
}
|
|
2376
|
+
const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', event => {
|
|
2377
|
+
if (event.pathChanged) {
|
|
2378
|
+
const restoreKey = getKey(event.fromLocation);
|
|
2379
|
+
for (const elementSelector in cache.state.next) {
|
|
2380
|
+
const entry = cache.state.next[elementSelector];
|
|
2381
|
+
if (elementSelector === windowKey) {
|
|
2382
|
+
entry.scrollX = window.scrollX || 0;
|
|
2383
|
+
entry.scrollY = window.scrollY || 0;
|
|
2384
|
+
} else if (elementSelector) {
|
|
2385
|
+
const element = document.querySelector(elementSelector);
|
|
2386
|
+
entry.scrollX = element?.scrollLeft || 0;
|
|
2387
|
+
entry.scrollY = element?.scrollTop || 0;
|
|
2710
2388
|
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2389
|
+
cache.set(c => {
|
|
2390
|
+
const next = {
|
|
2391
|
+
...c.next
|
|
2392
|
+
};
|
|
2393
|
+
delete next[elementSelector];
|
|
2394
|
+
return {
|
|
2395
|
+
...c,
|
|
2396
|
+
next,
|
|
2397
|
+
cached: {
|
|
2398
|
+
...c.cached,
|
|
2399
|
+
[[restoreKey, elementSelector].join(delimiter)]: entry
|
|
2400
|
+
}
|
|
2401
|
+
};
|
|
2402
|
+
});
|
|
2713
2403
|
}
|
|
2714
|
-
};
|
|
2715
|
-
const routeExt = makeRouteExt(router.getRoute(rootRouteId), router);
|
|
2716
|
-
Object.assign(router, routerExt, routeExt);
|
|
2717
|
-
},
|
|
2718
|
-
createRoute: _ref => {
|
|
2719
|
-
let {
|
|
2720
|
-
router,
|
|
2721
|
-
route
|
|
2722
|
-
} = _ref;
|
|
2723
|
-
const routeExt = makeRouteExt(route, router);
|
|
2724
|
-
Object.assign(route, routeExt);
|
|
2725
|
-
},
|
|
2726
|
-
loadComponent: async component => {
|
|
2727
|
-
if (component.preload && typeof document !== 'undefined') {
|
|
2728
|
-
component.preload(); // return await component.preload()
|
|
2729
2404
|
}
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
return router.useMatch(routeId, opts);
|
|
2773
|
-
}
|
|
2774
|
-
function useNearestMatch() {
|
|
2775
|
-
var _useMatches2;
|
|
2776
|
-
|
|
2777
|
-
const runtimeMatch = (_useMatches2 = useMatches()) == null ? void 0 : _useMatches2[0];
|
|
2778
|
-
invariant(runtimeMatch, "Could not find a nearest match!");
|
|
2779
|
-
return runtimeMatch;
|
|
2780
|
-
}
|
|
2781
|
-
function useRoute(routeId) {
|
|
2782
|
-
const router = useRouter();
|
|
2783
|
-
return router.useRoute(routeId);
|
|
2784
|
-
}
|
|
2785
|
-
function useSearch(_routeId) {
|
|
2786
|
-
return useRouter().state.location.search;
|
|
2787
|
-
}
|
|
2788
|
-
function linkProps(props) {
|
|
2789
|
-
const router = useRouter();
|
|
2790
|
-
return router.linkProps(props);
|
|
2405
|
+
});
|
|
2406
|
+
const unsubOnResolved = router.subscribe('onResolved', event => {
|
|
2407
|
+
if (event.pathChanged) {
|
|
2408
|
+
if (!router.resetNextScroll) {
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
router.resetNextScroll = true;
|
|
2412
|
+
const getKey = options?.getKey || defaultGetKey;
|
|
2413
|
+
const restoreKey = getKey(event.toLocation);
|
|
2414
|
+
let windowRestored = false;
|
|
2415
|
+
for (const cacheKey in cache.state.cached) {
|
|
2416
|
+
const entry = cache.state.cached[cacheKey];
|
|
2417
|
+
const [key, elementSelector] = cacheKey.split(delimiter);
|
|
2418
|
+
if (key === restoreKey) {
|
|
2419
|
+
if (elementSelector === windowKey) {
|
|
2420
|
+
windowRestored = true;
|
|
2421
|
+
window.scrollTo(entry.scrollX, entry.scrollY);
|
|
2422
|
+
} else if (elementSelector) {
|
|
2423
|
+
const element = document.querySelector(elementSelector);
|
|
2424
|
+
if (element) {
|
|
2425
|
+
element.scrollLeft = entry.scrollX;
|
|
2426
|
+
element.scrollTop = entry.scrollY;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
if (!windowRestored) {
|
|
2432
|
+
window.scrollTo(0, 0);
|
|
2433
|
+
}
|
|
2434
|
+
cache.set(c => ({
|
|
2435
|
+
...c,
|
|
2436
|
+
next: {}
|
|
2437
|
+
}));
|
|
2438
|
+
weakScrolledElements = new WeakSet();
|
|
2439
|
+
}
|
|
2440
|
+
});
|
|
2441
|
+
return () => {
|
|
2442
|
+
document.removeEventListener('scroll', onScroll);
|
|
2443
|
+
unsubOnBeforeLoad();
|
|
2444
|
+
unsubOnResolved();
|
|
2445
|
+
};
|
|
2446
|
+
}, []);
|
|
2791
2447
|
}
|
|
2792
|
-
function
|
|
2793
|
-
|
|
2794
|
-
return
|
|
2448
|
+
function ScrollRestoration(props) {
|
|
2449
|
+
useScrollRestoration(props);
|
|
2450
|
+
return null;
|
|
2795
2451
|
}
|
|
2796
|
-
function
|
|
2797
|
-
var _ref3, _match$__$pendingComp, _match$__$errorCompon;
|
|
2798
|
-
|
|
2452
|
+
function useElementScrollRestoration(options) {
|
|
2799
2453
|
const router = useRouter();
|
|
2800
|
-
const
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
const PendingComponent = (_ref3 = (_match$__$pendingComp = match.__.pendingComponent) != null ? _match$__$pendingComp : router.options.defaultPendingComponent) != null ? _ref3 : defaultPending;
|
|
2809
|
-
const errorComponent = (_match$__$errorCompon = match.__.errorComponent) != null ? _match$__$errorCompon : router.options.defaultErrorComponent;
|
|
2810
|
-
return /*#__PURE__*/React.createElement(MatchesProvider, {
|
|
2811
|
-
value: matches
|
|
2812
|
-
}, /*#__PURE__*/React.createElement(React.Suspense, {
|
|
2813
|
-
fallback: /*#__PURE__*/React.createElement(PendingComponent, null)
|
|
2814
|
-
}, /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
2815
|
-
errorComponent: errorComponent
|
|
2816
|
-
}, (() => {
|
|
2817
|
-
if (match.status === 'error') {
|
|
2818
|
-
throw match.error;
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
|
-
if (match.status === 'success') {
|
|
2822
|
-
var _ref4, _ref5;
|
|
2823
|
-
|
|
2824
|
-
return /*#__PURE__*/React.createElement((_ref4 = (_ref5 = match.__.component) != null ? _ref5 : router.options.defaultComponent) != null ? _ref4 : Outlet);
|
|
2454
|
+
const getKey = options?.getKey || defaultGetKey;
|
|
2455
|
+
let elementSelector = '';
|
|
2456
|
+
if (options.id) {
|
|
2457
|
+
elementSelector = `[data-scroll-restoration-id="${options.id}"]`;
|
|
2458
|
+
} else {
|
|
2459
|
+
const element = options.getElement?.();
|
|
2460
|
+
if (!element) {
|
|
2461
|
+
return;
|
|
2825
2462
|
}
|
|
2826
|
-
|
|
2827
|
-
throw match.__.loadPromise;
|
|
2828
|
-
})())));
|
|
2829
|
-
}
|
|
2830
|
-
|
|
2831
|
-
class CatchBoundary extends React.Component {
|
|
2832
|
-
constructor() {
|
|
2833
|
-
super(...arguments);
|
|
2834
|
-
this.state = {
|
|
2835
|
-
error: false
|
|
2836
|
-
};
|
|
2837
|
-
}
|
|
2838
|
-
|
|
2839
|
-
componentDidCatch(error, info) {
|
|
2840
|
-
console.error(error);
|
|
2841
|
-
this.setState({
|
|
2842
|
-
error,
|
|
2843
|
-
info
|
|
2844
|
-
});
|
|
2463
|
+
elementSelector = getCssSelector(element);
|
|
2845
2464
|
}
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
}
|
|
2855
|
-
|
|
2856
|
-
return this.props.children;
|
|
2465
|
+
const restoreKey = getKey(router.latestLocation);
|
|
2466
|
+
const cacheKey = [restoreKey, elementSelector].join(delimiter);
|
|
2467
|
+
return cache.state.cached[cacheKey];
|
|
2468
|
+
}
|
|
2469
|
+
function getCssSelector(el) {
|
|
2470
|
+
let path = [],
|
|
2471
|
+
parent;
|
|
2472
|
+
while (parent = el.parentNode) {
|
|
2473
|
+
path.unshift(`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el) + 1})`);
|
|
2474
|
+
el = parent;
|
|
2857
2475
|
}
|
|
2858
|
-
|
|
2476
|
+
return `${path.join(' > ')}`.toLowerCase();
|
|
2859
2477
|
}
|
|
2860
2478
|
|
|
2861
|
-
function
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
} =
|
|
2865
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
2866
|
-
style: {
|
|
2867
|
-
padding: '.5rem',
|
|
2868
|
-
maxWidth: '100%'
|
|
2869
|
-
}
|
|
2870
|
-
}, /*#__PURE__*/React.createElement("strong", {
|
|
2871
|
-
style: {
|
|
2872
|
-
fontSize: '1.2rem'
|
|
2873
|
-
}
|
|
2874
|
-
}, "Something went wrong!"), /*#__PURE__*/React.createElement("div", {
|
|
2875
|
-
style: {
|
|
2876
|
-
height: '.5rem'
|
|
2877
|
-
}
|
|
2878
|
-
}), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("pre", null, error.message ? /*#__PURE__*/React.createElement("code", {
|
|
2879
|
-
style: {
|
|
2880
|
-
fontSize: '.7em',
|
|
2881
|
-
border: '1px solid red',
|
|
2882
|
-
borderRadius: '.25rem',
|
|
2883
|
-
padding: '.5rem',
|
|
2884
|
-
color: 'red'
|
|
2885
|
-
}
|
|
2886
|
-
}, error.message) : null)));
|
|
2887
|
-
}
|
|
2888
|
-
function usePrompt(message, when) {
|
|
2889
|
-
const router = useRouter();
|
|
2479
|
+
function useBlocker(message, condition = true) {
|
|
2480
|
+
const {
|
|
2481
|
+
history
|
|
2482
|
+
} = useRouter();
|
|
2890
2483
|
React.useEffect(() => {
|
|
2891
|
-
if (!
|
|
2892
|
-
let unblock =
|
|
2484
|
+
if (!condition) return;
|
|
2485
|
+
let unblock = history.block((retry, cancel) => {
|
|
2893
2486
|
if (window.confirm(message)) {
|
|
2894
2487
|
unblock();
|
|
2895
|
-
|
|
2896
|
-
} else {
|
|
2897
|
-
router.location.pathname = window.location.pathname;
|
|
2488
|
+
retry();
|
|
2898
2489
|
}
|
|
2899
2490
|
});
|
|
2900
2491
|
return unblock;
|
|
2901
|
-
}
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
function Block({
|
|
2495
|
+
message,
|
|
2496
|
+
condition,
|
|
2497
|
+
children
|
|
2498
|
+
}) {
|
|
2499
|
+
useBlocker(message, condition);
|
|
2500
|
+
return children ?? null;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
function useNavigate(defaultOpts) {
|
|
2504
|
+
const {
|
|
2505
|
+
navigate
|
|
2506
|
+
} = useRouter();
|
|
2507
|
+
const match = useMatch({
|
|
2508
|
+
strict: false
|
|
2509
|
+
});
|
|
2510
|
+
return React.useCallback(opts => {
|
|
2511
|
+
return navigate({
|
|
2512
|
+
from: opts?.to ? match.pathname : undefined,
|
|
2513
|
+
...defaultOpts,
|
|
2514
|
+
...opts
|
|
2515
|
+
});
|
|
2516
|
+
}, []);
|
|
2902
2517
|
}
|
|
2903
|
-
function
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2518
|
+
function typedNavigate(navigate) {
|
|
2519
|
+
return navigate;
|
|
2520
|
+
} //
|
|
2521
|
+
|
|
2522
|
+
function Navigate(props) {
|
|
2523
|
+
const {
|
|
2524
|
+
navigate
|
|
2525
|
+
} = useRouter();
|
|
2526
|
+
const match = useMatch({
|
|
2527
|
+
strict: false
|
|
2528
|
+
});
|
|
2529
|
+
useLayoutEffect$1(() => {
|
|
2530
|
+
navigate({
|
|
2531
|
+
from: props.to ? match.pathname : undefined,
|
|
2532
|
+
...props
|
|
2533
|
+
});
|
|
2534
|
+
}, []);
|
|
2535
|
+
return null;
|
|
2911
2536
|
}
|
|
2912
2537
|
|
|
2913
|
-
export {
|
|
2538
|
+
export { Await, Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, deepEqual, defaultParseSearch, defaultStringifySearch, defer, encode, escapeJSON, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isDehydratedDeferred, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useAwaited, useBlocker, useElementScrollRestoration, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2914
2539
|
//# sourceMappingURL=index.js.map
|