@tanstack/react-router 0.0.1-beta.23 → 0.0.1-beta.230
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/build/cjs/CatchBoundary.js +123 -0
- package/build/cjs/CatchBoundary.js.map +1 -0
- package/build/cjs/Matches.js +232 -0
- package/build/cjs/Matches.js.map +1 -0
- package/build/cjs/RouterProvider.js +158 -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 +122 -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 +1099 -0
- package/build/cjs/router.js.map +1 -0
- package/build/cjs/scroll-restoration.js +179 -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 +2149 -2560
- 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 +6 -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 +2443 -2515
- 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 +387 -0
- package/src/RouterProvider.tsx +224 -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 +1660 -0
- package/src/scroll-restoration.tsx +192 -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,2046 @@ 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 locationKey = useRouterState().location.state?.key;
|
|
654
|
+
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent;
|
|
655
|
+
const pendingElement = PendingComponent ? /*#__PURE__*/React.createElement(PendingComponent, {
|
|
656
|
+
useMatch: route.useMatch,
|
|
657
|
+
useRouteContext: route.useRouteContext,
|
|
658
|
+
useSearch: route.useSearch,
|
|
659
|
+
useParams: route.useParams
|
|
660
|
+
}) : undefined;
|
|
661
|
+
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
662
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? pendingElement ? React.Suspense : SafeFragment;
|
|
663
|
+
const errorComponent = routeErrorComponent ? React.useCallback(props => {
|
|
664
|
+
return /*#__PURE__*/React.createElement(routeErrorComponent, {
|
|
665
|
+
...props,
|
|
666
|
+
useMatch: route.useMatch,
|
|
667
|
+
useRouteContext: route.useRouteContext,
|
|
668
|
+
useSearch: route.useSearch,
|
|
669
|
+
useParams: route.useParams
|
|
670
|
+
});
|
|
671
|
+
}, [route]) : undefined;
|
|
672
|
+
const ResolvedCatchBoundary = errorComponent ? CatchBoundary : SafeFragment;
|
|
673
|
+
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
674
|
+
value: matches
|
|
675
|
+
}, /*#__PURE__*/React.createElement(ResolvedSuspenseBoundary, {
|
|
676
|
+
fallback: pendingElement
|
|
677
|
+
}, /*#__PURE__*/React.createElement(ResolvedCatchBoundary, {
|
|
678
|
+
resetKey: locationKey,
|
|
679
|
+
errorComponent: errorComponent,
|
|
680
|
+
onCatch: () => {
|
|
681
|
+
warning(false, `Error in route match: ${match.id}`);
|
|
1362
682
|
}
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
});
|
|
1368
|
-
return route;
|
|
683
|
+
}, /*#__PURE__*/React.createElement(MatchInner, {
|
|
684
|
+
match: match,
|
|
685
|
+
pendingElement: pendingElement
|
|
686
|
+
}))));
|
|
1369
687
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
688
|
+
function MatchInner({
|
|
689
|
+
match,
|
|
690
|
+
pendingElement
|
|
691
|
+
}) {
|
|
692
|
+
const {
|
|
693
|
+
options,
|
|
694
|
+
routesById
|
|
695
|
+
} = useRouter();
|
|
696
|
+
const route = routesById[match.routeId];
|
|
697
|
+
if (match.status === 'error') {
|
|
698
|
+
throw match.error;
|
|
1375
699
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
700
|
+
if (match.status === 'pending') {
|
|
701
|
+
if (match.showPending) {
|
|
702
|
+
return pendingElement || null;
|
|
703
|
+
}
|
|
704
|
+
throw match.loadPromise;
|
|
1379
705
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
706
|
+
if (match.status === 'success') {
|
|
707
|
+
let comp = route.options.component ?? options.defaultComponent;
|
|
708
|
+
if (comp) {
|
|
709
|
+
return /*#__PURE__*/React.createElement(comp, {
|
|
710
|
+
useMatch: route.useMatch,
|
|
711
|
+
useRouteContext: route.useRouteContext,
|
|
712
|
+
useSearch: route.useSearch,
|
|
713
|
+
useParams: route.useParams,
|
|
714
|
+
useLoaderData: route.useLoaderData
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
return /*#__PURE__*/React.createElement(Outlet, null);
|
|
1388
718
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
719
|
+
invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
|
|
720
|
+
}
|
|
721
|
+
function Outlet() {
|
|
722
|
+
const matches = React.useContext(matchesContext).slice(1);
|
|
723
|
+
if (!matches[0]) {
|
|
724
|
+
return null;
|
|
1394
725
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
726
|
+
return /*#__PURE__*/React.createElement(Match, {
|
|
727
|
+
matches: matches
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
function useMatchRoute() {
|
|
731
|
+
const {
|
|
732
|
+
matchRoute
|
|
733
|
+
} = useRouter();
|
|
734
|
+
return React.useCallback(opts => {
|
|
735
|
+
const {
|
|
736
|
+
pending,
|
|
737
|
+
caseSensitive,
|
|
738
|
+
...rest
|
|
739
|
+
} = opts;
|
|
740
|
+
return matchRoute(rest, {
|
|
741
|
+
pending,
|
|
742
|
+
caseSensitive
|
|
743
|
+
});
|
|
744
|
+
}, []);
|
|
745
|
+
}
|
|
746
|
+
function MatchRoute(props) {
|
|
747
|
+
const matchRoute = useMatchRoute();
|
|
748
|
+
const params = matchRoute(props);
|
|
749
|
+
if (typeof props.children === 'function') {
|
|
750
|
+
return props.children(params);
|
|
1401
751
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
752
|
+
return !!params ? props.children : null;
|
|
753
|
+
}
|
|
754
|
+
function useMatch(opts) {
|
|
755
|
+
const nearestMatch = React.useContext(matchesContext)[0];
|
|
756
|
+
const nearestMatchRouteId = nearestMatch?.routeId;
|
|
757
|
+
const matchRouteId = useRouterState({
|
|
758
|
+
select: state => {
|
|
759
|
+
const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
|
|
760
|
+
return match.routeId;
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
if (opts?.strict ?? true) {
|
|
764
|
+
invariant(nearestMatchRouteId == matchRouteId, `useMatch("${matchRouteId}") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${matchRouteId}", { strict: false })' or 'useRoute("${matchRouteId}")' instead?`);
|
|
1405
765
|
}
|
|
766
|
+
const matchSelection = useRouterState({
|
|
767
|
+
select: state => {
|
|
768
|
+
const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
|
|
769
|
+
invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
|
|
770
|
+
return opts?.select ? opts.select(match) : match;
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
return matchSelection;
|
|
774
|
+
}
|
|
775
|
+
const matchesContext = /*#__PURE__*/React.createContext(null);
|
|
776
|
+
function useMatches(opts) {
|
|
777
|
+
const contextMatches = React.useContext(matchesContext);
|
|
778
|
+
return useRouterState({
|
|
779
|
+
select: state => {
|
|
780
|
+
const matches = state.matches.slice(state.matches.findIndex(d => d.id === contextMatches[0]?.id));
|
|
781
|
+
return opts?.select ? opts.select(matches) : matches;
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
function useLoaderData(opts) {
|
|
786
|
+
const match = useMatch({
|
|
787
|
+
...opts,
|
|
788
|
+
select: undefined
|
|
789
|
+
});
|
|
790
|
+
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
791
|
+
}
|
|
1406
792
|
|
|
1407
|
-
|
|
793
|
+
const routerContext = /*#__PURE__*/React.createContext(null);
|
|
794
|
+
if (typeof document !== 'undefined') {
|
|
795
|
+
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
796
|
+
}
|
|
797
|
+
class SearchParamError extends Error {}
|
|
798
|
+
class PathParamError extends Error {}
|
|
799
|
+
function getInitialRouterState(location) {
|
|
1408
800
|
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
801
|
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
|
-
routeMatch.routeSearch = nextSearch;
|
|
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 () => {
|
|
802
|
+
resolvedLocation: location,
|
|
803
|
+
location,
|
|
804
|
+
matches: [],
|
|
805
|
+
pendingMatches: [],
|
|
806
|
+
lastUpdated: Date.now()
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
function RouterProvider({
|
|
810
|
+
router,
|
|
811
|
+
...rest
|
|
812
|
+
}) {
|
|
813
|
+
// Allow the router to update options on the router instance
|
|
814
|
+
router.updateOptions({
|
|
815
|
+
...router.options,
|
|
816
|
+
...rest,
|
|
817
|
+
context: {
|
|
818
|
+
...router.options.context,
|
|
819
|
+
...rest?.context
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
const [preState, setState] = React.useState(() => router.state);
|
|
823
|
+
const [isTransitioning, startReactTransition] = React.useTransition();
|
|
824
|
+
const state = React.useMemo(() => ({
|
|
825
|
+
...preState,
|
|
826
|
+
status: isTransitioning ? 'pending' : 'idle',
|
|
827
|
+
location: isTransitioning ? router.latestLocation : preState.location,
|
|
828
|
+
pendingMatches: router.pendingMatches
|
|
829
|
+
}), [preState, isTransitioning]);
|
|
830
|
+
router.setState = setState;
|
|
831
|
+
router.state = state;
|
|
832
|
+
router.startReactTransition = startReactTransition;
|
|
833
|
+
React.useLayoutEffect(() => {
|
|
834
|
+
const unsub = router.history.subscribe(() => {
|
|
835
|
+
router.latestLocation = router.parseLocation(router.latestLocation);
|
|
836
|
+
if (state.location !== router.latestLocation) {
|
|
837
|
+
startReactTransition(() => {
|
|
1567
838
|
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;
|
|
839
|
+
router.load();
|
|
1581
840
|
} 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;
|
|
841
|
+
console.error(err);
|
|
1592
842
|
}
|
|
1593
843
|
});
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
const nextLocation = router.buildLocation({
|
|
847
|
+
search: true,
|
|
848
|
+
params: true,
|
|
849
|
+
hash: true,
|
|
850
|
+
state: true
|
|
851
|
+
});
|
|
852
|
+
if (state.location.href !== nextLocation.href) {
|
|
853
|
+
router.commitLocation({
|
|
854
|
+
...nextLocation,
|
|
855
|
+
replace: true
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
return () => {
|
|
859
|
+
unsub();
|
|
860
|
+
};
|
|
861
|
+
}, [router.history]);
|
|
862
|
+
React.useLayoutEffect(() => {
|
|
863
|
+
if (!isTransitioning && state.resolvedLocation !== state.location) {
|
|
864
|
+
router.emit({
|
|
865
|
+
type: 'onResolved',
|
|
866
|
+
fromLocation: state.resolvedLocation,
|
|
867
|
+
toLocation: state.location,
|
|
868
|
+
pathChanged: state.location.href !== state.resolvedLocation?.href
|
|
1609
869
|
});
|
|
1610
|
-
|
|
1611
|
-
|
|
870
|
+
router.pendingMatches = [];
|
|
871
|
+
setState(s => ({
|
|
872
|
+
...s,
|
|
873
|
+
resolvedLocation: s.location
|
|
874
|
+
}));
|
|
1612
875
|
}
|
|
1613
876
|
});
|
|
877
|
+
React.useLayoutEffect(() => {
|
|
878
|
+
startReactTransition(() => {
|
|
879
|
+
try {
|
|
880
|
+
router.load();
|
|
881
|
+
} catch (err) {
|
|
882
|
+
console.error(err);
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
}, []);
|
|
886
|
+
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
887
|
+
value: router
|
|
888
|
+
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
889
|
+
}
|
|
890
|
+
function getRouteMatch(state, id) {
|
|
891
|
+
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
892
|
+
}
|
|
893
|
+
function useRouterState(opts) {
|
|
894
|
+
const {
|
|
895
|
+
state
|
|
896
|
+
} = useRouter();
|
|
897
|
+
// return useStore(router.__store, opts?.select as any)
|
|
898
|
+
return opts?.select ? opts.select(state) : state;
|
|
899
|
+
}
|
|
900
|
+
function useRouter() {
|
|
901
|
+
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
902
|
+
const value = React.useContext(resolvedContext);
|
|
903
|
+
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
904
|
+
return value;
|
|
905
|
+
}
|
|
1614
906
|
|
|
1615
|
-
|
|
1616
|
-
|
|
907
|
+
function defer(_promise) {
|
|
908
|
+
const promise = _promise;
|
|
909
|
+
if (!promise.__deferredState) {
|
|
910
|
+
promise.__deferredState = {
|
|
911
|
+
uid: Math.random().toString(36).slice(2),
|
|
912
|
+
status: 'pending'
|
|
913
|
+
};
|
|
914
|
+
const state = promise.__deferredState;
|
|
915
|
+
promise.then(data => {
|
|
916
|
+
state.status = 'success';
|
|
917
|
+
state.data = data;
|
|
918
|
+
}).catch(error => {
|
|
919
|
+
state.status = 'error';
|
|
920
|
+
state.error = error;
|
|
921
|
+
});
|
|
1617
922
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
923
|
+
return promise;
|
|
924
|
+
}
|
|
925
|
+
function isDehydratedDeferred(obj) {
|
|
926
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
1620
927
|
}
|
|
1621
928
|
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
929
|
+
function useAwaited({
|
|
930
|
+
promise
|
|
931
|
+
}) {
|
|
932
|
+
const router = useRouter();
|
|
933
|
+
let state = promise.__deferredState;
|
|
934
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
935
|
+
if (isDehydratedDeferred(promise)) {
|
|
936
|
+
state = router.hydrateData(key);
|
|
937
|
+
promise = Promise.resolve(state.data);
|
|
938
|
+
promise.__deferredState = state;
|
|
939
|
+
}
|
|
940
|
+
if (state.status === 'pending') {
|
|
941
|
+
throw promise;
|
|
942
|
+
}
|
|
943
|
+
if (state.status === 'error') {
|
|
944
|
+
throw state.error;
|
|
945
|
+
}
|
|
946
|
+
router.dehydrateData(key, state);
|
|
947
|
+
return [state.data];
|
|
948
|
+
}
|
|
949
|
+
function Await(props) {
|
|
950
|
+
const awaited = useAwaited(props);
|
|
951
|
+
return props.children(...awaited);
|
|
952
|
+
}
|
|
1631
953
|
|
|
1632
|
-
|
|
1633
|
-
|
|
954
|
+
class FileRoute {
|
|
955
|
+
constructor(path) {
|
|
956
|
+
this.path = path;
|
|
957
|
+
}
|
|
958
|
+
createRoute = options => {
|
|
959
|
+
const route = new Route(options);
|
|
960
|
+
route.isRoot = false;
|
|
961
|
+
return route;
|
|
962
|
+
};
|
|
963
|
+
}
|
|
1634
964
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
}
|
|
965
|
+
function lazyRouteComponent(importer, exportName) {
|
|
966
|
+
let loadPromise;
|
|
967
|
+
const load = () => {
|
|
968
|
+
if (!loadPromise) {
|
|
969
|
+
loadPromise = importer();
|
|
1641
970
|
}
|
|
1642
|
-
|
|
1643
|
-
return query;
|
|
971
|
+
return loadPromise;
|
|
1644
972
|
};
|
|
973
|
+
const lazyComp = /*#__PURE__*/React.lazy(async () => {
|
|
974
|
+
const moduleExports = await load();
|
|
975
|
+
const comp = moduleExports[exportName ?? 'default'];
|
|
976
|
+
return {
|
|
977
|
+
default: comp
|
|
978
|
+
};
|
|
979
|
+
});
|
|
980
|
+
lazyComp.preload = load;
|
|
981
|
+
return lazyComp;
|
|
1645
982
|
}
|
|
1646
|
-
function stringifySearchWith(stringify) {
|
|
1647
|
-
return search => {
|
|
1648
|
-
search = _extends({}, search);
|
|
1649
983
|
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
try {
|
|
1658
|
-
search[key] = stringify(val);
|
|
1659
|
-
} catch (err) {// silent
|
|
1660
|
-
}
|
|
984
|
+
function _extends() {
|
|
985
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
986
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
987
|
+
var source = arguments[i];
|
|
988
|
+
for (var key in source) {
|
|
989
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
990
|
+
target[key] = source[key];
|
|
1661
991
|
}
|
|
1662
|
-
}
|
|
992
|
+
}
|
|
1663
993
|
}
|
|
1664
|
-
|
|
1665
|
-
const searchStr = encode(search).toString();
|
|
1666
|
-
return searchStr ? "?" + searchStr : '';
|
|
994
|
+
return target;
|
|
1667
995
|
};
|
|
996
|
+
return _extends.apply(this, arguments);
|
|
1668
997
|
}
|
|
1669
998
|
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
999
|
+
function useLinkProps(options) {
|
|
1000
|
+
const {
|
|
1001
|
+
buildLink
|
|
1002
|
+
} = useRouter();
|
|
1003
|
+
const match = useMatch({
|
|
1004
|
+
strict: false
|
|
1005
|
+
});
|
|
1006
|
+
const {
|
|
1007
|
+
// custom props
|
|
1008
|
+
type,
|
|
1009
|
+
children,
|
|
1010
|
+
target,
|
|
1011
|
+
activeProps = () => ({
|
|
1012
|
+
className: 'active'
|
|
1013
|
+
}),
|
|
1014
|
+
inactiveProps = () => ({}),
|
|
1015
|
+
activeOptions,
|
|
1016
|
+
disabled,
|
|
1017
|
+
hash,
|
|
1018
|
+
search,
|
|
1019
|
+
params,
|
|
1020
|
+
to,
|
|
1021
|
+
state,
|
|
1022
|
+
mask,
|
|
1023
|
+
preload,
|
|
1024
|
+
preloadDelay,
|
|
1025
|
+
replace,
|
|
1026
|
+
startTransition,
|
|
1027
|
+
resetScroll,
|
|
1028
|
+
// element props
|
|
1029
|
+
style,
|
|
1030
|
+
className,
|
|
1031
|
+
onClick,
|
|
1032
|
+
onFocus,
|
|
1033
|
+
onMouseEnter,
|
|
1034
|
+
onMouseLeave,
|
|
1035
|
+
onTouchStart,
|
|
1036
|
+
...rest
|
|
1037
|
+
} = options;
|
|
1038
|
+
const linkInfo = buildLink({
|
|
1039
|
+
from: options.to ? match.pathname : undefined,
|
|
1040
|
+
...options
|
|
1041
|
+
});
|
|
1042
|
+
if (linkInfo.type === 'external') {
|
|
1043
|
+
const {
|
|
1044
|
+
href
|
|
1045
|
+
} = linkInfo;
|
|
1046
|
+
return {
|
|
1047
|
+
href
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
const {
|
|
1051
|
+
handleClick,
|
|
1052
|
+
handleFocus,
|
|
1053
|
+
handleEnter,
|
|
1054
|
+
handleLeave,
|
|
1055
|
+
handleTouchStart,
|
|
1056
|
+
isActive,
|
|
1057
|
+
next
|
|
1058
|
+
} = linkInfo;
|
|
1059
|
+
const composeHandlers = handlers => e => {
|
|
1060
|
+
if (e.persist) e.persist();
|
|
1061
|
+
handlers.filter(Boolean).forEach(handler => {
|
|
1062
|
+
if (e.defaultPrevented) return;
|
|
1063
|
+
handler(e);
|
|
1064
|
+
});
|
|
1065
|
+
};
|
|
1673
1066
|
|
|
1674
|
-
|
|
1067
|
+
// Get the active props
|
|
1068
|
+
const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
|
|
1675
1069
|
|
|
1676
|
-
|
|
1070
|
+
// Get the inactive props
|
|
1071
|
+
const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
|
|
1677
1072
|
return {
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1073
|
+
...resolvedActiveProps,
|
|
1074
|
+
...resolvedInactiveProps,
|
|
1075
|
+
...rest,
|
|
1076
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
1077
|
+
onClick: composeHandlers([onClick, handleClick]),
|
|
1078
|
+
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
1079
|
+
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
1080
|
+
onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
|
|
1081
|
+
onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
|
|
1082
|
+
target,
|
|
1083
|
+
style: {
|
|
1084
|
+
...style,
|
|
1085
|
+
...resolvedActiveProps.style,
|
|
1086
|
+
...resolvedInactiveProps.style
|
|
1087
|
+
},
|
|
1088
|
+
className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
|
|
1089
|
+
...(disabled ? {
|
|
1090
|
+
role: 'link',
|
|
1091
|
+
'aria-disabled': true
|
|
1092
|
+
} : undefined),
|
|
1093
|
+
['data-status']: isActive ? 'active' : undefined
|
|
1686
1094
|
};
|
|
1687
1095
|
}
|
|
1096
|
+
const Link = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1097
|
+
const linkProps = useLinkProps(props);
|
|
1098
|
+
return /*#__PURE__*/React.createElement("a", _extends({
|
|
1099
|
+
ref: ref
|
|
1100
|
+
}, linkProps, {
|
|
1101
|
+
children: typeof props.children === 'function' ? props.children({
|
|
1102
|
+
isActive: linkProps['data-status'] === 'active'
|
|
1103
|
+
}) : props.children
|
|
1104
|
+
}));
|
|
1105
|
+
});
|
|
1688
1106
|
|
|
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
|
-
|
|
1777
|
-
|
|
1778
|
-
if (next.href !== router.location.href) {
|
|
1779
|
-
router.__.commitLocation(next, true);
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
if (!router.state.matches.length) {
|
|
1783
|
-
router.load();
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
const unsub = router.history.listen(event => {
|
|
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
|
-
}
|
|
1796
|
-
|
|
1797
|
-
return () => {
|
|
1798
|
-
unsub();
|
|
1107
|
+
// @ts-nocheck
|
|
1799
1108
|
|
|
1800
|
-
|
|
1801
|
-
// Be sure to unsubscribe if a new handler is set
|
|
1802
|
-
window.removeEventListener('visibilitychange', router.onFocus);
|
|
1803
|
-
window.removeEventListener('focus', router.onFocus);
|
|
1804
|
-
}
|
|
1805
|
-
};
|
|
1806
|
-
},
|
|
1807
|
-
onFocus: () => {
|
|
1808
|
-
router.load();
|
|
1809
|
-
},
|
|
1810
|
-
update: opts => {
|
|
1811
|
-
const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
|
|
1109
|
+
// 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.
|
|
1812
1110
|
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1111
|
+
function encode(obj, pfx) {
|
|
1112
|
+
var k,
|
|
1113
|
+
i,
|
|
1114
|
+
tmp,
|
|
1115
|
+
str = '';
|
|
1116
|
+
for (k in obj) {
|
|
1117
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
1118
|
+
if (Array.isArray(tmp)) {
|
|
1119
|
+
for (i = 0; i < tmp.length; i++) {
|
|
1120
|
+
str && (str += '&');
|
|
1121
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1816
1122
|
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
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);
|
|
1123
|
+
} else {
|
|
1124
|
+
str && (str += '&');
|
|
1125
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1832
1126
|
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return (pfx || '') + str;
|
|
1130
|
+
}
|
|
1131
|
+
function toValue(mix) {
|
|
1132
|
+
if (!mix) return '';
|
|
1133
|
+
var str = decodeURIComponent(mix);
|
|
1134
|
+
if (str === 'false') return false;
|
|
1135
|
+
if (str === 'true') return true;
|
|
1136
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
1137
|
+
}
|
|
1138
|
+
function decode(str) {
|
|
1139
|
+
var tmp,
|
|
1140
|
+
k,
|
|
1141
|
+
out = {},
|
|
1142
|
+
arr = str.split('&');
|
|
1143
|
+
while (tmp = arr.shift()) {
|
|
1144
|
+
tmp = tmp.split('=');
|
|
1145
|
+
k = tmp.shift();
|
|
1146
|
+
if (out[k] !== void 0) {
|
|
1147
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1148
|
+
} else {
|
|
1149
|
+
out[k] = toValue(tmp.shift());
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return out;
|
|
1153
|
+
}
|
|
1833
1154
|
|
|
1834
|
-
|
|
1835
|
-
},
|
|
1836
|
-
cancelMatches: () => {
|
|
1837
|
-
var _router$state$pending, _router$state$pending2;
|
|
1838
|
-
[...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
|
|
1839
|
-
match.cancel();
|
|
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
|
-
|
|
1155
|
+
// Detect if we're in the DOM
|
|
1851
1156
|
|
|
1852
|
-
|
|
1157
|
+
function redirect(opts) {
|
|
1158
|
+
opts.isRedirect = true;
|
|
1159
|
+
return opts;
|
|
1160
|
+
}
|
|
1161
|
+
function isRedirect(obj) {
|
|
1162
|
+
return !!obj?.isRedirect;
|
|
1163
|
+
}
|
|
1853
1164
|
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1165
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1166
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
1167
|
+
function parseSearchWith(parser) {
|
|
1168
|
+
return searchStr => {
|
|
1169
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
1170
|
+
searchStr = searchStr.substring(1);
|
|
1171
|
+
}
|
|
1172
|
+
let query = decode(searchStr);
|
|
1857
1173
|
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1174
|
+
// Try to parse any query params that might be json
|
|
1175
|
+
for (let key in query) {
|
|
1176
|
+
const value = query[key];
|
|
1177
|
+
if (typeof value === 'string') {
|
|
1178
|
+
try {
|
|
1179
|
+
query[key] = parser(value);
|
|
1180
|
+
} catch (err) {
|
|
1181
|
+
//
|
|
1865
1182
|
}
|
|
1866
|
-
|
|
1867
|
-
throw err;
|
|
1868
1183
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
matches: matches,
|
|
1881
|
-
location: router.location,
|
|
1882
|
-
status: 'loading'
|
|
1883
|
-
});
|
|
1184
|
+
}
|
|
1185
|
+
return query;
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
function stringifySearchWith(stringify, parser) {
|
|
1189
|
+
function stringifyValue(val) {
|
|
1190
|
+
if (typeof val === 'object' && val !== null) {
|
|
1191
|
+
try {
|
|
1192
|
+
return stringify(val);
|
|
1193
|
+
} catch (err) {
|
|
1194
|
+
// silent
|
|
1884
1195
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1196
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
1197
|
+
try {
|
|
1198
|
+
// Check if it's a valid parseable string.
|
|
1199
|
+
// If it is, then stringify it again.
|
|
1200
|
+
parser(val);
|
|
1201
|
+
return stringify(val);
|
|
1202
|
+
} catch (err) {
|
|
1203
|
+
// silent
|
|
1893
1204
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1205
|
+
}
|
|
1206
|
+
return val;
|
|
1207
|
+
}
|
|
1208
|
+
return search => {
|
|
1209
|
+
search = {
|
|
1210
|
+
...search
|
|
1211
|
+
};
|
|
1212
|
+
if (search) {
|
|
1213
|
+
Object.keys(search).forEach(key => {
|
|
1214
|
+
const val = search[key];
|
|
1215
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
1216
|
+
delete search[key];
|
|
1901
1217
|
} else {
|
|
1902
|
-
|
|
1218
|
+
search[key] = stringifyValue(val);
|
|
1903
1219
|
}
|
|
1904
1220
|
});
|
|
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
|
-
}
|
|
1221
|
+
}
|
|
1222
|
+
const searchStr = encode(search).toString();
|
|
1223
|
+
return searchStr ? `?${searchStr}` : '';
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1921
1226
|
|
|
1922
|
-
|
|
1227
|
+
//
|
|
1923
1228
|
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1229
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1230
|
+
const preloadWarning = 'Error preloading route! ☝️';
|
|
1231
|
+
class Router {
|
|
1232
|
+
// Option-independent properties
|
|
1233
|
+
tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
|
|
1234
|
+
resetNextScroll = true;
|
|
1235
|
+
navigateTimeout = null;
|
|
1236
|
+
latestLoadPromise = Promise.resolve();
|
|
1237
|
+
subscribers = new Set();
|
|
1238
|
+
pendingMatches = [];
|
|
1239
|
+
injectedHtml = [];
|
|
1240
|
+
|
|
1241
|
+
// Must build in constructor
|
|
1242
|
+
|
|
1243
|
+
constructor(options) {
|
|
1244
|
+
this.updateOptions({
|
|
1245
|
+
defaultPreloadDelay: 50,
|
|
1246
|
+
defaultPendingMs: 1000,
|
|
1247
|
+
defaultPendingMinMs: 500,
|
|
1248
|
+
context: undefined,
|
|
1249
|
+
...options,
|
|
1250
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
1251
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
startReactTransition = () => {
|
|
1255
|
+
warning(false, 'startReactTransition implementation is missing. If you see this, please file an issue.');
|
|
1256
|
+
};
|
|
1257
|
+
setState = () => {
|
|
1258
|
+
warning(false, 'setState implementation is missing. If you see this, please file an issue.');
|
|
1259
|
+
};
|
|
1260
|
+
updateOptions = newOptions => {
|
|
1261
|
+
this.options = {
|
|
1262
|
+
...this.options,
|
|
1263
|
+
...newOptions
|
|
1264
|
+
};
|
|
1265
|
+
this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
|
|
1266
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
1267
|
+
this.history = this.options.history ?? createBrowserHistory();
|
|
1268
|
+
this.latestLocation = this.parseLocation();
|
|
1269
|
+
}
|
|
1270
|
+
if (this.options.routeTree !== this.routeTree) {
|
|
1271
|
+
this.routeTree = this.options.routeTree;
|
|
1272
|
+
this.buildRouteTree();
|
|
1273
|
+
}
|
|
1274
|
+
if (!this.state) {
|
|
1275
|
+
this.state = getInitialRouterState(this.latestLocation);
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
buildRouteTree = () => {
|
|
1279
|
+
this.routesById = {};
|
|
1280
|
+
this.routesByPath = {};
|
|
1281
|
+
const recurseRoutes = childRoutes => {
|
|
1282
|
+
childRoutes.forEach((childRoute, i) => {
|
|
1283
|
+
// if (typeof childRoute === 'function') {
|
|
1284
|
+
// childRoute = (childRoute as any)()
|
|
1285
|
+
// }
|
|
1286
|
+
childRoute.init({
|
|
1287
|
+
originalIndex: i
|
|
1941
1288
|
});
|
|
1942
|
-
|
|
1289
|
+
const existingRoute = this.routesById[childRoute.id];
|
|
1290
|
+
invariant(!existingRoute, `Duplicate routes found with id: ${String(childRoute.id)}`);
|
|
1291
|
+
this.routesById[childRoute.id] = childRoute;
|
|
1292
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
1293
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
1294
|
+
if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith('/')) {
|
|
1295
|
+
this.routesByPath[trimmedFullPath] = childRoute;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
const children = childRoute.children;
|
|
1299
|
+
if (children?.length) {
|
|
1300
|
+
recurseRoutes(children);
|
|
1301
|
+
}
|
|
1943
1302
|
});
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1303
|
+
};
|
|
1304
|
+
recurseRoutes([this.routeTree]);
|
|
1305
|
+
this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
|
|
1306
|
+
const trimmed = trimPath(d.fullPath);
|
|
1307
|
+
const parsed = parsePathname(trimmed);
|
|
1308
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1309
|
+
parsed.shift();
|
|
1948
1310
|
}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
if (match.action) {
|
|
1953
|
-
match.action.current = undefined;
|
|
1954
|
-
match.action.submissions = [];
|
|
1311
|
+
const score = parsed.map(d => {
|
|
1312
|
+
if (d.type === 'param') {
|
|
1313
|
+
return 0.5;
|
|
1955
1314
|
}
|
|
1315
|
+
if (d.type === 'wildcard') {
|
|
1316
|
+
return 0.25;
|
|
1317
|
+
}
|
|
1318
|
+
return 1;
|
|
1956
1319
|
});
|
|
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
|
-
|
|
1320
|
+
return {
|
|
1321
|
+
child: d,
|
|
1322
|
+
trimmed,
|
|
1323
|
+
parsed,
|
|
1324
|
+
index: i,
|
|
1325
|
+
score
|
|
1326
|
+
};
|
|
1327
|
+
}).sort((a, b) => {
|
|
1328
|
+
let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
|
|
1329
|
+
if (isIndex !== 0) return isIndex;
|
|
1330
|
+
const length = Math.min(a.score.length, b.score.length);
|
|
1331
|
+
|
|
1332
|
+
// Sort by length of score
|
|
1333
|
+
if (a.score.length !== b.score.length) {
|
|
1334
|
+
return b.score.length - a.score.length;
|
|
1335
|
+
}
|
|
1980
1336
|
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
navigateOpts = router.location;
|
|
1337
|
+
// Sort by min available score
|
|
1338
|
+
for (let i = 0; i < length; i++) {
|
|
1339
|
+
if (a.score[i] !== b.score[i]) {
|
|
1340
|
+
return b.score[i] - a.score[i];
|
|
1341
|
+
}
|
|
1987
1342
|
}
|
|
1988
1343
|
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
},
|
|
1996
|
-
preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
|
|
1997
|
-
var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
|
|
1344
|
+
// Sort by min available parsed value
|
|
1345
|
+
for (let i = 0; i < length; i++) {
|
|
1346
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
1347
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1998
1350
|
|
|
1999
|
-
|
|
2000
|
-
|
|
1351
|
+
// Sort by length of trimmed full path
|
|
1352
|
+
if (a.trimmed !== b.trimmed) {
|
|
1353
|
+
return a.trimmed > b.trimmed ? 1 : -1;
|
|
2001
1354
|
}
|
|
2002
1355
|
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
1356
|
+
// Sort by original index
|
|
1357
|
+
return a.index - b.index;
|
|
1358
|
+
}).map((d, i) => {
|
|
1359
|
+
d.child.rank = i;
|
|
1360
|
+
return d.child;
|
|
1361
|
+
});
|
|
1362
|
+
};
|
|
1363
|
+
subscribe = (eventType, fn) => {
|
|
1364
|
+
const listener = {
|
|
1365
|
+
eventType,
|
|
1366
|
+
fn
|
|
1367
|
+
};
|
|
1368
|
+
this.subscribers.add(listener);
|
|
1369
|
+
return () => {
|
|
1370
|
+
this.subscribers.delete(listener);
|
|
1371
|
+
};
|
|
1372
|
+
};
|
|
1373
|
+
emit = routerEvent => {
|
|
1374
|
+
this.subscribers.forEach(listener => {
|
|
1375
|
+
if (listener.eventType === routerEvent.type) {
|
|
1376
|
+
listener.fn(routerEvent);
|
|
1377
|
+
}
|
|
1378
|
+
});
|
|
1379
|
+
};
|
|
1380
|
+
checkLatest = promise => {
|
|
1381
|
+
return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
|
|
1382
|
+
};
|
|
1383
|
+
parseLocation = previousLocation => {
|
|
1384
|
+
const parse = ({
|
|
1385
|
+
pathname,
|
|
1386
|
+
search,
|
|
1387
|
+
hash,
|
|
1388
|
+
state
|
|
1389
|
+
}) => {
|
|
1390
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1391
|
+
return {
|
|
1392
|
+
pathname: pathname,
|
|
1393
|
+
searchStr: search,
|
|
1394
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1395
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1396
|
+
href: `${pathname}${search}${hash}`,
|
|
1397
|
+
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1398
|
+
};
|
|
1399
|
+
};
|
|
1400
|
+
const location = parse(this.history.location);
|
|
1401
|
+
let {
|
|
1402
|
+
__tempLocation,
|
|
1403
|
+
__tempKey
|
|
1404
|
+
} = location.state;
|
|
1405
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
1406
|
+
// Sync up the location keys
|
|
1407
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
1408
|
+
parsedTempLocation.state.key = location.state.key;
|
|
1409
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
1410
|
+
return {
|
|
1411
|
+
...parsedTempLocation,
|
|
1412
|
+
maskedLocation: location
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
return location;
|
|
1416
|
+
};
|
|
1417
|
+
resolvePathWithBase = (from, path) => {
|
|
1418
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1419
|
+
};
|
|
1420
|
+
get looseRoutesById() {
|
|
1421
|
+
return this.routesById;
|
|
1422
|
+
}
|
|
1423
|
+
matchRoutes = (pathname, locationSearch, opts) => {
|
|
1424
|
+
let routeParams = {};
|
|
1425
|
+
let foundRoute = this.flatRoutes.find(route => {
|
|
1426
|
+
const matchedParams = matchPathname(this.basepath, trimPathRight(pathname), {
|
|
1427
|
+
to: route.fullPath,
|
|
1428
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
|
|
1429
|
+
fuzzy: false
|
|
2011
1430
|
});
|
|
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;
|
|
1431
|
+
if (matchedParams) {
|
|
1432
|
+
routeParams = matchedParams;
|
|
1433
|
+
return true;
|
|
2022
1434
|
}
|
|
1435
|
+
return false;
|
|
1436
|
+
});
|
|
1437
|
+
let routeCursor = foundRoute || this.routesById['__root__'];
|
|
1438
|
+
let matchedRoutes = [routeCursor];
|
|
1439
|
+
// let includingLayouts = true
|
|
1440
|
+
while (routeCursor?.parentRoute) {
|
|
1441
|
+
routeCursor = routeCursor.parentRoute;
|
|
1442
|
+
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1443
|
+
}
|
|
2023
1444
|
|
|
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
|
-
}
|
|
1445
|
+
// Existing matches are matches that are already loaded along with
|
|
1446
|
+
// pending matches that are still loading
|
|
2068
1447
|
|
|
2069
|
-
|
|
1448
|
+
const parseErrors = matchedRoutes.map(route => {
|
|
1449
|
+
let parsedParamsError;
|
|
1450
|
+
if (route.options.parseParams) {
|
|
1451
|
+
try {
|
|
1452
|
+
const parsedParams = route.options.parseParams(routeParams);
|
|
1453
|
+
// Add the parsed params to the accumulated params bag
|
|
1454
|
+
Object.assign(routeParams, parsedParams);
|
|
1455
|
+
} catch (err) {
|
|
1456
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1457
|
+
cause: err
|
|
2070
1458
|
});
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
if (!foundRoutes.length) {
|
|
2077
|
-
return;
|
|
1459
|
+
if (opts?.throwOnError) {
|
|
1460
|
+
throw parsedParamsError;
|
|
1461
|
+
}
|
|
1462
|
+
return parsedParamsError;
|
|
2078
1463
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
1464
|
+
}
|
|
1465
|
+
return;
|
|
1466
|
+
});
|
|
1467
|
+
const matches = [];
|
|
1468
|
+
matchedRoutes.forEach((route, index) => {
|
|
1469
|
+
// Take each matched route and resolve + validate its search params
|
|
1470
|
+
// This has to happen serially because each route's search params
|
|
1471
|
+
// can depend on the parent route's search params
|
|
1472
|
+
// It must also happen before we create the match so that we can
|
|
1473
|
+
// pass the search params to the route's potential key function
|
|
1474
|
+
// which is used to uniquely identify the route match in state
|
|
1475
|
+
|
|
1476
|
+
const parentMatch = matches[index - 1];
|
|
1477
|
+
const [preMatchSearch, searchError] = (() => {
|
|
1478
|
+
// Validate the search params and stabilize them
|
|
1479
|
+
const parentSearch = parentMatch?.search ?? locationSearch;
|
|
1480
|
+
try {
|
|
1481
|
+
const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
|
|
1482
|
+
let search = validator?.(parentSearch) ?? {};
|
|
1483
|
+
return [{
|
|
1484
|
+
...parentSearch,
|
|
1485
|
+
...search
|
|
1486
|
+
}, undefined];
|
|
1487
|
+
} catch (err) {
|
|
1488
|
+
const searchError = new SearchParamError(err.message, {
|
|
1489
|
+
cause: err
|
|
2090
1490
|
});
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
|
|
2096
|
-
recurse(foundRoute.childRoutes);
|
|
1491
|
+
if (opts?.throwOnError) {
|
|
1492
|
+
throw searchError;
|
|
1493
|
+
}
|
|
1494
|
+
return [parentSearch, searchError];
|
|
2097
1495
|
}
|
|
1496
|
+
})();
|
|
1497
|
+
const interpolatedPath = interpolatePath(route.path, routeParams);
|
|
1498
|
+
const matchId = interpolatePath(route.id, routeParams, true) + (route.options.key?.({
|
|
1499
|
+
search: preMatchSearch,
|
|
1500
|
+
location: this.state.location
|
|
1501
|
+
}) ?? '');
|
|
1502
|
+
|
|
1503
|
+
// Waste not, want not. If we already have a match for this route,
|
|
1504
|
+
// reuse it. This is important for layout routes, which might stick
|
|
1505
|
+
// around between navigation actions that only change leaf routes.
|
|
1506
|
+
const existingMatch = getRouteMatch(this.state, matchId);
|
|
1507
|
+
const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1508
|
+
|
|
1509
|
+
// Create a fresh route match
|
|
1510
|
+
const hasLoaders = !!(route.options.loader || componentTypes.some(d => route.options[d]?.preload));
|
|
1511
|
+
const match = existingMatch ? {
|
|
1512
|
+
...existingMatch,
|
|
1513
|
+
cause
|
|
1514
|
+
} : {
|
|
1515
|
+
id: matchId,
|
|
1516
|
+
routeId: route.id,
|
|
1517
|
+
params: routeParams,
|
|
1518
|
+
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1519
|
+
updatedAt: Date.now(),
|
|
1520
|
+
search: {},
|
|
1521
|
+
searchError: undefined,
|
|
1522
|
+
status: hasLoaders ? 'pending' : 'success',
|
|
1523
|
+
showPending: false,
|
|
1524
|
+
isFetching: false,
|
|
1525
|
+
invalid: false,
|
|
1526
|
+
error: undefined,
|
|
1527
|
+
paramsError: parseErrors[index],
|
|
1528
|
+
loadPromise: Promise.resolve(),
|
|
1529
|
+
context: undefined,
|
|
1530
|
+
abortController: new AbortController(),
|
|
1531
|
+
shouldReloadDeps: undefined,
|
|
1532
|
+
fetchedAt: 0,
|
|
1533
|
+
cause
|
|
2098
1534
|
};
|
|
2099
1535
|
|
|
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
|
-
|
|
1536
|
+
// Regardless of whether we're reusing an existing match or creating
|
|
1537
|
+
// a new one, we need to update the match's search params
|
|
1538
|
+
match.search = replaceEqualDeep(match.search, preMatchSearch);
|
|
1539
|
+
// And also update the searchError if there is one
|
|
1540
|
+
match.searchError = searchError;
|
|
1541
|
+
matches.push(match);
|
|
1542
|
+
});
|
|
1543
|
+
return matches;
|
|
1544
|
+
};
|
|
1545
|
+
cancelMatch = id => {
|
|
1546
|
+
getRouteMatch(this.state, id)?.abortController?.abort();
|
|
1547
|
+
};
|
|
1548
|
+
cancelMatches = () => {
|
|
1549
|
+
this.state.matches.forEach(match => {
|
|
1550
|
+
this.cancelMatch(match.id);
|
|
1551
|
+
});
|
|
1552
|
+
};
|
|
1553
|
+
buildLocation = opts => {
|
|
1554
|
+
const build = (dest = {}, matches) => {
|
|
1555
|
+
const from = this.latestLocation;
|
|
1556
|
+
const fromPathname = dest.from ?? from.pathname;
|
|
1557
|
+
let pathname = this.resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1558
|
+
const fromMatches = this.matchRoutes(fromPathname, from.search);
|
|
1559
|
+
const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
|
|
1560
|
+
const prevParams = {
|
|
1561
|
+
...last(fromMatches)?.params
|
|
1562
|
+
};
|
|
1563
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1564
|
+
if (nextParams) {
|
|
1565
|
+
matches?.map(d => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1566
|
+
nextParams = {
|
|
1567
|
+
...nextParams,
|
|
1568
|
+
...fn(nextParams)
|
|
1569
|
+
};
|
|
2146
1570
|
});
|
|
2147
|
-
|
|
2148
|
-
if (res.ok) {
|
|
2149
|
-
return res.json();
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
throw new Error('Failed to fetch match data');
|
|
2153
1571
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
const
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
search
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
1572
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1573
|
+
const preSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1574
|
+
const postSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1575
|
+
|
|
1576
|
+
// Pre filters first
|
|
1577
|
+
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
|
|
1578
|
+
|
|
1579
|
+
// Then the link/navigate function
|
|
1580
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1581
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1582
|
+
: preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1583
|
+
: {};
|
|
1584
|
+
|
|
1585
|
+
// Then post filters
|
|
1586
|
+
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1587
|
+
const search = replaceEqualDeep(from.search, postFilteredSearch);
|
|
1588
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1589
|
+
const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
|
|
1590
|
+
const hashStr = hash ? `#${hash}` : '';
|
|
1591
|
+
let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
|
|
1592
|
+
nextState = replaceEqualDeep(from.state, nextState);
|
|
1593
|
+
return {
|
|
1594
|
+
pathname,
|
|
1595
|
+
search,
|
|
1596
|
+
searchStr,
|
|
1597
|
+
state: nextState,
|
|
1598
|
+
hash,
|
|
1599
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1600
|
+
unmaskOnReload: dest.unmaskOnReload
|
|
1601
|
+
};
|
|
1602
|
+
};
|
|
1603
|
+
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
1604
|
+
let next = build(dest);
|
|
1605
|
+
let maskedNext = maskedDest ? build(maskedDest) : undefined;
|
|
1606
|
+
if (!maskedNext) {
|
|
1607
|
+
let params = {};
|
|
1608
|
+
let foundMask = this.options.routeMasks?.find(d => {
|
|
1609
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1610
|
+
to: d.from,
|
|
1611
|
+
caseSensitive: false,
|
|
1612
|
+
fuzzy: false
|
|
1613
|
+
});
|
|
1614
|
+
if (match) {
|
|
1615
|
+
params = match;
|
|
1616
|
+
return true;
|
|
1617
|
+
}
|
|
2187
1618
|
return false;
|
|
1619
|
+
});
|
|
1620
|
+
if (foundMask) {
|
|
1621
|
+
foundMask = {
|
|
1622
|
+
...foundMask,
|
|
1623
|
+
from: interpolatePath(foundMask.from, params)
|
|
1624
|
+
};
|
|
1625
|
+
maskedDest = foundMask;
|
|
1626
|
+
maskedNext = build(maskedDest);
|
|
2188
1627
|
}
|
|
2189
|
-
|
|
2190
|
-
return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
|
|
2191
|
-
to: next.pathname
|
|
2192
|
-
}));
|
|
2193
1628
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
} = _ref7;
|
|
2208
|
-
// If this link simply reloads the current route,
|
|
2209
|
-
// make sure it has a new key so it will trigger a data refresh
|
|
2210
|
-
// If this `to` is a valid external URL, return
|
|
2211
|
-
// null for LinkUtils
|
|
2212
|
-
const toString = String(to);
|
|
2213
|
-
const fromString = String(from);
|
|
2214
|
-
let isExternal;
|
|
2215
|
-
|
|
2216
|
-
try {
|
|
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
|
|
1629
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1630
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1631
|
+
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1632
|
+
const final = build(dest, nextMatches);
|
|
1633
|
+
if (maskedFinal) {
|
|
1634
|
+
final.maskedLocation = maskedFinal;
|
|
1635
|
+
}
|
|
1636
|
+
return final;
|
|
1637
|
+
};
|
|
1638
|
+
if (opts.mask) {
|
|
1639
|
+
return buildWithMatches(opts, {
|
|
1640
|
+
...pick(opts, ['from']),
|
|
1641
|
+
...opts.mask
|
|
2229
1642
|
});
|
|
2230
|
-
}
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
1643
|
+
}
|
|
1644
|
+
return buildWithMatches(opts);
|
|
1645
|
+
};
|
|
1646
|
+
commitLocation = async ({
|
|
1647
|
+
startTransition,
|
|
1648
|
+
...next
|
|
1649
|
+
}) => {
|
|
1650
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1651
|
+
const isSameUrl = this.latestLocation.href === next.href;
|
|
1652
|
+
|
|
1653
|
+
// If the next urls are the same and we're not replacing,
|
|
1654
|
+
// do nothing
|
|
1655
|
+
if (!isSameUrl || !next.replace) {
|
|
2234
1656
|
let {
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
new URL("" + to);
|
|
2256
|
-
return {
|
|
2257
|
-
type: 'external',
|
|
2258
|
-
href: to
|
|
1657
|
+
maskedLocation,
|
|
1658
|
+
...nextHistory
|
|
1659
|
+
} = next;
|
|
1660
|
+
if (maskedLocation) {
|
|
1661
|
+
nextHistory = {
|
|
1662
|
+
...maskedLocation,
|
|
1663
|
+
state: {
|
|
1664
|
+
...maskedLocation.state,
|
|
1665
|
+
__tempKey: undefined,
|
|
1666
|
+
__tempLocation: {
|
|
1667
|
+
...nextHistory,
|
|
1668
|
+
search: nextHistory.searchStr,
|
|
1669
|
+
state: {
|
|
1670
|
+
...nextHistory.state,
|
|
1671
|
+
__tempKey: undefined,
|
|
1672
|
+
__tempLocation: undefined,
|
|
1673
|
+
key: undefined
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
2259
1677
|
};
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
const nextOpts = {
|
|
2263
|
-
from,
|
|
2264
|
-
to,
|
|
2265
|
-
search,
|
|
2266
|
-
params,
|
|
2267
|
-
hash,
|
|
2268
|
-
replace
|
|
2269
|
-
};
|
|
2270
|
-
const next = router.buildNext(nextOpts);
|
|
2271
|
-
preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
|
|
2272
|
-
const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0; // Compare path/hash for matches
|
|
2273
|
-
|
|
2274
|
-
const pathIsEqual = router.state.location.pathname === next.pathname;
|
|
2275
|
-
const currentPathSplit = router.state.location.pathname.split('/');
|
|
2276
|
-
const nextPathSplit = next.pathname.split('/');
|
|
2277
|
-
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2278
|
-
const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
|
|
2279
|
-
|
|
2280
|
-
const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
|
|
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
|
|
2304
|
-
});
|
|
1678
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
1679
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
2305
1680
|
}
|
|
1681
|
+
}
|
|
1682
|
+
const apply = () => {
|
|
1683
|
+
this.history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
2306
1684
|
};
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
1685
|
+
if (startTransition ?? true) {
|
|
1686
|
+
this.startReactTransition(apply);
|
|
1687
|
+
} else {
|
|
1688
|
+
apply();
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
1692
|
+
return this.latestLoadPromise;
|
|
1693
|
+
};
|
|
1694
|
+
buildAndCommitLocation = ({
|
|
1695
|
+
replace,
|
|
1696
|
+
resetScroll,
|
|
1697
|
+
startTransition,
|
|
1698
|
+
...rest
|
|
1699
|
+
} = {}) => {
|
|
1700
|
+
const location = this.buildLocation(rest);
|
|
1701
|
+
return this.commitLocation({
|
|
1702
|
+
...location,
|
|
1703
|
+
startTransition,
|
|
1704
|
+
replace,
|
|
1705
|
+
resetScroll
|
|
1706
|
+
});
|
|
1707
|
+
};
|
|
1708
|
+
navigate = ({
|
|
1709
|
+
from,
|
|
1710
|
+
to = '',
|
|
1711
|
+
...rest
|
|
1712
|
+
}) => {
|
|
1713
|
+
// If this link simply reloads the current route,
|
|
1714
|
+
// make sure it has a new key so it will trigger a data refresh
|
|
1715
|
+
|
|
1716
|
+
// If this `to` is a valid external URL, return
|
|
1717
|
+
// null for LinkUtils
|
|
1718
|
+
const toString = String(to);
|
|
1719
|
+
const fromString = typeof from === 'undefined' ? from : String(from);
|
|
1720
|
+
let isExternal;
|
|
1721
|
+
try {
|
|
1722
|
+
new URL(`${toString}`);
|
|
1723
|
+
isExternal = true;
|
|
1724
|
+
} catch (e) {}
|
|
1725
|
+
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1726
|
+
return this.buildAndCommitLocation({
|
|
1727
|
+
...rest,
|
|
1728
|
+
from: fromString,
|
|
1729
|
+
to: toString
|
|
1730
|
+
});
|
|
1731
|
+
};
|
|
1732
|
+
loadMatches = async ({
|
|
1733
|
+
checkLatest,
|
|
1734
|
+
matches,
|
|
1735
|
+
preload,
|
|
1736
|
+
invalidate
|
|
1737
|
+
}) => {
|
|
1738
|
+
let latestPromise;
|
|
1739
|
+
let firstBadMatchIndex;
|
|
1740
|
+
|
|
1741
|
+
// Check each match middleware to see if the route can be accessed
|
|
1742
|
+
try {
|
|
1743
|
+
for (let [index, match] of matches.entries()) {
|
|
1744
|
+
const parentMatch = matches[index - 1];
|
|
1745
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1746
|
+
const handleError = (err, code) => {
|
|
1747
|
+
err.routerCode = code;
|
|
1748
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
1749
|
+
if (isRedirect(err)) {
|
|
1750
|
+
throw err;
|
|
2314
1751
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
});
|
|
2322
|
-
}, preloadDelay);
|
|
2323
|
-
}
|
|
2324
|
-
};
|
|
2325
|
-
|
|
2326
|
-
const handleLeave = e => {
|
|
2327
|
-
const target = e.target || {};
|
|
2328
|
-
|
|
2329
|
-
if (target.preloadTimeout) {
|
|
2330
|
-
clearTimeout(target.preloadTimeout);
|
|
2331
|
-
target.preloadTimeout = null;
|
|
2332
|
-
}
|
|
2333
|
-
};
|
|
2334
|
-
|
|
2335
|
-
return {
|
|
2336
|
-
type: 'internal',
|
|
2337
|
-
next,
|
|
2338
|
-
handleFocus,
|
|
2339
|
-
handleClick,
|
|
2340
|
-
handleEnter,
|
|
2341
|
-
handleLeave,
|
|
2342
|
-
isActive,
|
|
2343
|
-
disabled
|
|
2344
|
-
};
|
|
2345
|
-
},
|
|
2346
|
-
buildNext: opts => {
|
|
2347
|
-
const next = router.__.buildLocation(opts);
|
|
2348
|
-
|
|
2349
|
-
const matches = router.matchRoutes(next.pathname);
|
|
2350
|
-
|
|
2351
|
-
const __preSearchFilters = matches.map(match => {
|
|
2352
|
-
var _match$options$preSea;
|
|
2353
|
-
|
|
2354
|
-
return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
|
|
2355
|
-
}).flat().filter(Boolean);
|
|
2356
|
-
|
|
2357
|
-
const __postSearchFilters = matches.map(match => {
|
|
2358
|
-
var _match$options$postSe;
|
|
2359
|
-
|
|
2360
|
-
return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
|
|
2361
|
-
}).flat().filter(Boolean);
|
|
2362
|
-
|
|
2363
|
-
return router.__.buildLocation(_extends({}, opts, {
|
|
2364
|
-
__preSearchFilters,
|
|
2365
|
-
__postSearchFilters
|
|
2366
|
-
}));
|
|
2367
|
-
},
|
|
2368
|
-
__: {
|
|
2369
|
-
buildRouteTree: rootRouteConfig => {
|
|
2370
|
-
const recurseRoutes = (routeConfigs, parent) => {
|
|
2371
|
-
return routeConfigs.map(routeConfig => {
|
|
2372
|
-
const routeOptions = routeConfig.options;
|
|
2373
|
-
const route = createRoute(routeConfig, routeOptions, parent, router);
|
|
2374
|
-
const existingRoute = router.routesById[route.routeId];
|
|
2375
|
-
|
|
2376
|
-
if (existingRoute) {
|
|
2377
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
2378
|
-
console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
|
|
2379
|
-
}
|
|
2380
|
-
|
|
2381
|
-
throw new Error();
|
|
1752
|
+
try {
|
|
1753
|
+
route.options.onError?.(err);
|
|
1754
|
+
} catch (errorHandlerErr) {
|
|
1755
|
+
err = errorHandlerErr;
|
|
1756
|
+
if (isRedirect(errorHandlerErr)) {
|
|
1757
|
+
throw errorHandlerErr;
|
|
2382
1758
|
}
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
1759
|
+
}
|
|
1760
|
+
matches[index] = match = {
|
|
1761
|
+
...match,
|
|
1762
|
+
error: err,
|
|
1763
|
+
status: 'error',
|
|
1764
|
+
updatedAt: Date.now()
|
|
1765
|
+
};
|
|
2388
1766
|
};
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
1767
|
+
try {
|
|
1768
|
+
if (match.paramsError) {
|
|
1769
|
+
handleError(match.paramsError, 'PARSE_PARAMS');
|
|
1770
|
+
}
|
|
1771
|
+
if (match.searchError) {
|
|
1772
|
+
handleError(match.searchError, 'VALIDATE_SEARCH');
|
|
1773
|
+
}
|
|
1774
|
+
const parentContext = parentMatch?.context ?? this.options.context ?? {};
|
|
1775
|
+
const beforeLoadContext = (await route.options.beforeLoad?.({
|
|
1776
|
+
search: match.search,
|
|
1777
|
+
abortController: match.abortController,
|
|
1778
|
+
params: match.params,
|
|
1779
|
+
preload: !!preload,
|
|
1780
|
+
context: parentContext,
|
|
1781
|
+
location: this.state.location,
|
|
1782
|
+
// TOOD: just expose state and router, etc
|
|
1783
|
+
navigate: opts => this.navigate({
|
|
1784
|
+
...opts,
|
|
1785
|
+
from: match.pathname
|
|
1786
|
+
}),
|
|
1787
|
+
buildLocation: this.buildLocation,
|
|
1788
|
+
cause: match.cause
|
|
1789
|
+
})) ?? {};
|
|
1790
|
+
const context = {
|
|
1791
|
+
...parentContext,
|
|
1792
|
+
...beforeLoadContext
|
|
1793
|
+
};
|
|
1794
|
+
matches[index] = match = {
|
|
1795
|
+
...match,
|
|
1796
|
+
context: replaceEqualDeep(match.context, context)
|
|
1797
|
+
};
|
|
1798
|
+
} catch (err) {
|
|
1799
|
+
handleError(err, 'BEFORE_LOAD');
|
|
1800
|
+
break;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
} catch (err) {
|
|
1804
|
+
if (isRedirect(err)) {
|
|
1805
|
+
if (!preload) this.navigate(err);
|
|
1806
|
+
return matches;
|
|
1807
|
+
}
|
|
1808
|
+
throw err;
|
|
1809
|
+
}
|
|
1810
|
+
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
1811
|
+
const matchPromises = [];
|
|
1812
|
+
validResolvedMatches.forEach((match, index) => {
|
|
1813
|
+
matchPromises.push((async () => {
|
|
1814
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
1815
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1816
|
+
const handleIfRedirect = err => {
|
|
1817
|
+
if (isRedirect(err)) {
|
|
1818
|
+
if (!preload) {
|
|
1819
|
+
this.navigate(err);
|
|
1820
|
+
}
|
|
1821
|
+
return true;
|
|
1822
|
+
}
|
|
1823
|
+
return false;
|
|
2405
1824
|
};
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
1825
|
+
let loadPromise;
|
|
1826
|
+
matches[index] = match = {
|
|
1827
|
+
...match,
|
|
1828
|
+
fetchedAt: Date.now(),
|
|
1829
|
+
invalid: false,
|
|
1830
|
+
showPending: false
|
|
1831
|
+
};
|
|
1832
|
+
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
1833
|
+
let pendingPromise;
|
|
1834
|
+
if (!preload && pendingMs && (route.options.pendingComponent ?? this.options.defaultPendingComponent)) {
|
|
1835
|
+
pendingPromise = new Promise(r => setTimeout(r, pendingMs));
|
|
2416
1836
|
}
|
|
1837
|
+
if (match.isFetching) {
|
|
1838
|
+
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
1839
|
+
} else {
|
|
1840
|
+
const loaderContext = {
|
|
1841
|
+
params: match.params,
|
|
1842
|
+
search: match.search,
|
|
1843
|
+
preload: !!preload,
|
|
1844
|
+
parentMatchPromise,
|
|
1845
|
+
abortController: match.abortController,
|
|
1846
|
+
context: match.context,
|
|
1847
|
+
location: this.state.location,
|
|
1848
|
+
navigate: opts => this.navigate({
|
|
1849
|
+
...opts,
|
|
1850
|
+
from: match.pathname
|
|
1851
|
+
}),
|
|
1852
|
+
cause: match.cause
|
|
1853
|
+
};
|
|
2417
1854
|
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
1855
|
+
// Default to reloading the route all the time
|
|
1856
|
+
let shouldReload = true;
|
|
1857
|
+
let shouldReloadDeps = typeof route.options.shouldReload === 'function' ? route.options.shouldReload?.(loaderContext) : !!(route.options.shouldReload ?? true);
|
|
1858
|
+
if (match.cause === 'enter' || invalidate) {
|
|
1859
|
+
match.shouldReloadDeps = shouldReloadDeps;
|
|
1860
|
+
} else if (match.cause === 'stay') {
|
|
1861
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
1862
|
+
// compare the deps to see if they've changed
|
|
1863
|
+
shouldReload = !deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
1864
|
+
match.shouldReloadDeps = shouldReloadDeps;
|
|
1865
|
+
} else {
|
|
1866
|
+
shouldReload = !!shouldReloadDeps;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
2430
1869
|
|
|
2431
|
-
|
|
1870
|
+
// If the user doesn't want the route to reload, just
|
|
1871
|
+
// resolve with the existing loader data
|
|
2432
1872
|
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
1873
|
+
if (!shouldReload) {
|
|
1874
|
+
loadPromise = Promise.resolve(match.loaderData);
|
|
1875
|
+
} else {
|
|
1876
|
+
// Otherwise, load the route
|
|
1877
|
+
matches[index] = match = {
|
|
1878
|
+
...match,
|
|
1879
|
+
isFetching: true
|
|
1880
|
+
};
|
|
1881
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
1882
|
+
const component = route.options[type];
|
|
1883
|
+
if (component?.preload) {
|
|
1884
|
+
await component.preload();
|
|
1885
|
+
}
|
|
1886
|
+
}));
|
|
1887
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
1888
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
1889
|
+
}
|
|
2437
1890
|
}
|
|
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
|
|
1891
|
+
matches[index] = match = {
|
|
1892
|
+
...match,
|
|
1893
|
+
loadPromise
|
|
2461
1894
|
};
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
if (!replace) {
|
|
2469
|
-
nextAction = 'push';
|
|
2470
|
-
}
|
|
2471
|
-
|
|
2472
|
-
const isSameUrl = router.__.parseLocation(history.location).href === next.href;
|
|
2473
|
-
|
|
2474
|
-
if (isSameUrl && !next.key) {
|
|
2475
|
-
nextAction = 'replace';
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
|
-
if (nextAction === 'replace') {
|
|
2479
|
-
history.replace({
|
|
2480
|
-
pathname: next.pathname,
|
|
2481
|
-
hash: next.hash,
|
|
2482
|
-
search: next.searchStr
|
|
2483
|
-
}, _extends({
|
|
2484
|
-
id
|
|
2485
|
-
}, next.state));
|
|
2486
|
-
} else {
|
|
2487
|
-
history.push({
|
|
2488
|
-
pathname: next.pathname,
|
|
2489
|
-
hash: next.hash,
|
|
2490
|
-
search: next.searchStr
|
|
2491
|
-
}, {
|
|
2492
|
-
id
|
|
2493
|
-
});
|
|
1895
|
+
if (!preload) {
|
|
1896
|
+
this.setState(s => ({
|
|
1897
|
+
...s,
|
|
1898
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1899
|
+
}));
|
|
2494
1900
|
}
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
1901
|
+
let didShowPending = false;
|
|
1902
|
+
await new Promise(async resolve => {
|
|
1903
|
+
// If the route has a pending component and a pendingMs option,
|
|
1904
|
+
// forcefully show the pending component
|
|
1905
|
+
if (pendingPromise) {
|
|
1906
|
+
pendingPromise.then(() => {
|
|
1907
|
+
didShowPending = true;
|
|
1908
|
+
matches[index] = match = {
|
|
1909
|
+
...match,
|
|
1910
|
+
showPending: true
|
|
1911
|
+
};
|
|
1912
|
+
this.setState(s => ({
|
|
1913
|
+
...s,
|
|
1914
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1915
|
+
}));
|
|
1916
|
+
resolve();
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
try {
|
|
1920
|
+
const loaderData = await loadPromise;
|
|
1921
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1922
|
+
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
1923
|
+
if (didShowPending && pendingMinMs) {
|
|
1924
|
+
await new Promise(r => setTimeout(r, pendingMinMs));
|
|
1925
|
+
}
|
|
1926
|
+
matches[index] = match = {
|
|
1927
|
+
...match,
|
|
1928
|
+
error: undefined,
|
|
1929
|
+
status: 'success',
|
|
1930
|
+
isFetching: false,
|
|
1931
|
+
updatedAt: Date.now(),
|
|
1932
|
+
loaderData,
|
|
1933
|
+
loadPromise: undefined
|
|
1934
|
+
};
|
|
1935
|
+
} catch (error) {
|
|
1936
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1937
|
+
if (handleIfRedirect(error)) return;
|
|
1938
|
+
try {
|
|
1939
|
+
route.options.onError?.(error);
|
|
1940
|
+
} catch (onErrorError) {
|
|
1941
|
+
error = onErrorError;
|
|
1942
|
+
if (handleIfRedirect(onErrorError)) return;
|
|
1943
|
+
}
|
|
1944
|
+
matches[index] = match = {
|
|
1945
|
+
...match,
|
|
1946
|
+
error,
|
|
1947
|
+
status: 'error',
|
|
1948
|
+
isFetching: false,
|
|
1949
|
+
updatedAt: Date.now()
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
if (!preload) {
|
|
1953
|
+
this.setState(s => ({
|
|
1954
|
+
...s,
|
|
1955
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1956
|
+
}));
|
|
1957
|
+
}
|
|
1958
|
+
resolve();
|
|
2503
1959
|
});
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
1960
|
+
})());
|
|
1961
|
+
});
|
|
1962
|
+
await Promise.all(matchPromises);
|
|
1963
|
+
return matches;
|
|
2507
1964
|
};
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
router.options.createRouter == null ? void 0 : router.options.createRouter(router);
|
|
2511
|
-
return router;
|
|
2512
|
-
}
|
|
2513
|
-
|
|
2514
|
-
function isCtrlEvent(e) {
|
|
2515
|
-
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
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));
|
|
2524
|
-
}
|
|
2525
|
-
});
|
|
2526
|
-
}
|
|
2527
|
-
|
|
2528
|
-
const _excluded = ["type", "children", "target", "activeProps", "inactiveProps", "activeOptions", "disabled", "hash", "search", "params", "to", "preload", "preloadDelay", "preloadMaxAge", "replace", "style", "className", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onTouchStart", "onTouchEnd"],
|
|
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));
|
|
1965
|
+
invalidate = () => this.load({
|
|
1966
|
+
invalidate: true
|
|
2540
1967
|
});
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
1968
|
+
load = async opts => {
|
|
1969
|
+
const promise = new Promise(async (resolve, reject) => {
|
|
1970
|
+
const next = this.latestLocation;
|
|
1971
|
+
const prevLocation = this.state.resolvedLocation;
|
|
1972
|
+
const pathDidChange = prevLocation.href !== next.href;
|
|
1973
|
+
let latestPromise;
|
|
1974
|
+
|
|
1975
|
+
// Cancel any pending matches
|
|
1976
|
+
this.cancelMatches();
|
|
1977
|
+
this.emit({
|
|
1978
|
+
type: 'onBeforeLoad',
|
|
1979
|
+
fromLocation: prevLocation,
|
|
1980
|
+
toLocation: next,
|
|
1981
|
+
pathChanged: pathDidChange
|
|
2548
1982
|
});
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
|
-
return promise;
|
|
2552
|
-
};
|
|
2553
|
-
|
|
2554
|
-
return finalComp;
|
|
2555
|
-
}
|
|
2556
|
-
//
|
|
2557
|
-
function Link(props) {
|
|
2558
|
-
const router = useRouter();
|
|
2559
|
-
return /*#__PURE__*/React.createElement(router.Link, props);
|
|
2560
|
-
}
|
|
2561
|
-
const matchesContext = /*#__PURE__*/React.createContext(null);
|
|
2562
|
-
const routerContext = /*#__PURE__*/React.createContext(null);
|
|
2563
|
-
function MatchesProvider(props) {
|
|
2564
|
-
return /*#__PURE__*/React.createElement(matchesContext.Provider, props);
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
const useRouterSubscription = router => {
|
|
2568
|
-
useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state, () => router.state);
|
|
2569
|
-
};
|
|
2570
1983
|
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
1984
|
+
// Match the routes
|
|
1985
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
1986
|
+
debug: true
|
|
1987
|
+
});
|
|
1988
|
+
this.pendingMatches = matches;
|
|
1989
|
+
const previousMatches = this.state.matches;
|
|
1990
|
+
|
|
1991
|
+
// Ingest the new matches
|
|
1992
|
+
this.setState(s => ({
|
|
1993
|
+
...s,
|
|
1994
|
+
status: 'pending',
|
|
1995
|
+
location: next,
|
|
1996
|
+
matches
|
|
1997
|
+
}));
|
|
1998
|
+
try {
|
|
1999
|
+
try {
|
|
2000
|
+
// Load the matches
|
|
2001
|
+
await this.loadMatches({
|
|
2002
|
+
matches,
|
|
2003
|
+
checkLatest: () => this.checkLatest(promise),
|
|
2004
|
+
invalidate: opts?.invalidate
|
|
2005
|
+
});
|
|
2006
|
+
} catch (err) {
|
|
2007
|
+
// swallow this error, since we'll display the
|
|
2008
|
+
// errors on the route components
|
|
2577
2009
|
}
|
|
2578
2010
|
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
|
|
2583
|
-
return resolvedRoute;
|
|
2584
|
-
},
|
|
2585
|
-
linkProps: options => {
|
|
2586
|
-
var _functionalUpdate, _functionalUpdate2;
|
|
2587
|
-
|
|
2588
|
-
const {
|
|
2589
|
-
// custom props
|
|
2590
|
-
target,
|
|
2591
|
-
activeProps = () => ({
|
|
2592
|
-
className: 'active'
|
|
2593
|
-
}),
|
|
2594
|
-
inactiveProps = () => ({}),
|
|
2595
|
-
disabled,
|
|
2596
|
-
// element props
|
|
2597
|
-
style,
|
|
2598
|
-
className,
|
|
2599
|
-
onClick,
|
|
2600
|
-
onFocus,
|
|
2601
|
-
onMouseEnter,
|
|
2602
|
-
onMouseLeave
|
|
2603
|
-
} = options,
|
|
2604
|
-
rest = _objectWithoutPropertiesLoose(options, _excluded);
|
|
2605
|
-
|
|
2606
|
-
const linkInfo = route.buildLink(options);
|
|
2607
|
-
|
|
2608
|
-
if (linkInfo.type === 'external') {
|
|
2609
|
-
const {
|
|
2610
|
-
href
|
|
2611
|
-
} = linkInfo;
|
|
2612
|
-
return {
|
|
2613
|
-
href
|
|
2614
|
-
};
|
|
2011
|
+
// Only apply the latest transition
|
|
2012
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2013
|
+
return latestPromise;
|
|
2615
2014
|
}
|
|
2616
|
-
|
|
2617
|
-
const
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
const composeHandlers = handlers => e => {
|
|
2633
|
-
e.persist();
|
|
2634
|
-
handlers.forEach(handler => {
|
|
2635
|
-
if (handler) handler(e);
|
|
2015
|
+
const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
|
|
2016
|
+
const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
|
|
2017
|
+
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id))
|
|
2018
|
+
|
|
2019
|
+
// setState((s) => ({
|
|
2020
|
+
// ...s,
|
|
2021
|
+
// status: 'idle',
|
|
2022
|
+
// resolvedLocation: s.location,
|
|
2023
|
+
// }))
|
|
2024
|
+
|
|
2025
|
+
//
|
|
2026
|
+
;
|
|
2027
|
+
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matches, hook]) => {
|
|
2028
|
+
matches.forEach(match => {
|
|
2029
|
+
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2636
2030
|
});
|
|
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
2031
|
});
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
ref: ref
|
|
2664
|
-
}, linkProps, {
|
|
2665
|
-
children: typeof props.children === 'function' ? props.children({
|
|
2666
|
-
isActive: linkProps['data-status'] === 'active'
|
|
2667
|
-
}) : props.children
|
|
2668
|
-
}));
|
|
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
|
|
2032
|
+
this.emit({
|
|
2033
|
+
type: 'onLoad',
|
|
2034
|
+
fromLocation: prevLocation,
|
|
2035
|
+
toLocation: next,
|
|
2036
|
+
pathChanged: pathDidChange
|
|
2680
2037
|
});
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2038
|
+
resolve();
|
|
2039
|
+
} catch (err) {
|
|
2040
|
+
// Only apply the latest transition
|
|
2041
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2042
|
+
return latestPromise;
|
|
2684
2043
|
}
|
|
2685
|
-
|
|
2686
|
-
return typeof opts.children === 'function' ? opts.children(params) : opts.children;
|
|
2044
|
+
reject(err);
|
|
2687
2045
|
}
|
|
2688
|
-
};
|
|
2046
|
+
});
|
|
2047
|
+
this.latestLoadPromise = promise;
|
|
2048
|
+
return this.latestLoadPromise;
|
|
2689
2049
|
};
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2050
|
+
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
2051
|
+
let next = this.buildLocation(navigateOpts);
|
|
2052
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
2053
|
+
throwOnError: true
|
|
2054
|
+
});
|
|
2055
|
+
await this.loadMatches({
|
|
2056
|
+
matches,
|
|
2057
|
+
preload: true,
|
|
2058
|
+
checkLatest: () => undefined
|
|
2059
|
+
});
|
|
2060
|
+
return [last(matches), matches];
|
|
2061
|
+
};
|
|
2062
|
+
buildLink = dest => {
|
|
2063
|
+
// If this link simply reloads the current route,
|
|
2064
|
+
// make sure it has a new key so it will trigger a data refresh
|
|
2065
|
+
|
|
2066
|
+
// If this `to` is a valid external URL, return
|
|
2067
|
+
// null for LinkUtils
|
|
2068
|
+
|
|
2069
|
+
const {
|
|
2070
|
+
to,
|
|
2071
|
+
preload: userPreload,
|
|
2072
|
+
preloadDelay: userPreloadDelay,
|
|
2073
|
+
activeOptions,
|
|
2074
|
+
disabled,
|
|
2075
|
+
target,
|
|
2076
|
+
replace,
|
|
2077
|
+
resetScroll,
|
|
2078
|
+
startTransition
|
|
2079
|
+
} = dest;
|
|
2080
|
+
try {
|
|
2081
|
+
new URL(`${to}`);
|
|
2082
|
+
return {
|
|
2083
|
+
type: 'external',
|
|
2084
|
+
href: to
|
|
2713
2085
|
};
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2086
|
+
} catch (e) {}
|
|
2087
|
+
const nextOpts = dest;
|
|
2088
|
+
const next = this.buildLocation(nextOpts);
|
|
2089
|
+
const preload = userPreload ?? this.options.defaultPreload;
|
|
2090
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
2091
|
+
|
|
2092
|
+
// Compare path/hash for matches
|
|
2093
|
+
const currentPathSplit = this.latestLocation.pathname.split('/');
|
|
2094
|
+
const nextPathSplit = next.pathname.split('/');
|
|
2095
|
+
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2096
|
+
// Combine the matches based on user this.options
|
|
2097
|
+
const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
|
|
2098
|
+
const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
|
|
2099
|
+
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
|
|
2100
|
+
|
|
2101
|
+
// The final "active" test
|
|
2102
|
+
const isActive = pathTest && hashTest && searchTest;
|
|
2103
|
+
|
|
2104
|
+
// The click handler
|
|
2105
|
+
const handleClick = e => {
|
|
2106
|
+
if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
|
|
2107
|
+
e.preventDefault();
|
|
2108
|
+
|
|
2109
|
+
// All is well? Navigate!
|
|
2110
|
+
this.commitLocation({
|
|
2111
|
+
...next,
|
|
2112
|
+
replace,
|
|
2113
|
+
resetScroll,
|
|
2114
|
+
startTransition
|
|
2115
|
+
});
|
|
2728
2116
|
}
|
|
2117
|
+
};
|
|
2729
2118
|
|
|
2730
|
-
|
|
2119
|
+
// The click handler
|
|
2120
|
+
const handleFocus = e => {
|
|
2121
|
+
if (preload) {
|
|
2122
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2123
|
+
console.warn(err);
|
|
2124
|
+
console.warn(preloadWarning);
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
const handleTouchStart = e => {
|
|
2129
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2130
|
+
console.warn(err);
|
|
2131
|
+
console.warn(preloadWarning);
|
|
2132
|
+
});
|
|
2133
|
+
};
|
|
2134
|
+
const handleEnter = e => {
|
|
2135
|
+
const target = e.target || {};
|
|
2136
|
+
if (preload) {
|
|
2137
|
+
if (target.preloadTimeout) {
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
target.preloadTimeout = setTimeout(() => {
|
|
2141
|
+
target.preloadTimeout = null;
|
|
2142
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2143
|
+
console.warn(err);
|
|
2144
|
+
console.warn(preloadWarning);
|
|
2145
|
+
});
|
|
2146
|
+
}, preloadDelay);
|
|
2147
|
+
}
|
|
2148
|
+
};
|
|
2149
|
+
const handleLeave = e => {
|
|
2150
|
+
const target = e.target || {};
|
|
2151
|
+
if (target.preloadTimeout) {
|
|
2152
|
+
clearTimeout(target.preloadTimeout);
|
|
2153
|
+
target.preloadTimeout = null;
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
return {
|
|
2157
|
+
type: 'internal',
|
|
2158
|
+
next,
|
|
2159
|
+
handleFocus,
|
|
2160
|
+
handleClick,
|
|
2161
|
+
handleEnter,
|
|
2162
|
+
handleLeave,
|
|
2163
|
+
handleTouchStart,
|
|
2164
|
+
isActive,
|
|
2165
|
+
disabled
|
|
2166
|
+
};
|
|
2167
|
+
};
|
|
2168
|
+
matchRoute = (location, opts) => {
|
|
2169
|
+
location = {
|
|
2170
|
+
...location,
|
|
2171
|
+
to: location.to ? this.resolvePathWithBase(location.from || '', location.to) : undefined
|
|
2172
|
+
};
|
|
2173
|
+
const next = this.buildLocation(location);
|
|
2174
|
+
if (opts?.pending && this.state.status !== 'pending') {
|
|
2175
|
+
return false;
|
|
2731
2176
|
}
|
|
2732
|
-
|
|
2733
|
-
return coreRouter;
|
|
2734
|
-
}
|
|
2735
|
-
function RouterProvider(_ref2) {
|
|
2736
|
-
var _router$options$useCo;
|
|
2177
|
+
const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
|
|
2737
2178
|
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
rest = _objectWithoutPropertiesLoose(_ref2, _excluded3);
|
|
2743
|
-
|
|
2744
|
-
router.update(rest);
|
|
2745
|
-
const defaultRouterContext = React.useRef({});
|
|
2746
|
-
const userContext = (_router$options$useCo = router.options.useContext == null ? void 0 : router.options.useContext()) != null ? _router$options$useCo : defaultRouterContext.current;
|
|
2747
|
-
router.context = userContext;
|
|
2748
|
-
useRouterSubscription(router);
|
|
2749
|
-
React.useEffect(() => {
|
|
2750
|
-
return router.mount();
|
|
2751
|
-
}, [router]);
|
|
2752
|
-
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
2753
|
-
value: {
|
|
2754
|
-
router: router
|
|
2179
|
+
// const baseLocation = state.resolvedLocation
|
|
2180
|
+
|
|
2181
|
+
if (!baseLocation) {
|
|
2182
|
+
return false;
|
|
2755
2183
|
}
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
}
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2184
|
+
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
2185
|
+
...opts,
|
|
2186
|
+
to: next.pathname
|
|
2187
|
+
});
|
|
2188
|
+
if (!match) {
|
|
2189
|
+
return false;
|
|
2190
|
+
}
|
|
2191
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
2192
|
+
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
2193
|
+
}
|
|
2194
|
+
return match;
|
|
2195
|
+
};
|
|
2196
|
+
injectHtml = async html => {
|
|
2197
|
+
this.injectedHtml.push(html);
|
|
2198
|
+
};
|
|
2199
|
+
dehydrateData = (key, getData) => {
|
|
2200
|
+
if (typeof document === 'undefined') {
|
|
2201
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2202
|
+
this.injectHtml(async () => {
|
|
2203
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2204
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2205
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2206
|
+
;(() => {
|
|
2207
|
+
var el = document.getElementById('${id}')
|
|
2208
|
+
el.parentElement.removeChild(el)
|
|
2209
|
+
})()
|
|
2210
|
+
</script>`;
|
|
2211
|
+
});
|
|
2212
|
+
return () => this.hydrateData(key);
|
|
2213
|
+
}
|
|
2214
|
+
return () => undefined;
|
|
2215
|
+
};
|
|
2216
|
+
hydrateData = key => {
|
|
2217
|
+
if (typeof document !== 'undefined') {
|
|
2218
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2219
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2220
|
+
}
|
|
2221
|
+
return undefined;
|
|
2222
|
+
};
|
|
2775
2223
|
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2224
|
+
// dehydrate = (): DehydratedRouter => {
|
|
2225
|
+
// return {
|
|
2226
|
+
// state: {
|
|
2227
|
+
// dehydratedMatches: this.state.matches.map((d) =>
|
|
2228
|
+
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
2229
|
+
// ),
|
|
2230
|
+
// },
|
|
2231
|
+
// }
|
|
2232
|
+
// }
|
|
2233
|
+
|
|
2234
|
+
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
2235
|
+
// let _ctx = __do_not_use_server_ctx
|
|
2236
|
+
// // Client hydrates from window
|
|
2237
|
+
// if (typeof document !== 'undefined') {
|
|
2238
|
+
// _ctx = window.__TSR_DEHYDRATED__
|
|
2239
|
+
// }
|
|
2240
|
+
|
|
2241
|
+
// invariant(
|
|
2242
|
+
// _ctx,
|
|
2243
|
+
// 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
|
|
2244
|
+
// )
|
|
2245
|
+
|
|
2246
|
+
// const ctx = _ctx
|
|
2247
|
+
// this.dehydratedData = ctx.payload as any
|
|
2248
|
+
// this.options.hydrate?.(ctx.payload as any)
|
|
2249
|
+
// const dehydratedState = ctx.router.state
|
|
2250
|
+
|
|
2251
|
+
// let matches = this.matchRoutes(
|
|
2252
|
+
// this.state.location.pathname,
|
|
2253
|
+
// this.state.location.search,
|
|
2254
|
+
// ).map((match) => {
|
|
2255
|
+
// const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
2256
|
+
// (d) => d.id === match.id,
|
|
2257
|
+
// )
|
|
2258
|
+
|
|
2259
|
+
// invariant(
|
|
2260
|
+
// dehydratedMatch,
|
|
2261
|
+
// `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
2262
|
+
// )
|
|
2263
|
+
|
|
2264
|
+
// if (dehydratedMatch) {
|
|
2265
|
+
// return {
|
|
2266
|
+
// ...match,
|
|
2267
|
+
// ...dehydratedMatch,
|
|
2268
|
+
// }
|
|
2269
|
+
// }
|
|
2270
|
+
// return match
|
|
2271
|
+
// })
|
|
2272
|
+
|
|
2273
|
+
// this.setState((s) => {
|
|
2274
|
+
// return {
|
|
2275
|
+
// ...s,
|
|
2276
|
+
// matches: dehydratedState.dehydratedMatches as any,
|
|
2277
|
+
// }
|
|
2278
|
+
// })
|
|
2279
|
+
// }
|
|
2280
|
+
|
|
2281
|
+
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
2282
|
+
// state.matches
|
|
2283
|
+
// .find((d) => d.id === matchId)
|
|
2284
|
+
// ?.__promisesByKey[key]?.resolve(value)
|
|
2285
|
+
// }
|
|
2783
2286
|
}
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
return
|
|
2287
|
+
|
|
2288
|
+
// A function that takes an import() argument which is a function and returns a new function that will
|
|
2289
|
+
// proxy arguments from the caller to the imported function, retaining all type
|
|
2290
|
+
// information along the way
|
|
2291
|
+
function lazyFn(fn, key) {
|
|
2292
|
+
return async (...args) => {
|
|
2293
|
+
const imported = await fn();
|
|
2294
|
+
return imported[key || 'default'](...args);
|
|
2295
|
+
};
|
|
2790
2296
|
}
|
|
2791
|
-
function
|
|
2792
|
-
|
|
2793
|
-
return /*#__PURE__*/React.createElement(router.MatchRoute, props);
|
|
2297
|
+
function isCtrlEvent(e) {
|
|
2298
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
2794
2299
|
}
|
|
2795
|
-
function Outlet() {
|
|
2796
|
-
var _ref3, _match$__$pendingComp, _match$__$errorCompon;
|
|
2797
2300
|
|
|
2301
|
+
const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
2302
|
+
const windowKey = 'window';
|
|
2303
|
+
const delimiter = '___';
|
|
2304
|
+
let weakScrolledElements = new WeakSet();
|
|
2305
|
+
let cache;
|
|
2306
|
+
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2307
|
+
const defaultGetKey = location => location.state.key;
|
|
2308
|
+
function useScrollRestoration(options) {
|
|
2798
2309
|
const router = useRouter();
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2310
|
+
useLayoutEffect(() => {
|
|
2311
|
+
const getKey = options?.getKey || defaultGetKey;
|
|
2312
|
+
if (sessionsStorage) {
|
|
2313
|
+
if (!cache) {
|
|
2314
|
+
cache = (() => {
|
|
2315
|
+
const storageKey = 'tsr-scroll-restoration-v2';
|
|
2316
|
+
const state = JSON.parse(window.sessionStorage.getItem(storageKey) || 'null') || {
|
|
2317
|
+
cached: {},
|
|
2318
|
+
next: {}
|
|
2319
|
+
};
|
|
2320
|
+
return {
|
|
2321
|
+
state,
|
|
2322
|
+
set: updater => {
|
|
2323
|
+
cache.state = functionalUpdate(updater, cache.state);
|
|
2324
|
+
window.sessionStorage.setItem(storageKey, JSON.stringify(cache.state));
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
})();
|
|
2328
|
+
}
|
|
2818
2329
|
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2330
|
+
const {
|
|
2331
|
+
history
|
|
2332
|
+
} = window;
|
|
2333
|
+
if (history.scrollRestoration) {
|
|
2334
|
+
history.scrollRestoration = 'manual';
|
|
2824
2335
|
}
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2336
|
+
const onScroll = event => {
|
|
2337
|
+
if (weakScrolledElements.has(event.target)) return;
|
|
2338
|
+
weakScrolledElements.add(event.target);
|
|
2339
|
+
const elementSelector = event.target === document || event.target === window ? windowKey : getCssSelector(event.target);
|
|
2340
|
+
if (!cache.state.next[elementSelector]) {
|
|
2341
|
+
cache.set(c => ({
|
|
2342
|
+
...c,
|
|
2343
|
+
next: {
|
|
2344
|
+
...c.next,
|
|
2345
|
+
[elementSelector]: {
|
|
2346
|
+
scrollX: NaN,
|
|
2347
|
+
scrollY: NaN
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
}));
|
|
2351
|
+
}
|
|
2835
2352
|
};
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
var _this$props$errorComp;
|
|
2848
|
-
|
|
2849
|
-
const errorComponent = (_this$props$errorComp = this.props.errorComponent) != null ? _this$props$errorComp : DefaultErrorBoundary;
|
|
2850
|
-
|
|
2851
|
-
if (this.state.error) {
|
|
2852
|
-
return /*#__PURE__*/React.createElement(errorComponent, this.state);
|
|
2353
|
+
const getCssSelector = el => {
|
|
2354
|
+
let path = [],
|
|
2355
|
+
parent;
|
|
2356
|
+
while (parent = el.parentNode) {
|
|
2357
|
+
path.unshift(`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el) + 1})`);
|
|
2358
|
+
el = parent;
|
|
2359
|
+
}
|
|
2360
|
+
return `${path.join(' > ')}`.toLowerCase();
|
|
2361
|
+
};
|
|
2362
|
+
if (typeof document !== 'undefined') {
|
|
2363
|
+
document.addEventListener('scroll', onScroll, true);
|
|
2853
2364
|
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2365
|
+
const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', event => {
|
|
2366
|
+
if (event.pathChanged) {
|
|
2367
|
+
const restoreKey = getKey(event.fromLocation);
|
|
2368
|
+
for (const elementSelector in cache.state.next) {
|
|
2369
|
+
const entry = cache.state.next[elementSelector];
|
|
2370
|
+
if (elementSelector === windowKey) {
|
|
2371
|
+
entry.scrollX = window.scrollX || 0;
|
|
2372
|
+
entry.scrollY = window.scrollY || 0;
|
|
2373
|
+
} else if (elementSelector) {
|
|
2374
|
+
const element = document.querySelector(elementSelector);
|
|
2375
|
+
entry.scrollX = element?.scrollLeft || 0;
|
|
2376
|
+
entry.scrollY = element?.scrollTop || 0;
|
|
2377
|
+
}
|
|
2378
|
+
cache.set(c => {
|
|
2379
|
+
const next = {
|
|
2380
|
+
...c.next
|
|
2381
|
+
};
|
|
2382
|
+
delete next[elementSelector];
|
|
2383
|
+
return {
|
|
2384
|
+
...c,
|
|
2385
|
+
next,
|
|
2386
|
+
cached: {
|
|
2387
|
+
...c.cached,
|
|
2388
|
+
[[restoreKey, elementSelector].join(delimiter)]: entry
|
|
2389
|
+
}
|
|
2390
|
+
};
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
});
|
|
2395
|
+
const unsubOnResolved = router.subscribe('onResolved', event => {
|
|
2396
|
+
if (event.pathChanged) {
|
|
2397
|
+
if (!router.resetNextScroll) {
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2400
|
+
router.resetNextScroll = true;
|
|
2401
|
+
const getKey = options?.getKey || defaultGetKey;
|
|
2402
|
+
const restoreKey = getKey(event.toLocation);
|
|
2403
|
+
let windowRestored = false;
|
|
2404
|
+
for (const cacheKey in cache.state.cached) {
|
|
2405
|
+
const entry = cache.state.cached[cacheKey];
|
|
2406
|
+
const [key, elementSelector] = cacheKey.split(delimiter);
|
|
2407
|
+
if (key === restoreKey) {
|
|
2408
|
+
if (elementSelector === windowKey) {
|
|
2409
|
+
windowRestored = true;
|
|
2410
|
+
window.scrollTo(entry.scrollX, entry.scrollY);
|
|
2411
|
+
} else if (elementSelector) {
|
|
2412
|
+
const element = document.querySelector(elementSelector);
|
|
2413
|
+
if (element) {
|
|
2414
|
+
element.scrollLeft = entry.scrollX;
|
|
2415
|
+
element.scrollTop = entry.scrollY;
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
if (!windowRestored) {
|
|
2421
|
+
window.scrollTo(0, 0);
|
|
2422
|
+
}
|
|
2423
|
+
cache.set(c => ({
|
|
2424
|
+
...c,
|
|
2425
|
+
next: {}
|
|
2426
|
+
}));
|
|
2427
|
+
weakScrolledElements = new WeakSet();
|
|
2428
|
+
}
|
|
2429
|
+
});
|
|
2430
|
+
return () => {
|
|
2431
|
+
document.removeEventListener('scroll', onScroll);
|
|
2432
|
+
unsubOnBeforeLoad();
|
|
2433
|
+
unsubOnResolved();
|
|
2434
|
+
};
|
|
2435
|
+
}, []);
|
|
2858
2436
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
error
|
|
2863
|
-
} = _ref6;
|
|
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)));
|
|
2437
|
+
function ScrollRestoration(props) {
|
|
2438
|
+
useScrollRestoration(props);
|
|
2439
|
+
return null;
|
|
2886
2440
|
}
|
|
2887
|
-
|
|
2888
|
-
|
|
2441
|
+
|
|
2442
|
+
function useBlocker(message, condition = true) {
|
|
2443
|
+
const {
|
|
2444
|
+
history
|
|
2445
|
+
} = useRouter();
|
|
2889
2446
|
React.useEffect(() => {
|
|
2890
|
-
if (!
|
|
2891
|
-
let unblock =
|
|
2447
|
+
if (!condition) return;
|
|
2448
|
+
let unblock = history.block((retry, cancel) => {
|
|
2892
2449
|
if (window.confirm(message)) {
|
|
2893
2450
|
unblock();
|
|
2894
|
-
|
|
2895
|
-
} else {
|
|
2896
|
-
router.location.pathname = window.location.pathname;
|
|
2451
|
+
retry();
|
|
2897
2452
|
}
|
|
2898
2453
|
});
|
|
2899
2454
|
return unblock;
|
|
2900
|
-
}
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
function Block({
|
|
2458
|
+
message,
|
|
2459
|
+
condition,
|
|
2460
|
+
children
|
|
2461
|
+
}) {
|
|
2462
|
+
useBlocker(message, condition);
|
|
2463
|
+
return children ?? null;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
function useNavigate(defaultOpts) {
|
|
2467
|
+
const {
|
|
2468
|
+
navigate
|
|
2469
|
+
} = useRouter();
|
|
2470
|
+
const match = useMatch({
|
|
2471
|
+
strict: false
|
|
2472
|
+
});
|
|
2473
|
+
return React.useCallback(opts => {
|
|
2474
|
+
return navigate({
|
|
2475
|
+
from: opts?.to ? match.pathname : undefined,
|
|
2476
|
+
...defaultOpts,
|
|
2477
|
+
...opts
|
|
2478
|
+
});
|
|
2479
|
+
}, []);
|
|
2901
2480
|
}
|
|
2902
|
-
function
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2481
|
+
function typedNavigate(navigate) {
|
|
2482
|
+
return navigate;
|
|
2483
|
+
} //
|
|
2484
|
+
|
|
2485
|
+
function Navigate(props) {
|
|
2486
|
+
const {
|
|
2487
|
+
navigate
|
|
2488
|
+
} = useRouter();
|
|
2489
|
+
const match = useMatch({
|
|
2490
|
+
strict: false
|
|
2491
|
+
});
|
|
2492
|
+
useLayoutEffect$1(() => {
|
|
2493
|
+
navigate({
|
|
2494
|
+
from: props.to ? match.pathname : undefined,
|
|
2495
|
+
...props
|
|
2496
|
+
});
|
|
2497
|
+
}, []);
|
|
2498
|
+
return null;
|
|
2910
2499
|
}
|
|
2911
2500
|
|
|
2912
|
-
export {
|
|
2501
|
+
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, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2913
2502
|
//# sourceMappingURL=index.js.map
|