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