@tanstack/router-core 0.0.1-beta.45 → 0.0.1-beta.49
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/build/cjs/actions.js +94 -0
- package/build/cjs/actions.js.map +1 -0
- package/build/cjs/history.js +163 -0
- package/build/cjs/history.js.map +1 -0
- package/build/cjs/index.js +18 -20
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/interop.js +175 -0
- package/build/cjs/interop.js.map +1 -0
- package/build/cjs/path.js +4 -5
- package/build/cjs/path.js.map +1 -1
- package/build/cjs/route.js +16 -138
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/routeConfig.js +1 -7
- package/build/cjs/routeConfig.js.map +1 -1
- package/build/cjs/routeMatch.js +194 -199
- package/build/cjs/routeMatch.js.map +1 -1
- package/build/cjs/router.js +726 -703
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/store.js +54 -0
- package/build/cjs/store.js.map +1 -0
- package/build/esm/index.js +1305 -1114
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +229 -192
- package/build/types/index.d.ts +172 -109
- package/build/umd/index.development.js +1381 -2331
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +3 -3
- package/src/actions.ts +157 -0
- package/src/history.ts +199 -0
- package/src/index.ts +4 -7
- package/src/interop.ts +169 -0
- package/src/link.ts +2 -2
- package/src/route.ts +34 -239
- package/src/routeConfig.ts +3 -34
- package/src/routeInfo.ts +6 -21
- package/src/routeMatch.ts +270 -285
- package/src/router.ts +967 -963
- package/src/store.ts +52 -0
- package/build/cjs/sharedClone.js +0 -122
- package/build/cjs/sharedClone.js.map +0 -1
- package/src/sharedClone.ts +0 -118
|
@@ -9,1901 +9,783 @@
|
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
11
|
(function (global, factory) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
13
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
14
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RouterCore = {}));
|
|
15
15
|
})(this, (function (exports) { 'use strict';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
for (var key in source) {
|
|
22
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
23
|
-
target[key] = source[key];
|
|
24
|
-
}
|
|
17
|
+
var prefix = 'Invariant failed';
|
|
18
|
+
function invariant(condition, message) {
|
|
19
|
+
if (condition) {
|
|
20
|
+
return;
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
* entries in the stack are lost.
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
Action["Push"] = "PUSH";
|
|
55
|
-
/**
|
|
56
|
-
* A REPLACE indicates the entry at the current index in the history stack
|
|
57
|
-
* being replaced by a new one.
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
Action["Replace"] = "REPLACE";
|
|
61
|
-
})(Action || (Action = {}));
|
|
62
|
-
|
|
63
|
-
var readOnly = function (obj) {
|
|
64
|
-
return Object.freeze(obj);
|
|
65
|
-
} ;
|
|
66
|
-
|
|
67
|
-
function warning$1(cond, message) {
|
|
68
|
-
if (!cond) {
|
|
69
|
-
// eslint-disable-next-line no-console
|
|
70
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
// Welcome to debugging history!
|
|
74
|
-
//
|
|
75
|
-
// This error is thrown as a convenience so you can more easily
|
|
76
|
-
// find the source for a warning that appears in the console by
|
|
77
|
-
// enabling "pause on exceptions" in your JavaScript debugger.
|
|
78
|
-
throw new Error(message); // eslint-disable-next-line no-empty
|
|
79
|
-
} catch (e) {}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
var BeforeUnloadEventType = 'beforeunload';
|
|
84
|
-
var HashChangeEventType = 'hashchange';
|
|
85
|
-
var PopStateEventType = 'popstate';
|
|
86
|
-
/**
|
|
87
|
-
* Browser history stores the location in regular URLs. This is the standard for
|
|
88
|
-
* most web apps, but it requires some configuration on the server to ensure you
|
|
89
|
-
* serve the same app at multiple URLs.
|
|
90
|
-
*
|
|
91
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
function createBrowserHistory(options) {
|
|
95
|
-
if (options === void 0) {
|
|
96
|
-
options = {};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
var _options = options,
|
|
100
|
-
_options$window = _options.window,
|
|
101
|
-
window = _options$window === void 0 ? document.defaultView : _options$window;
|
|
102
|
-
var globalHistory = window.history;
|
|
103
|
-
|
|
104
|
-
function getIndexAndLocation() {
|
|
105
|
-
var _window$location = window.location,
|
|
106
|
-
pathname = _window$location.pathname,
|
|
107
|
-
search = _window$location.search,
|
|
108
|
-
hash = _window$location.hash;
|
|
109
|
-
var state = globalHistory.state || {};
|
|
110
|
-
return [state.idx, readOnly({
|
|
111
|
-
pathname: pathname,
|
|
112
|
-
search: search,
|
|
113
|
-
hash: hash,
|
|
114
|
-
state: state.usr || null,
|
|
115
|
-
key: state.key || 'default'
|
|
116
|
-
})];
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
var blockedPopTx = null;
|
|
120
|
-
|
|
121
|
-
function handlePop() {
|
|
122
|
-
if (blockedPopTx) {
|
|
123
|
-
blockers.call(blockedPopTx);
|
|
124
|
-
blockedPopTx = null;
|
|
125
|
-
} else {
|
|
126
|
-
var nextAction = Action.Pop;
|
|
127
|
-
|
|
128
|
-
var _getIndexAndLocation = getIndexAndLocation(),
|
|
129
|
-
nextIndex = _getIndexAndLocation[0],
|
|
130
|
-
nextLocation = _getIndexAndLocation[1];
|
|
131
|
-
|
|
132
|
-
if (blockers.length) {
|
|
133
|
-
if (nextIndex != null) {
|
|
134
|
-
var delta = index - nextIndex;
|
|
135
|
-
|
|
136
|
-
if (delta) {
|
|
137
|
-
// Revert the POP
|
|
138
|
-
blockedPopTx = {
|
|
139
|
-
action: nextAction,
|
|
140
|
-
location: nextLocation,
|
|
141
|
-
retry: function retry() {
|
|
142
|
-
go(delta * -1);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
go(delta);
|
|
146
|
-
}
|
|
147
|
-
} else {
|
|
148
|
-
// Trying to POP to a location with no index. We did not create
|
|
149
|
-
// this location, so we can't effectively block the navigation.
|
|
150
|
-
warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
|
|
151
|
-
// detail and link to it here so people can understand better what
|
|
152
|
-
// is going on and how to avoid it.
|
|
153
|
-
"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.") ;
|
|
22
|
+
var provided = typeof message === 'function' ? message() : message;
|
|
23
|
+
var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
|
|
24
|
+
throw new Error(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// While the public API was clearly inspired by the "history" npm package,
|
|
28
|
+
// This implementation attempts to be more lightweight by
|
|
29
|
+
// making assumptions about the way TanStack Router works
|
|
30
|
+
|
|
31
|
+
const popStateEvent = 'popstate';
|
|
32
|
+
function createHistory(opts) {
|
|
33
|
+
let currentLocation = opts.getLocation();
|
|
34
|
+
let unsub = () => {};
|
|
35
|
+
let listeners = new Set();
|
|
36
|
+
const onUpdate = () => {
|
|
37
|
+
currentLocation = opts.getLocation();
|
|
38
|
+
listeners.forEach(listener => listener());
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
get location() {
|
|
42
|
+
return currentLocation;
|
|
43
|
+
},
|
|
44
|
+
listen: cb => {
|
|
45
|
+
if (listeners.size === 0) {
|
|
46
|
+
unsub = opts.listener(onUpdate);
|
|
154
47
|
}
|
|
155
|
-
|
|
156
|
-
|
|
48
|
+
listeners.add(cb);
|
|
49
|
+
return () => {
|
|
50
|
+
listeners.delete(cb);
|
|
51
|
+
if (listeners.size === 0) {
|
|
52
|
+
unsub();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
push: (path, state) => {
|
|
57
|
+
opts.pushState(path, state);
|
|
58
|
+
onUpdate();
|
|
59
|
+
},
|
|
60
|
+
replace: (path, state) => {
|
|
61
|
+
opts.replaceState(path, state);
|
|
62
|
+
onUpdate();
|
|
63
|
+
},
|
|
64
|
+
go: index => {
|
|
65
|
+
opts.go(index);
|
|
66
|
+
onUpdate();
|
|
67
|
+
},
|
|
68
|
+
back: () => {
|
|
69
|
+
opts.back();
|
|
70
|
+
onUpdate();
|
|
71
|
+
},
|
|
72
|
+
forward: () => {
|
|
73
|
+
opts.forward();
|
|
74
|
+
onUpdate();
|
|
157
75
|
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
window.addEventListener(PopStateEventType, handlePop);
|
|
162
|
-
var action = Action.Pop;
|
|
163
|
-
|
|
164
|
-
var _getIndexAndLocation2 = getIndexAndLocation(),
|
|
165
|
-
index = _getIndexAndLocation2[0],
|
|
166
|
-
location = _getIndexAndLocation2[1];
|
|
167
|
-
|
|
168
|
-
var listeners = createEvents();
|
|
169
|
-
var blockers = createEvents();
|
|
170
|
-
|
|
171
|
-
if (index == null) {
|
|
172
|
-
index = 0;
|
|
173
|
-
globalHistory.replaceState(_extends({}, globalHistory.state, {
|
|
174
|
-
idx: index
|
|
175
|
-
}), '');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function createHref(to) {
|
|
179
|
-
return typeof to === 'string' ? to : createPath(to);
|
|
180
|
-
} // state defaults to `null` because `window.history.state` does
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
function getNextLocation(to, state) {
|
|
184
|
-
if (state === void 0) {
|
|
185
|
-
state = null;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return readOnly(_extends({
|
|
189
|
-
pathname: location.pathname,
|
|
190
|
-
hash: '',
|
|
191
|
-
search: ''
|
|
192
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
193
|
-
state: state,
|
|
194
|
-
key: createKey()
|
|
195
|
-
}));
|
|
76
|
+
};
|
|
196
77
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
78
|
+
function createBrowserHistory(opts) {
|
|
79
|
+
const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.hash}${window.location.search}`);
|
|
80
|
+
const createHref = opts?.createHref ?? (path => path);
|
|
81
|
+
const getLocation = () => parseLocation(getHref(), history.state);
|
|
82
|
+
return createHistory({
|
|
83
|
+
getLocation,
|
|
84
|
+
listener: onUpdate => {
|
|
85
|
+
window.addEventListener(popStateEvent, onUpdate);
|
|
86
|
+
return () => {
|
|
87
|
+
window.removeEventListener(popStateEvent, onUpdate);
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
pushState: (path, state) => {
|
|
91
|
+
window.history.pushState({
|
|
92
|
+
...state,
|
|
93
|
+
key: createRandomKey()
|
|
94
|
+
}, '', createHref(path));
|
|
95
|
+
},
|
|
96
|
+
replaceState: (path, state) => {
|
|
97
|
+
window.history.replaceState({
|
|
98
|
+
...state,
|
|
99
|
+
key: createRandomKey()
|
|
100
|
+
}, '', createHref(path));
|
|
101
|
+
},
|
|
102
|
+
back: () => window.history.back(),
|
|
103
|
+
forward: () => window.history.forward(),
|
|
104
|
+
go: n => window.history.go(n)
|
|
105
|
+
});
|
|
204
106
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
retry: retry
|
|
211
|
-
}), false);
|
|
107
|
+
function createHashHistory() {
|
|
108
|
+
return createBrowserHistory({
|
|
109
|
+
getHref: () => window.location.hash.substring(1),
|
|
110
|
+
createHref: path => `#${path}`
|
|
111
|
+
});
|
|
212
112
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
113
|
+
function createMemoryHistory(opts = {
|
|
114
|
+
initialEntries: ['/']
|
|
115
|
+
}) {
|
|
116
|
+
const entries = opts.initialEntries;
|
|
117
|
+
let index = opts.initialIndex ?? entries.length - 1;
|
|
118
|
+
let currentState = {};
|
|
119
|
+
const getLocation = () => parseLocation(entries[index], currentState);
|
|
120
|
+
return createHistory({
|
|
121
|
+
getLocation,
|
|
122
|
+
listener: onUpdate => {
|
|
123
|
+
window.addEventListener(popStateEvent, onUpdate);
|
|
124
|
+
// We might need to handle the hashchange event in the future
|
|
125
|
+
// window.addEventListener(hashChangeEvent, onUpdate)
|
|
126
|
+
return () => {
|
|
127
|
+
window.removeEventListener(popStateEvent, onUpdate);
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
pushState: (path, state) => {
|
|
131
|
+
currentState = {
|
|
132
|
+
...state,
|
|
133
|
+
key: createRandomKey()
|
|
134
|
+
};
|
|
135
|
+
entries.push(path);
|
|
136
|
+
index++;
|
|
137
|
+
},
|
|
138
|
+
replaceState: (path, state) => {
|
|
139
|
+
currentState = {
|
|
140
|
+
...state,
|
|
141
|
+
key: createRandomKey()
|
|
142
|
+
};
|
|
143
|
+
entries[index] = path;
|
|
144
|
+
},
|
|
145
|
+
back: () => {
|
|
146
|
+
index--;
|
|
147
|
+
},
|
|
148
|
+
forward: () => {
|
|
149
|
+
index = Math.min(index + 1, entries.length - 1);
|
|
150
|
+
},
|
|
151
|
+
go: n => window.history.go(n)
|
|
224
152
|
});
|
|
225
153
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
historyState = _getHistoryStateAndUr[0],
|
|
238
|
-
url = _getHistoryStateAndUr[1]; // TODO: Support forced reloading
|
|
239
|
-
// try...catch because iOS limits us to 100 pushState calls :/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
try {
|
|
243
|
-
globalHistory.pushState(historyState, '', url);
|
|
244
|
-
} catch (error) {
|
|
245
|
-
// They are going to lose state here, but there is no real
|
|
246
|
-
// way to warn them about it since the page will refresh...
|
|
247
|
-
window.location.assign(url);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
applyTx(nextAction);
|
|
251
|
-
}
|
|
154
|
+
function parseLocation(href, state) {
|
|
155
|
+
let hashIndex = href.indexOf('#');
|
|
156
|
+
let searchIndex = href.indexOf('?');
|
|
157
|
+
const pathEnd = Math.min(hashIndex, searchIndex);
|
|
158
|
+
return {
|
|
159
|
+
href,
|
|
160
|
+
pathname: pathEnd > -1 ? href.substring(0, pathEnd) : href,
|
|
161
|
+
hash: hashIndex > -1 ? href.substring(hashIndex, searchIndex) : '',
|
|
162
|
+
search: searchIndex > -1 ? href.substring(searchIndex) : '',
|
|
163
|
+
state
|
|
164
|
+
};
|
|
252
165
|
}
|
|
253
166
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
function retry() {
|
|
259
|
-
replace(to, state);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
263
|
-
var _getHistoryStateAndUr2 = getHistoryStateAndUrl(nextLocation, index),
|
|
264
|
-
historyState = _getHistoryStateAndUr2[0],
|
|
265
|
-
url = _getHistoryStateAndUr2[1]; // TODO: Support forced reloading
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
globalHistory.replaceState(historyState, '', url);
|
|
269
|
-
applyTx(nextAction);
|
|
270
|
-
}
|
|
167
|
+
// Thanks co-pilot!
|
|
168
|
+
function createRandomKey() {
|
|
169
|
+
return (Math.random() + 1).toString(36).substring(7);
|
|
271
170
|
}
|
|
272
171
|
|
|
273
|
-
function
|
|
274
|
-
|
|
172
|
+
function last(arr) {
|
|
173
|
+
return arr[arr.length - 1];
|
|
275
174
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
get location() {
|
|
283
|
-
return location;
|
|
284
|
-
},
|
|
285
|
-
|
|
286
|
-
createHref: createHref,
|
|
287
|
-
push: push,
|
|
288
|
-
replace: replace,
|
|
289
|
-
go: go,
|
|
290
|
-
back: function back() {
|
|
291
|
-
go(-1);
|
|
292
|
-
},
|
|
293
|
-
forward: function forward() {
|
|
294
|
-
go(1);
|
|
295
|
-
},
|
|
296
|
-
listen: function listen(listener) {
|
|
297
|
-
return listeners.push(listener);
|
|
298
|
-
},
|
|
299
|
-
block: function block(blocker) {
|
|
300
|
-
var unblock = blockers.push(blocker);
|
|
301
|
-
|
|
302
|
-
if (blockers.length === 1) {
|
|
303
|
-
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return function () {
|
|
307
|
-
unblock(); // Remove the beforeunload listener so the document may
|
|
308
|
-
// still be salvageable in the pagehide event.
|
|
309
|
-
// See https://html.spec.whatwg.org/#unloading-documents
|
|
310
|
-
|
|
311
|
-
if (!blockers.length) {
|
|
312
|
-
window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
313
|
-
}
|
|
314
|
-
};
|
|
175
|
+
function warning(cond, message) {
|
|
176
|
+
if (cond) {
|
|
177
|
+
if (typeof console !== 'undefined') console.warn(message);
|
|
178
|
+
try {
|
|
179
|
+
throw new Error(message);
|
|
180
|
+
} catch {}
|
|
315
181
|
}
|
|
316
|
-
|
|
317
|
-
return history;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Hash history stores the location in window.location.hash. This makes it ideal
|
|
321
|
-
* for situations where you don't want to send the location to the server for
|
|
322
|
-
* some reason, either because you do cannot configure it or the URL space is
|
|
323
|
-
* reserved for something else.
|
|
324
|
-
*
|
|
325
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
|
|
326
|
-
*/
|
|
327
|
-
|
|
328
|
-
function createHashHistory(options) {
|
|
329
|
-
if (options === void 0) {
|
|
330
|
-
options = {};
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
var _options2 = options,
|
|
334
|
-
_options2$window = _options2.window,
|
|
335
|
-
window = _options2$window === void 0 ? document.defaultView : _options2$window;
|
|
336
|
-
var globalHistory = window.history;
|
|
337
|
-
|
|
338
|
-
function getIndexAndLocation() {
|
|
339
|
-
var _parsePath = parsePath(window.location.hash.substr(1)),
|
|
340
|
-
_parsePath$pathname = _parsePath.pathname,
|
|
341
|
-
pathname = _parsePath$pathname === void 0 ? '/' : _parsePath$pathname,
|
|
342
|
-
_parsePath$search = _parsePath.search,
|
|
343
|
-
search = _parsePath$search === void 0 ? '' : _parsePath$search,
|
|
344
|
-
_parsePath$hash = _parsePath.hash,
|
|
345
|
-
hash = _parsePath$hash === void 0 ? '' : _parsePath$hash;
|
|
346
|
-
|
|
347
|
-
var state = globalHistory.state || {};
|
|
348
|
-
return [state.idx, readOnly({
|
|
349
|
-
pathname: pathname,
|
|
350
|
-
search: search,
|
|
351
|
-
hash: hash,
|
|
352
|
-
state: state.usr || null,
|
|
353
|
-
key: state.key || 'default'
|
|
354
|
-
})];
|
|
182
|
+
return true;
|
|
355
183
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
function
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
184
|
+
function isFunction(d) {
|
|
185
|
+
return typeof d === 'function';
|
|
186
|
+
}
|
|
187
|
+
function functionalUpdate(updater, previous) {
|
|
188
|
+
if (isFunction(updater)) {
|
|
189
|
+
return updater(previous);
|
|
190
|
+
}
|
|
191
|
+
return updater;
|
|
192
|
+
}
|
|
193
|
+
function pick(parent, keys) {
|
|
194
|
+
return keys.reduce((obj, key) => {
|
|
195
|
+
obj[key] = parent[key];
|
|
196
|
+
return obj;
|
|
197
|
+
}, {});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function joinPaths(paths) {
|
|
201
|
+
return cleanPath(paths.filter(Boolean).join('/'));
|
|
202
|
+
}
|
|
203
|
+
function cleanPath(path) {
|
|
204
|
+
// remove double slashes
|
|
205
|
+
return path.replace(/\/{2,}/g, '/');
|
|
206
|
+
}
|
|
207
|
+
function trimPathLeft(path) {
|
|
208
|
+
return path === '/' ? path : path.replace(/^\/{1,}/, '');
|
|
209
|
+
}
|
|
210
|
+
function trimPathRight(path) {
|
|
211
|
+
return path === '/' ? path : path.replace(/\/{1,}$/, '');
|
|
212
|
+
}
|
|
213
|
+
function trimPath(path) {
|
|
214
|
+
return trimPathRight(trimPathLeft(path));
|
|
215
|
+
}
|
|
216
|
+
function resolvePath(basepath, base, to) {
|
|
217
|
+
base = base.replace(new RegExp(`^${basepath}`), '/');
|
|
218
|
+
to = to.replace(new RegExp(`^${basepath}`), '/');
|
|
219
|
+
let baseSegments = parsePathname(base);
|
|
220
|
+
const toSegments = parsePathname(to);
|
|
221
|
+
toSegments.forEach((toSegment, index) => {
|
|
222
|
+
if (toSegment.value === '/') {
|
|
223
|
+
if (!index) {
|
|
224
|
+
// Leading slash
|
|
225
|
+
baseSegments = [toSegment];
|
|
226
|
+
} else if (index === toSegments.length - 1) {
|
|
227
|
+
// Trailing Slash
|
|
228
|
+
baseSegments.push(toSegment);
|
|
229
|
+
} else ;
|
|
230
|
+
} else if (toSegment.value === '..') {
|
|
231
|
+
// Extra trailing slash? pop it off
|
|
232
|
+
if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
|
|
233
|
+
baseSegments.pop();
|
|
392
234
|
}
|
|
235
|
+
baseSegments.pop();
|
|
236
|
+
} else if (toSegment.value === '.') {
|
|
237
|
+
return;
|
|
393
238
|
} else {
|
|
394
|
-
|
|
239
|
+
baseSegments.push(toSegment);
|
|
395
240
|
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
window.addEventListener(PopStateEventType, handlePop); // popstate does not fire on hashchange in IE 11 and old (trident) Edge
|
|
400
|
-
// https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
|
|
401
|
-
|
|
402
|
-
window.addEventListener(HashChangeEventType, function () {
|
|
403
|
-
var _getIndexAndLocation5 = getIndexAndLocation(),
|
|
404
|
-
nextLocation = _getIndexAndLocation5[1]; // Ignore extraneous hashchange events.
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (createPath(nextLocation) !== createPath(location)) {
|
|
408
|
-
handlePop();
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
var action = Action.Pop;
|
|
412
|
-
|
|
413
|
-
var _getIndexAndLocation6 = getIndexAndLocation(),
|
|
414
|
-
index = _getIndexAndLocation6[0],
|
|
415
|
-
location = _getIndexAndLocation6[1];
|
|
416
|
-
|
|
417
|
-
var listeners = createEvents();
|
|
418
|
-
var blockers = createEvents();
|
|
419
|
-
|
|
420
|
-
if (index == null) {
|
|
421
|
-
index = 0;
|
|
422
|
-
globalHistory.replaceState(_extends({}, globalHistory.state, {
|
|
423
|
-
idx: index
|
|
424
|
-
}), '');
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function getBaseHref() {
|
|
428
|
-
var base = document.querySelector('base');
|
|
429
|
-
var href = '';
|
|
430
|
-
|
|
431
|
-
if (base && base.getAttribute('href')) {
|
|
432
|
-
var url = window.location.href;
|
|
433
|
-
var hashIndex = url.indexOf('#');
|
|
434
|
-
href = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return href;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function createHref(to) {
|
|
441
|
-
return getBaseHref() + '#' + (typeof to === 'string' ? to : createPath(to));
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
function getNextLocation(to, state) {
|
|
445
|
-
if (state === void 0) {
|
|
446
|
-
state = null;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return readOnly(_extends({
|
|
450
|
-
pathname: location.pathname,
|
|
451
|
-
hash: '',
|
|
452
|
-
search: ''
|
|
453
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
454
|
-
state: state,
|
|
455
|
-
key: createKey()
|
|
456
|
-
}));
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
function getHistoryStateAndUrl(nextLocation, index) {
|
|
460
|
-
return [{
|
|
461
|
-
usr: nextLocation.state,
|
|
462
|
-
key: nextLocation.key,
|
|
463
|
-
idx: index
|
|
464
|
-
}, createHref(nextLocation)];
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
function allowTx(action, location, retry) {
|
|
468
|
-
return !blockers.length || (blockers.call({
|
|
469
|
-
action: action,
|
|
470
|
-
location: location,
|
|
471
|
-
retry: retry
|
|
472
|
-
}), false);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
function applyTx(nextAction) {
|
|
476
|
-
action = nextAction;
|
|
477
|
-
|
|
478
|
-
var _getIndexAndLocation7 = getIndexAndLocation();
|
|
479
|
-
|
|
480
|
-
index = _getIndexAndLocation7[0];
|
|
481
|
-
location = _getIndexAndLocation7[1];
|
|
482
|
-
listeners.call({
|
|
483
|
-
action: action,
|
|
484
|
-
location: location
|
|
485
241
|
});
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
url = _getHistoryStateAndUr3[1]; // TODO: Support forced reloading
|
|
502
|
-
// try...catch because iOS limits us to 100 pushState calls :/
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
try {
|
|
506
|
-
globalHistory.pushState(historyState, '', url);
|
|
507
|
-
} catch (error) {
|
|
508
|
-
// They are going to lose state here, but there is no real
|
|
509
|
-
// way to warn them about it since the page will refresh...
|
|
510
|
-
window.location.assign(url);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
applyTx(nextAction);
|
|
242
|
+
const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
|
|
243
|
+
return cleanPath(joined);
|
|
244
|
+
}
|
|
245
|
+
function parsePathname(pathname) {
|
|
246
|
+
if (!pathname) {
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
pathname = cleanPath(pathname);
|
|
250
|
+
const segments = [];
|
|
251
|
+
if (pathname.slice(0, 1) === '/') {
|
|
252
|
+
pathname = pathname.substring(1);
|
|
253
|
+
segments.push({
|
|
254
|
+
type: 'pathname',
|
|
255
|
+
value: '/'
|
|
256
|
+
});
|
|
514
257
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
function replace(to, state) {
|
|
518
|
-
var nextAction = Action.Replace;
|
|
519
|
-
var nextLocation = getNextLocation(to, state);
|
|
520
|
-
|
|
521
|
-
function retry() {
|
|
522
|
-
replace(to, state);
|
|
258
|
+
if (!pathname) {
|
|
259
|
+
return segments;
|
|
523
260
|
}
|
|
524
261
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
globalHistory.replaceState(historyState, '', url);
|
|
534
|
-
applyTx(nextAction);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
function go(delta) {
|
|
539
|
-
globalHistory.go(delta);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
var history = {
|
|
543
|
-
get action() {
|
|
544
|
-
return action;
|
|
545
|
-
},
|
|
546
|
-
|
|
547
|
-
get location() {
|
|
548
|
-
return location;
|
|
549
|
-
},
|
|
550
|
-
|
|
551
|
-
createHref: createHref,
|
|
552
|
-
push: push,
|
|
553
|
-
replace: replace,
|
|
554
|
-
go: go,
|
|
555
|
-
back: function back() {
|
|
556
|
-
go(-1);
|
|
557
|
-
},
|
|
558
|
-
forward: function forward() {
|
|
559
|
-
go(1);
|
|
560
|
-
},
|
|
561
|
-
listen: function listen(listener) {
|
|
562
|
-
return listeners.push(listener);
|
|
563
|
-
},
|
|
564
|
-
block: function block(blocker) {
|
|
565
|
-
var unblock = blockers.push(blocker);
|
|
566
|
-
|
|
567
|
-
if (blockers.length === 1) {
|
|
568
|
-
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
262
|
+
// Remove empty segments and '.' segments
|
|
263
|
+
const split = pathname.split('/').filter(Boolean);
|
|
264
|
+
segments.push(...split.map(part => {
|
|
265
|
+
if (part.startsWith('*')) {
|
|
266
|
+
return {
|
|
267
|
+
type: 'wildcard',
|
|
268
|
+
value: part
|
|
269
|
+
};
|
|
569
270
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
271
|
+
if (part.charAt(0) === '$') {
|
|
272
|
+
return {
|
|
273
|
+
type: 'param',
|
|
274
|
+
value: part
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
type: 'pathname',
|
|
279
|
+
value: part
|
|
579
280
|
};
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
return history;
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* Memory history stores the current location in memory. It is designed for use
|
|
586
|
-
* in stateful non-browser environments like tests and React Native.
|
|
587
|
-
*
|
|
588
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#creatememoryhistory
|
|
589
|
-
*/
|
|
590
|
-
|
|
591
|
-
function createMemoryHistory(options) {
|
|
592
|
-
if (options === void 0) {
|
|
593
|
-
options = {};
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
var _options3 = options,
|
|
597
|
-
_options3$initialEntr = _options3.initialEntries,
|
|
598
|
-
initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
|
|
599
|
-
initialIndex = _options3.initialIndex;
|
|
600
|
-
var entries = initialEntries.map(function (entry) {
|
|
601
|
-
var location = readOnly(_extends({
|
|
602
|
-
pathname: '/',
|
|
603
|
-
search: '',
|
|
604
|
-
hash: '',
|
|
605
|
-
state: null,
|
|
606
|
-
key: createKey()
|
|
607
|
-
}, typeof entry === 'string' ? parsePath(entry) : entry));
|
|
608
|
-
warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: " + JSON.stringify(entry) + ")") ;
|
|
609
|
-
return location;
|
|
610
|
-
});
|
|
611
|
-
var index = clamp(initialIndex == null ? entries.length - 1 : initialIndex, 0, entries.length - 1);
|
|
612
|
-
var action = Action.Pop;
|
|
613
|
-
var location = entries[index];
|
|
614
|
-
var listeners = createEvents();
|
|
615
|
-
var blockers = createEvents();
|
|
616
|
-
|
|
617
|
-
function createHref(to) {
|
|
618
|
-
return typeof to === 'string' ? to : createPath(to);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
function getNextLocation(to, state) {
|
|
622
|
-
if (state === void 0) {
|
|
623
|
-
state = null;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
return readOnly(_extends({
|
|
627
|
-
pathname: location.pathname,
|
|
628
|
-
search: '',
|
|
629
|
-
hash: ''
|
|
630
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
631
|
-
state: state,
|
|
632
|
-
key: createKey()
|
|
633
281
|
}));
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
location: location,
|
|
640
|
-
retry: retry
|
|
641
|
-
}), false);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
function applyTx(nextAction, nextLocation) {
|
|
645
|
-
action = nextAction;
|
|
646
|
-
location = nextLocation;
|
|
647
|
-
listeners.call({
|
|
648
|
-
action: action,
|
|
649
|
-
location: location
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
function push(to, state) {
|
|
654
|
-
var nextAction = Action.Push;
|
|
655
|
-
var nextLocation = getNextLocation(to, state);
|
|
656
|
-
|
|
657
|
-
function retry() {
|
|
658
|
-
push(to, state);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.push(" + JSON.stringify(to) + ")") ;
|
|
662
|
-
|
|
663
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
664
|
-
index += 1;
|
|
665
|
-
entries.splice(index, entries.length, nextLocation);
|
|
666
|
-
applyTx(nextAction, nextLocation);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
function replace(to, state) {
|
|
671
|
-
var nextAction = Action.Replace;
|
|
672
|
-
var nextLocation = getNextLocation(to, state);
|
|
673
|
-
|
|
674
|
-
function retry() {
|
|
675
|
-
replace(to, state);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.replace(" + JSON.stringify(to) + ")") ;
|
|
679
|
-
|
|
680
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
681
|
-
entries[index] = nextLocation;
|
|
682
|
-
applyTx(nextAction, nextLocation);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
function go(delta) {
|
|
687
|
-
var nextIndex = clamp(index + delta, 0, entries.length - 1);
|
|
688
|
-
var nextAction = Action.Pop;
|
|
689
|
-
var nextLocation = entries[nextIndex];
|
|
690
|
-
|
|
691
|
-
function retry() {
|
|
692
|
-
go(delta);
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
696
|
-
index = nextIndex;
|
|
697
|
-
applyTx(nextAction, nextLocation);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
var history = {
|
|
702
|
-
get index() {
|
|
703
|
-
return index;
|
|
704
|
-
},
|
|
705
|
-
|
|
706
|
-
get action() {
|
|
707
|
-
return action;
|
|
708
|
-
},
|
|
709
|
-
|
|
710
|
-
get location() {
|
|
711
|
-
return location;
|
|
712
|
-
},
|
|
713
|
-
|
|
714
|
-
createHref: createHref,
|
|
715
|
-
push: push,
|
|
716
|
-
replace: replace,
|
|
717
|
-
go: go,
|
|
718
|
-
back: function back() {
|
|
719
|
-
go(-1);
|
|
720
|
-
},
|
|
721
|
-
forward: function forward() {
|
|
722
|
-
go(1);
|
|
723
|
-
},
|
|
724
|
-
listen: function listen(listener) {
|
|
725
|
-
return listeners.push(listener);
|
|
726
|
-
},
|
|
727
|
-
block: function block(blocker) {
|
|
728
|
-
return blockers.push(blocker);
|
|
729
|
-
}
|
|
730
|
-
};
|
|
731
|
-
return history;
|
|
732
|
-
} ////////////////////////////////////////////////////////////////////////////////
|
|
733
|
-
// UTILS
|
|
734
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
735
|
-
|
|
736
|
-
function clamp(n, lowerBound, upperBound) {
|
|
737
|
-
return Math.min(Math.max(n, lowerBound), upperBound);
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
function promptBeforeUnload(event) {
|
|
741
|
-
// Cancel the event.
|
|
742
|
-
event.preventDefault(); // Chrome (and legacy IE) requires returnValue to be set.
|
|
743
|
-
|
|
744
|
-
event.returnValue = '';
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
function createEvents() {
|
|
748
|
-
var handlers = [];
|
|
749
|
-
return {
|
|
750
|
-
get length() {
|
|
751
|
-
return handlers.length;
|
|
752
|
-
},
|
|
753
|
-
|
|
754
|
-
push: function push(fn) {
|
|
755
|
-
handlers.push(fn);
|
|
756
|
-
return function () {
|
|
757
|
-
handlers = handlers.filter(function (handler) {
|
|
758
|
-
return handler !== fn;
|
|
759
|
-
});
|
|
760
|
-
};
|
|
761
|
-
},
|
|
762
|
-
call: function call(arg) {
|
|
763
|
-
handlers.forEach(function (fn) {
|
|
764
|
-
return fn && fn(arg);
|
|
282
|
+
if (pathname.slice(-1) === '/') {
|
|
283
|
+
pathname = pathname.substring(1);
|
|
284
|
+
segments.push({
|
|
285
|
+
type: 'pathname',
|
|
286
|
+
value: '/'
|
|
765
287
|
});
|
|
766
288
|
}
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
function createKey() {
|
|
771
|
-
return Math.random().toString(36).substr(2, 8);
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Creates a string URL path from the given pathname, search, and hash components.
|
|
775
|
-
*
|
|
776
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createpath
|
|
777
|
-
*/
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
function createPath(_ref) {
|
|
781
|
-
var _ref$pathname = _ref.pathname,
|
|
782
|
-
pathname = _ref$pathname === void 0 ? '/' : _ref$pathname,
|
|
783
|
-
_ref$search = _ref.search,
|
|
784
|
-
search = _ref$search === void 0 ? '' : _ref$search,
|
|
785
|
-
_ref$hash = _ref.hash,
|
|
786
|
-
hash = _ref$hash === void 0 ? '' : _ref$hash;
|
|
787
|
-
if (search && search !== '?') pathname += search.charAt(0) === '?' ? search : '?' + search;
|
|
788
|
-
if (hash && hash !== '#') pathname += hash.charAt(0) === '#' ? hash : '#' + hash;
|
|
789
|
-
return pathname;
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* Parses a string URL path into its separate pathname, search, and hash components.
|
|
793
|
-
*
|
|
794
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
|
|
795
|
-
*/
|
|
796
|
-
|
|
797
|
-
function parsePath(path) {
|
|
798
|
-
var parsedPath = {};
|
|
799
|
-
|
|
800
|
-
if (path) {
|
|
801
|
-
var hashIndex = path.indexOf('#');
|
|
802
|
-
|
|
803
|
-
if (hashIndex >= 0) {
|
|
804
|
-
parsedPath.hash = path.substr(hashIndex);
|
|
805
|
-
path = path.substr(0, hashIndex);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
var searchIndex = path.indexOf('?');
|
|
809
|
-
|
|
810
|
-
if (searchIndex >= 0) {
|
|
811
|
-
parsedPath.search = path.substr(searchIndex);
|
|
812
|
-
path = path.substr(0, searchIndex);
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
if (path) {
|
|
816
|
-
parsedPath.pathname = path;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
return parsedPath;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
var prefix = 'Invariant failed';
|
|
824
|
-
function invariant(condition, message) {
|
|
825
|
-
if (condition) {
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
var provided = typeof message === 'function' ? message() : message;
|
|
829
|
-
var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
|
|
830
|
-
throw new Error(value);
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
function last(arr) {
|
|
834
|
-
return arr[arr.length - 1];
|
|
835
|
-
}
|
|
836
|
-
function warning(cond, message) {
|
|
837
|
-
if (cond) {
|
|
838
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
839
|
-
try {
|
|
840
|
-
throw new Error(message);
|
|
841
|
-
} catch {}
|
|
842
|
-
}
|
|
843
|
-
return true;
|
|
844
|
-
}
|
|
845
|
-
function isFunction(d) {
|
|
846
|
-
return typeof d === 'function';
|
|
847
|
-
}
|
|
848
|
-
function functionalUpdate(updater, previous) {
|
|
849
|
-
if (isFunction(updater)) {
|
|
850
|
-
return updater(previous);
|
|
289
|
+
return segments;
|
|
851
290
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
return obj;
|
|
858
|
-
}, {});
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
function joinPaths(paths) {
|
|
862
|
-
return cleanPath(paths.filter(Boolean).join('/'));
|
|
863
|
-
}
|
|
864
|
-
function cleanPath(path) {
|
|
865
|
-
// remove double slashes
|
|
866
|
-
return path.replace(/\/{2,}/g, '/');
|
|
867
|
-
}
|
|
868
|
-
function trimPathLeft(path) {
|
|
869
|
-
return path === '/' ? path : path.replace(/^\/{1,}/, '');
|
|
870
|
-
}
|
|
871
|
-
function trimPathRight(path) {
|
|
872
|
-
return path === '/' ? path : path.replace(/\/{1,}$/, '');
|
|
873
|
-
}
|
|
874
|
-
function trimPath(path) {
|
|
875
|
-
return trimPathRight(trimPathLeft(path));
|
|
876
|
-
}
|
|
877
|
-
function resolvePath(basepath, base, to) {
|
|
878
|
-
base = base.replace(new RegExp(`^${basepath}`), '/');
|
|
879
|
-
to = to.replace(new RegExp(`^${basepath}`), '/');
|
|
880
|
-
let baseSegments = parsePathname(base);
|
|
881
|
-
const toSegments = parsePathname(to);
|
|
882
|
-
toSegments.forEach((toSegment, index) => {
|
|
883
|
-
if (toSegment.value === '/') {
|
|
884
|
-
if (!index) {
|
|
885
|
-
// Leading slash
|
|
886
|
-
baseSegments = [toSegment];
|
|
887
|
-
} else if (index === toSegments.length - 1) {
|
|
888
|
-
// Trailing Slash
|
|
889
|
-
baseSegments.push(toSegment);
|
|
890
|
-
} else ;
|
|
891
|
-
} else if (toSegment.value === '..') {
|
|
892
|
-
var _last;
|
|
893
|
-
// Extra trailing slash? pop it off
|
|
894
|
-
if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
|
|
895
|
-
baseSegments.pop();
|
|
291
|
+
function interpolatePath(path, params, leaveWildcard) {
|
|
292
|
+
const interpolatedPathSegments = parsePathname(path);
|
|
293
|
+
return joinPaths(interpolatedPathSegments.map(segment => {
|
|
294
|
+
if (segment.value === '*' && !leaveWildcard) {
|
|
295
|
+
return '';
|
|
896
296
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
|
|
905
|
-
return cleanPath(joined);
|
|
906
|
-
}
|
|
907
|
-
function parsePathname(pathname) {
|
|
908
|
-
if (!pathname) {
|
|
909
|
-
return [];
|
|
910
|
-
}
|
|
911
|
-
pathname = cleanPath(pathname);
|
|
912
|
-
const segments = [];
|
|
913
|
-
if (pathname.slice(0, 1) === '/') {
|
|
914
|
-
pathname = pathname.substring(1);
|
|
915
|
-
segments.push({
|
|
916
|
-
type: 'pathname',
|
|
917
|
-
value: '/'
|
|
918
|
-
});
|
|
919
|
-
}
|
|
920
|
-
if (!pathname) {
|
|
921
|
-
return segments;
|
|
297
|
+
if (segment.type === 'param') {
|
|
298
|
+
return params[segment.value.substring(1)] ?? '';
|
|
299
|
+
}
|
|
300
|
+
return segment.value;
|
|
301
|
+
}));
|
|
922
302
|
}
|
|
303
|
+
function matchPathname(basepath, currentPathname, matchLocation) {
|
|
304
|
+
const pathParams = matchByPath(basepath, currentPathname, matchLocation);
|
|
305
|
+
// const searchMatched = matchBySearch(currentLocation.search, matchLocation)
|
|
923
306
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
segments.push(...split.map(part => {
|
|
927
|
-
if (part.startsWith('*')) {
|
|
928
|
-
return {
|
|
929
|
-
type: 'wildcard',
|
|
930
|
-
value: part
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
if (part.charAt(0) === '$') {
|
|
934
|
-
return {
|
|
935
|
-
type: 'param',
|
|
936
|
-
value: part
|
|
937
|
-
};
|
|
938
|
-
}
|
|
939
|
-
return {
|
|
940
|
-
type: 'pathname',
|
|
941
|
-
value: part
|
|
942
|
-
};
|
|
943
|
-
}));
|
|
944
|
-
if (pathname.slice(-1) === '/') {
|
|
945
|
-
pathname = pathname.substring(1);
|
|
946
|
-
segments.push({
|
|
947
|
-
type: 'pathname',
|
|
948
|
-
value: '/'
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
return segments;
|
|
952
|
-
}
|
|
953
|
-
function interpolatePath(path, params, leaveWildcard) {
|
|
954
|
-
const interpolatedPathSegments = parsePathname(path);
|
|
955
|
-
return joinPaths(interpolatedPathSegments.map(segment => {
|
|
956
|
-
if (segment.value === '*' && !leaveWildcard) {
|
|
957
|
-
return '';
|
|
958
|
-
}
|
|
959
|
-
if (segment.type === 'param') {
|
|
960
|
-
return params[segment.value.substring(1)] ?? '';
|
|
307
|
+
if (matchLocation.to && !pathParams) {
|
|
308
|
+
return;
|
|
961
309
|
}
|
|
962
|
-
return
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
const routeSegment = routeSegments[i];
|
|
987
|
-
const isLastRouteSegment = i === routeSegments.length - 1;
|
|
988
|
-
const isLastBaseSegment = i === baseSegments.length - 1;
|
|
989
|
-
if (routeSegment) {
|
|
990
|
-
if (routeSegment.type === 'wildcard') {
|
|
991
|
-
if (baseSegment != null && baseSegment.value) {
|
|
992
|
-
params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
|
|
993
|
-
return true;
|
|
994
|
-
}
|
|
995
|
-
return false;
|
|
996
|
-
}
|
|
997
|
-
if (routeSegment.type === 'pathname') {
|
|
998
|
-
if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
|
|
999
|
-
return true;
|
|
310
|
+
return pathParams ?? {};
|
|
311
|
+
}
|
|
312
|
+
function matchByPath(basepath, from, matchLocation) {
|
|
313
|
+
if (!from.startsWith(basepath)) {
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
from = basepath != '/' ? from.substring(basepath.length) : from;
|
|
317
|
+
const baseSegments = parsePathname(from);
|
|
318
|
+
const to = `${matchLocation.to ?? '*'}`;
|
|
319
|
+
const routeSegments = parsePathname(to);
|
|
320
|
+
const params = {};
|
|
321
|
+
let isMatch = (() => {
|
|
322
|
+
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
323
|
+
const baseSegment = baseSegments[i];
|
|
324
|
+
const routeSegment = routeSegments[i];
|
|
325
|
+
const isLastRouteSegment = i === routeSegments.length - 1;
|
|
326
|
+
const isLastBaseSegment = i === baseSegments.length - 1;
|
|
327
|
+
if (routeSegment) {
|
|
328
|
+
if (routeSegment.type === 'wildcard') {
|
|
329
|
+
if (baseSegment?.value) {
|
|
330
|
+
params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
return false;
|
|
1000
334
|
}
|
|
1001
|
-
if (
|
|
1002
|
-
if (
|
|
1003
|
-
|
|
335
|
+
if (routeSegment.type === 'pathname') {
|
|
336
|
+
if (routeSegment.value === '/' && !baseSegment?.value) {
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
if (baseSegment) {
|
|
340
|
+
if (matchLocation.caseSensitive) {
|
|
341
|
+
if (routeSegment.value !== baseSegment.value) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
} else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
|
|
1004
345
|
return false;
|
|
1005
346
|
}
|
|
1006
|
-
} else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
|
|
1007
|
-
return false;
|
|
1008
347
|
}
|
|
1009
348
|
}
|
|
1010
|
-
|
|
1011
|
-
if (!baseSegment) {
|
|
1012
|
-
return false;
|
|
1013
|
-
}
|
|
1014
|
-
if (routeSegment.type === 'param') {
|
|
1015
|
-
if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
|
|
349
|
+
if (!baseSegment) {
|
|
1016
350
|
return false;
|
|
1017
351
|
}
|
|
1018
|
-
if (
|
|
1019
|
-
|
|
352
|
+
if (routeSegment.type === 'param') {
|
|
353
|
+
if (baseSegment?.value === '/') {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
if (baseSegment.value.charAt(0) !== '$') {
|
|
357
|
+
params[routeSegment.value.substring(1)] = baseSegment.value;
|
|
358
|
+
}
|
|
1020
359
|
}
|
|
1021
360
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
return !!matchLocation.fuzzy;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
return true;
|
|
1028
|
-
})();
|
|
1029
|
-
return isMatch ? params : undefined;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// @ts-nocheck
|
|
1033
|
-
|
|
1034
|
-
// 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.
|
|
1035
|
-
|
|
1036
|
-
function encode(obj, pfx) {
|
|
1037
|
-
var k,
|
|
1038
|
-
i,
|
|
1039
|
-
tmp,
|
|
1040
|
-
str = '';
|
|
1041
|
-
for (k in obj) {
|
|
1042
|
-
if ((tmp = obj[k]) !== void 0) {
|
|
1043
|
-
if (Array.isArray(tmp)) {
|
|
1044
|
-
for (i = 0; i < tmp.length; i++) {
|
|
1045
|
-
str && (str += '&');
|
|
1046
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1047
|
-
}
|
|
1048
|
-
} else {
|
|
1049
|
-
str && (str += '&');
|
|
1050
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
return (pfx || '') + str;
|
|
1055
|
-
}
|
|
1056
|
-
function toValue(mix) {
|
|
1057
|
-
if (!mix) return '';
|
|
1058
|
-
var str = decodeURIComponent(mix);
|
|
1059
|
-
if (str === 'false') return false;
|
|
1060
|
-
if (str === 'true') return true;
|
|
1061
|
-
if (str.charAt(0) === '0') return str;
|
|
1062
|
-
return +str * 0 === 0 ? +str : str;
|
|
1063
|
-
}
|
|
1064
|
-
function decode(str) {
|
|
1065
|
-
var tmp,
|
|
1066
|
-
k,
|
|
1067
|
-
out = {},
|
|
1068
|
-
arr = str.split('&');
|
|
1069
|
-
while (tmp = arr.shift()) {
|
|
1070
|
-
tmp = tmp.split('=');
|
|
1071
|
-
k = tmp.shift();
|
|
1072
|
-
if (out[k] !== void 0) {
|
|
1073
|
-
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1074
|
-
} else {
|
|
1075
|
-
out[k] = toValue(tmp.shift());
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
return out;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
// src/core.ts
|
|
1082
|
-
var CurrentReaction = void 0;
|
|
1083
|
-
var CurrentGets = null;
|
|
1084
|
-
var CurrentGetsIndex = 0;
|
|
1085
|
-
var EffectQueue = null;
|
|
1086
|
-
var CacheClean = 0;
|
|
1087
|
-
var CacheCheck = 1;
|
|
1088
|
-
var CacheDirty = 2;
|
|
1089
|
-
var Reactive = class {
|
|
1090
|
-
value;
|
|
1091
|
-
fn;
|
|
1092
|
-
observers = null;
|
|
1093
|
-
sources = null;
|
|
1094
|
-
state;
|
|
1095
|
-
effect;
|
|
1096
|
-
cleanups = null;
|
|
1097
|
-
alwaysUpdate = false;
|
|
1098
|
-
constructor(fnOrValue, type) {
|
|
1099
|
-
if (type != 0 /* Signal */) {
|
|
1100
|
-
this.fn = fnOrValue;
|
|
1101
|
-
this.value = void 0;
|
|
1102
|
-
this.state = CacheDirty;
|
|
1103
|
-
console.error("Memos and effects must be wrapped in a createRoot");
|
|
1104
|
-
this.effect = type == 2 /* Effect */;
|
|
1105
|
-
if (this.effect)
|
|
1106
|
-
this.update();
|
|
1107
|
-
} else {
|
|
1108
|
-
this.fn = void 0;
|
|
1109
|
-
this.value = fnOrValue;
|
|
1110
|
-
this.state = CacheClean;
|
|
1111
|
-
this.effect = false;
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
get() {
|
|
1115
|
-
if (CurrentReaction) {
|
|
1116
|
-
if (!CurrentGets && CurrentReaction.sources && CurrentReaction.sources[CurrentGetsIndex] == this) {
|
|
1117
|
-
CurrentGetsIndex++;
|
|
1118
|
-
} else {
|
|
1119
|
-
if (!CurrentGets)
|
|
1120
|
-
CurrentGets = [this];
|
|
1121
|
-
else
|
|
1122
|
-
CurrentGets.push(this);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
if (this.fn)
|
|
1126
|
-
this.updateIfNecessary();
|
|
1127
|
-
return this.value;
|
|
1128
|
-
}
|
|
1129
|
-
set(value) {
|
|
1130
|
-
const notInBatch = !EffectQueue;
|
|
1131
|
-
const newValue = typeof value === "function" ? value(this.value) : value;
|
|
1132
|
-
if ((this.value !== newValue || this.alwaysUpdate) && this.observers) {
|
|
1133
|
-
for (let i = 0; i < this.observers.length; i++) {
|
|
1134
|
-
this.observers[i].stale(CacheDirty);
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
this.value = newValue;
|
|
1138
|
-
if (notInBatch)
|
|
1139
|
-
stabilize();
|
|
1140
|
-
return newValue;
|
|
1141
|
-
}
|
|
1142
|
-
stale(state) {
|
|
1143
|
-
if (this.state < state) {
|
|
1144
|
-
if (this.state === CacheClean && this.effect) {
|
|
1145
|
-
if (EffectQueue)
|
|
1146
|
-
EffectQueue.push(this);
|
|
1147
|
-
else
|
|
1148
|
-
EffectQueue = [this];
|
|
1149
|
-
}
|
|
1150
|
-
this.state = state;
|
|
1151
|
-
if (this.observers) {
|
|
1152
|
-
for (let i = 0; i < this.observers.length; i++) {
|
|
1153
|
-
this.observers[i].stale(CacheCheck);
|
|
361
|
+
if (isLastRouteSegment && !isLastBaseSegment) {
|
|
362
|
+
return !!matchLocation.fuzzy;
|
|
1154
363
|
}
|
|
1155
364
|
}
|
|
1156
|
-
|
|
365
|
+
return true;
|
|
366
|
+
})();
|
|
367
|
+
return isMatch ? params : undefined;
|
|
1157
368
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
if (this.sources && CurrentGetsIndex > 0) {
|
|
1175
|
-
this.sources.length = CurrentGetsIndex + CurrentGets.length;
|
|
1176
|
-
for (let i = 0; i < CurrentGets.length; i++) {
|
|
1177
|
-
this.sources[CurrentGetsIndex + i] = CurrentGets[i];
|
|
369
|
+
|
|
370
|
+
// @ts-nocheck
|
|
371
|
+
|
|
372
|
+
// 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.
|
|
373
|
+
|
|
374
|
+
function encode(obj, pfx) {
|
|
375
|
+
var k,
|
|
376
|
+
i,
|
|
377
|
+
tmp,
|
|
378
|
+
str = '';
|
|
379
|
+
for (k in obj) {
|
|
380
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
381
|
+
if (Array.isArray(tmp)) {
|
|
382
|
+
for (i = 0; i < tmp.length; i++) {
|
|
383
|
+
str && (str += '&');
|
|
384
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1178
385
|
}
|
|
1179
386
|
} else {
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
for (let i = CurrentGetsIndex; i < this.sources.length; i++) {
|
|
1183
|
-
const source = this.sources[i];
|
|
1184
|
-
if (!source.observers) {
|
|
1185
|
-
source.observers = [this];
|
|
1186
|
-
} else {
|
|
1187
|
-
source.observers.push(this);
|
|
1188
|
-
}
|
|
387
|
+
str && (str += '&');
|
|
388
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1189
389
|
}
|
|
1190
|
-
} else if (this.sources && CurrentGetsIndex < this.sources.length) {
|
|
1191
|
-
this.removeParentObservers(CurrentGetsIndex);
|
|
1192
|
-
this.sources.length = CurrentGetsIndex;
|
|
1193
390
|
}
|
|
1194
|
-
} finally {
|
|
1195
|
-
CurrentGets = prevGets;
|
|
1196
|
-
CurrentReaction = prevReaction;
|
|
1197
|
-
CurrentGetsIndex = prevIndex;
|
|
1198
391
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
392
|
+
return (pfx || '') + str;
|
|
393
|
+
}
|
|
394
|
+
function toValue(mix) {
|
|
395
|
+
if (!mix) return '';
|
|
396
|
+
var str = decodeURIComponent(mix);
|
|
397
|
+
if (str === 'false') return false;
|
|
398
|
+
if (str === 'true') return true;
|
|
399
|
+
if (str.charAt(0) === '0') return str;
|
|
400
|
+
return +str * 0 === 0 ? +str : str;
|
|
401
|
+
}
|
|
402
|
+
function decode(str) {
|
|
403
|
+
var tmp,
|
|
404
|
+
k,
|
|
405
|
+
out = {},
|
|
406
|
+
arr = str.split('&');
|
|
407
|
+
while (tmp = arr.shift()) {
|
|
408
|
+
tmp = tmp.split('=');
|
|
409
|
+
k = tmp.shift();
|
|
410
|
+
if (out[k] !== void 0) {
|
|
411
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
412
|
+
} else {
|
|
413
|
+
out[k] = toValue(tmp.shift());
|
|
1202
414
|
}
|
|
1203
415
|
}
|
|
1204
|
-
|
|
416
|
+
return out;
|
|
1205
417
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
if (!this.sources)
|
|
1222
|
-
return;
|
|
1223
|
-
for (let i = index; i < this.sources.length; i++) {
|
|
1224
|
-
const source = this.sources[i];
|
|
1225
|
-
const swap = source.observers.findIndex((v) => v === this);
|
|
1226
|
-
source.observers[swap] = source.observers[source.observers.length - 1];
|
|
1227
|
-
source.observers.pop();
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
destroy() {
|
|
1231
|
-
if (this.cleanups) {
|
|
1232
|
-
this.cleanups.forEach((c) => c());
|
|
1233
|
-
this.cleanups = null;
|
|
418
|
+
|
|
419
|
+
class Route {
|
|
420
|
+
constructor(routeConfig, options, originalIndex, parent, router) {
|
|
421
|
+
Object.assign(this, {
|
|
422
|
+
...routeConfig,
|
|
423
|
+
originalIndex,
|
|
424
|
+
options,
|
|
425
|
+
getRouter: () => router,
|
|
426
|
+
childRoutes: undefined,
|
|
427
|
+
getParentRoute: () => parent
|
|
428
|
+
});
|
|
429
|
+
router.options.createRoute?.({
|
|
430
|
+
router,
|
|
431
|
+
route: this
|
|
432
|
+
});
|
|
1234
433
|
}
|
|
1235
|
-
this.removeParentObservers(0);
|
|
1236
|
-
}
|
|
1237
|
-
};
|
|
1238
|
-
function stabilize() {
|
|
1239
|
-
if (!EffectQueue)
|
|
1240
|
-
return;
|
|
1241
|
-
for (let i = 0; i < EffectQueue.length; i++) {
|
|
1242
|
-
EffectQueue[i].get();
|
|
1243
434
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
stabilize();
|
|
1250
|
-
return out;
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
// src/store.ts
|
|
1254
|
-
var $RAW = Symbol("store-raw");
|
|
1255
|
-
var $TRACK = Symbol("track");
|
|
1256
|
-
var $PROXY = Symbol("store-proxy");
|
|
1257
|
-
var $NODE = Symbol("store-node");
|
|
1258
|
-
function wrap(value) {
|
|
1259
|
-
let p = value[$PROXY];
|
|
1260
|
-
if (!p) {
|
|
1261
|
-
Object.defineProperty(value, $PROXY, {
|
|
1262
|
-
value: p = new Proxy(value, proxyTraps)
|
|
1263
|
-
});
|
|
1264
|
-
if (!Array.isArray(value)) {
|
|
1265
|
-
const keys = Object.keys(value);
|
|
1266
|
-
const desc = Object.getOwnPropertyDescriptors(value);
|
|
1267
|
-
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1268
|
-
const prop = keys[i];
|
|
1269
|
-
if (desc[prop].get) {
|
|
1270
|
-
const get = desc[prop].get.bind(p);
|
|
1271
|
-
Object.defineProperty(value, prop, {
|
|
1272
|
-
enumerable: desc[prop].enumerable,
|
|
1273
|
-
get
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
435
|
+
|
|
436
|
+
const rootRouteId = '__root__';
|
|
437
|
+
const createRouteConfig = (options = {}, children = [], isRoot = true, parentId, parentPath) => {
|
|
438
|
+
if (isRoot) {
|
|
439
|
+
options.path = rootRouteId;
|
|
1277
440
|
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
let proto;
|
|
1283
|
-
return obj != null && typeof obj === "object" && (obj[$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));
|
|
1284
|
-
}
|
|
1285
|
-
function unwrap(item, set = /* @__PURE__ */ new Set()) {
|
|
1286
|
-
let result, unwrapped, v, prop;
|
|
1287
|
-
if (result = item != null && item[$RAW])
|
|
1288
|
-
return result;
|
|
1289
|
-
if (!isWrappable(item) || set.has(item))
|
|
1290
|
-
return item;
|
|
1291
|
-
if (Array.isArray(item)) {
|
|
1292
|
-
if (Object.isFrozen(item))
|
|
1293
|
-
item = item.slice(0);
|
|
1294
|
-
else
|
|
1295
|
-
set.add(item);
|
|
1296
|
-
for (let i = 0, l = item.length; i < l; i++) {
|
|
1297
|
-
v = item[i];
|
|
1298
|
-
if ((unwrapped = unwrap(v, set)) !== v)
|
|
1299
|
-
item[i] = unwrapped;
|
|
441
|
+
|
|
442
|
+
// Strip the root from parentIds
|
|
443
|
+
if (parentId === rootRouteId) {
|
|
444
|
+
parentId = '';
|
|
1300
445
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
const keys = Object.keys(item);
|
|
1307
|
-
const desc = Object.getOwnPropertyDescriptors(item);
|
|
1308
|
-
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1309
|
-
prop = keys[i];
|
|
1310
|
-
if (desc[prop].get)
|
|
1311
|
-
continue;
|
|
1312
|
-
v = item[prop];
|
|
1313
|
-
if ((unwrapped = unwrap(v, set)) !== v)
|
|
1314
|
-
item[prop] = unwrapped;
|
|
446
|
+
let path = isRoot ? rootRouteId : options.path;
|
|
447
|
+
|
|
448
|
+
// If the path is anything other than an index path, trim it up
|
|
449
|
+
if (path && path !== '/') {
|
|
450
|
+
path = trimPath(path);
|
|
1315
451
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
let nodes = target[$NODE];
|
|
1321
|
-
if (!nodes)
|
|
1322
|
-
Object.defineProperty(target, $NODE, { value: nodes = {} });
|
|
1323
|
-
return nodes;
|
|
1324
|
-
}
|
|
1325
|
-
function getDataNode(nodes, property, value) {
|
|
1326
|
-
return nodes[property] || (nodes[property] = createDataNode(value));
|
|
1327
|
-
}
|
|
1328
|
-
function proxyDescriptor(target, property) {
|
|
1329
|
-
const desc = Reflect.getOwnPropertyDescriptor(target, property);
|
|
1330
|
-
if (!desc || desc.get || !desc.configurable || property === $PROXY || property === $NODE)
|
|
1331
|
-
return desc;
|
|
1332
|
-
delete desc.value;
|
|
1333
|
-
delete desc.writable;
|
|
1334
|
-
desc.get = () => target[$PROXY][property];
|
|
1335
|
-
return desc;
|
|
1336
|
-
}
|
|
1337
|
-
function trackSelf(target) {
|
|
1338
|
-
if (CurrentReaction) {
|
|
1339
|
-
const nodes = getDataNodes(target);
|
|
1340
|
-
(nodes._ || (nodes._ = createDataNode())).get();
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
function ownKeys(target) {
|
|
1344
|
-
trackSelf(target);
|
|
1345
|
-
return Reflect.ownKeys(target);
|
|
1346
|
-
}
|
|
1347
|
-
function createDataNode(value) {
|
|
1348
|
-
const s = new Reactive(value, 0);
|
|
1349
|
-
s.alwaysUpdate = true;
|
|
1350
|
-
return s;
|
|
1351
|
-
}
|
|
1352
|
-
var Writing = false;
|
|
1353
|
-
var proxyTraps = {
|
|
1354
|
-
get(target, property, receiver) {
|
|
1355
|
-
if (property === $RAW)
|
|
1356
|
-
return target;
|
|
1357
|
-
if (property === $PROXY)
|
|
1358
|
-
return receiver;
|
|
1359
|
-
if (property === $TRACK) {
|
|
1360
|
-
trackSelf(target);
|
|
1361
|
-
return receiver;
|
|
452
|
+
const routeId = path || options.id;
|
|
453
|
+
let id = joinPaths([parentId, routeId]);
|
|
454
|
+
if (path === rootRouteId) {
|
|
455
|
+
path = '/';
|
|
1362
456
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
let value = tracked ? nodes[property].get() : target[property];
|
|
1366
|
-
if (property === $NODE || property === "__proto__")
|
|
1367
|
-
return value;
|
|
1368
|
-
if (!tracked) {
|
|
1369
|
-
const desc = Object.getOwnPropertyDescriptor(target, property);
|
|
1370
|
-
if (CurrentReaction && (typeof value !== "function" || target.hasOwnProperty(property)) && !(desc && desc.get))
|
|
1371
|
-
value = getDataNode(nodes, property, value).get();
|
|
457
|
+
if (id !== rootRouteId) {
|
|
458
|
+
id = joinPaths(['/', id]);
|
|
1372
459
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
deleteProperty(target, property) {
|
|
1386
|
-
Writing && setProperty(target, property, void 0, true);
|
|
1387
|
-
return true;
|
|
1388
|
-
},
|
|
1389
|
-
ownKeys,
|
|
1390
|
-
getOwnPropertyDescriptor: proxyDescriptor
|
|
1391
|
-
};
|
|
1392
|
-
function setProperty(state, property, value, deleting = false) {
|
|
1393
|
-
if (!deleting && state[property] === value)
|
|
1394
|
-
return;
|
|
1395
|
-
const prev = state[property];
|
|
1396
|
-
const len = state.length;
|
|
1397
|
-
if (deleting)
|
|
1398
|
-
delete state[property];
|
|
1399
|
-
else
|
|
1400
|
-
state[property] = value;
|
|
1401
|
-
const nodes = getDataNodes(state);
|
|
1402
|
-
let node;
|
|
1403
|
-
if (node = getDataNode(nodes, property, prev))
|
|
1404
|
-
node.set(() => value);
|
|
1405
|
-
if (Array.isArray(state) && state.length !== len)
|
|
1406
|
-
(node = getDataNode(nodes, "length", len)) && node.set(state.length);
|
|
1407
|
-
(node = nodes._) && node.set();
|
|
1408
|
-
}
|
|
1409
|
-
function createStore(store) {
|
|
1410
|
-
const unwrappedStore = unwrap(store);
|
|
1411
|
-
const wrappedStore = wrap(unwrappedStore);
|
|
1412
|
-
const setStore = (fn) => {
|
|
1413
|
-
batch(() => {
|
|
1414
|
-
try {
|
|
1415
|
-
Writing = true;
|
|
1416
|
-
fn(wrappedStore);
|
|
1417
|
-
} finally {
|
|
1418
|
-
Writing = false;
|
|
460
|
+
const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
|
|
461
|
+
return {
|
|
462
|
+
id: id,
|
|
463
|
+
routeId: routeId,
|
|
464
|
+
path: path,
|
|
465
|
+
fullPath: fullPath,
|
|
466
|
+
options: options,
|
|
467
|
+
children,
|
|
468
|
+
addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
|
|
469
|
+
createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath),
|
|
470
|
+
generate: () => {
|
|
471
|
+
invariant(false, `routeConfig.generate() is used by TanStack Router's file-based routing code generation and should not actually be called during runtime. `);
|
|
1419
472
|
}
|
|
1420
|
-
}
|
|
1421
|
-
};
|
|
1422
|
-
return [wrappedStore, setStore];
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
function createRoute(routeConfig, options, originalIndex, parent, router) {
|
|
1426
|
-
const {
|
|
1427
|
-
id,
|
|
1428
|
-
routeId,
|
|
1429
|
-
path: routePath,
|
|
1430
|
-
fullPath
|
|
1431
|
-
} = routeConfig;
|
|
1432
|
-
let route = {
|
|
1433
|
-
routeInfo: undefined,
|
|
1434
|
-
routeId: id,
|
|
1435
|
-
routeRouteId: routeId,
|
|
1436
|
-
originalIndex,
|
|
1437
|
-
routePath,
|
|
1438
|
-
fullPath,
|
|
1439
|
-
options,
|
|
1440
|
-
router,
|
|
1441
|
-
childRoutes: undefined,
|
|
1442
|
-
parentRoute: parent,
|
|
1443
|
-
get action() {
|
|
1444
|
-
let action = router.store.actions[id] || (() => {
|
|
1445
|
-
router.setStore(s => {
|
|
1446
|
-
s.actions[id] = {
|
|
1447
|
-
submissions: [],
|
|
1448
|
-
submit: async (submission, actionOpts) => {
|
|
1449
|
-
if (!route) {
|
|
1450
|
-
return;
|
|
1451
|
-
}
|
|
1452
|
-
const invalidate = (actionOpts == null ? void 0 : actionOpts.invalidate) ?? true;
|
|
1453
|
-
const [actionStore, setActionStore] = createStore({
|
|
1454
|
-
submittedAt: Date.now(),
|
|
1455
|
-
status: 'pending',
|
|
1456
|
-
submission,
|
|
1457
|
-
isMulti: !!(actionOpts != null && actionOpts.multi)
|
|
1458
|
-
});
|
|
1459
|
-
router.setStore(s => {
|
|
1460
|
-
if (!(actionOpts != null && actionOpts.multi)) {
|
|
1461
|
-
s.actions[id].submissions = action.submissions.filter(d => d.isMulti);
|
|
1462
|
-
}
|
|
1463
|
-
s.actions[id].current = actionStore;
|
|
1464
|
-
s.actions[id].latest = actionStore;
|
|
1465
|
-
s.actions[id].submissions.push(actionStore);
|
|
1466
|
-
});
|
|
1467
|
-
try {
|
|
1468
|
-
const res = await (route.options.action == null ? void 0 : route.options.action(submission));
|
|
1469
|
-
setActionStore(s => {
|
|
1470
|
-
s.data = res;
|
|
1471
|
-
});
|
|
1472
|
-
if (invalidate) {
|
|
1473
|
-
router.invalidateRoute({
|
|
1474
|
-
to: '.',
|
|
1475
|
-
fromCurrent: true
|
|
1476
|
-
});
|
|
1477
|
-
await router.reload();
|
|
1478
|
-
}
|
|
1479
|
-
setActionStore(s => {
|
|
1480
|
-
s.status = 'success';
|
|
1481
|
-
});
|
|
1482
|
-
return res;
|
|
1483
|
-
} catch (err) {
|
|
1484
|
-
console.error(err);
|
|
1485
|
-
setActionStore(s => {
|
|
1486
|
-
s.error = err;
|
|
1487
|
-
s.status = 'error';
|
|
1488
|
-
});
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
});
|
|
1493
|
-
return router.store.actions[id];
|
|
1494
|
-
})();
|
|
1495
|
-
return action;
|
|
1496
|
-
},
|
|
1497
|
-
get loader() {
|
|
1498
|
-
let loader = router.store.loaders[id] || (() => {
|
|
1499
|
-
router.setStore(s => {
|
|
1500
|
-
s.loaders[id] = {
|
|
1501
|
-
pending: [],
|
|
1502
|
-
fetch: async loaderContext => {
|
|
1503
|
-
if (!route) {
|
|
1504
|
-
return;
|
|
1505
|
-
}
|
|
1506
|
-
const loaderState = {
|
|
1507
|
-
loadedAt: Date.now(),
|
|
1508
|
-
loaderContext
|
|
1509
|
-
};
|
|
1510
|
-
router.setStore(s => {
|
|
1511
|
-
s.loaders[id].current = loaderState;
|
|
1512
|
-
s.loaders[id].latest = loaderState;
|
|
1513
|
-
s.loaders[id].pending.push(loaderState);
|
|
1514
|
-
});
|
|
1515
|
-
try {
|
|
1516
|
-
return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
|
|
1517
|
-
} finally {
|
|
1518
|
-
router.setStore(s => {
|
|
1519
|
-
s.loaders[id].pending = s.loaders[id].pending.filter(d => d !== loaderState);
|
|
1520
|
-
});
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
});
|
|
1525
|
-
return router.store.loaders[id];
|
|
1526
|
-
})();
|
|
1527
|
-
return loader;
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
// buildLink: (options) => {
|
|
1531
|
-
// return router.buildLink({
|
|
1532
|
-
// ...options,
|
|
1533
|
-
// from: fullPath,
|
|
1534
|
-
// } as any) as any
|
|
1535
|
-
// },
|
|
1536
|
-
|
|
1537
|
-
// navigate: (options) => {
|
|
1538
|
-
// return router.navigate({
|
|
1539
|
-
// ...options,
|
|
1540
|
-
// from: fullPath,
|
|
1541
|
-
// } as any) as any
|
|
1542
|
-
// },
|
|
1543
|
-
|
|
1544
|
-
// matchRoute: (matchLocation, opts) => {
|
|
1545
|
-
// return router.matchRoute(
|
|
1546
|
-
// {
|
|
1547
|
-
// ...matchLocation,
|
|
1548
|
-
// from: fullPath,
|
|
1549
|
-
// } as any,
|
|
1550
|
-
// opts,
|
|
1551
|
-
// ) as any
|
|
1552
|
-
// },
|
|
473
|
+
};
|
|
1553
474
|
};
|
|
1554
475
|
|
|
1555
|
-
router.options.createRoute == null ? void 0 : router.options.createRoute({
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
476
|
+
function n(n){for(var r=arguments.length,t=Array(r>1?r-1:0),e=1;e<r;e++)t[e-1]=arguments[e];{var i=Y[n],o=i?"function"==typeof i?i.apply(null,t):i:"unknown error nr: "+n;throw Error("[Immer] "+o)}}function r(n){return !!n&&!!n[Q]}function t(n){var r;return !!n&&(function(n){if(!n||"object"!=typeof n)return !1;var r=Object.getPrototypeOf(n);if(null===r)return !0;var t=Object.hasOwnProperty.call(r,"constructor")&&r.constructor;return t===Object||"function"==typeof t&&Function.toString.call(t)===Z}(n)||Array.isArray(n)||!!n[L]||!!(null===(r=n.constructor)||void 0===r?void 0:r[L])||s(n)||v(n))}function i(n,r,t){void 0===t&&(t=!1),0===o(n)?(t?Object.keys:nn)(n).forEach((function(e){t&&"symbol"==typeof e||r(e,n[e],n);})):n.forEach((function(t,e){return r(e,t,n)}));}function o(n){var r=n[Q];return r?r.i>3?r.i-4:r.i:Array.isArray(n)?1:s(n)?2:v(n)?3:0}function u(n,r){return 2===o(n)?n.has(r):Object.prototype.hasOwnProperty.call(n,r)}function a(n,r){return 2===o(n)?n.get(r):n[r]}function f(n,r,t){var e=o(n);2===e?n.set(r,t):3===e?(n.delete(r),n.add(t)):n[r]=t;}function c(n,r){return n===r?0!==n||1/n==1/r:n!=n&&r!=r}function s(n){return X&&n instanceof Map}function v(n){return q&&n instanceof Set}function p(n){return n.o||n.t}function l(n){if(Array.isArray(n))return Array.prototype.slice.call(n);var r=rn(n);delete r[Q];for(var t=nn(r),e=0;e<t.length;e++){var i=t[e],o=r[i];!1===o.writable&&(o.writable=!0,o.configurable=!0),(o.get||o.set)&&(r[i]={configurable:!0,writable:!0,enumerable:o.enumerable,value:n[i]});}return Object.create(Object.getPrototypeOf(n),r)}function d(n,e){return void 0===e&&(e=!1),y(n)||r(n)||!t(n)?n:(o(n)>1&&(n.set=n.add=n.clear=n.delete=h),Object.freeze(n),e&&i(n,(function(n,r){return d(r,!0)}),!0),n)}function h(){n(2);}function y(n){return null==n||"object"!=typeof n||Object.isFrozen(n)}function b(r){var t=tn[r];return t||n(18,r),t}function _(){return U||n(0),U}function j(n,r){r&&(b("Patches"),n.u=[],n.s=[],n.v=r);}function O(n){g(n),n.p.forEach(S),n.p=null;}function g(n){n===U&&(U=n.l);}function w(n){return U={p:[],l:U,h:n,m:!0,_:0}}function S(n){var r=n[Q];0===r.i||1===r.i?r.j():r.O=!0;}function P(r,e){e._=e.p.length;var i=e.p[0],o=void 0!==r&&r!==i;return e.h.g||b("ES5").S(e,r,o),o?(i[Q].P&&(O(e),n(4)),t(r)&&(r=M(e,r),e.l||x(e,r)),e.u&&b("Patches").M(i[Q].t,r,e.u,e.s)):r=M(e,i,[]),O(e),e.u&&e.v(e.u,e.s),r!==H?r:void 0}function M(n,r,t){if(y(r))return r;var e=r[Q];if(!e)return i(r,(function(i,o){return A(n,e,r,i,o,t)}),!0),r;if(e.A!==n)return r;if(!e.P)return x(n,e.t,!0),e.t;if(!e.I){e.I=!0,e.A._--;var o=4===e.i||5===e.i?e.o=l(e.k):e.o;i(3===e.i?new Set(o):o,(function(r,i){return A(n,e,o,r,i,t)})),x(n,o,!1),t&&n.u&&b("Patches").R(e,t,n.u,n.s);}return e.o}function A(e,i,o,a,c,s){if(c===o&&n(5),r(c)){var v=M(e,c,s&&i&&3!==i.i&&!u(i.D,a)?s.concat(a):void 0);if(f(o,a,v),!r(v))return;e.m=!1;}if(t(c)&&!y(c)){if(!e.h.F&&e._<1)return;M(e,c),i&&i.A.l||x(e,c);}}function x(n,r,t){void 0===t&&(t=!1),n.h.F&&n.m&&d(r,t);}function z(n,r){var t=n[Q];return (t?p(t):n)[r]}function I(n,r){if(r in n)for(var t=Object.getPrototypeOf(n);t;){var e=Object.getOwnPropertyDescriptor(t,r);if(e)return e;t=Object.getPrototypeOf(t);}}function k(n){n.P||(n.P=!0,n.l&&k(n.l));}function E(n){n.o||(n.o=l(n.t));}function R(n,r,t){var e=s(r)?b("MapSet").N(r,t):v(r)?b("MapSet").T(r,t):n.g?function(n,r){var t=Array.isArray(n),e={i:t?1:0,A:r?r.A:_(),P:!1,I:!1,D:{},l:r,t:n,k:null,o:null,j:null,C:!1},i=e,o=en;t&&(i=[e],o=on);var u=Proxy.revocable(i,o),a=u.revoke,f=u.proxy;return e.k=f,e.j=a,f}(r,t):b("ES5").J(r,t);return (t?t.A:_()).p.push(e),e}function D(e){return r(e)||n(22,e),function n(r){if(!t(r))return r;var e,u=r[Q],c=o(r);if(u){if(!u.P&&(u.i<4||!b("ES5").K(u)))return u.t;u.I=!0,e=F(r,c),u.I=!1;}else e=F(r,c);return i(e,(function(r,t){u&&a(u.t,r)===t||f(e,r,n(t));})),3===c?new Set(e):e}(e)}function F(n,r){switch(r){case 2:return new Map(n);case 3:return Array.from(n)}return l(n)}var G,U,W="undefined"!=typeof Symbol&&"symbol"==typeof Symbol("x"),X="undefined"!=typeof Map,q="undefined"!=typeof Set,B="undefined"!=typeof Proxy&&void 0!==Proxy.revocable&&"undefined"!=typeof Reflect,H=W?Symbol.for("immer-nothing"):((G={})["immer-nothing"]=!0,G),L=W?Symbol.for("immer-draftable"):"__$immer_draftable",Q=W?Symbol.for("immer-state"):"__$immer_state",Y={0:"Illegal state",1:"Immer drafts cannot have computed properties",2:"This object has been frozen and should not be mutated",3:function(n){return "Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+n},4:"An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",5:"Immer forbids circular references",6:"The first or second argument to `produce` must be a function",7:"The third argument to `produce` must be a function or undefined",8:"First argument to `createDraft` must be a plain object, an array, or an immerable object",9:"First argument to `finishDraft` must be a draft returned by `createDraft`",10:"The given draft is already finalized",11:"Object.defineProperty() cannot be used on an Immer draft",12:"Object.setPrototypeOf() cannot be used on an Immer draft",13:"Immer only supports deleting array indices",14:"Immer only supports setting array indices and the 'length' property",15:function(n){return "Cannot apply patch, path doesn't resolve: "+n},16:'Sets cannot have "replace" patches.',17:function(n){return "Unsupported patch operation: "+n},18:function(n){return "The plugin for '"+n+"' has not been loaded into Immer. To enable the plugin, import and call `enable"+n+"()` when initializing your application."},20:"Cannot use proxies if Proxy, Proxy.revocable or Reflect are not available",21:function(n){return "produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '"+n+"'"},22:function(n){return "'current' expects a draft, got: "+n},23:function(n){return "'original' expects a draft, got: "+n},24:"Patching reserved attributes like __proto__, prototype and constructor is not allowed"},Z=""+Object.prototype.constructor,nn="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(n){return Object.getOwnPropertyNames(n).concat(Object.getOwnPropertySymbols(n))}:Object.getOwnPropertyNames,rn=Object.getOwnPropertyDescriptors||function(n){var r={};return nn(n).forEach((function(t){r[t]=Object.getOwnPropertyDescriptor(n,t);})),r},tn={},en={get:function(n,r){if(r===Q)return n;var e=p(n);if(!u(e,r))return function(n,r,t){var e,i=I(r,t);return i?"value"in i?i.value:null===(e=i.get)||void 0===e?void 0:e.call(n.k):void 0}(n,e,r);var i=e[r];return n.I||!t(i)?i:i===z(n.t,r)?(E(n),n.o[r]=R(n.A.h,i,n)):i},has:function(n,r){return r in p(n)},ownKeys:function(n){return Reflect.ownKeys(p(n))},set:function(n,r,t){var e=I(p(n),r);if(null==e?void 0:e.set)return e.set.call(n.k,t),!0;if(!n.P){var i=z(p(n),r),o=null==i?void 0:i[Q];if(o&&o.t===t)return n.o[r]=t,n.D[r]=!1,!0;if(c(t,i)&&(void 0!==t||u(n.t,r)))return !0;E(n),k(n);}return n.o[r]===t&&"number"!=typeof t&&(void 0!==t||r in n.o)||(n.o[r]=t,n.D[r]=!0,!0)},deleteProperty:function(n,r){return void 0!==z(n.t,r)||r in n.t?(n.D[r]=!1,E(n),k(n)):delete n.D[r],n.o&&delete n.o[r],!0},getOwnPropertyDescriptor:function(n,r){var t=p(n),e=Reflect.getOwnPropertyDescriptor(t,r);return e?{writable:!0,configurable:1!==n.i||"length"!==r,enumerable:e.enumerable,value:t[r]}:e},defineProperty:function(){n(11);},getPrototypeOf:function(n){return Object.getPrototypeOf(n.t)},setPrototypeOf:function(){n(12);}},on={};i(en,(function(n,r){on[n]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)};})),on.deleteProperty=function(r,t){return isNaN(parseInt(t))&&n(13),on.set.call(this,r,t,void 0)},on.set=function(r,t,e){return "length"!==t&&isNaN(parseInt(t))&&n(14),en.set.call(this,r[0],t,e,r[0])};var un=function(){function e(r){var e=this;this.g=B,this.F=!0,this.produce=function(r,i,o){if("function"==typeof r&&"function"!=typeof i){var u=i;i=r;var a=e;return function(n){var r=this;void 0===n&&(n=u);for(var t=arguments.length,e=Array(t>1?t-1:0),o=1;o<t;o++)e[o-1]=arguments[o];return a.produce(n,(function(n){var t;return (t=i).call.apply(t,[r,n].concat(e))}))}}var f;if("function"!=typeof i&&n(6),void 0!==o&&"function"!=typeof o&&n(7),t(r)){var c=w(e),s=R(e,r,void 0),v=!0;try{f=i(s),v=!1;}finally{v?O(c):g(c);}return "undefined"!=typeof Promise&&f instanceof Promise?f.then((function(n){return j(c,o),P(n,c)}),(function(n){throw O(c),n})):(j(c,o),P(f,c))}if(!r||"object"!=typeof r){if(void 0===(f=i(r))&&(f=r),f===H&&(f=void 0),e.F&&d(f,!0),o){var p=[],l=[];b("Patches").M(r,f,p,l),o(p,l);}return f}n(21,r);},this.produceWithPatches=function(n,r){if("function"==typeof n)return function(r){for(var t=arguments.length,i=Array(t>1?t-1:0),o=1;o<t;o++)i[o-1]=arguments[o];return e.produceWithPatches(r,(function(r){return n.apply(void 0,[r].concat(i))}))};var t,i,o=e.produce(n,r,(function(n,r){t=n,i=r;}));return "undefined"!=typeof Promise&&o instanceof Promise?o.then((function(n){return [n,t,i]})):[o,t,i]},"boolean"==typeof(null==r?void 0:r.useProxies)&&this.setUseProxies(r.useProxies),"boolean"==typeof(null==r?void 0:r.autoFreeze)&&this.setAutoFreeze(r.autoFreeze);}var i=e.prototype;return i.createDraft=function(e){t(e)||n(8),r(e)&&(e=D(e));var i=w(this),o=R(this,e,void 0);return o[Q].C=!0,g(i),o},i.finishDraft=function(r,t){var e=r&&r[Q];(e&&e.C||n(9),e.I&&n(10));var i=e.A;return j(i,t),P(void 0,i)},i.setAutoFreeze=function(n){this.F=n;},i.setUseProxies=function(r){r&&!B&&n(20),this.g=r;},i.applyPatches=function(n,t){var e;for(e=t.length-1;e>=0;e--){var i=t[e];if(0===i.path.length&&"replace"===i.op){n=i.value;break}}e>-1&&(t=t.slice(e+1));var o=b("Patches").$;return r(n)?o(n,t):this.produce(n,(function(n){return o(n,t)}))},e}(),an=new un,fn=an.produce;an.produceWithPatches.bind(an);var sn=an.setAutoFreeze.bind(an);an.setUseProxies.bind(an);an.applyPatches.bind(an);an.createDraft.bind(an);an.finishDraft.bind(an);
|
|
477
|
+
|
|
478
|
+
sn(false);
|
|
479
|
+
let queue = [];
|
|
480
|
+
let batching = false;
|
|
481
|
+
function flush() {
|
|
482
|
+
if (batching) return;
|
|
483
|
+
queue.forEach(cb => cb());
|
|
484
|
+
queue = [];
|
|
485
|
+
}
|
|
486
|
+
function createStore(initialState, debug) {
|
|
487
|
+
const listeners = new Set();
|
|
488
|
+
const store = {
|
|
489
|
+
state: initialState,
|
|
490
|
+
subscribe: listener => {
|
|
491
|
+
listeners.add(listener);
|
|
492
|
+
return () => listeners.delete(listener);
|
|
493
|
+
},
|
|
494
|
+
setState: updater => {
|
|
495
|
+
const previous = store.state;
|
|
496
|
+
store.state = fn(d => {
|
|
497
|
+
updater(d);
|
|
498
|
+
})(previous);
|
|
499
|
+
if (debug) console.log(store.state);
|
|
500
|
+
queue.push(() => listeners.forEach(listener => listener(store.state, previous)));
|
|
501
|
+
flush();
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
return store;
|
|
505
|
+
}
|
|
506
|
+
function batch(cb) {
|
|
507
|
+
batching = true;
|
|
508
|
+
cb();
|
|
509
|
+
batching = false;
|
|
510
|
+
flush();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// /**
|
|
514
|
+
// * This function converts a store to an immutable value, which is
|
|
515
|
+
// * more complex than you think. On first read, (when prev is undefined)
|
|
516
|
+
// * every value must be recursively touched so tracking is "deep".
|
|
517
|
+
// * Every object/array structure must also be cloned to
|
|
518
|
+
// * have a new reference, otherwise it will get mutated by subsequent
|
|
519
|
+
// * store updates.
|
|
520
|
+
// *
|
|
521
|
+
// * In the case that prev is supplied, we have to do deep comparisons
|
|
522
|
+
// * between prev and next objects/array references and if they are deeply
|
|
523
|
+
// * equal, we can return the prev version for referential equality.
|
|
524
|
+
// */
|
|
525
|
+
// export function storeToImmutable<T>(prev: any, next: T): T {
|
|
526
|
+
// const cache = new Map()
|
|
527
|
+
|
|
528
|
+
// // Visit all nodes
|
|
529
|
+
// // clone all next structures
|
|
530
|
+
// // from bottom up, if prev === next, return prev
|
|
531
|
+
|
|
532
|
+
// function recurse(prev: any, next: any) {
|
|
533
|
+
// if (cache.has(next)) {
|
|
534
|
+
// return cache.get(next)
|
|
535
|
+
// }
|
|
536
|
+
|
|
537
|
+
// const prevIsArray = Array.isArray(prev)
|
|
538
|
+
// const nextIsArray = Array.isArray(next)
|
|
539
|
+
// const prevIsObj = isPlainObject(prev)
|
|
540
|
+
// const nextIsObj = isPlainObject(next)
|
|
541
|
+
// const nextIsComplex = nextIsArray || nextIsObj
|
|
542
|
+
|
|
543
|
+
// const isArray = prevIsArray && nextIsArray
|
|
544
|
+
// const isObj = prevIsObj && nextIsObj
|
|
545
|
+
|
|
546
|
+
// const isSameStructure = isArray || isObj
|
|
547
|
+
|
|
548
|
+
// if (nextIsComplex) {
|
|
549
|
+
// const prevSize = isArray
|
|
550
|
+
// ? prev.length
|
|
551
|
+
// : isObj
|
|
552
|
+
// ? Object.keys(prev).length
|
|
553
|
+
// : -1
|
|
554
|
+
// const nextKeys = isArray ? next : Object.keys(next)
|
|
555
|
+
// const nextSize = nextKeys.length
|
|
556
|
+
|
|
557
|
+
// let changed = false
|
|
558
|
+
// const copy: any = nextIsArray ? [] : {}
|
|
559
|
+
|
|
560
|
+
// for (let i = 0; i < nextSize; i++) {
|
|
561
|
+
// const key = isArray ? i : nextKeys[i]
|
|
562
|
+
// const prevValue = isSameStructure ? prev[key] : undefined
|
|
563
|
+
// const nextValue = next[key]
|
|
564
|
+
|
|
565
|
+
// // Recurse the new value
|
|
566
|
+
// try {
|
|
567
|
+
// console.count(key)
|
|
568
|
+
// copy[key] = recurse(prevValue, nextValue)
|
|
569
|
+
// } catch {}
|
|
570
|
+
|
|
571
|
+
// // If the new value has changed reference,
|
|
572
|
+
// // mark the obj/array as changed
|
|
573
|
+
// if (!changed && copy[key] !== prevValue) {
|
|
574
|
+
// changed = true
|
|
575
|
+
// }
|
|
576
|
+
// }
|
|
577
|
+
|
|
578
|
+
// // No items have changed!
|
|
579
|
+
// // If something has changed, return a clone of the next obj/array
|
|
580
|
+
// if (changed || prevSize !== nextSize) {
|
|
581
|
+
// cache.set(next, copy)
|
|
582
|
+
// return copy
|
|
583
|
+
// }
|
|
584
|
+
|
|
585
|
+
// // If they are exactly the same, return the prev obj/array
|
|
586
|
+
// cache.set(next, prev)
|
|
587
|
+
// return prev
|
|
588
|
+
// }
|
|
589
|
+
|
|
590
|
+
// cache.set(next, next)
|
|
591
|
+
// return next
|
|
592
|
+
// }
|
|
593
|
+
|
|
594
|
+
// return recurse(prev, next)
|
|
595
|
+
// }
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* This function returns `a` if `b` is deeply equal.
|
|
599
|
+
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
600
|
+
* This can be used for structural sharing between immutable JSON values for example.
|
|
601
|
+
* Do not use this with signals
|
|
602
|
+
*/
|
|
603
|
+
function replaceEqualDeep(prev, _next) {
|
|
604
|
+
if (prev === _next) {
|
|
1617
605
|
return prev;
|
|
1618
606
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
const isArray = prevIsArray && nextIsArray;
|
|
1627
|
-
const isObj = prevIsObj && nextIsObj;
|
|
1628
|
-
const isSameStructure = isArray || isObj;
|
|
1629
|
-
|
|
1630
|
-
// Both are arrays or objects
|
|
1631
|
-
if (isSameStructure) {
|
|
1632
|
-
const aSize = isArray ? prev.length : Object.keys(prev).length;
|
|
1633
|
-
const bItems = isArray ? next : Object.keys(next);
|
|
1634
|
-
const bSize = bItems.length;
|
|
1635
|
-
const copy = isArray ? [] : {};
|
|
607
|
+
const next = _next;
|
|
608
|
+
const array = Array.isArray(prev) && Array.isArray(next);
|
|
609
|
+
if (array || isPlainObject(prev) && isPlainObject(next)) {
|
|
610
|
+
const prevSize = array ? prev.length : Object.keys(prev).length;
|
|
611
|
+
const nextItems = array ? next : Object.keys(next);
|
|
612
|
+
const nextSize = nextItems.length;
|
|
613
|
+
const copy = array ? [] : {};
|
|
1636
614
|
let equalItems = 0;
|
|
1637
|
-
for (let i = 0; i <
|
|
1638
|
-
const key =
|
|
615
|
+
for (let i = 0; i < nextSize; i++) {
|
|
616
|
+
const key = array ? i : nextItems[i];
|
|
617
|
+
copy[key] = replaceEqualDeep(prev[key], next[key]);
|
|
1639
618
|
if (copy[key] === prev[key]) {
|
|
1640
619
|
equalItems++;
|
|
1641
620
|
}
|
|
1642
621
|
}
|
|
1643
|
-
|
|
1644
|
-
things.set(next, prev);
|
|
1645
|
-
return prev;
|
|
1646
|
-
}
|
|
1647
|
-
things.set(next, copy);
|
|
1648
|
-
for (let i = 0; i < bSize; i++) {
|
|
1649
|
-
const key = isArray ? i : bItems[i];
|
|
1650
|
-
if (typeof bItems[i] === 'function') {
|
|
1651
|
-
copy[key] = prev[key];
|
|
1652
|
-
} else {
|
|
1653
|
-
copy[key] = recurse(prev[key], next[key]);
|
|
1654
|
-
}
|
|
1655
|
-
if (copy[key] === prev[key]) {
|
|
1656
|
-
equalItems++;
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
return copy;
|
|
1660
|
-
}
|
|
1661
|
-
if (nextIsArray) {
|
|
1662
|
-
const copy = [];
|
|
1663
|
-
things.set(next, copy);
|
|
1664
|
-
for (let i = 0; i < next.length; i++) {
|
|
1665
|
-
copy[i] = recurse(undefined, next[i]);
|
|
1666
|
-
}
|
|
1667
|
-
return copy;
|
|
1668
|
-
}
|
|
1669
|
-
if (nextIsObj) {
|
|
1670
|
-
const copy = {};
|
|
1671
|
-
things.set(next, copy);
|
|
1672
|
-
const nextKeys = Object.keys(next);
|
|
1673
|
-
for (let i = 0; i < nextKeys.length; i++) {
|
|
1674
|
-
const key = nextKeys[i];
|
|
1675
|
-
copy[key] = recurse(undefined, next[key]);
|
|
1676
|
-
}
|
|
1677
|
-
return copy;
|
|
622
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy;
|
|
1678
623
|
}
|
|
1679
624
|
return next;
|
|
1680
625
|
}
|
|
1681
|
-
return recurse(prev, next);
|
|
1682
|
-
}
|
|
1683
626
|
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
627
|
+
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
628
|
+
function isPlainObject(o) {
|
|
629
|
+
if (!hasObjectPrototype(o)) {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
1689
632
|
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
633
|
+
// If has modified constructor
|
|
634
|
+
const ctor = o.constructor;
|
|
635
|
+
if (typeof ctor === 'undefined') {
|
|
636
|
+
return true;
|
|
637
|
+
}
|
|
1695
638
|
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
639
|
+
// If has modified prototype
|
|
640
|
+
const prot = ctor.prototype;
|
|
641
|
+
if (!hasObjectPrototype(prot)) {
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
1701
644
|
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
645
|
+
// If constructor does not have an Object-specific method
|
|
646
|
+
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
1706
649
|
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
}
|
|
1710
|
-
function hasObjectPrototype(o) {
|
|
1711
|
-
return Object.prototype.toString.call(o) === '[object Object]';
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1715
|
-
function createRouteMatch(router, route, opts) {
|
|
1716
|
-
let componentsPromise;
|
|
1717
|
-
let dataPromise;
|
|
1718
|
-
let latestId = '';
|
|
1719
|
-
let resolve = () => {};
|
|
1720
|
-
function setLoaderData(loaderData) {
|
|
1721
|
-
batch(() => {
|
|
1722
|
-
setStore(s => {
|
|
1723
|
-
s.routeLoaderData = sharedClone(s.routeLoaderData, loaderData);
|
|
1724
|
-
});
|
|
1725
|
-
updateLoaderData();
|
|
1726
|
-
});
|
|
650
|
+
// Most likely a plain Object
|
|
651
|
+
return true;
|
|
1727
652
|
}
|
|
1728
|
-
function
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
653
|
+
function hasObjectPrototype(o) {
|
|
654
|
+
return Object.prototype.toString.call(o) === '[object Object]';
|
|
655
|
+
}
|
|
656
|
+
function trackDeep(obj) {
|
|
657
|
+
const seen = new Set();
|
|
658
|
+
JSON.stringify(obj, (_, value) => {
|
|
659
|
+
if (typeof value === 'function') {
|
|
660
|
+
return undefined;
|
|
661
|
+
}
|
|
662
|
+
if (typeof value === 'object' && value !== null) {
|
|
663
|
+
if (seen.has(value)) return;
|
|
664
|
+
seen.add(value);
|
|
665
|
+
}
|
|
666
|
+
return value;
|
|
1735
667
|
});
|
|
668
|
+
return obj;
|
|
1736
669
|
}
|
|
1737
|
-
const [store, setStore] = createStore({
|
|
1738
|
-
routeSearch: {},
|
|
1739
|
-
search: {},
|
|
1740
|
-
status: 'idle',
|
|
1741
|
-
routeLoaderData: {},
|
|
1742
|
-
loaderData: {},
|
|
1743
|
-
isFetching: false,
|
|
1744
|
-
invalid: false,
|
|
1745
|
-
invalidAt: Infinity,
|
|
1746
|
-
get isInvalid() {
|
|
1747
|
-
const now = Date.now();
|
|
1748
|
-
return this.invalid || this.invalidAt < now;
|
|
1749
|
-
}
|
|
1750
|
-
});
|
|
1751
|
-
const routeMatch = {
|
|
1752
|
-
...route,
|
|
1753
|
-
...opts,
|
|
1754
|
-
store,
|
|
1755
|
-
// setStore,
|
|
1756
|
-
router,
|
|
1757
|
-
childMatches: [],
|
|
1758
|
-
__: {
|
|
1759
|
-
setParentMatch: parentMatch => {
|
|
1760
|
-
batch(() => {
|
|
1761
|
-
setStore(s => {
|
|
1762
|
-
s.parentMatch = parentMatch;
|
|
1763
|
-
});
|
|
1764
|
-
updateLoaderData();
|
|
1765
|
-
});
|
|
1766
|
-
},
|
|
1767
|
-
abortController: new AbortController(),
|
|
1768
|
-
validate: () => {
|
|
1769
|
-
var _store$parentMatch2;
|
|
1770
|
-
// Validate the search params and stabilize them
|
|
1771
|
-
const parentSearch = ((_store$parentMatch2 = store.parentMatch) == null ? void 0 : _store$parentMatch2.store.search) ?? router.store.currentLocation.search;
|
|
1772
|
-
try {
|
|
1773
|
-
const prevSearch = store.routeSearch;
|
|
1774
|
-
const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
|
|
1775
|
-
let nextSearch = sharedClone(prevSearch, (validator == null ? void 0 : validator(parentSearch)) ?? {});
|
|
1776
|
-
batch(() => {
|
|
1777
|
-
// Invalidate route matches when search param stability changes
|
|
1778
|
-
if (prevSearch !== nextSearch) {
|
|
1779
|
-
setStore(s => s.invalid = true);
|
|
1780
|
-
}
|
|
1781
670
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
// Do not proceed with loading the route
|
|
1809
|
-
return;
|
|
1810
|
-
}
|
|
671
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
672
|
+
class RouteMatch {
|
|
673
|
+
abortController = new AbortController();
|
|
674
|
+
#latestId = '';
|
|
675
|
+
#resolve = () => {};
|
|
676
|
+
onLoaderDataListeners = new Set();
|
|
677
|
+
constructor(router, route, opts) {
|
|
678
|
+
Object.assign(this, {
|
|
679
|
+
route,
|
|
680
|
+
router,
|
|
681
|
+
matchId: opts.matchId,
|
|
682
|
+
pathname: opts.pathname,
|
|
683
|
+
params: opts.params,
|
|
684
|
+
store: createStore({
|
|
685
|
+
routeSearch: {},
|
|
686
|
+
search: {},
|
|
687
|
+
status: 'idle',
|
|
688
|
+
routeLoaderData: {},
|
|
689
|
+
loaderData: {},
|
|
690
|
+
isFetching: false,
|
|
691
|
+
invalid: false,
|
|
692
|
+
invalidAt: Infinity
|
|
693
|
+
})
|
|
694
|
+
});
|
|
695
|
+
if (!this.__hasLoaders()) {
|
|
696
|
+
this.store.setState(s => s.status = 'success');
|
|
1811
697
|
}
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
},
|
|
1826
|
-
load: async loaderOpts => {
|
|
698
|
+
}
|
|
699
|
+
#setLoaderData = loaderData => {
|
|
700
|
+
batch(() => {
|
|
701
|
+
this.store.setState(s => {
|
|
702
|
+
s.routeLoaderData = loaderData;
|
|
703
|
+
});
|
|
704
|
+
this.#updateLoaderData();
|
|
705
|
+
});
|
|
706
|
+
};
|
|
707
|
+
cancel = () => {
|
|
708
|
+
this.abortController?.abort();
|
|
709
|
+
};
|
|
710
|
+
load = async loaderOpts => {
|
|
1827
711
|
const now = Date.now();
|
|
1828
|
-
const minMaxAge = loaderOpts
|
|
712
|
+
const minMaxAge = loaderOpts?.preload ? Math.max(loaderOpts?.maxAge, loaderOpts?.gcMaxAge) : 0;
|
|
1829
713
|
|
|
1830
714
|
// If this is a preload, add it to the preload cache
|
|
1831
|
-
if (loaderOpts
|
|
715
|
+
if (loaderOpts?.preload && minMaxAge > 0) {
|
|
1832
716
|
// If the match is currently active, don't preload it
|
|
1833
|
-
if (router.store.currentMatches.find(d => d.
|
|
717
|
+
if (this.router.store.state.currentMatches.find(d => d.id === this.id)) {
|
|
1834
718
|
return;
|
|
1835
719
|
}
|
|
1836
|
-
router.store.
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
720
|
+
this.router.store.setState(s => {
|
|
721
|
+
s.matchCache[this.id] = {
|
|
722
|
+
gc: now + loaderOpts.gcMaxAge,
|
|
723
|
+
match: this
|
|
724
|
+
};
|
|
725
|
+
});
|
|
1840
726
|
}
|
|
1841
727
|
|
|
1842
728
|
// If the match is invalid, errored or idle, trigger it to load
|
|
1843
|
-
if (store.status === 'success' &&
|
|
1844
|
-
const maxAge = loaderOpts
|
|
1845
|
-
await
|
|
729
|
+
if (this.store.state.status === 'success' && this.getIsInvalid() || this.store.state.status === 'error' || this.store.state.status === 'idle') {
|
|
730
|
+
const maxAge = loaderOpts?.preload ? loaderOpts?.maxAge : undefined;
|
|
731
|
+
await this.fetch({
|
|
1846
732
|
maxAge
|
|
1847
733
|
});
|
|
1848
734
|
}
|
|
1849
|
-
}
|
|
1850
|
-
fetch
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
735
|
+
};
|
|
736
|
+
fetch = async opts => {
|
|
737
|
+
this.__loadPromise = new Promise(async resolve => {
|
|
738
|
+
const loadId = '' + Date.now() + Math.random();
|
|
739
|
+
this.#latestId = loadId;
|
|
740
|
+
const checkLatest = () => loadId !== this.#latestId ? this.__loadPromise?.then(() => resolve()) : undefined;
|
|
741
|
+
let latestPromise;
|
|
742
|
+
batch(() => {
|
|
743
|
+
// If the match was in an error state, set it
|
|
744
|
+
// to a loading state again. Otherwise, keep it
|
|
745
|
+
// as loading or resolved
|
|
746
|
+
if (this.store.state.status === 'idle') {
|
|
747
|
+
this.store.setState(s => s.status = 'loading');
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// We started loading the route, so it's no longer invalid
|
|
751
|
+
this.store.setState(s => s.invalid = false);
|
|
752
|
+
});
|
|
1866
753
|
|
|
1867
|
-
// We started loading the route, so it's no longer invalid
|
|
1868
|
-
setStore(s => s.invalid = false);
|
|
1869
|
-
});
|
|
1870
|
-
routeMatch.__.loadPromise = new Promise(async r => {
|
|
1871
754
|
// We are now fetching, even if it's in the background of a
|
|
1872
755
|
// resolved state
|
|
1873
|
-
|
|
1874
|
-
resolve =
|
|
1875
|
-
componentsPromise = (async () => {
|
|
756
|
+
this.store.setState(s => s.isFetching = true);
|
|
757
|
+
this.#resolve = resolve;
|
|
758
|
+
const componentsPromise = (async () => {
|
|
1876
759
|
// then run all component and data loaders in parallel
|
|
1877
760
|
// For each component type, potentially load it asynchronously
|
|
1878
761
|
|
|
1879
762
|
await Promise.all(componentTypes.map(async type => {
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
routeMatch.__[type] = await router.options.loadComponent(component);
|
|
763
|
+
const component = this.route.options[type];
|
|
764
|
+
if (this[type]?.preload) {
|
|
765
|
+
this[type] = await this.router.options.loadComponent(component);
|
|
1884
766
|
}
|
|
1885
767
|
}));
|
|
1886
768
|
})();
|
|
1887
|
-
dataPromise = Promise.resolve().then(async () => {
|
|
769
|
+
const dataPromise = Promise.resolve().then(async () => {
|
|
1888
770
|
try {
|
|
1889
|
-
if (
|
|
1890
|
-
const data = await router.loadMatchData(
|
|
1891
|
-
|
|
1892
|
-
setLoaderData(data);
|
|
771
|
+
if (this.route.options.loader) {
|
|
772
|
+
const data = await this.router.loadMatchData(this);
|
|
773
|
+
if (latestPromise = checkLatest()) return latestPromise;
|
|
774
|
+
this.#setLoaderData(data);
|
|
1893
775
|
}
|
|
1894
|
-
|
|
776
|
+
this.store.setState(s => {
|
|
1895
777
|
s.error = undefined;
|
|
1896
778
|
s.status = 'success';
|
|
1897
779
|
s.updatedAt = Date.now();
|
|
1898
|
-
s.invalidAt = s.updatedAt + (
|
|
780
|
+
s.invalidAt = s.updatedAt + (opts?.maxAge ?? this.route.options.loaderMaxAge ?? this.router.options.defaultLoaderMaxAge ?? 0);
|
|
1899
781
|
});
|
|
1900
|
-
return store.routeLoaderData;
|
|
782
|
+
return this.store.state.routeLoaderData;
|
|
1901
783
|
} catch (err) {
|
|
1902
|
-
|
|
784
|
+
if (latestPromise = checkLatest()) return latestPromise;
|
|
1903
785
|
{
|
|
1904
786
|
console.error(err);
|
|
1905
787
|
}
|
|
1906
|
-
|
|
788
|
+
this.store.setState(s => {
|
|
1907
789
|
s.error = err;
|
|
1908
790
|
s.status = 'error';
|
|
1909
791
|
s.updatedAt = Date.now();
|
|
@@ -1912,10 +794,10 @@
|
|
|
1912
794
|
}
|
|
1913
795
|
});
|
|
1914
796
|
const after = async () => {
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
797
|
+
if (latestPromise = checkLatest()) return latestPromise;
|
|
798
|
+
this.store.setState(s => s.isFetching = false);
|
|
799
|
+
this.#resolve();
|
|
800
|
+
delete this.__loadPromise;
|
|
1919
801
|
};
|
|
1920
802
|
try {
|
|
1921
803
|
await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
|
|
@@ -1924,439 +806,359 @@
|
|
|
1924
806
|
after();
|
|
1925
807
|
}
|
|
1926
808
|
});
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
809
|
+
return this.__loadPromise;
|
|
810
|
+
};
|
|
811
|
+
invalidate = async () => {
|
|
812
|
+
this.store.setState(s => s.invalid = true);
|
|
813
|
+
if (this.router.store.state.currentMatches.find(d => d.id === this.id)) {
|
|
814
|
+
await this.load();
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
__hasLoaders = () => {
|
|
818
|
+
return !!(this.route.options.loader || componentTypes.some(d => this.route.options[d]?.preload));
|
|
819
|
+
};
|
|
820
|
+
getIsInvalid = () => {
|
|
821
|
+
const now = Date.now();
|
|
822
|
+
return this.store.state.invalid || this.store.state.invalidAt < now;
|
|
823
|
+
};
|
|
824
|
+
#updateLoaderData = () => {
|
|
825
|
+
this.store.setState(s => {
|
|
826
|
+
s.loaderData = replaceEqualDeep(s.loaderData, {
|
|
827
|
+
...this.parentMatch?.store.state.loaderData,
|
|
828
|
+
...s.routeLoaderData
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
this.onLoaderDataListeners.forEach(listener => listener());
|
|
832
|
+
};
|
|
833
|
+
__setParentMatch = parentMatch => {
|
|
834
|
+
if (!this.parentMatch && parentMatch) {
|
|
835
|
+
this.parentMatch = parentMatch;
|
|
836
|
+
this.parentMatch.__onLoaderData(() => {
|
|
837
|
+
this.#updateLoaderData();
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
__onLoaderData = listener => {
|
|
842
|
+
this.onLoaderDataListeners.add(listener);
|
|
843
|
+
// return () => this.onLoaderDataListeners.delete(listener)
|
|
844
|
+
};
|
|
1945
845
|
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
const
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
846
|
+
__validate = () => {
|
|
847
|
+
// Validate the search params and stabilize them
|
|
848
|
+
const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
|
|
849
|
+
try {
|
|
850
|
+
const prevSearch = this.store.state.routeSearch;
|
|
851
|
+
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
|
|
852
|
+
let nextSearch = validator?.(parentSearch) ?? {};
|
|
853
|
+
batch(() => {
|
|
854
|
+
// Invalidate route matches when search param stability changes
|
|
855
|
+
if (prevSearch !== nextSearch) {
|
|
856
|
+
this.store.setState(s => s.invalid = true);
|
|
857
|
+
}
|
|
858
|
+
this.store.setState(s => {
|
|
859
|
+
s.routeSearch = nextSearch;
|
|
860
|
+
s.search = {
|
|
861
|
+
...parentSearch,
|
|
862
|
+
...nextSearch
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
});
|
|
866
|
+
componentTypes.map(async type => {
|
|
867
|
+
const component = this.route.options[type];
|
|
868
|
+
if (typeof this[type] !== 'function') {
|
|
869
|
+
this[type] = component;
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
} catch (err) {
|
|
873
|
+
console.error(err);
|
|
874
|
+
const error = new Error('Invalid search params found', {
|
|
875
|
+
cause: err
|
|
876
|
+
});
|
|
877
|
+
error.code = 'INVALID_SEARCH_PARAMS';
|
|
878
|
+
this.store.setState(s => {
|
|
879
|
+
s.status = 'error';
|
|
880
|
+
s.error = error;
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
// Do not proceed with loading the route
|
|
884
|
+
return;
|
|
1955
885
|
}
|
|
1956
|
-
}
|
|
1957
|
-
return query;
|
|
1958
|
-
};
|
|
1959
|
-
}
|
|
1960
|
-
function stringifySearchWith(stringify) {
|
|
1961
|
-
return search => {
|
|
1962
|
-
search = {
|
|
1963
|
-
...search
|
|
1964
886
|
};
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
890
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify);
|
|
891
|
+
function parseSearchWith(parser) {
|
|
892
|
+
return searchStr => {
|
|
893
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
894
|
+
searchStr = searchStr.substring(1);
|
|
895
|
+
}
|
|
896
|
+
let query = decode(searchStr);
|
|
897
|
+
|
|
898
|
+
// Try to parse any query params that might be json
|
|
899
|
+
for (let key in query) {
|
|
900
|
+
const value = query[key];
|
|
901
|
+
if (typeof value === 'string') {
|
|
1971
902
|
try {
|
|
1972
|
-
|
|
903
|
+
query[key] = parser(value);
|
|
1973
904
|
} catch (err) {
|
|
1974
|
-
//
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
});
|
|
1978
|
-
}
|
|
1979
|
-
const searchStr = encode(search).toString();
|
|
1980
|
-
return searchStr ? `?${searchStr}` : '';
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
var _window$document;
|
|
1985
|
-
// Detect if we're in the DOM
|
|
1986
|
-
const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement);
|
|
1987
|
-
|
|
1988
|
-
// This is the default history object if none is defined
|
|
1989
|
-
const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
|
|
1990
|
-
function getInitialRouterState() {
|
|
1991
|
-
return {
|
|
1992
|
-
status: 'idle',
|
|
1993
|
-
latestLocation: null,
|
|
1994
|
-
currentLocation: null,
|
|
1995
|
-
currentMatches: [],
|
|
1996
|
-
actions: {},
|
|
1997
|
-
loaders: {},
|
|
1998
|
-
lastUpdated: Date.now(),
|
|
1999
|
-
matchCache: {},
|
|
2000
|
-
get isFetching() {
|
|
2001
|
-
return this.status === 'loading' || this.currentMatches.some(d => d.store.isFetching);
|
|
2002
|
-
},
|
|
2003
|
-
get isPreloading() {
|
|
2004
|
-
return Object.values(this.matchCache).some(d => d.match.store.isFetching && !this.currentMatches.find(dd => dd.matchId === d.match.matchId));
|
|
2005
|
-
}
|
|
2006
|
-
};
|
|
2007
|
-
}
|
|
2008
|
-
function createRouter(userOptions) {
|
|
2009
|
-
const originalOptions = {
|
|
2010
|
-
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
2011
|
-
defaultLoaderMaxAge: 0,
|
|
2012
|
-
defaultPreloadMaxAge: 2000,
|
|
2013
|
-
defaultPreloadDelay: 50,
|
|
2014
|
-
context: undefined,
|
|
2015
|
-
...userOptions,
|
|
2016
|
-
stringifySearch: (userOptions == null ? void 0 : userOptions.stringifySearch) ?? defaultStringifySearch,
|
|
2017
|
-
parseSearch: (userOptions == null ? void 0 : userOptions.parseSearch) ?? defaultParseSearch
|
|
2018
|
-
};
|
|
2019
|
-
const [store, setStore] = createStore(getInitialRouterState());
|
|
2020
|
-
let navigationPromise;
|
|
2021
|
-
let startedLoadingAt = Date.now();
|
|
2022
|
-
let resolveNavigation = () => {};
|
|
2023
|
-
function onFocus() {
|
|
2024
|
-
router.load();
|
|
2025
|
-
}
|
|
2026
|
-
function buildRouteTree(rootRouteConfig) {
|
|
2027
|
-
const recurseRoutes = (routeConfigs, parent) => {
|
|
2028
|
-
return routeConfigs.map((routeConfig, i) => {
|
|
2029
|
-
const routeOptions = routeConfig.options;
|
|
2030
|
-
const route = createRoute(routeConfig, routeOptions, i, parent, router);
|
|
2031
|
-
const existingRoute = router.routesById[route.routeId];
|
|
2032
|
-
if (existingRoute) {
|
|
2033
|
-
{
|
|
2034
|
-
console.warn(`Duplicate routes found with id: ${String(route.routeId)}`, router.routesById, route);
|
|
905
|
+
//
|
|
2035
906
|
}
|
|
2036
|
-
throw new Error();
|
|
2037
907
|
}
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
|
|
2041
|
-
return route;
|
|
2042
|
-
});
|
|
2043
|
-
};
|
|
2044
|
-
const routes = recurseRoutes([rootRouteConfig]);
|
|
2045
|
-
return routes[0];
|
|
2046
|
-
}
|
|
2047
|
-
function parseLocation(location, previousLocation) {
|
|
2048
|
-
const parsedSearch = router.options.parseSearch(location.search);
|
|
2049
|
-
return {
|
|
2050
|
-
pathname: location.pathname,
|
|
2051
|
-
searchStr: location.search,
|
|
2052
|
-
search: sharedClone(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
|
|
2053
|
-
hash: location.hash.split('#').reverse()[0] ?? '',
|
|
2054
|
-
href: `${location.pathname}${location.search}${location.hash}`,
|
|
2055
|
-
state: location.state,
|
|
2056
|
-
key: location.key
|
|
908
|
+
}
|
|
909
|
+
return query;
|
|
2057
910
|
};
|
|
2058
911
|
}
|
|
2059
|
-
function
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
Object.assign({}, nextParams, fn(nextParams));
|
|
2081
|
-
});
|
|
2082
|
-
}
|
|
2083
|
-
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
2084
|
-
|
|
2085
|
-
// Pre filters first
|
|
2086
|
-
const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), store.latestLocation.search) : store.latestLocation.search;
|
|
2087
|
-
|
|
2088
|
-
// Then the link/navigate function
|
|
2089
|
-
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
2090
|
-
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
2091
|
-
: (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
2092
|
-
: {};
|
|
2093
|
-
|
|
2094
|
-
// Then post filters
|
|
2095
|
-
const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
2096
|
-
const search = sharedClone(store.latestLocation.search, postFilteredSearch);
|
|
2097
|
-
const searchStr = router.options.stringifySearch(search);
|
|
2098
|
-
let hash = dest.hash === true ? store.latestLocation.hash : functionalUpdate(dest.hash, store.latestLocation.hash);
|
|
2099
|
-
hash = hash ? `#${hash}` : '';
|
|
2100
|
-
return {
|
|
2101
|
-
pathname,
|
|
2102
|
-
search,
|
|
2103
|
-
searchStr,
|
|
2104
|
-
state: store.latestLocation.state,
|
|
2105
|
-
hash,
|
|
2106
|
-
href: `${pathname}${searchStr}${hash}`,
|
|
2107
|
-
key: dest.key
|
|
912
|
+
function stringifySearchWith(stringify) {
|
|
913
|
+
return search => {
|
|
914
|
+
search = {
|
|
915
|
+
...search
|
|
916
|
+
};
|
|
917
|
+
if (search) {
|
|
918
|
+
Object.keys(search).forEach(key => {
|
|
919
|
+
const val = search[key];
|
|
920
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
921
|
+
delete search[key];
|
|
922
|
+
} else if (val && typeof val === 'object' && val !== null) {
|
|
923
|
+
try {
|
|
924
|
+
search[key] = stringify(val);
|
|
925
|
+
} catch (err) {
|
|
926
|
+
// silent
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
const searchStr = encode(search).toString();
|
|
932
|
+
return searchStr ? `?${searchStr}` : '';
|
|
2108
933
|
};
|
|
2109
934
|
}
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
search: next.searchStr
|
|
2124
|
-
}, {
|
|
2125
|
-
id,
|
|
2126
|
-
...next.state
|
|
935
|
+
|
|
936
|
+
const defaultFetchServerDataFn = async ({
|
|
937
|
+
router,
|
|
938
|
+
routeMatch
|
|
939
|
+
}) => {
|
|
940
|
+
const next = router.buildNext({
|
|
941
|
+
to: '.',
|
|
942
|
+
search: d => ({
|
|
943
|
+
...(d ?? {}),
|
|
944
|
+
__data: {
|
|
945
|
+
matchId: routeMatch.id
|
|
946
|
+
}
|
|
947
|
+
})
|
|
2127
948
|
});
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
previousNavigationResolve();
|
|
2132
|
-
resolve();
|
|
2133
|
-
};
|
|
949
|
+
const res = await fetch(next.href, {
|
|
950
|
+
method: 'GET',
|
|
951
|
+
signal: routeMatch.abortController.signal
|
|
2134
952
|
});
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
currentMatches: store.currentMatches.map(match => ({
|
|
2157
|
-
matchId: match.matchId,
|
|
2158
|
-
store: pick(match.store, ['status', 'routeLoaderData', 'isInvalid', 'invalidAt'])
|
|
2159
|
-
}))
|
|
2160
|
-
},
|
|
2161
|
-
context: router.options.context
|
|
953
|
+
if (res.ok) {
|
|
954
|
+
return res.json();
|
|
955
|
+
}
|
|
956
|
+
throw new Error('Failed to fetch match data');
|
|
957
|
+
};
|
|
958
|
+
class Router {
|
|
959
|
+
// __location: Location<TAllRouteInfo['fullSearchSchema']>
|
|
960
|
+
|
|
961
|
+
startedLoadingAt = Date.now();
|
|
962
|
+
resolveNavigation = () => {};
|
|
963
|
+
constructor(options) {
|
|
964
|
+
this.options = {
|
|
965
|
+
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
966
|
+
defaultLoaderMaxAge: 0,
|
|
967
|
+
defaultPreloadMaxAge: 2000,
|
|
968
|
+
defaultPreloadDelay: 50,
|
|
969
|
+
context: undefined,
|
|
970
|
+
...options,
|
|
971
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
972
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch,
|
|
973
|
+
fetchServerDataFn: options?.fetchServerDataFn ?? defaultFetchServerDataFn
|
|
2162
974
|
};
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
router.options.context = dehydratedRouter.context;
|
|
975
|
+
this.history = this.options?.history ?? isServer ? createMemoryHistory() : createBrowserHistory();
|
|
976
|
+
this.store = createStore(getInitialRouterState());
|
|
977
|
+
this.basepath = '';
|
|
978
|
+
this.update(options);
|
|
2168
979
|
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
Object.assign(match, dehydratedMatch);
|
|
2177
|
-
});
|
|
2178
|
-
currentMatches.forEach(match => match.__.validate());
|
|
2179
|
-
Object.assign(s, {
|
|
2180
|
-
...dehydratedRouter.store,
|
|
2181
|
-
currentMatches
|
|
2182
|
-
});
|
|
2183
|
-
});
|
|
2184
|
-
},
|
|
2185
|
-
mount: () => {
|
|
980
|
+
// Allow frameworks to hook into the router creation
|
|
981
|
+
this.options.createRouter?.(this);
|
|
982
|
+
}
|
|
983
|
+
reset = () => {
|
|
984
|
+
this.store.setState(s => Object.assign(s, getInitialRouterState()));
|
|
985
|
+
};
|
|
986
|
+
mount = () => {
|
|
2186
987
|
// Mount only does anything on the client
|
|
2187
988
|
if (!isServer) {
|
|
2188
989
|
// If the router matches are empty, load the matches
|
|
2189
|
-
if (!store.currentMatches.length) {
|
|
2190
|
-
|
|
990
|
+
if (!this.store.state.currentMatches.length) {
|
|
991
|
+
this.load();
|
|
2191
992
|
}
|
|
2192
|
-
const
|
|
2193
|
-
|
|
993
|
+
const unsubHistory = this.history.listen(() => {
|
|
994
|
+
this.load(this.#parseLocation(this.store.state.latestLocation));
|
|
2194
995
|
});
|
|
996
|
+
const visibilityChangeEvent = 'visibilitychange';
|
|
997
|
+
const focusEvent = 'focus';
|
|
2195
998
|
|
|
2196
999
|
// addEventListener does not exist in React Native, but window does
|
|
2197
1000
|
// In the future, we might need to invert control here for more adapters
|
|
2198
1001
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
2199
1002
|
if (window.addEventListener) {
|
|
2200
1003
|
// Listen to visibilitychange and focus
|
|
2201
|
-
window.addEventListener(
|
|
2202
|
-
window.addEventListener(
|
|
1004
|
+
window.addEventListener(visibilityChangeEvent, this.#onFocus, false);
|
|
1005
|
+
window.addEventListener(focusEvent, this.#onFocus, false);
|
|
2203
1006
|
}
|
|
2204
1007
|
return () => {
|
|
2205
|
-
|
|
1008
|
+
unsubHistory();
|
|
2206
1009
|
if (window.removeEventListener) {
|
|
2207
1010
|
// Be sure to unsubscribe if a new handler is set
|
|
2208
|
-
|
|
2209
|
-
window.removeEventListener(
|
|
1011
|
+
|
|
1012
|
+
window.removeEventListener(visibilityChangeEvent, this.#onFocus);
|
|
1013
|
+
window.removeEventListener(focusEvent, this.#onFocus);
|
|
2210
1014
|
}
|
|
2211
1015
|
};
|
|
2212
1016
|
}
|
|
2213
1017
|
return () => {};
|
|
2214
|
-
}
|
|
2215
|
-
update
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
router.history = opts.history;
|
|
2220
|
-
}
|
|
2221
|
-
setStore(s => {
|
|
2222
|
-
s.latestLocation = parseLocation(router.history.location);
|
|
1018
|
+
};
|
|
1019
|
+
update = opts => {
|
|
1020
|
+
if (!this.store.state.latestLocation) {
|
|
1021
|
+
this.store.setState(s => {
|
|
1022
|
+
s.latestLocation = this.#parseLocation();
|
|
2223
1023
|
s.currentLocation = s.latestLocation;
|
|
2224
1024
|
});
|
|
2225
1025
|
}
|
|
2226
|
-
Object.assign(
|
|
1026
|
+
Object.assign(this.options, opts);
|
|
2227
1027
|
const {
|
|
2228
1028
|
basepath,
|
|
2229
1029
|
routeConfig
|
|
2230
|
-
} =
|
|
2231
|
-
|
|
1030
|
+
} = this.options;
|
|
1031
|
+
this.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
|
|
2232
1032
|
if (routeConfig) {
|
|
2233
|
-
|
|
2234
|
-
|
|
1033
|
+
this.routesById = {};
|
|
1034
|
+
this.routeTree = this.#buildRouteTree(routeConfig);
|
|
2235
1035
|
}
|
|
2236
|
-
return
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
|
-
|
|
1036
|
+
return this;
|
|
1037
|
+
};
|
|
1038
|
+
buildNext = opts => {
|
|
1039
|
+
const next = this.#buildLocation(opts);
|
|
1040
|
+
const matches = this.matchRoutes(next.pathname);
|
|
1041
|
+
const __preSearchFilters = matches.map(match => match.route.options.preSearchFilters ?? []).flat().filter(Boolean);
|
|
1042
|
+
const __postSearchFilters = matches.map(match => match.route.options.postSearchFilters ?? []).flat().filter(Boolean);
|
|
1043
|
+
return this.#buildLocation({
|
|
1044
|
+
...opts,
|
|
1045
|
+
__preSearchFilters,
|
|
1046
|
+
__postSearchFilters
|
|
1047
|
+
});
|
|
1048
|
+
};
|
|
1049
|
+
cancelMatches = () => {
|
|
1050
|
+
[...this.store.state.currentMatches, ...(this.store.state.pendingMatches || [])].forEach(match => {
|
|
2240
1051
|
match.cancel();
|
|
2241
1052
|
});
|
|
2242
|
-
}
|
|
2243
|
-
load
|
|
1053
|
+
};
|
|
1054
|
+
load = async next => {
|
|
2244
1055
|
let now = Date.now();
|
|
2245
1056
|
const startedAt = now;
|
|
2246
|
-
startedLoadingAt = startedAt;
|
|
1057
|
+
this.startedLoadingAt = startedAt;
|
|
2247
1058
|
|
|
2248
1059
|
// Cancel any pending matches
|
|
2249
|
-
|
|
1060
|
+
this.cancelMatches();
|
|
2250
1061
|
let matches;
|
|
2251
1062
|
batch(() => {
|
|
2252
1063
|
if (next) {
|
|
2253
1064
|
// Ingest the new location
|
|
2254
|
-
|
|
1065
|
+
this.store.setState(s => {
|
|
2255
1066
|
s.latestLocation = next;
|
|
2256
1067
|
});
|
|
2257
1068
|
}
|
|
2258
1069
|
|
|
2259
1070
|
// Match the routes
|
|
2260
|
-
matches =
|
|
1071
|
+
matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
|
|
2261
1072
|
strictParseParams: true
|
|
2262
1073
|
});
|
|
2263
|
-
|
|
2264
|
-
setStore(s => {
|
|
1074
|
+
this.store.setState(s => {
|
|
2265
1075
|
s.status = 'loading';
|
|
2266
1076
|
s.pendingMatches = matches;
|
|
2267
|
-
s.pendingLocation = store.latestLocation;
|
|
1077
|
+
s.pendingLocation = this.store.state.latestLocation;
|
|
2268
1078
|
});
|
|
2269
1079
|
});
|
|
2270
1080
|
|
|
2271
1081
|
// Load the matches
|
|
2272
1082
|
try {
|
|
2273
|
-
await
|
|
1083
|
+
await this.loadMatches(matches);
|
|
2274
1084
|
} catch (err) {
|
|
2275
|
-
console.
|
|
1085
|
+
console.warn(err);
|
|
2276
1086
|
invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
|
|
2277
1087
|
}
|
|
2278
|
-
if (startedLoadingAt !== startedAt) {
|
|
1088
|
+
if (this.startedLoadingAt !== startedAt) {
|
|
2279
1089
|
// Ignore side-effects of outdated side-effects
|
|
2280
|
-
return navigationPromise;
|
|
1090
|
+
return this.navigationPromise;
|
|
2281
1091
|
}
|
|
2282
|
-
const previousMatches = store.currentMatches;
|
|
1092
|
+
const previousMatches = this.store.state.currentMatches;
|
|
2283
1093
|
const exiting = [],
|
|
2284
1094
|
staying = [];
|
|
2285
1095
|
previousMatches.forEach(d => {
|
|
2286
|
-
if (matches.find(dd => dd.
|
|
1096
|
+
if (matches.find(dd => dd.id === d.id)) {
|
|
2287
1097
|
staying.push(d);
|
|
2288
1098
|
} else {
|
|
2289
1099
|
exiting.push(d);
|
|
2290
1100
|
}
|
|
2291
1101
|
});
|
|
2292
1102
|
const entering = matches.filter(d => {
|
|
2293
|
-
return !previousMatches.find(dd => dd.
|
|
1103
|
+
return !previousMatches.find(dd => dd.id === d.id);
|
|
2294
1104
|
});
|
|
2295
1105
|
now = Date.now();
|
|
2296
1106
|
exiting.forEach(d => {
|
|
2297
|
-
d.
|
|
1107
|
+
d.__onExit?.({
|
|
2298
1108
|
params: d.params,
|
|
2299
|
-
search: d.store.routeSearch
|
|
1109
|
+
search: d.store.state.routeSearch
|
|
2300
1110
|
});
|
|
2301
1111
|
|
|
2302
|
-
// Clear
|
|
2303
|
-
if (d.store.status === 'error' && !d.store.isFetching) {
|
|
2304
|
-
d.store.
|
|
2305
|
-
|
|
1112
|
+
// Clear non-loading error states when match leaves
|
|
1113
|
+
if (d.store.state.status === 'error' && !d.store.state.isFetching) {
|
|
1114
|
+
d.store.setState(s => {
|
|
1115
|
+
s.status = 'idle';
|
|
1116
|
+
s.error = undefined;
|
|
1117
|
+
});
|
|
2306
1118
|
}
|
|
2307
|
-
const gc = Math.max(d.options.loaderGcMaxAge ??
|
|
1119
|
+
const gc = Math.max(d.route.options.loaderGcMaxAge ?? this.options.defaultLoaderGcMaxAge ?? 0, d.route.options.loaderMaxAge ?? this.options.defaultLoaderMaxAge ?? 0);
|
|
2308
1120
|
if (gc > 0) {
|
|
2309
|
-
store.
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
1121
|
+
this.store.setState(s => {
|
|
1122
|
+
s.matchCache[d.id] = {
|
|
1123
|
+
gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
|
|
1124
|
+
match: d
|
|
1125
|
+
};
|
|
1126
|
+
});
|
|
2313
1127
|
}
|
|
2314
1128
|
});
|
|
2315
1129
|
staying.forEach(d => {
|
|
2316
|
-
d.
|
|
1130
|
+
d.route.options.onTransition?.({
|
|
2317
1131
|
params: d.params,
|
|
2318
|
-
search: d.store.routeSearch
|
|
1132
|
+
search: d.store.state.routeSearch
|
|
2319
1133
|
});
|
|
2320
1134
|
});
|
|
2321
1135
|
entering.forEach(d => {
|
|
2322
|
-
d.
|
|
1136
|
+
d.__onExit = d.route.options.onLoaded?.({
|
|
2323
1137
|
params: d.params,
|
|
2324
|
-
search: d.store.search
|
|
1138
|
+
search: d.store.state.search
|
|
2325
1139
|
});
|
|
2326
|
-
delete store.matchCache[d.
|
|
2327
|
-
});
|
|
2328
|
-
if (startedLoadingAt !== startedAt) {
|
|
2329
|
-
// Ignore side-effects of match loading
|
|
2330
|
-
return;
|
|
2331
|
-
}
|
|
2332
|
-
matches.forEach(match => {
|
|
2333
|
-
// Clear actions
|
|
2334
|
-
if (match.action) {
|
|
2335
|
-
// TODO: Check reactivity here
|
|
2336
|
-
match.action.current = undefined;
|
|
2337
|
-
match.action.submissions = [];
|
|
2338
|
-
}
|
|
1140
|
+
delete this.store.state.matchCache[d.id];
|
|
2339
1141
|
});
|
|
2340
|
-
|
|
2341
|
-
console.log('set', matches);
|
|
1142
|
+
this.store.setState(s => {
|
|
2342
1143
|
Object.assign(s, {
|
|
2343
1144
|
status: 'idle',
|
|
2344
|
-
currentLocation: store.latestLocation,
|
|
1145
|
+
currentLocation: this.store.state.latestLocation,
|
|
2345
1146
|
currentMatches: matches,
|
|
2346
1147
|
pendingLocation: undefined,
|
|
2347
1148
|
pendingMatches: undefined
|
|
2348
1149
|
});
|
|
2349
1150
|
});
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
1151
|
+
this.options.onRouteChange?.();
|
|
1152
|
+
this.resolveNavigation();
|
|
1153
|
+
};
|
|
1154
|
+
cleanMatchCache = () => {
|
|
2353
1155
|
const now = Date.now();
|
|
2354
|
-
|
|
1156
|
+
this.store.setState(s => {
|
|
2355
1157
|
Object.keys(s.matchCache).forEach(matchId => {
|
|
2356
1158
|
const entry = s.matchCache[matchId];
|
|
2357
1159
|
|
|
2358
1160
|
// Don't remove loading matches
|
|
2359
|
-
if (entry.match.store.status === 'loading') {
|
|
1161
|
+
if (entry.match.store.state.status === 'loading') {
|
|
2360
1162
|
return;
|
|
2361
1163
|
}
|
|
2362
1164
|
|
|
@@ -2369,64 +1171,60 @@
|
|
|
2369
1171
|
delete s.matchCache[matchId];
|
|
2370
1172
|
});
|
|
2371
1173
|
});
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
1174
|
+
};
|
|
1175
|
+
getRoute = id => {
|
|
1176
|
+
const route = this.routesById[id];
|
|
1177
|
+
invariant(route, `Route with id "${id}" not found`);
|
|
1178
|
+
return route;
|
|
1179
|
+
};
|
|
1180
|
+
loadRoute = async (navigateOpts = this.store.state.latestLocation) => {
|
|
1181
|
+
const next = this.buildNext(navigateOpts);
|
|
1182
|
+
const matches = this.matchRoutes(next.pathname, {
|
|
2379
1183
|
strictParseParams: true
|
|
2380
1184
|
});
|
|
2381
|
-
await
|
|
1185
|
+
await this.loadMatches(matches);
|
|
2382
1186
|
return matches;
|
|
2383
|
-
}
|
|
2384
|
-
preloadRoute
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
}
|
|
2388
|
-
const next = router.buildNext(navigateOpts);
|
|
2389
|
-
const matches = router.matchRoutes(next.pathname, {
|
|
1187
|
+
};
|
|
1188
|
+
preloadRoute = async (navigateOpts = this.store.state.latestLocation, loaderOpts) => {
|
|
1189
|
+
const next = this.buildNext(navigateOpts);
|
|
1190
|
+
const matches = this.matchRoutes(next.pathname, {
|
|
2390
1191
|
strictParseParams: true
|
|
2391
1192
|
});
|
|
2392
|
-
await
|
|
1193
|
+
await this.loadMatches(matches, {
|
|
2393
1194
|
preload: true,
|
|
2394
|
-
maxAge: loaderOpts.maxAge ??
|
|
2395
|
-
gcMaxAge: loaderOpts.gcMaxAge ??
|
|
1195
|
+
maxAge: loaderOpts.maxAge ?? this.options.defaultPreloadMaxAge ?? this.options.defaultLoaderMaxAge ?? 0,
|
|
1196
|
+
gcMaxAge: loaderOpts.gcMaxAge ?? this.options.defaultPreloadGcMaxAge ?? this.options.defaultLoaderGcMaxAge ?? 0
|
|
2396
1197
|
});
|
|
2397
1198
|
return matches;
|
|
2398
|
-
}
|
|
2399
|
-
matchRoutes
|
|
2400
|
-
router.cleanMatchCache();
|
|
1199
|
+
};
|
|
1200
|
+
matchRoutes = (pathname, opts) => {
|
|
2401
1201
|
const matches = [];
|
|
2402
|
-
if (!
|
|
1202
|
+
if (!this.routeTree) {
|
|
2403
1203
|
return matches;
|
|
2404
1204
|
}
|
|
2405
|
-
const existingMatches = [...store.currentMatches, ...(store.pendingMatches ?? [])];
|
|
1205
|
+
const existingMatches = [...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])];
|
|
2406
1206
|
const recurse = async routes => {
|
|
2407
|
-
var _foundRoute$childRout;
|
|
2408
1207
|
const parentMatch = last(matches);
|
|
2409
|
-
let params =
|
|
2410
|
-
const filteredRoutes =
|
|
1208
|
+
let params = parentMatch?.params ?? {};
|
|
1209
|
+
const filteredRoutes = this.options.filterRoutes?.(routes) ?? routes;
|
|
2411
1210
|
let foundRoutes = [];
|
|
2412
1211
|
const findMatchInRoutes = (parentRoutes, routes) => {
|
|
2413
1212
|
routes.some(route => {
|
|
2414
|
-
|
|
2415
|
-
if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
|
|
1213
|
+
if (!route.path && route.childRoutes?.length) {
|
|
2416
1214
|
return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
|
|
2417
1215
|
}
|
|
2418
|
-
const fuzzy = !!(route.
|
|
2419
|
-
const matchParams = matchPathname(
|
|
1216
|
+
const fuzzy = !!(route.path !== '/' || route.childRoutes?.length);
|
|
1217
|
+
const matchParams = matchPathname(this.basepath, pathname, {
|
|
2420
1218
|
to: route.fullPath,
|
|
2421
1219
|
fuzzy,
|
|
2422
|
-
caseSensitive: route.options.caseSensitive ??
|
|
1220
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive
|
|
2423
1221
|
});
|
|
2424
1222
|
if (matchParams) {
|
|
2425
1223
|
let parsedParams;
|
|
2426
1224
|
try {
|
|
2427
|
-
parsedParams =
|
|
1225
|
+
parsedParams = route.options.parseParams?.(matchParams) ?? matchParams;
|
|
2428
1226
|
} catch (err) {
|
|
2429
|
-
if (opts
|
|
1227
|
+
if (opts?.strictParseParams) {
|
|
2430
1228
|
throw err;
|
|
2431
1229
|
}
|
|
2432
1230
|
}
|
|
@@ -2447,79 +1245,71 @@
|
|
|
2447
1245
|
return;
|
|
2448
1246
|
}
|
|
2449
1247
|
foundRoutes.forEach(foundRoute => {
|
|
2450
|
-
|
|
2451
|
-
const
|
|
2452
|
-
const
|
|
2453
|
-
const match = existingMatches.find(d => d.matchId === matchId) || ((_store$matchCache$mat = store.matchCache[matchId]) == null ? void 0 : _store$matchCache$mat.match) || createRouteMatch(router, foundRoute, {
|
|
2454
|
-
parentMatch,
|
|
1248
|
+
const interpolatedPath = interpolatePath(foundRoute.path, params);
|
|
1249
|
+
const matchId = interpolatePath(foundRoute.id, params, true);
|
|
1250
|
+
const match = existingMatches.find(d => d.id === matchId) || this.store.state.matchCache[matchId]?.match || new RouteMatch(this, foundRoute, {
|
|
2455
1251
|
matchId,
|
|
2456
1252
|
params,
|
|
2457
|
-
pathname: joinPaths([
|
|
1253
|
+
pathname: joinPaths([this.basepath, interpolatedPath])
|
|
2458
1254
|
});
|
|
2459
1255
|
matches.push(match);
|
|
2460
1256
|
});
|
|
2461
1257
|
const foundRoute = last(foundRoutes);
|
|
2462
|
-
if (
|
|
1258
|
+
if (foundRoute.childRoutes?.length) {
|
|
2463
1259
|
recurse(foundRoute.childRoutes);
|
|
2464
1260
|
}
|
|
2465
1261
|
};
|
|
2466
|
-
recurse([
|
|
1262
|
+
recurse([this.routeTree]);
|
|
2467
1263
|
linkMatches(matches);
|
|
2468
1264
|
return matches;
|
|
2469
|
-
}
|
|
2470
|
-
loadMatches
|
|
1265
|
+
};
|
|
1266
|
+
loadMatches = async (resolvedMatches, loaderOpts) => {
|
|
1267
|
+
this.cleanMatchCache();
|
|
2471
1268
|
resolvedMatches.forEach(async match => {
|
|
2472
1269
|
// Validate the match (loads search params etc)
|
|
2473
|
-
match.
|
|
1270
|
+
match.__validate();
|
|
2474
1271
|
});
|
|
2475
1272
|
|
|
2476
1273
|
// Check each match middleware to see if the route can be accessed
|
|
2477
1274
|
await Promise.all(resolvedMatches.map(async match => {
|
|
2478
1275
|
try {
|
|
2479
|
-
await
|
|
2480
|
-
router:
|
|
1276
|
+
await match.route.options.beforeLoad?.({
|
|
1277
|
+
router: this,
|
|
2481
1278
|
match
|
|
2482
|
-
})
|
|
1279
|
+
});
|
|
2483
1280
|
} catch (err) {
|
|
2484
|
-
if (!
|
|
2485
|
-
match.
|
|
1281
|
+
if (!loaderOpts?.preload) {
|
|
1282
|
+
match.route.options.onLoadError?.(err);
|
|
2486
1283
|
}
|
|
2487
1284
|
throw err;
|
|
2488
1285
|
}
|
|
2489
1286
|
}));
|
|
2490
|
-
const matchPromises = resolvedMatches.map(async match => {
|
|
2491
|
-
|
|
2492
|
-
const search = match.store.search;
|
|
2493
|
-
if (
|
|
1287
|
+
const matchPromises = resolvedMatches.map(async (match, index) => {
|
|
1288
|
+
const prevMatch = resolvedMatches[1];
|
|
1289
|
+
const search = match.store.state.search;
|
|
1290
|
+
if (search.__data?.matchId && search.__data.matchId !== match.id) {
|
|
2494
1291
|
return;
|
|
2495
1292
|
}
|
|
2496
1293
|
match.load(loaderOpts);
|
|
2497
|
-
if (match.store.status !== 'success' && match.
|
|
1294
|
+
if (match.store.state.status !== 'success' && match.__loadPromise) {
|
|
2498
1295
|
// Wait for the first sign of activity from the match
|
|
2499
|
-
await match.
|
|
1296
|
+
await match.__loadPromise;
|
|
1297
|
+
}
|
|
1298
|
+
if (prevMatch) {
|
|
1299
|
+
await prevMatch.__loadPromise;
|
|
2500
1300
|
}
|
|
2501
1301
|
});
|
|
2502
1302
|
await Promise.all(matchPromises);
|
|
2503
|
-
}
|
|
2504
|
-
loadMatchData
|
|
2505
|
-
if (isServer || !
|
|
2506
|
-
return (await
|
|
2507
|
-
// parentLoaderPromise: routeMatch.parentMatch
|
|
1303
|
+
};
|
|
1304
|
+
loadMatchData = async routeMatch => {
|
|
1305
|
+
if (isServer || !this.options.useServerData) {
|
|
1306
|
+
return (await routeMatch.route.options.loader?.({
|
|
1307
|
+
// parentLoaderPromise: routeMatch.parentMatch.dataPromise,
|
|
2508
1308
|
params: routeMatch.params,
|
|
2509
|
-
search: routeMatch.store.routeSearch,
|
|
2510
|
-
signal: routeMatch.
|
|
2511
|
-
}))
|
|
1309
|
+
search: routeMatch.store.state.routeSearch,
|
|
1310
|
+
signal: routeMatch.abortController.signal
|
|
1311
|
+
})) || {};
|
|
2512
1312
|
} else {
|
|
2513
|
-
const next = router.buildNext({
|
|
2514
|
-
to: '.',
|
|
2515
|
-
search: d => ({
|
|
2516
|
-
...(d ?? {}),
|
|
2517
|
-
__data: {
|
|
2518
|
-
matchId: routeMatch.matchId
|
|
2519
|
-
}
|
|
2520
|
-
})
|
|
2521
|
-
});
|
|
2522
|
-
|
|
2523
1313
|
// Refresh:
|
|
2524
1314
|
// '/dashboard'
|
|
2525
1315
|
// '/dashboard/invoices/'
|
|
@@ -2530,65 +1320,39 @@
|
|
|
2530
1320
|
|
|
2531
1321
|
// TODO: batch requests when possible
|
|
2532
1322
|
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
1323
|
+
return this.options.fetchServerDataFn({
|
|
1324
|
+
router: this,
|
|
1325
|
+
routeMatch
|
|
2536
1326
|
});
|
|
2537
|
-
|
|
2538
|
-
if (res.ok) {
|
|
2539
|
-
return res.json();
|
|
2540
|
-
}
|
|
2541
|
-
throw new Error('Failed to fetch match data');
|
|
2542
1327
|
}
|
|
2543
|
-
}
|
|
2544
|
-
invalidateRoute
|
|
2545
|
-
const next =
|
|
2546
|
-
const unloadedMatchIds =
|
|
2547
|
-
[...store.currentMatches, ...(store.pendingMatches ?? [])].
|
|
2548
|
-
if (unloadedMatchIds.includes(match.
|
|
2549
|
-
match.invalidate();
|
|
2550
|
-
}
|
|
2551
|
-
});
|
|
2552
|
-
},
|
|
2553
|
-
reload: () => navigate({
|
|
2554
|
-
fromCurrent: true,
|
|
2555
|
-
replace: true,
|
|
2556
|
-
search: true
|
|
2557
|
-
}),
|
|
2558
|
-
resolvePath: (from, path) => {
|
|
2559
|
-
return resolvePath(router.basepath, from, cleanPath(path));
|
|
2560
|
-
},
|
|
2561
|
-
matchRoute: (location, opts) => {
|
|
2562
|
-
// const location = router.buildNext(opts)
|
|
2563
|
-
|
|
2564
|
-
location = {
|
|
2565
|
-
...location,
|
|
2566
|
-
to: location.to ? router.resolvePath(location.from ?? '', location.to) : undefined
|
|
2567
|
-
};
|
|
2568
|
-
const next = router.buildNext(location);
|
|
2569
|
-
if (opts != null && opts.pending) {
|
|
2570
|
-
if (!store.pendingLocation) {
|
|
2571
|
-
return false;
|
|
1328
|
+
};
|
|
1329
|
+
invalidateRoute = async opts => {
|
|
1330
|
+
const next = this.buildNext(opts);
|
|
1331
|
+
const unloadedMatchIds = this.matchRoutes(next.pathname).map(d => d.id);
|
|
1332
|
+
await Promise.allSettled([...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])].map(async match => {
|
|
1333
|
+
if (unloadedMatchIds.includes(match.id)) {
|
|
1334
|
+
return match.invalidate();
|
|
2572
1335
|
}
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
to: next.pathname
|
|
1336
|
+
}));
|
|
1337
|
+
};
|
|
1338
|
+
reload = () => {
|
|
1339
|
+
this.navigate({
|
|
1340
|
+
fromCurrent: true,
|
|
1341
|
+
replace: true,
|
|
1342
|
+
search: true
|
|
2581
1343
|
});
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
1344
|
+
};
|
|
1345
|
+
resolvePath = (from, path) => {
|
|
1346
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1347
|
+
};
|
|
1348
|
+
navigate = async ({
|
|
1349
|
+
from,
|
|
1350
|
+
to = '.',
|
|
1351
|
+
search,
|
|
1352
|
+
hash,
|
|
1353
|
+
replace,
|
|
1354
|
+
params
|
|
1355
|
+
}) => {
|
|
2592
1356
|
// If this link simply reloads the current route,
|
|
2593
1357
|
// make sure it has a new key so it will trigger a data refresh
|
|
2594
1358
|
|
|
@@ -2601,8 +1365,8 @@
|
|
|
2601
1365
|
new URL(`${toString}`);
|
|
2602
1366
|
isExternal = true;
|
|
2603
1367
|
} catch (e) {}
|
|
2604
|
-
invariant(!isExternal, 'Attempting to navigate to external url with
|
|
2605
|
-
return
|
|
1368
|
+
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1369
|
+
return this.#commitLocation({
|
|
2606
1370
|
from: fromString,
|
|
2607
1371
|
to: toString,
|
|
2608
1372
|
search,
|
|
@@ -2610,23 +1374,42 @@
|
|
|
2610
1374
|
replace,
|
|
2611
1375
|
params
|
|
2612
1376
|
});
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
to
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
1377
|
+
};
|
|
1378
|
+
matchRoute = (location, opts) => {
|
|
1379
|
+
location = {
|
|
1380
|
+
...location,
|
|
1381
|
+
to: location.to ? this.resolvePath(location.from ?? '', location.to) : undefined
|
|
1382
|
+
};
|
|
1383
|
+
const next = this.buildNext(location);
|
|
1384
|
+
if (opts?.pending) {
|
|
1385
|
+
if (!this.store.state.pendingLocation) {
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
return matchPathname(this.basepath, this.store.state.pendingLocation.pathname, {
|
|
1389
|
+
...opts,
|
|
1390
|
+
to: next.pathname
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
return matchPathname(this.basepath, this.store.state.currentLocation.pathname, {
|
|
1394
|
+
...opts,
|
|
1395
|
+
to: next.pathname
|
|
1396
|
+
});
|
|
1397
|
+
};
|
|
1398
|
+
buildLink = ({
|
|
1399
|
+
from,
|
|
1400
|
+
to = '.',
|
|
1401
|
+
search,
|
|
1402
|
+
params,
|
|
1403
|
+
hash,
|
|
1404
|
+
target,
|
|
1405
|
+
replace,
|
|
1406
|
+
activeOptions,
|
|
1407
|
+
preload,
|
|
1408
|
+
preloadMaxAge: userPreloadMaxAge,
|
|
1409
|
+
preloadGcMaxAge: userPreloadGcMaxAge,
|
|
1410
|
+
preloadDelay: userPreloadDelay,
|
|
1411
|
+
disabled
|
|
1412
|
+
}) => {
|
|
2630
1413
|
// If this link simply reloads the current route,
|
|
2631
1414
|
// make sure it has a new key so it will trigger a data refresh
|
|
2632
1415
|
|
|
@@ -2648,19 +1431,19 @@
|
|
|
2648
1431
|
hash,
|
|
2649
1432
|
replace
|
|
2650
1433
|
};
|
|
2651
|
-
const next =
|
|
2652
|
-
preload = preload ??
|
|
2653
|
-
const preloadDelay = userPreloadDelay ??
|
|
1434
|
+
const next = this.buildNext(nextOpts);
|
|
1435
|
+
preload = preload ?? this.options.defaultPreload;
|
|
1436
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
2654
1437
|
|
|
2655
1438
|
// Compare path/hash for matches
|
|
2656
|
-
const pathIsEqual = store.currentLocation.pathname === next.pathname;
|
|
2657
|
-
const currentPathSplit = store.currentLocation.pathname.split('/');
|
|
1439
|
+
const pathIsEqual = this.store.state.currentLocation.pathname === next.pathname;
|
|
1440
|
+
const currentPathSplit = this.store.state.currentLocation.pathname.split('/');
|
|
2658
1441
|
const nextPathSplit = next.pathname.split('/');
|
|
2659
1442
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2660
|
-
const hashIsEqual = store.currentLocation.hash === next.hash;
|
|
1443
|
+
const hashIsEqual = this.store.state.currentLocation.hash === next.hash;
|
|
2661
1444
|
// Combine the matches based on user options
|
|
2662
|
-
const pathTest = activeOptions
|
|
2663
|
-
const hashTest = activeOptions
|
|
1445
|
+
const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual;
|
|
1446
|
+
const hashTest = activeOptions?.includeHash ? hashIsEqual : true;
|
|
2664
1447
|
|
|
2665
1448
|
// The final "active" test
|
|
2666
1449
|
const isActive = pathTest && hashTest;
|
|
@@ -2670,22 +1453,22 @@
|
|
|
2670
1453
|
if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
|
|
2671
1454
|
e.preventDefault();
|
|
2672
1455
|
if (pathIsEqual && !search && !hash) {
|
|
2673
|
-
|
|
1456
|
+
this.invalidateRoute(nextOpts);
|
|
2674
1457
|
}
|
|
2675
1458
|
|
|
2676
1459
|
// All is well? Navigate!
|
|
2677
|
-
|
|
1460
|
+
this.#commitLocation(nextOpts);
|
|
2678
1461
|
}
|
|
2679
1462
|
};
|
|
2680
1463
|
|
|
2681
1464
|
// The click handler
|
|
2682
1465
|
const handleFocus = e => {
|
|
2683
1466
|
if (preload) {
|
|
2684
|
-
|
|
1467
|
+
this.preloadRoute(nextOpts, {
|
|
2685
1468
|
maxAge: userPreloadMaxAge,
|
|
2686
1469
|
gcMaxAge: userPreloadGcMaxAge
|
|
2687
1470
|
}).catch(err => {
|
|
2688
|
-
console.
|
|
1471
|
+
console.warn(err);
|
|
2689
1472
|
console.warn('Error preloading route! ☝️');
|
|
2690
1473
|
});
|
|
2691
1474
|
}
|
|
@@ -2698,11 +1481,11 @@
|
|
|
2698
1481
|
}
|
|
2699
1482
|
target.preloadTimeout = setTimeout(() => {
|
|
2700
1483
|
target.preloadTimeout = null;
|
|
2701
|
-
|
|
1484
|
+
this.preloadRoute(nextOpts, {
|
|
2702
1485
|
maxAge: userPreloadMaxAge,
|
|
2703
1486
|
gcMaxAge: userPreloadGcMaxAge
|
|
2704
1487
|
}).catch(err => {
|
|
2705
|
-
console.
|
|
1488
|
+
console.warn(err);
|
|
2706
1489
|
console.warn('Error preloading route! ☝️');
|
|
2707
1490
|
});
|
|
2708
1491
|
}, preloadDelay);
|
|
@@ -2725,71 +1508,338 @@
|
|
|
2725
1508
|
isActive,
|
|
2726
1509
|
disabled
|
|
2727
1510
|
};
|
|
2728
|
-
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
1511
|
+
};
|
|
1512
|
+
dehydrate = () => {
|
|
1513
|
+
return {
|
|
1514
|
+
state: {
|
|
1515
|
+
...pick(this.store.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
|
|
1516
|
+
currentMatches: this.store.state.currentMatches.map(match => ({
|
|
1517
|
+
matchId: match.id,
|
|
1518
|
+
state: {
|
|
1519
|
+
...pick(match.store.state, ['status', 'routeLoaderData', 'invalidAt', 'invalid'])
|
|
1520
|
+
}
|
|
1521
|
+
}))
|
|
1522
|
+
},
|
|
1523
|
+
context: this.options.context
|
|
1524
|
+
};
|
|
1525
|
+
};
|
|
1526
|
+
hydrate = dehydratedRouter => {
|
|
1527
|
+
this.store.setState(s => {
|
|
1528
|
+
// Update the context TODO: make this part of state?
|
|
1529
|
+
this.options.context = dehydratedRouter.context;
|
|
1530
|
+
|
|
1531
|
+
// Match the routes
|
|
1532
|
+
const currentMatches = this.matchRoutes(dehydratedRouter.state.latestLocation.pathname, {
|
|
1533
|
+
strictParseParams: true
|
|
1534
|
+
});
|
|
1535
|
+
currentMatches.forEach((match, index) => {
|
|
1536
|
+
const dehydratedMatch = dehydratedRouter.state.currentMatches[index];
|
|
1537
|
+
invariant(dehydratedMatch && dehydratedMatch.matchId === match.id, 'Oh no! There was a hydration mismatch when attempting to rethis.store the state of the router! 😬');
|
|
1538
|
+
Object.assign(match, dehydratedMatch);
|
|
1539
|
+
});
|
|
1540
|
+
currentMatches.forEach(match => match.__validate());
|
|
1541
|
+
Object.assign(s, {
|
|
1542
|
+
...dehydratedRouter.state,
|
|
1543
|
+
currentMatches
|
|
1544
|
+
});
|
|
2738
1545
|
});
|
|
2739
|
-
}
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
1546
|
+
};
|
|
1547
|
+
getLoader = opts => {
|
|
1548
|
+
const id = opts.from || '/';
|
|
1549
|
+
const route = this.getRoute(id);
|
|
1550
|
+
if (!route) return undefined;
|
|
1551
|
+
let loader = this.store.state.loaders[id] || (() => {
|
|
1552
|
+
this.store.setState(s => {
|
|
1553
|
+
s.loaders[id] = {
|
|
1554
|
+
pending: [],
|
|
1555
|
+
fetch: async loaderContext => {
|
|
1556
|
+
if (!route) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
const loaderState = {
|
|
1560
|
+
loadedAt: Date.now(),
|
|
1561
|
+
loaderContext
|
|
1562
|
+
};
|
|
1563
|
+
this.store.setState(s => {
|
|
1564
|
+
s.loaders[id].current = loaderState;
|
|
1565
|
+
s.loaders[id].latest = loaderState;
|
|
1566
|
+
s.loaders[id].pending.push(loaderState);
|
|
1567
|
+
});
|
|
1568
|
+
try {
|
|
1569
|
+
return await route.options.loader?.(loaderContext);
|
|
1570
|
+
} finally {
|
|
1571
|
+
this.store.setState(s => {
|
|
1572
|
+
s.loaders[id].pending = s.loaders[id].pending.filter(d => d !== loaderState);
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
};
|
|
1577
|
+
});
|
|
1578
|
+
return this.store.state.loaders[id];
|
|
1579
|
+
})();
|
|
1580
|
+
return loader;
|
|
1581
|
+
};
|
|
1582
|
+
#buildRouteTree = rootRouteConfig => {
|
|
1583
|
+
const recurseRoutes = (routeConfigs, parent) => {
|
|
1584
|
+
return routeConfigs.map((routeConfig, i) => {
|
|
1585
|
+
const routeOptions = routeConfig.options;
|
|
1586
|
+
const route = new Route(routeConfig, routeOptions, i, parent, this);
|
|
1587
|
+
const existingRoute = this.routesById[route.id];
|
|
1588
|
+
if (existingRoute) {
|
|
1589
|
+
{
|
|
1590
|
+
console.warn(`Duplicate routes found with id: ${String(route.id)}`, this.routesById, route);
|
|
1591
|
+
}
|
|
1592
|
+
throw new Error();
|
|
1593
|
+
}
|
|
1594
|
+
this.routesById[route.id] = route;
|
|
1595
|
+
const children = routeConfig.children;
|
|
1596
|
+
route.childRoutes = children.length ? recurseRoutes(children, route) : undefined;
|
|
1597
|
+
return route;
|
|
1598
|
+
});
|
|
1599
|
+
};
|
|
1600
|
+
const routes = recurseRoutes([rootRouteConfig]);
|
|
1601
|
+
return routes[0];
|
|
1602
|
+
};
|
|
1603
|
+
#parseLocation = previousLocation => {
|
|
1604
|
+
let {
|
|
1605
|
+
pathname,
|
|
1606
|
+
search,
|
|
1607
|
+
hash,
|
|
1608
|
+
state
|
|
1609
|
+
} = this.history.location;
|
|
1610
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1611
|
+
console.log({
|
|
1612
|
+
pathname: pathname,
|
|
1613
|
+
searchStr: search,
|
|
1614
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1615
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1616
|
+
href: `${pathname}${search}${hash}`,
|
|
1617
|
+
state: state,
|
|
1618
|
+
key: state?.key || '__init__'
|
|
1619
|
+
});
|
|
1620
|
+
return {
|
|
1621
|
+
pathname: pathname,
|
|
1622
|
+
searchStr: search,
|
|
1623
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1624
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1625
|
+
href: `${pathname}${search}${hash}`,
|
|
1626
|
+
state: state,
|
|
1627
|
+
key: state?.key || '__init__'
|
|
1628
|
+
};
|
|
1629
|
+
};
|
|
1630
|
+
#onFocus = () => {
|
|
1631
|
+
this.load();
|
|
1632
|
+
};
|
|
1633
|
+
#buildLocation = (dest = {}) => {
|
|
1634
|
+
const fromPathname = dest.fromCurrent ? this.store.state.latestLocation.pathname : dest.from ?? this.store.state.latestLocation.pathname;
|
|
1635
|
+
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
|
|
1636
|
+
const fromMatches = this.matchRoutes(this.store.state.latestLocation.pathname, {
|
|
1637
|
+
strictParseParams: true
|
|
1638
|
+
});
|
|
1639
|
+
const toMatches = this.matchRoutes(pathname);
|
|
1640
|
+
const prevParams = {
|
|
1641
|
+
...last(fromMatches)?.params
|
|
1642
|
+
};
|
|
1643
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1644
|
+
if (nextParams) {
|
|
1645
|
+
toMatches.map(d => d.route.options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1646
|
+
Object.assign({}, nextParams, fn(nextParams));
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1650
|
+
|
|
1651
|
+
// Pre filters first
|
|
1652
|
+
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.store.state.latestLocation.search) : this.store.state.latestLocation.search;
|
|
1653
|
+
|
|
1654
|
+
// Then the link/navigate function
|
|
1655
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1656
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1657
|
+
: dest.__preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1658
|
+
: {};
|
|
1659
|
+
|
|
1660
|
+
// Then post filters
|
|
1661
|
+
const postFilteredSearch = dest.__postSearchFilters?.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1662
|
+
const search = replaceEqualDeep(this.store.state.latestLocation.search, postFilteredSearch);
|
|
1663
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1664
|
+
let hash = dest.hash === true ? this.store.state.latestLocation.hash : functionalUpdate(dest.hash, this.store.state.latestLocation.hash);
|
|
1665
|
+
hash = hash ? `#${hash}` : '';
|
|
1666
|
+
return {
|
|
1667
|
+
pathname,
|
|
1668
|
+
search,
|
|
1669
|
+
searchStr,
|
|
1670
|
+
state: this.store.state.latestLocation.state,
|
|
1671
|
+
hash,
|
|
1672
|
+
href: `${pathname}${searchStr}${hash}`,
|
|
1673
|
+
key: dest.key
|
|
1674
|
+
};
|
|
1675
|
+
};
|
|
1676
|
+
#commitLocation = location => {
|
|
1677
|
+
const next = this.buildNext(location);
|
|
1678
|
+
const id = '' + Date.now() + Math.random();
|
|
1679
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1680
|
+
let nextAction = 'replace';
|
|
1681
|
+
if (!location.replace) {
|
|
1682
|
+
nextAction = 'push';
|
|
1683
|
+
}
|
|
1684
|
+
const isSameUrl = this.store.state.latestLocation.href === next.href;
|
|
1685
|
+
if (isSameUrl && !next.key) {
|
|
1686
|
+
nextAction = 'replace';
|
|
1687
|
+
}
|
|
1688
|
+
const href = `${next.pathname}${next.searchStr}${next.hash ? `#${next.hash}` : ''}`;
|
|
1689
|
+
this.history[nextAction === 'push' ? 'push' : 'replace'](href, {
|
|
1690
|
+
id,
|
|
1691
|
+
...next.state
|
|
1692
|
+
});
|
|
1693
|
+
this.load(this.#parseLocation(this.store.state.latestLocation));
|
|
1694
|
+
return this.navigationPromise = new Promise(resolve => {
|
|
1695
|
+
const previousNavigationResolve = this.resolveNavigation;
|
|
1696
|
+
this.resolveNavigation = () => {
|
|
1697
|
+
previousNavigationResolve();
|
|
1698
|
+
resolve();
|
|
1699
|
+
};
|
|
1700
|
+
});
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
// Detect if we're in the DOM
|
|
1705
|
+
const isServer = typeof window === 'undefined' || !window.document.createElement;
|
|
1706
|
+
function getInitialRouterState() {
|
|
1707
|
+
return {
|
|
1708
|
+
status: 'idle',
|
|
1709
|
+
latestLocation: null,
|
|
1710
|
+
currentLocation: null,
|
|
1711
|
+
currentMatches: [],
|
|
1712
|
+
loaders: {},
|
|
1713
|
+
lastUpdated: Date.now(),
|
|
1714
|
+
matchCache: {},
|
|
1715
|
+
get isFetching() {
|
|
1716
|
+
return this.status === 'loading' || this.currentMatches.some(d => d.store.state.isFetching);
|
|
1717
|
+
},
|
|
1718
|
+
get isPreloading() {
|
|
1719
|
+
return Object.values(this.matchCache).some(d => d.match.store.state.isFetching && !this.currentMatches.find(dd => dd.id === d.match.id));
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
function isCtrlEvent(e) {
|
|
1724
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1725
|
+
}
|
|
1726
|
+
function linkMatches(matches) {
|
|
1727
|
+
matches.forEach((match, index) => {
|
|
1728
|
+
const parent = matches[index - 1];
|
|
1729
|
+
if (parent) {
|
|
1730
|
+
match.__setParentMatch(parent);
|
|
1731
|
+
}
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// createRouterAction is a constrained identify function that takes options: key, action, onSuccess, onError, onSettled, etc
|
|
1736
|
+
function createAction(options) {
|
|
1737
|
+
const store = createStore({
|
|
1738
|
+
submissions: []
|
|
1739
|
+
}, options.debug);
|
|
1740
|
+
return {
|
|
1741
|
+
options,
|
|
1742
|
+
store,
|
|
1743
|
+
reset: () => {
|
|
1744
|
+
store.setState(s => {
|
|
1745
|
+
s.submissions = [];
|
|
1746
|
+
});
|
|
1747
|
+
},
|
|
1748
|
+
submit: async payload => {
|
|
1749
|
+
const submission = {
|
|
1750
|
+
submittedAt: Date.now(),
|
|
1751
|
+
status: 'pending',
|
|
1752
|
+
payload: payload,
|
|
1753
|
+
invalidate: () => {
|
|
1754
|
+
setSubmission(s => {
|
|
1755
|
+
s.isInvalid = true;
|
|
1756
|
+
});
|
|
1757
|
+
},
|
|
1758
|
+
getIsLatest: () => store.state.submissions[store.state.submissions.length - 1]?.submittedAt === submission.submittedAt
|
|
1759
|
+
};
|
|
1760
|
+
const setSubmission = updater => {
|
|
1761
|
+
store.setState(s => {
|
|
1762
|
+
const a = s.submissions.find(d => d.submittedAt === submission.submittedAt);
|
|
1763
|
+
invariant(a, 'Could not find submission in store');
|
|
1764
|
+
updater(a);
|
|
1765
|
+
});
|
|
1766
|
+
};
|
|
1767
|
+
store.setState(s => {
|
|
1768
|
+
s.submissions.push(submission);
|
|
1769
|
+
s.submissions.reverse();
|
|
1770
|
+
s.submissions = s.submissions.slice(0, options.maxSubmissions ?? 10);
|
|
1771
|
+
s.submissions.reverse();
|
|
1772
|
+
});
|
|
1773
|
+
const after = async () => {
|
|
1774
|
+
options.onEachSettled?.(submission);
|
|
1775
|
+
if (submission.getIsLatest()) await options.onLatestSettled?.(submission);
|
|
1776
|
+
};
|
|
1777
|
+
try {
|
|
1778
|
+
const res = await options.action?.(submission.payload);
|
|
1779
|
+
setSubmission(s => {
|
|
1780
|
+
s.response = res;
|
|
1781
|
+
});
|
|
1782
|
+
await options.onEachSuccess?.(submission);
|
|
1783
|
+
if (submission.getIsLatest()) await options.onLatestSuccess?.(submission);
|
|
1784
|
+
await after();
|
|
1785
|
+
setSubmission(s => {
|
|
1786
|
+
s.status = 'success';
|
|
1787
|
+
});
|
|
1788
|
+
return res;
|
|
1789
|
+
} catch (err) {
|
|
1790
|
+
console.error(err);
|
|
1791
|
+
setSubmission(s => {
|
|
1792
|
+
s.error = err;
|
|
1793
|
+
});
|
|
1794
|
+
await options.onEachError?.(submission);
|
|
1795
|
+
if (submission.getIsLatest()) await options.onLatestError?.(submission);
|
|
1796
|
+
await after();
|
|
1797
|
+
setSubmission(s => {
|
|
1798
|
+
s.status = 'error';
|
|
1799
|
+
});
|
|
1800
|
+
throw err;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
exports.Route = Route;
|
|
1807
|
+
exports.RouteMatch = RouteMatch;
|
|
1808
|
+
exports.Router = Router;
|
|
1809
|
+
exports.batch = batch;
|
|
1810
|
+
exports.cleanPath = cleanPath;
|
|
1811
|
+
exports.createAction = createAction;
|
|
1812
|
+
exports.createBrowserHistory = createBrowserHistory;
|
|
1813
|
+
exports.createHashHistory = createHashHistory;
|
|
1814
|
+
exports.createMemoryHistory = createMemoryHistory;
|
|
1815
|
+
exports.createRouteConfig = createRouteConfig;
|
|
1816
|
+
exports.createStore = createStore;
|
|
1817
|
+
exports.decode = decode;
|
|
1818
|
+
exports.defaultFetchServerDataFn = defaultFetchServerDataFn;
|
|
1819
|
+
exports.defaultParseSearch = defaultParseSearch;
|
|
1820
|
+
exports.defaultStringifySearch = defaultStringifySearch;
|
|
1821
|
+
exports.encode = encode;
|
|
1822
|
+
exports.functionalUpdate = functionalUpdate;
|
|
1823
|
+
exports.interpolatePath = interpolatePath;
|
|
1824
|
+
exports.invariant = invariant;
|
|
1825
|
+
exports.joinPaths = joinPaths;
|
|
1826
|
+
exports.last = last;
|
|
1827
|
+
exports.matchByPath = matchByPath;
|
|
1828
|
+
exports.matchPathname = matchPathname;
|
|
1829
|
+
exports.parsePathname = parsePathname;
|
|
1830
|
+
exports.parseSearchWith = parseSearchWith;
|
|
1831
|
+
exports.pick = pick;
|
|
1832
|
+
exports.replaceEqualDeep = replaceEqualDeep;
|
|
1833
|
+
exports.resolvePath = resolvePath;
|
|
1834
|
+
exports.rootRouteId = rootRouteId;
|
|
1835
|
+
exports.stringifySearchWith = stringifySearchWith;
|
|
1836
|
+
exports.trackDeep = trackDeep;
|
|
1837
|
+
exports.trimPath = trimPath;
|
|
1838
|
+
exports.trimPathLeft = trimPathLeft;
|
|
1839
|
+
exports.trimPathRight = trimPathRight;
|
|
1840
|
+
exports.warning = warning;
|
|
1841
|
+
|
|
1842
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2793
1843
|
|
|
2794
1844
|
}));
|
|
2795
1845
|
//# sourceMappingURL=index.development.js.map
|