@tanstack/router-core 0.0.1-beta.14 → 0.0.1-beta.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/build/cjs/history.js +226 -0
- package/build/cjs/history.js.map +1 -0
- package/build/cjs/{packages/router-core/src/index.js → index.js} +33 -15
- package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
- package/build/cjs/{packages/router-core/src/path.js → path.js} +45 -56
- package/build/cjs/path.js.map +1 -0
- package/build/cjs/{packages/router-core/src/qss.js → qss.js} +10 -16
- package/build/cjs/qss.js.map +1 -0
- package/build/cjs/route.js +147 -0
- package/build/cjs/route.js.map +1 -0
- package/build/cjs/router.js +1102 -0
- package/build/cjs/router.js.map +1 -0
- package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +11 -13
- package/build/cjs/searchParams.js.map +1 -0
- package/build/cjs/{packages/router-core/src/utils.js → utils.js} +54 -64
- package/build/cjs/utils.js.map +1 -0
- package/build/esm/index.js +1439 -2099
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +59 -49
- package/build/stats-react.json +186 -249
- package/build/types/index.d.ts +559 -422
- package/build/umd/index.development.js +1675 -2232
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +12 -2
- package/build/umd/index.production.js.map +1 -1
- package/package.json +11 -7
- package/src/history.ts +292 -0
- package/src/index.ts +2 -10
- package/src/link.ts +116 -113
- package/src/path.ts +37 -17
- package/src/qss.ts +1 -2
- package/src/route.ts +927 -218
- package/src/routeInfo.ts +121 -197
- package/src/router.ts +1481 -1018
- package/src/searchParams.ts +1 -1
- package/src/utils.ts +80 -49
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
- package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
- package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
- package/build/cjs/node_modules/history/index.js +0 -815
- package/build/cjs/node_modules/history/index.js.map +0 -1
- package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
- package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
- package/build/cjs/packages/router-core/src/path.js.map +0 -1
- package/build/cjs/packages/router-core/src/qss.js.map +0 -1
- package/build/cjs/packages/router-core/src/route.js +0 -147
- package/build/cjs/packages/router-core/src/route.js.map +0 -1
- package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
- package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
- package/build/cjs/packages/router-core/src/routeMatch.js +0 -226
- package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
- package/build/cjs/packages/router-core/src/router.js +0 -832
- package/build/cjs/packages/router-core/src/router.js.map +0 -1
- package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
- package/build/cjs/packages/router-core/src/utils.js.map +0 -1
- package/src/frameworks.ts +0 -11
- package/src/routeConfig.ts +0 -489
- package/src/routeMatch.ts +0 -312
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* router-core
|
|
2
|
+
* @tanstack/router-core/src/index.ts
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) TanStack
|
|
5
5
|
*
|
|
@@ -9,2136 +9,1386 @@
|
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
11
|
(function (global, factory) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('use-sync-external-store/shim/with-selector')) :
|
|
13
|
+
typeof define === 'function' && define.amd ? define(['exports', 'use-sync-external-store/shim/with-selector'], 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
|
-
|
|
22
|
-
for (var key in source) {
|
|
23
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
24
|
-
target[key] = source[key];
|
|
25
|
-
}
|
|
17
|
+
var prefix = 'Invariant failed';
|
|
18
|
+
function invariant(condition, message) {
|
|
19
|
+
if (condition) {
|
|
20
|
+
return;
|
|
26
21
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
return _extends$1.apply(this, arguments);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Actions represent the type of change to a location value.
|
|
36
|
-
*
|
|
37
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#action
|
|
38
|
-
*/
|
|
39
|
-
var Action;
|
|
40
|
-
|
|
41
|
-
(function (Action) {
|
|
42
|
-
/**
|
|
43
|
-
* A POP indicates a change to an arbitrary index in the history stack, such
|
|
44
|
-
* as a back or forward navigation. It does not describe the direction of the
|
|
45
|
-
* navigation, only that the current index changed.
|
|
46
|
-
*
|
|
47
|
-
* Note: This is the default action for newly created history objects.
|
|
48
|
-
*/
|
|
49
|
-
Action["Pop"] = "POP";
|
|
50
|
-
/**
|
|
51
|
-
* A PUSH indicates a new entry being added to the history stack, such as when
|
|
52
|
-
* a link is clicked and a new page loads. When this happens, all subsequent
|
|
53
|
-
* entries in the stack are lost.
|
|
54
|
-
*/
|
|
55
|
-
|
|
56
|
-
Action["Push"] = "PUSH";
|
|
57
|
-
/**
|
|
58
|
-
* A REPLACE indicates the entry at the current index in the history stack
|
|
59
|
-
* being replaced by a new one.
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
Action["Replace"] = "REPLACE";
|
|
63
|
-
})(Action || (Action = {}));
|
|
64
|
-
|
|
65
|
-
var readOnly = function (obj) {
|
|
66
|
-
return Object.freeze(obj);
|
|
67
|
-
} ;
|
|
68
|
-
|
|
69
|
-
function warning$1(cond, message) {
|
|
70
|
-
if (!cond) {
|
|
71
|
-
// eslint-disable-next-line no-console
|
|
72
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
// Welcome to debugging history!
|
|
76
|
-
//
|
|
77
|
-
// This error is thrown as a convenience so you can more easily
|
|
78
|
-
// find the source for a warning that appears in the console by
|
|
79
|
-
// enabling "pause on exceptions" in your JavaScript debugger.
|
|
80
|
-
throw new Error(message); // eslint-disable-next-line no-empty
|
|
81
|
-
} catch (e) {}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
var BeforeUnloadEventType = 'beforeunload';
|
|
86
|
-
var HashChangeEventType = 'hashchange';
|
|
87
|
-
var PopStateEventType = 'popstate';
|
|
88
|
-
/**
|
|
89
|
-
* Browser history stores the location in regular URLs. This is the standard for
|
|
90
|
-
* most web apps, but it requires some configuration on the server to ensure you
|
|
91
|
-
* serve the same app at multiple URLs.
|
|
92
|
-
*
|
|
93
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
|
|
94
|
-
*/
|
|
95
|
-
|
|
96
|
-
function createBrowserHistory(options) {
|
|
97
|
-
if (options === void 0) {
|
|
98
|
-
options = {};
|
|
22
|
+
var provided = typeof message === 'function' ? message() : message;
|
|
23
|
+
var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
|
|
24
|
+
throw new Error(value);
|
|
99
25
|
}
|
|
100
26
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
function getIndexAndLocation() {
|
|
107
|
-
var _window$location = window.location,
|
|
108
|
-
pathname = _window$location.pathname,
|
|
109
|
-
search = _window$location.search,
|
|
110
|
-
hash = _window$location.hash;
|
|
111
|
-
var state = globalHistory.state || {};
|
|
112
|
-
return [state.idx, readOnly({
|
|
113
|
-
pathname: pathname,
|
|
114
|
-
search: search,
|
|
115
|
-
hash: hash,
|
|
116
|
-
state: state.usr || null,
|
|
117
|
-
key: state.key || 'default'
|
|
118
|
-
})];
|
|
119
|
-
}
|
|
27
|
+
function warning(condition, message) {
|
|
28
|
+
{
|
|
29
|
+
if (condition) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
120
32
|
|
|
121
|
-
|
|
33
|
+
var text = "Warning: " + message;
|
|
122
34
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
blockedPopTx = null;
|
|
127
|
-
} else {
|
|
128
|
-
var nextAction = Action.Pop;
|
|
35
|
+
if (typeof console !== 'undefined') {
|
|
36
|
+
console.warn(text);
|
|
37
|
+
}
|
|
129
38
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
39
|
+
try {
|
|
40
|
+
throw Error(text);
|
|
41
|
+
} catch (x) {}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
133
44
|
|
|
45
|
+
// While the public API was clearly inspired by the "history" npm package,
|
|
46
|
+
// This implementation attempts to be more lightweight by
|
|
47
|
+
// making assumptions about the way TanStack Router works
|
|
48
|
+
|
|
49
|
+
const pushStateEvent = 'pushstate';
|
|
50
|
+
const popStateEvent = 'popstate';
|
|
51
|
+
const beforeUnloadEvent = 'beforeunload';
|
|
52
|
+
const beforeUnloadListener = event => {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
return event.returnValue = '';
|
|
56
|
+
};
|
|
57
|
+
const stopBlocking = () => {
|
|
58
|
+
removeEventListener(beforeUnloadEvent, beforeUnloadListener, {
|
|
59
|
+
capture: true
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
function createHistory(opts) {
|
|
63
|
+
let location = opts.getLocation();
|
|
64
|
+
let unsub = () => {};
|
|
65
|
+
let listeners = new Set();
|
|
66
|
+
let blockers = [];
|
|
67
|
+
let queue = [];
|
|
68
|
+
const tryFlush = () => {
|
|
134
69
|
if (blockers.length) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
70
|
+
blockers[0]?.(tryFlush, () => {
|
|
71
|
+
blockers = [];
|
|
72
|
+
stopBlocking();
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
while (queue.length) {
|
|
77
|
+
queue.shift()?.();
|
|
78
|
+
}
|
|
79
|
+
if (!opts.listener) {
|
|
80
|
+
onUpdate();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const queueTask = task => {
|
|
84
|
+
queue.push(task);
|
|
85
|
+
tryFlush();
|
|
86
|
+
};
|
|
87
|
+
const onUpdate = () => {
|
|
88
|
+
location = opts.getLocation();
|
|
89
|
+
listeners.forEach(listener => listener());
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
get location() {
|
|
93
|
+
return location;
|
|
94
|
+
},
|
|
95
|
+
listen: cb => {
|
|
96
|
+
if (listeners.size === 0) {
|
|
97
|
+
unsub = typeof opts.listener === 'function' ? opts.listener(onUpdate) : () => {};
|
|
98
|
+
}
|
|
99
|
+
listeners.add(cb);
|
|
100
|
+
return () => {
|
|
101
|
+
listeners.delete(cb);
|
|
102
|
+
if (listeners.size === 0) {
|
|
103
|
+
unsub();
|
|
148
104
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
push: (path, state) => {
|
|
108
|
+
queueTask(() => {
|
|
109
|
+
opts.pushState(path, state);
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
replace: (path, state) => {
|
|
113
|
+
queueTask(() => {
|
|
114
|
+
opts.replaceState(path, state);
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
go: index => {
|
|
118
|
+
queueTask(() => {
|
|
119
|
+
opts.go(index);
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
back: () => {
|
|
123
|
+
queueTask(() => {
|
|
124
|
+
opts.back();
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
forward: () => {
|
|
128
|
+
queueTask(() => {
|
|
129
|
+
opts.forward();
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
createHref: str => opts.createHref(str),
|
|
133
|
+
block: cb => {
|
|
134
|
+
blockers.push(cb);
|
|
135
|
+
if (blockers.length === 1) {
|
|
136
|
+
addEventListener(beforeUnloadEvent, beforeUnloadListener, {
|
|
137
|
+
capture: true
|
|
138
|
+
});
|
|
156
139
|
}
|
|
157
|
-
|
|
158
|
-
|
|
140
|
+
return () => {
|
|
141
|
+
blockers = blockers.filter(b => b !== cb);
|
|
142
|
+
if (!blockers.length) {
|
|
143
|
+
stopBlocking();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
159
146
|
}
|
|
160
|
-
}
|
|
147
|
+
};
|
|
161
148
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
149
|
+
function createBrowserHistory(opts) {
|
|
150
|
+
const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.search}${window.location.hash}`);
|
|
151
|
+
const createHref = opts?.createHref ?? (path => path);
|
|
152
|
+
const getLocation = () => parseLocation(getHref(), history.state);
|
|
153
|
+
return createHistory({
|
|
154
|
+
getLocation,
|
|
155
|
+
listener: onUpdate => {
|
|
156
|
+
window.addEventListener(pushStateEvent, onUpdate);
|
|
157
|
+
window.addEventListener(popStateEvent, onUpdate);
|
|
158
|
+
var pushState = window.history.pushState;
|
|
159
|
+
window.history.pushState = function () {
|
|
160
|
+
let res = pushState.apply(history, arguments);
|
|
161
|
+
onUpdate();
|
|
162
|
+
return res;
|
|
163
|
+
};
|
|
164
|
+
var replaceState = window.history.replaceState;
|
|
165
|
+
window.history.replaceState = function () {
|
|
166
|
+
let res = replaceState.apply(history, arguments);
|
|
167
|
+
onUpdate();
|
|
168
|
+
return res;
|
|
169
|
+
};
|
|
170
|
+
return () => {
|
|
171
|
+
window.history.pushState = pushState;
|
|
172
|
+
window.history.replaceState = replaceState;
|
|
173
|
+
window.removeEventListener(pushStateEvent, onUpdate);
|
|
174
|
+
window.removeEventListener(popStateEvent, onUpdate);
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
pushState: (path, state) => {
|
|
178
|
+
window.history.pushState({
|
|
179
|
+
...state,
|
|
180
|
+
key: createRandomKey()
|
|
181
|
+
}, '', createHref(path));
|
|
182
|
+
},
|
|
183
|
+
replaceState: (path, state) => {
|
|
184
|
+
window.history.replaceState({
|
|
185
|
+
...state,
|
|
186
|
+
key: createRandomKey()
|
|
187
|
+
}, '', createHref(path));
|
|
188
|
+
},
|
|
189
|
+
back: () => window.history.back(),
|
|
190
|
+
forward: () => window.history.forward(),
|
|
191
|
+
go: n => window.history.go(n),
|
|
192
|
+
createHref: path => createHref(path)
|
|
193
|
+
});
|
|
178
194
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
function getNextLocation(to, state) {
|
|
186
|
-
if (state === void 0) {
|
|
187
|
-
state = null;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return readOnly(_extends$1({
|
|
191
|
-
pathname: location.pathname,
|
|
192
|
-
hash: '',
|
|
193
|
-
search: ''
|
|
194
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
195
|
-
state: state,
|
|
196
|
-
key: createKey()
|
|
197
|
-
}));
|
|
195
|
+
function createHashHistory() {
|
|
196
|
+
return createBrowserHistory({
|
|
197
|
+
getHref: () => window.location.hash.substring(1),
|
|
198
|
+
createHref: path => `#${path}`
|
|
199
|
+
});
|
|
198
200
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
201
|
+
function createMemoryHistory(opts = {
|
|
202
|
+
initialEntries: ['/']
|
|
203
|
+
}) {
|
|
204
|
+
const entries = opts.initialEntries;
|
|
205
|
+
let index = opts.initialIndex ?? entries.length - 1;
|
|
206
|
+
let currentState = {};
|
|
207
|
+
const getLocation = () => parseLocation(entries[index], currentState);
|
|
208
|
+
return createHistory({
|
|
209
|
+
getLocation,
|
|
210
|
+
listener: false,
|
|
211
|
+
pushState: (path, state) => {
|
|
212
|
+
currentState = {
|
|
213
|
+
...state,
|
|
214
|
+
key: createRandomKey()
|
|
215
|
+
};
|
|
216
|
+
entries.push(path);
|
|
217
|
+
index++;
|
|
218
|
+
},
|
|
219
|
+
replaceState: (path, state) => {
|
|
220
|
+
currentState = {
|
|
221
|
+
...state,
|
|
222
|
+
key: createRandomKey()
|
|
223
|
+
};
|
|
224
|
+
entries[index] = path;
|
|
225
|
+
},
|
|
226
|
+
back: () => {
|
|
227
|
+
index--;
|
|
228
|
+
},
|
|
229
|
+
forward: () => {
|
|
230
|
+
index = Math.min(index + 1, entries.length - 1);
|
|
231
|
+
},
|
|
232
|
+
go: n => window.history.go(n),
|
|
233
|
+
createHref: path => path
|
|
234
|
+
});
|
|
206
235
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
function parseLocation(href, state) {
|
|
237
|
+
let hashIndex = href.indexOf('#');
|
|
238
|
+
let searchIndex = href.indexOf('?');
|
|
239
|
+
return {
|
|
240
|
+
href,
|
|
241
|
+
pathname: href.substring(0, hashIndex > 0 ? searchIndex > 0 ? Math.min(hashIndex, searchIndex) : hashIndex : searchIndex > 0 ? searchIndex : href.length),
|
|
242
|
+
hash: hashIndex > -1 ? href.substring(hashIndex) : '',
|
|
243
|
+
search: searchIndex > -1 ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex) : '',
|
|
244
|
+
state
|
|
245
|
+
};
|
|
214
246
|
}
|
|
215
247
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
var _getIndexAndLocation3 = getIndexAndLocation();
|
|
220
|
-
|
|
221
|
-
index = _getIndexAndLocation3[0];
|
|
222
|
-
location = _getIndexAndLocation3[1];
|
|
223
|
-
listeners.call({
|
|
224
|
-
action: action,
|
|
225
|
-
location: location
|
|
226
|
-
});
|
|
248
|
+
// Thanks co-pilot!
|
|
249
|
+
function createRandomKey() {
|
|
250
|
+
return (Math.random() + 1).toString(36).substring(7);
|
|
227
251
|
}
|
|
228
252
|
|
|
229
|
-
function
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
253
|
+
function last(arr) {
|
|
254
|
+
return arr[arr.length - 1];
|
|
255
|
+
}
|
|
256
|
+
function isFunction(d) {
|
|
257
|
+
return typeof d === 'function';
|
|
258
|
+
}
|
|
259
|
+
function functionalUpdate(updater, previous) {
|
|
260
|
+
if (isFunction(updater)) {
|
|
261
|
+
return updater(previous);
|
|
235
262
|
}
|
|
263
|
+
return updater;
|
|
264
|
+
}
|
|
265
|
+
function pick(parent, keys) {
|
|
266
|
+
return keys.reduce((obj, key) => {
|
|
267
|
+
obj[key] = parent[key];
|
|
268
|
+
return obj;
|
|
269
|
+
}, {});
|
|
270
|
+
}
|
|
236
271
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
272
|
+
/**
|
|
273
|
+
* This function returns `a` if `b` is deeply equal.
|
|
274
|
+
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
275
|
+
* This can be used for structural sharing between immutable JSON values for example.
|
|
276
|
+
* Do not use this with signals
|
|
277
|
+
*/
|
|
278
|
+
function replaceEqualDeep(prev, _next) {
|
|
279
|
+
if (prev === _next) {
|
|
280
|
+
return prev;
|
|
281
|
+
}
|
|
282
|
+
const next = _next;
|
|
283
|
+
const array = Array.isArray(prev) && Array.isArray(next);
|
|
284
|
+
if (array || isPlainObject(prev) && isPlainObject(next)) {
|
|
285
|
+
const prevSize = array ? prev.length : Object.keys(prev).length;
|
|
286
|
+
const nextItems = array ? next : Object.keys(next);
|
|
287
|
+
const nextSize = nextItems.length;
|
|
288
|
+
const copy = array ? [] : {};
|
|
289
|
+
let equalItems = 0;
|
|
290
|
+
for (let i = 0; i < nextSize; i++) {
|
|
291
|
+
const key = array ? i : nextItems[i];
|
|
292
|
+
copy[key] = replaceEqualDeep(prev[key], next[key]);
|
|
293
|
+
if (copy[key] === prev[key]) {
|
|
294
|
+
equalItems++;
|
|
295
|
+
}
|
|
250
296
|
}
|
|
251
|
-
|
|
252
|
-
applyTx(nextAction);
|
|
297
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy;
|
|
253
298
|
}
|
|
299
|
+
return next;
|
|
254
300
|
}
|
|
255
301
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
302
|
+
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
303
|
+
function isPlainObject(o) {
|
|
304
|
+
if (!hasObjectPrototype(o)) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
259
307
|
|
|
260
|
-
|
|
261
|
-
|
|
308
|
+
// If has modified constructor
|
|
309
|
+
const ctor = o.constructor;
|
|
310
|
+
if (typeof ctor === 'undefined') {
|
|
311
|
+
return true;
|
|
262
312
|
}
|
|
263
313
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
314
|
+
// If has modified prototype
|
|
315
|
+
const prot = ctor.prototype;
|
|
316
|
+
if (!hasObjectPrototype(prot)) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
268
319
|
|
|
320
|
+
// If constructor does not have an Object-specific method
|
|
321
|
+
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
269
324
|
|
|
270
|
-
|
|
271
|
-
|
|
325
|
+
// Most likely a plain Object
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
function hasObjectPrototype(o) {
|
|
329
|
+
return Object.prototype.toString.call(o) === '[object Object]';
|
|
330
|
+
}
|
|
331
|
+
function partialDeepEqual(a, b) {
|
|
332
|
+
if (a === b) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
if (typeof a !== typeof b) {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
339
|
+
return !Object.keys(b).some(key => !partialDeepEqual(a[key], b[key]));
|
|
272
340
|
}
|
|
341
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
342
|
+
return a.length === b.length && a.every((item, index) => partialDeepEqual(item, b[index]));
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
273
345
|
}
|
|
274
346
|
|
|
275
|
-
function
|
|
276
|
-
|
|
347
|
+
function joinPaths(paths) {
|
|
348
|
+
return cleanPath(paths.filter(Boolean).join('/'));
|
|
277
349
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
350
|
+
function cleanPath(path) {
|
|
351
|
+
// remove double slashes
|
|
352
|
+
return path.replace(/\/{2,}/g, '/');
|
|
353
|
+
}
|
|
354
|
+
function trimPathLeft(path) {
|
|
355
|
+
return path === '/' ? path : path.replace(/^\/{1,}/, '');
|
|
356
|
+
}
|
|
357
|
+
function trimPathRight(path) {
|
|
358
|
+
return path === '/' ? path : path.replace(/\/{1,}$/, '');
|
|
359
|
+
}
|
|
360
|
+
function trimPath(path) {
|
|
361
|
+
return trimPathRight(trimPathLeft(path));
|
|
362
|
+
}
|
|
363
|
+
function resolvePath(basepath, base, to) {
|
|
364
|
+
base = base.replace(new RegExp(`^${basepath}`), '/');
|
|
365
|
+
to = to.replace(new RegExp(`^${basepath}`), '/');
|
|
366
|
+
let baseSegments = parsePathname(base);
|
|
367
|
+
const toSegments = parsePathname(to);
|
|
368
|
+
toSegments.forEach((toSegment, index) => {
|
|
369
|
+
if (toSegment.value === '/') {
|
|
370
|
+
if (!index) {
|
|
371
|
+
// Leading slash
|
|
372
|
+
baseSegments = [toSegment];
|
|
373
|
+
} else if (index === toSegments.length - 1) {
|
|
374
|
+
// Trailing Slash
|
|
375
|
+
baseSegments.push(toSegment);
|
|
376
|
+
} else ;
|
|
377
|
+
} else if (toSegment.value === '..') {
|
|
378
|
+
// Extra trailing slash? pop it off
|
|
379
|
+
if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
|
|
380
|
+
baseSegments.pop();
|
|
381
|
+
}
|
|
382
|
+
baseSegments.pop();
|
|
383
|
+
} else if (toSegment.value === '.') {
|
|
384
|
+
return;
|
|
385
|
+
} else {
|
|
386
|
+
baseSegments.push(toSegment);
|
|
306
387
|
}
|
|
388
|
+
});
|
|
389
|
+
const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
|
|
390
|
+
return cleanPath(joined);
|
|
391
|
+
}
|
|
392
|
+
function parsePathname(pathname) {
|
|
393
|
+
if (!pathname) {
|
|
394
|
+
return [];
|
|
395
|
+
}
|
|
396
|
+
pathname = cleanPath(pathname);
|
|
397
|
+
const segments = [];
|
|
398
|
+
if (pathname.slice(0, 1) === '/') {
|
|
399
|
+
pathname = pathname.substring(1);
|
|
400
|
+
segments.push({
|
|
401
|
+
type: 'pathname',
|
|
402
|
+
value: '/'
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (!pathname) {
|
|
406
|
+
return segments;
|
|
407
|
+
}
|
|
307
408
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
409
|
+
// Remove empty segments and '.' segments
|
|
410
|
+
const split = pathname.split('/').filter(Boolean);
|
|
411
|
+
segments.push(...split.map(part => {
|
|
412
|
+
if (part === '$' || part === '*') {
|
|
413
|
+
return {
|
|
414
|
+
type: 'wildcard',
|
|
415
|
+
value: part
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
if (part.charAt(0) === '$') {
|
|
419
|
+
return {
|
|
420
|
+
type: 'param',
|
|
421
|
+
value: part
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
type: 'pathname',
|
|
426
|
+
value: part
|
|
316
427
|
};
|
|
428
|
+
}));
|
|
429
|
+
if (pathname.slice(-1) === '/') {
|
|
430
|
+
pathname = pathname.substring(1);
|
|
431
|
+
segments.push({
|
|
432
|
+
type: 'pathname',
|
|
433
|
+
value: '/'
|
|
434
|
+
});
|
|
317
435
|
}
|
|
318
|
-
|
|
319
|
-
return history;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Hash history stores the location in window.location.hash. This makes it ideal
|
|
323
|
-
* for situations where you don't want to send the location to the server for
|
|
324
|
-
* some reason, either because you do cannot configure it or the URL space is
|
|
325
|
-
* reserved for something else.
|
|
326
|
-
*
|
|
327
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
|
|
328
|
-
*/
|
|
329
|
-
|
|
330
|
-
function createHashHistory(options) {
|
|
331
|
-
if (options === void 0) {
|
|
332
|
-
options = {};
|
|
436
|
+
return segments;
|
|
333
437
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
hash = _parsePath$hash === void 0 ? '' : _parsePath$hash;
|
|
348
|
-
|
|
349
|
-
var state = globalHistory.state || {};
|
|
350
|
-
return [state.idx, readOnly({
|
|
351
|
-
pathname: pathname,
|
|
352
|
-
search: search,
|
|
353
|
-
hash: hash,
|
|
354
|
-
state: state.usr || null,
|
|
355
|
-
key: state.key || 'default'
|
|
356
|
-
})];
|
|
438
|
+
function interpolatePath(path, params, leaveWildcards = false) {
|
|
439
|
+
const interpolatedPathSegments = parsePathname(path);
|
|
440
|
+
return joinPaths(interpolatedPathSegments.map(segment => {
|
|
441
|
+
if (segment.type === 'wildcard') {
|
|
442
|
+
const value = params[segment.value];
|
|
443
|
+
if (leaveWildcards) return `${segment.value}${value ?? ''}`;
|
|
444
|
+
return value;
|
|
445
|
+
}
|
|
446
|
+
if (segment.type === 'param') {
|
|
447
|
+
return params[segment.value.substring(1)] ?? '';
|
|
448
|
+
}
|
|
449
|
+
return segment.value;
|
|
450
|
+
}));
|
|
357
451
|
}
|
|
452
|
+
function matchPathname(basepath, currentPathname, matchLocation) {
|
|
453
|
+
const pathParams = matchByPath(basepath, currentPathname, matchLocation);
|
|
454
|
+
// const searchMatched = matchBySearch(location.search, matchLocation)
|
|
358
455
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
456
|
+
if (matchLocation.to && !pathParams) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
return pathParams ?? {};
|
|
460
|
+
}
|
|
461
|
+
function matchByPath(basepath, from, matchLocation) {
|
|
462
|
+
// Remove the base path from the pathname
|
|
463
|
+
from = basepath != '/' ? from.substring(basepath.length) : from;
|
|
464
|
+
// Default to to $ (wildcard)
|
|
465
|
+
const to = `${matchLocation.to ?? '$'}`;
|
|
466
|
+
// Parse the from and to
|
|
467
|
+
const baseSegments = parsePathname(from);
|
|
468
|
+
const routeSegments = parsePathname(to);
|
|
469
|
+
if (!from.startsWith('/')) {
|
|
470
|
+
baseSegments.unshift({
|
|
471
|
+
type: 'pathname',
|
|
472
|
+
value: '/'
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
if (!to.startsWith('/')) {
|
|
476
|
+
routeSegments.unshift({
|
|
477
|
+
type: 'pathname',
|
|
478
|
+
value: '/'
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
const params = {};
|
|
482
|
+
let isMatch = (() => {
|
|
483
|
+
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
484
|
+
const baseSegment = baseSegments[i];
|
|
485
|
+
const routeSegment = routeSegments[i];
|
|
486
|
+
const isLastBaseSegment = i >= baseSegments.length - 1;
|
|
487
|
+
const isLastRouteSegment = i >= routeSegments.length - 1;
|
|
488
|
+
if (routeSegment) {
|
|
489
|
+
if (routeSegment.type === 'wildcard') {
|
|
490
|
+
if (baseSegment?.value) {
|
|
491
|
+
params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
if (routeSegment.type === 'pathname') {
|
|
497
|
+
if (routeSegment.value === '/' && !baseSegment?.value) {
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
if (baseSegment) {
|
|
501
|
+
if (matchLocation.caseSensitive) {
|
|
502
|
+
if (routeSegment.value !== baseSegment.value) {
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
} else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
|
|
506
|
+
return false;
|
|
383
507
|
}
|
|
384
|
-
}
|
|
385
|
-
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (!baseSegment) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
if (routeSegment.type === 'param') {
|
|
514
|
+
if (baseSegment?.value === '/') {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
if (baseSegment.value.charAt(0) !== '$') {
|
|
518
|
+
params[routeSegment.value.substring(1)] = baseSegment.value;
|
|
519
|
+
}
|
|
386
520
|
}
|
|
387
|
-
} else {
|
|
388
|
-
// Trying to POP to a location with no index. We did not create
|
|
389
|
-
// this location, so we can't effectively block the navigation.
|
|
390
|
-
warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
|
|
391
|
-
// detail and link to it here so people can understand better
|
|
392
|
-
// what is going on and how to avoid it.
|
|
393
|
-
"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.") ;
|
|
394
521
|
}
|
|
395
|
-
|
|
396
|
-
|
|
522
|
+
if (!isLastBaseSegment && isLastRouteSegment) {
|
|
523
|
+
return !!matchLocation.fuzzy;
|
|
524
|
+
}
|
|
397
525
|
}
|
|
398
|
-
|
|
526
|
+
return true;
|
|
527
|
+
})();
|
|
528
|
+
return isMatch ? params : undefined;
|
|
399
529
|
}
|
|
400
530
|
|
|
401
|
-
|
|
402
|
-
// https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
|
|
403
|
-
|
|
404
|
-
window.addEventListener(HashChangeEventType, function () {
|
|
405
|
-
var _getIndexAndLocation5 = getIndexAndLocation(),
|
|
406
|
-
nextLocation = _getIndexAndLocation5[1]; // Ignore extraneous hashchange events.
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (createPath(nextLocation) !== createPath(location)) {
|
|
410
|
-
handlePop();
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
var action = Action.Pop;
|
|
414
|
-
|
|
415
|
-
var _getIndexAndLocation6 = getIndexAndLocation(),
|
|
416
|
-
index = _getIndexAndLocation6[0],
|
|
417
|
-
location = _getIndexAndLocation6[1];
|
|
418
|
-
|
|
419
|
-
var listeners = createEvents();
|
|
420
|
-
var blockers = createEvents();
|
|
421
|
-
|
|
422
|
-
if (index == null) {
|
|
423
|
-
index = 0;
|
|
424
|
-
globalHistory.replaceState(_extends$1({}, globalHistory.state, {
|
|
425
|
-
idx: index
|
|
426
|
-
}), '');
|
|
427
|
-
}
|
|
531
|
+
// @ts-nocheck
|
|
428
532
|
|
|
429
|
-
|
|
430
|
-
var base = document.querySelector('base');
|
|
431
|
-
var href = '';
|
|
533
|
+
// 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.
|
|
432
534
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
535
|
+
function encode(obj, pfx) {
|
|
536
|
+
var k,
|
|
537
|
+
i,
|
|
538
|
+
tmp,
|
|
539
|
+
str = '';
|
|
540
|
+
for (k in obj) {
|
|
541
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
542
|
+
if (Array.isArray(tmp)) {
|
|
543
|
+
for (i = 0; i < tmp.length; i++) {
|
|
544
|
+
str && (str += '&');
|
|
545
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
str && (str += '&');
|
|
549
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
437
552
|
}
|
|
438
|
-
|
|
439
|
-
return href;
|
|
553
|
+
return (pfx || '') + str;
|
|
440
554
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
555
|
+
function toValue(mix) {
|
|
556
|
+
if (!mix) return '';
|
|
557
|
+
var str = decodeURIComponent(mix);
|
|
558
|
+
if (str === 'false') return false;
|
|
559
|
+
if (str === 'true') return true;
|
|
560
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
444
561
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
562
|
+
function decode(str) {
|
|
563
|
+
var tmp,
|
|
564
|
+
k,
|
|
565
|
+
out = {},
|
|
566
|
+
arr = str.split('&');
|
|
567
|
+
while (tmp = arr.shift()) {
|
|
568
|
+
tmp = tmp.split('=');
|
|
569
|
+
k = tmp.shift();
|
|
570
|
+
if (out[k] !== void 0) {
|
|
571
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
572
|
+
} else {
|
|
573
|
+
out[k] = toValue(tmp.shift());
|
|
574
|
+
}
|
|
449
575
|
}
|
|
450
|
-
|
|
451
|
-
return readOnly(_extends$1({
|
|
452
|
-
pathname: location.pathname,
|
|
453
|
-
hash: '',
|
|
454
|
-
search: ''
|
|
455
|
-
}, typeof to === 'string' ? parsePath(to) : to, {
|
|
456
|
-
state: state,
|
|
457
|
-
key: createKey()
|
|
458
|
-
}));
|
|
576
|
+
return out;
|
|
459
577
|
}
|
|
460
578
|
|
|
461
|
-
|
|
462
|
-
return [{
|
|
463
|
-
usr: nextLocation.state,
|
|
464
|
-
key: nextLocation.key,
|
|
465
|
-
idx: index
|
|
466
|
-
}, createHref(nextLocation)];
|
|
467
|
-
}
|
|
579
|
+
const rootRouteId = '__root__';
|
|
468
580
|
|
|
469
|
-
|
|
470
|
-
return !blockers.length || (blockers.call({
|
|
471
|
-
action: action,
|
|
472
|
-
location: location,
|
|
473
|
-
retry: retry
|
|
474
|
-
}), false);
|
|
475
|
-
}
|
|
581
|
+
// | ParseParamsObj<TPath, TParams>
|
|
476
582
|
|
|
477
|
-
|
|
478
|
-
action = nextAction;
|
|
583
|
+
// The parse type here allows a zod schema to be passed directly to the validator
|
|
479
584
|
|
|
480
|
-
|
|
585
|
+
class Route {
|
|
586
|
+
// Set up in this.init()
|
|
481
587
|
|
|
482
|
-
|
|
483
|
-
location = _getIndexAndLocation7[1];
|
|
484
|
-
listeners.call({
|
|
485
|
-
action: action,
|
|
486
|
-
location: location
|
|
487
|
-
});
|
|
488
|
-
}
|
|
588
|
+
// customId!: TCustomId
|
|
489
589
|
|
|
490
|
-
|
|
491
|
-
var nextAction = Action.Push;
|
|
492
|
-
var nextLocation = getNextLocation(to, state);
|
|
590
|
+
// Optional
|
|
493
591
|
|
|
494
|
-
|
|
495
|
-
|
|
592
|
+
constructor(options) {
|
|
593
|
+
this.options = options || {};
|
|
594
|
+
this.isRoot = !options?.getParentRoute;
|
|
595
|
+
Route.__onInit(this);
|
|
496
596
|
}
|
|
597
|
+
init = opts => {
|
|
598
|
+
this.originalIndex = opts.originalIndex;
|
|
599
|
+
this.router = opts.router;
|
|
600
|
+
const options = this.options;
|
|
601
|
+
const isRoot = !options?.path && !options?.id;
|
|
602
|
+
this.parentRoute = this.options?.getParentRoute?.();
|
|
603
|
+
if (isRoot) {
|
|
604
|
+
this.path = rootRouteId;
|
|
605
|
+
} else {
|
|
606
|
+
invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
|
|
607
|
+
}
|
|
608
|
+
let path = isRoot ? rootRouteId : options.path;
|
|
497
609
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
var _getHistoryStateAndUr3 = getHistoryStateAndUrl(nextLocation, index + 1),
|
|
502
|
-
historyState = _getHistoryStateAndUr3[0],
|
|
503
|
-
url = _getHistoryStateAndUr3[1]; // TODO: Support forced reloading
|
|
504
|
-
// try...catch because iOS limits us to 100 pushState calls :/
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
try {
|
|
508
|
-
globalHistory.pushState(historyState, '', url);
|
|
509
|
-
} catch (error) {
|
|
510
|
-
// They are going to lose state here, but there is no real
|
|
511
|
-
// way to warn them about it since the page will refresh...
|
|
512
|
-
window.location.assign(url);
|
|
610
|
+
// If the path is anything other than an index path, trim it up
|
|
611
|
+
if (path && path !== '/') {
|
|
612
|
+
path = trimPath(path);
|
|
513
613
|
}
|
|
614
|
+
const customId = options?.id || path;
|
|
514
615
|
|
|
515
|
-
|
|
616
|
+
// Strip the parentId prefix from the first level of children
|
|
617
|
+
let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
|
|
618
|
+
if (path === rootRouteId) {
|
|
619
|
+
path = '/';
|
|
620
|
+
}
|
|
621
|
+
if (id !== rootRouteId) {
|
|
622
|
+
id = joinPaths(['/', id]);
|
|
623
|
+
}
|
|
624
|
+
const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
|
|
625
|
+
this.path = path;
|
|
626
|
+
this.id = id;
|
|
627
|
+
// this.customId = customId as TCustomId
|
|
628
|
+
this.fullPath = fullPath;
|
|
629
|
+
this.to = fullPath;
|
|
630
|
+
};
|
|
631
|
+
addChildren = children => {
|
|
632
|
+
this.children = children;
|
|
633
|
+
return this;
|
|
634
|
+
};
|
|
635
|
+
update = options => {
|
|
636
|
+
Object.assign(this.options, options);
|
|
637
|
+
return this;
|
|
638
|
+
};
|
|
639
|
+
static __onInit = route => {
|
|
640
|
+
// This is a dummy static method that should get
|
|
641
|
+
// replaced by a framework specific implementation if necessary
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
class RouterContext {
|
|
645
|
+
constructor() {}
|
|
646
|
+
createRootRoute = options => {
|
|
647
|
+
return new RootRoute(options);
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
class RootRoute extends Route {
|
|
651
|
+
constructor(options) {
|
|
652
|
+
super(options);
|
|
516
653
|
}
|
|
517
654
|
}
|
|
518
655
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
656
|
+
// const rootRoute = new RootRoute({
|
|
657
|
+
// validateSearch: () => null as unknown as { root?: boolean },
|
|
658
|
+
// })
|
|
659
|
+
|
|
660
|
+
// const aRoute = new Route({
|
|
661
|
+
// getParentRoute: () => rootRoute,
|
|
662
|
+
// path: 'a',
|
|
663
|
+
// validateSearch: () => null as unknown as { a?: string },
|
|
664
|
+
// })
|
|
665
|
+
|
|
666
|
+
// const bRoute = new Route({
|
|
667
|
+
// getParentRoute: () => aRoute,
|
|
668
|
+
// path: 'b',
|
|
669
|
+
// })
|
|
670
|
+
|
|
671
|
+
// const rootIsRoot = rootRoute.isRoot
|
|
672
|
+
// // ^?
|
|
673
|
+
// const aIsRoot = aRoute.isRoot
|
|
674
|
+
// // ^?
|
|
675
|
+
|
|
676
|
+
// const rId = rootRoute.id
|
|
677
|
+
// // ^?
|
|
678
|
+
// const aId = aRoute.id
|
|
679
|
+
// // ^?
|
|
680
|
+
// const bId = bRoute.id
|
|
681
|
+
// // ^?
|
|
682
|
+
|
|
683
|
+
// const rPath = rootRoute.fullPath
|
|
684
|
+
// // ^?
|
|
685
|
+
// const aPath = aRoute.fullPath
|
|
686
|
+
// // ^?
|
|
687
|
+
// const bPath = bRoute.fullPath
|
|
688
|
+
// // ^?
|
|
689
|
+
|
|
690
|
+
// const rSearch = rootRoute.__types.fullSearchSchema
|
|
691
|
+
// // ^?
|
|
692
|
+
// const aSearch = aRoute.__types.fullSearchSchema
|
|
693
|
+
// // ^?
|
|
694
|
+
// const bSearch = bRoute.__types.fullSearchSchema
|
|
695
|
+
// // ^?
|
|
696
|
+
|
|
697
|
+
// const config = rootRoute.addChildren([aRoute.addChildren([bRoute])])
|
|
698
|
+
// // ^?
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* @tanstack/store/src/index.ts
|
|
702
|
+
*
|
|
703
|
+
* Copyright (c) TanStack
|
|
704
|
+
*
|
|
705
|
+
* This source code is licensed under the MIT license found in the
|
|
706
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
707
|
+
*
|
|
708
|
+
* @license MIT
|
|
709
|
+
*/
|
|
710
|
+
class Store {
|
|
711
|
+
listeners = new Set();
|
|
712
|
+
_batching = false;
|
|
713
|
+
_flushing = 0;
|
|
714
|
+
_nextPriority = null;
|
|
715
|
+
constructor(initialState, options) {
|
|
716
|
+
this.state = initialState;
|
|
717
|
+
this.options = options;
|
|
525
718
|
}
|
|
719
|
+
subscribe = listener => {
|
|
720
|
+
this.listeners.add(listener);
|
|
721
|
+
const unsub = this.options?.onSubscribe?.(listener, this);
|
|
722
|
+
return () => {
|
|
723
|
+
this.listeners.delete(listener);
|
|
724
|
+
unsub?.();
|
|
725
|
+
};
|
|
726
|
+
};
|
|
727
|
+
setState = (updater, opts) => {
|
|
728
|
+
const previous = this.state;
|
|
729
|
+
this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
|
|
730
|
+
const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high';
|
|
731
|
+
if (this._nextPriority === null) {
|
|
732
|
+
this._nextPriority = priority;
|
|
733
|
+
} else if (this._nextPriority === 'high') {
|
|
734
|
+
this._nextPriority = priority;
|
|
735
|
+
} else {
|
|
736
|
+
this._nextPriority = this.options?.defaultPriority ?? 'high';
|
|
737
|
+
}
|
|
526
738
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
historyState = _getHistoryStateAndUr4[0],
|
|
532
|
-
url = _getHistoryStateAndUr4[1]; // TODO: Support forced reloading
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
globalHistory.replaceState(historyState, '', url);
|
|
536
|
-
applyTx(nextAction);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
739
|
+
// Always run onUpdate, regardless of batching
|
|
740
|
+
this.options?.onUpdate?.({
|
|
741
|
+
priority: this._nextPriority
|
|
742
|
+
});
|
|
539
743
|
|
|
540
|
-
|
|
541
|
-
|
|
744
|
+
// Attempt to flush
|
|
745
|
+
this._flush();
|
|
746
|
+
};
|
|
747
|
+
_flush = () => {
|
|
748
|
+
if (this._batching) return;
|
|
749
|
+
const flushId = ++this._flushing;
|
|
750
|
+
this.listeners.forEach(listener => {
|
|
751
|
+
if (this._flushing !== flushId) return;
|
|
752
|
+
listener({
|
|
753
|
+
priority: this._nextPriority ?? 'high'
|
|
754
|
+
});
|
|
755
|
+
});
|
|
756
|
+
};
|
|
757
|
+
batch = cb => {
|
|
758
|
+
if (this._batching) return cb();
|
|
759
|
+
this._batching = true;
|
|
760
|
+
cb();
|
|
761
|
+
this._batching = false;
|
|
762
|
+
this._flush();
|
|
763
|
+
};
|
|
542
764
|
}
|
|
543
765
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
return location;
|
|
551
|
-
},
|
|
552
|
-
|
|
553
|
-
createHref: createHref,
|
|
554
|
-
push: push,
|
|
555
|
-
replace: replace,
|
|
556
|
-
go: go,
|
|
557
|
-
back: function back() {
|
|
558
|
-
go(-1);
|
|
559
|
-
},
|
|
560
|
-
forward: function forward() {
|
|
561
|
-
go(1);
|
|
562
|
-
},
|
|
563
|
-
listen: function listen(listener) {
|
|
564
|
-
return listeners.push(listener);
|
|
565
|
-
},
|
|
566
|
-
block: function block(blocker) {
|
|
567
|
-
var unblock = blockers.push(blocker);
|
|
568
|
-
|
|
569
|
-
if (blockers.length === 1) {
|
|
570
|
-
window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
766
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
767
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify);
|
|
768
|
+
function parseSearchWith(parser) {
|
|
769
|
+
return searchStr => {
|
|
770
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
771
|
+
searchStr = searchStr.substring(1);
|
|
571
772
|
}
|
|
773
|
+
let query = decode(searchStr);
|
|
572
774
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
775
|
+
// Try to parse any query params that might be json
|
|
776
|
+
for (let key in query) {
|
|
777
|
+
const value = query[key];
|
|
778
|
+
if (typeof value === 'string') {
|
|
779
|
+
try {
|
|
780
|
+
query[key] = parser(value);
|
|
781
|
+
} catch (err) {
|
|
782
|
+
//
|
|
783
|
+
}
|
|
580
784
|
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return history;
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Memory history stores the current location in memory. It is designed for use
|
|
588
|
-
* in stateful non-browser environments like tests and React Native.
|
|
589
|
-
*
|
|
590
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#creatememoryhistory
|
|
591
|
-
*/
|
|
592
|
-
|
|
593
|
-
function createMemoryHistory(options) {
|
|
594
|
-
if (options === void 0) {
|
|
595
|
-
options = {};
|
|
785
|
+
}
|
|
786
|
+
return query;
|
|
787
|
+
};
|
|
596
788
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
function createHref(to) {
|
|
620
|
-
return typeof to === 'string' ? to : createPath(to);
|
|
789
|
+
function stringifySearchWith(stringify) {
|
|
790
|
+
return search => {
|
|
791
|
+
search = {
|
|
792
|
+
...search
|
|
793
|
+
};
|
|
794
|
+
if (search) {
|
|
795
|
+
Object.keys(search).forEach(key => {
|
|
796
|
+
const val = search[key];
|
|
797
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
798
|
+
delete search[key];
|
|
799
|
+
} else if (val && typeof val === 'object' && val !== null) {
|
|
800
|
+
try {
|
|
801
|
+
search[key] = stringify(val);
|
|
802
|
+
} catch (err) {
|
|
803
|
+
// silent
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
const searchStr = encode(search).toString();
|
|
809
|
+
return searchStr ? `?${searchStr}` : '';
|
|
810
|
+
};
|
|
621
811
|
}
|
|
622
812
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
813
|
+
//
|
|
814
|
+
|
|
815
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
816
|
+
class Router {
|
|
817
|
+
#unsubHistory;
|
|
818
|
+
constructor(options) {
|
|
819
|
+
this.options = {
|
|
820
|
+
defaultPreloadDelay: 50,
|
|
821
|
+
context: undefined,
|
|
822
|
+
...options,
|
|
823
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
824
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
825
|
+
// fetchServerDataFn: options?.fetchServerDataFn ?? defaultFetchServerDataFn,
|
|
826
|
+
};
|
|
627
827
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
function allowTx(action, location, retry) {
|
|
639
|
-
return !blockers.length || (blockers.call({
|
|
640
|
-
action: action,
|
|
641
|
-
location: location,
|
|
642
|
-
retry: retry
|
|
643
|
-
}), false);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
function applyTx(nextAction, nextLocation) {
|
|
647
|
-
action = nextAction;
|
|
648
|
-
location = nextLocation;
|
|
649
|
-
listeners.call({
|
|
650
|
-
action: action,
|
|
651
|
-
location: location
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
function push(to, state) {
|
|
656
|
-
var nextAction = Action.Push;
|
|
657
|
-
var nextLocation = getNextLocation(to, state);
|
|
658
|
-
|
|
659
|
-
function retry() {
|
|
660
|
-
push(to, state);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.push(" + JSON.stringify(to) + ")") ;
|
|
664
|
-
|
|
665
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
666
|
-
index += 1;
|
|
667
|
-
entries.splice(index, entries.length, nextLocation);
|
|
668
|
-
applyTx(nextAction, nextLocation);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
function replace(to, state) {
|
|
673
|
-
var nextAction = Action.Replace;
|
|
674
|
-
var nextLocation = getNextLocation(to, state);
|
|
675
|
-
|
|
676
|
-
function retry() {
|
|
677
|
-
replace(to, state);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.replace(" + JSON.stringify(to) + ")") ;
|
|
681
|
-
|
|
682
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
683
|
-
entries[index] = nextLocation;
|
|
684
|
-
applyTx(nextAction, nextLocation);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
function go(delta) {
|
|
689
|
-
var nextIndex = clamp(index + delta, 0, entries.length - 1);
|
|
690
|
-
var nextAction = Action.Pop;
|
|
691
|
-
var nextLocation = entries[nextIndex];
|
|
692
|
-
|
|
693
|
-
function retry() {
|
|
694
|
-
go(delta);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
698
|
-
index = nextIndex;
|
|
699
|
-
applyTx(nextAction, nextLocation);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
var history = {
|
|
704
|
-
get index() {
|
|
705
|
-
return index;
|
|
706
|
-
},
|
|
707
|
-
|
|
708
|
-
get action() {
|
|
709
|
-
return action;
|
|
710
|
-
},
|
|
711
|
-
|
|
712
|
-
get location() {
|
|
713
|
-
return location;
|
|
714
|
-
},
|
|
715
|
-
|
|
716
|
-
createHref: createHref,
|
|
717
|
-
push: push,
|
|
718
|
-
replace: replace,
|
|
719
|
-
go: go,
|
|
720
|
-
back: function back() {
|
|
721
|
-
go(-1);
|
|
722
|
-
},
|
|
723
|
-
forward: function forward() {
|
|
724
|
-
go(1);
|
|
725
|
-
},
|
|
726
|
-
listen: function listen(listener) {
|
|
727
|
-
return listeners.push(listener);
|
|
728
|
-
},
|
|
729
|
-
block: function block(blocker) {
|
|
730
|
-
return blockers.push(blocker);
|
|
731
|
-
}
|
|
732
|
-
};
|
|
733
|
-
return history;
|
|
734
|
-
} ////////////////////////////////////////////////////////////////////////////////
|
|
735
|
-
// UTILS
|
|
736
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
737
|
-
|
|
738
|
-
function clamp(n, lowerBound, upperBound) {
|
|
739
|
-
return Math.min(Math.max(n, lowerBound), upperBound);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function promptBeforeUnload(event) {
|
|
743
|
-
// Cancel the event.
|
|
744
|
-
event.preventDefault(); // Chrome (and legacy IE) requires returnValue to be set.
|
|
745
|
-
|
|
746
|
-
event.returnValue = '';
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
function createEvents() {
|
|
750
|
-
var handlers = [];
|
|
751
|
-
return {
|
|
752
|
-
get length() {
|
|
753
|
-
return handlers.length;
|
|
754
|
-
},
|
|
755
|
-
|
|
756
|
-
push: function push(fn) {
|
|
757
|
-
handlers.push(fn);
|
|
758
|
-
return function () {
|
|
759
|
-
handlers = handlers.filter(function (handler) {
|
|
760
|
-
return handler !== fn;
|
|
761
|
-
});
|
|
762
|
-
};
|
|
763
|
-
},
|
|
764
|
-
call: function call(arg) {
|
|
765
|
-
handlers.forEach(function (fn) {
|
|
766
|
-
return fn && fn(arg);
|
|
767
|
-
});
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
function createKey() {
|
|
773
|
-
return Math.random().toString(36).substr(2, 8);
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Creates a string URL path from the given pathname, search, and hash components.
|
|
777
|
-
*
|
|
778
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createpath
|
|
779
|
-
*/
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
function createPath(_ref) {
|
|
783
|
-
var _ref$pathname = _ref.pathname,
|
|
784
|
-
pathname = _ref$pathname === void 0 ? '/' : _ref$pathname,
|
|
785
|
-
_ref$search = _ref.search,
|
|
786
|
-
search = _ref$search === void 0 ? '' : _ref$search,
|
|
787
|
-
_ref$hash = _ref.hash,
|
|
788
|
-
hash = _ref$hash === void 0 ? '' : _ref$hash;
|
|
789
|
-
if (search && search !== '?') pathname += search.charAt(0) === '?' ? search : '?' + search;
|
|
790
|
-
if (hash && hash !== '#') pathname += hash.charAt(0) === '#' ? hash : '#' + hash;
|
|
791
|
-
return pathname;
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Parses a string URL path into its separate pathname, search, and hash components.
|
|
795
|
-
*
|
|
796
|
-
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
|
|
797
|
-
*/
|
|
798
|
-
|
|
799
|
-
function parsePath(path) {
|
|
800
|
-
var parsedPath = {};
|
|
801
|
-
|
|
802
|
-
if (path) {
|
|
803
|
-
var hashIndex = path.indexOf('#');
|
|
804
|
-
|
|
805
|
-
if (hashIndex >= 0) {
|
|
806
|
-
parsedPath.hash = path.substr(hashIndex);
|
|
807
|
-
path = path.substr(0, hashIndex);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
var searchIndex = path.indexOf('?');
|
|
811
|
-
|
|
812
|
-
if (searchIndex >= 0) {
|
|
813
|
-
parsedPath.search = path.substr(searchIndex);
|
|
814
|
-
path = path.substr(0, searchIndex);
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if (path) {
|
|
818
|
-
parsedPath.pathname = path;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
return parsedPath;
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
var prefix = 'Invariant failed';
|
|
826
|
-
function invariant(condition, message) {
|
|
827
|
-
if (condition) {
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
var provided = typeof message === 'function' ? message() : message;
|
|
831
|
-
var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
|
|
832
|
-
throw new Error(value);
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
|
|
836
|
-
// k: infer I,
|
|
837
|
-
// ) => any
|
|
838
|
-
// ? I
|
|
839
|
-
// : never
|
|
840
|
-
|
|
841
|
-
/**
|
|
842
|
-
* This function returns `a` if `b` is deeply equal.
|
|
843
|
-
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
844
|
-
* This can be used for structural sharing between JSON values for example.
|
|
845
|
-
*/
|
|
846
|
-
function replaceEqualDeep(prev, next) {
|
|
847
|
-
if (prev === next) {
|
|
848
|
-
return prev;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
const array = Array.isArray(prev) && Array.isArray(next);
|
|
852
|
-
|
|
853
|
-
if (array || isPlainObject(prev) && isPlainObject(next)) {
|
|
854
|
-
const aSize = array ? prev.length : Object.keys(prev).length;
|
|
855
|
-
const bItems = array ? next : Object.keys(next);
|
|
856
|
-
const bSize = bItems.length;
|
|
857
|
-
const copy = array ? [] : {};
|
|
858
|
-
let equalItems = 0;
|
|
859
|
-
|
|
860
|
-
for (let i = 0; i < bSize; i++) {
|
|
861
|
-
const key = array ? i : bItems[i];
|
|
862
|
-
copy[key] = replaceEqualDeep(prev[key], next[key]);
|
|
863
|
-
|
|
864
|
-
if (copy[key] === prev[key]) {
|
|
865
|
-
equalItems++;
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
return aSize === bSize && equalItems === aSize ? prev : copy;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
return next;
|
|
873
|
-
} // Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
874
|
-
|
|
875
|
-
function isPlainObject(o) {
|
|
876
|
-
if (!hasObjectPrototype(o)) {
|
|
877
|
-
return false;
|
|
878
|
-
} // If has modified constructor
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
const ctor = o.constructor;
|
|
882
|
-
|
|
883
|
-
if (typeof ctor === 'undefined') {
|
|
884
|
-
return true;
|
|
885
|
-
} // If has modified prototype
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
const prot = ctor.prototype;
|
|
889
|
-
|
|
890
|
-
if (!hasObjectPrototype(prot)) {
|
|
891
|
-
return false;
|
|
892
|
-
} // If constructor does not have an Object-specific method
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
896
|
-
return false;
|
|
897
|
-
} // Most likely a plain Object
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
return true;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
function hasObjectPrototype(o) {
|
|
904
|
-
return Object.prototype.toString.call(o) === '[object Object]';
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
function last(arr) {
|
|
908
|
-
return arr[arr.length - 1];
|
|
909
|
-
}
|
|
910
|
-
function warning(cond, message) {
|
|
911
|
-
if (cond) {
|
|
912
|
-
if (typeof console !== 'undefined') console.warn(message);
|
|
913
|
-
|
|
914
|
-
try {
|
|
915
|
-
throw new Error(message);
|
|
916
|
-
} catch (_unused) {}
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
return true;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
function isFunction(d) {
|
|
923
|
-
return typeof d === 'function';
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
function functionalUpdate(updater, previous) {
|
|
927
|
-
if (isFunction(updater)) {
|
|
928
|
-
return updater(previous);
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
return updater;
|
|
932
|
-
}
|
|
933
|
-
function pick(parent, keys) {
|
|
934
|
-
return keys.reduce((obj, key) => {
|
|
935
|
-
obj[key] = parent[key];
|
|
936
|
-
return obj;
|
|
937
|
-
}, {});
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
function joinPaths(paths) {
|
|
941
|
-
return cleanPath(paths.filter(Boolean).join('/'));
|
|
942
|
-
}
|
|
943
|
-
function cleanPath(path) {
|
|
944
|
-
// remove double slashes
|
|
945
|
-
return path.replace(/\/{2,}/g, '/');
|
|
946
|
-
}
|
|
947
|
-
function trimPathLeft(path) {
|
|
948
|
-
return path === '/' ? path : path.replace(/^\/{1,}/, '');
|
|
949
|
-
}
|
|
950
|
-
function trimPathRight(path) {
|
|
951
|
-
return path === '/' ? path : path.replace(/\/{1,}$/, '');
|
|
952
|
-
}
|
|
953
|
-
function trimPath(path) {
|
|
954
|
-
return trimPathRight(trimPathLeft(path));
|
|
955
|
-
}
|
|
956
|
-
function resolvePath(basepath, base, to) {
|
|
957
|
-
base = base.replace(new RegExp("^" + basepath), '/');
|
|
958
|
-
to = to.replace(new RegExp("^" + basepath), '/');
|
|
959
|
-
let baseSegments = parsePathname(base);
|
|
960
|
-
const toSegments = parsePathname(to);
|
|
961
|
-
toSegments.forEach((toSegment, index) => {
|
|
962
|
-
if (toSegment.value === '/') {
|
|
963
|
-
if (!index) {
|
|
964
|
-
// Leading slash
|
|
965
|
-
baseSegments = [toSegment];
|
|
966
|
-
} else if (index === toSegments.length - 1) {
|
|
967
|
-
// Trailing Slash
|
|
968
|
-
baseSegments.push(toSegment);
|
|
969
|
-
} else ;
|
|
970
|
-
} else if (toSegment.value === '..') {
|
|
971
|
-
var _last;
|
|
972
|
-
|
|
973
|
-
// Extra trailing slash? pop it off
|
|
974
|
-
if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
|
|
975
|
-
baseSegments.pop();
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
baseSegments.pop();
|
|
979
|
-
} else if (toSegment.value === '.') {
|
|
980
|
-
return;
|
|
981
|
-
} else {
|
|
982
|
-
baseSegments.push(toSegment);
|
|
983
|
-
}
|
|
984
|
-
});
|
|
985
|
-
const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
|
|
986
|
-
return cleanPath(joined);
|
|
987
|
-
}
|
|
988
|
-
function parsePathname(pathname) {
|
|
989
|
-
if (!pathname) {
|
|
990
|
-
return [];
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
pathname = cleanPath(pathname);
|
|
994
|
-
const segments = [];
|
|
995
|
-
|
|
996
|
-
if (pathname.slice(0, 1) === '/') {
|
|
997
|
-
pathname = pathname.substring(1);
|
|
998
|
-
segments.push({
|
|
999
|
-
type: 'pathname',
|
|
1000
|
-
value: '/'
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
if (!pathname) {
|
|
1005
|
-
return segments;
|
|
1006
|
-
} // Remove empty segments and '.' segments
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
const split = pathname.split('/').filter(Boolean);
|
|
1010
|
-
segments.push(...split.map(part => {
|
|
1011
|
-
if (part.startsWith('*')) {
|
|
1012
|
-
return {
|
|
1013
|
-
type: 'wildcard',
|
|
1014
|
-
value: part
|
|
1015
|
-
};
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
if (part.charAt(0) === ':') {
|
|
1019
|
-
return {
|
|
1020
|
-
type: 'param',
|
|
1021
|
-
value: part
|
|
1022
|
-
};
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
return {
|
|
1026
|
-
type: 'pathname',
|
|
1027
|
-
value: part
|
|
1028
|
-
};
|
|
1029
|
-
}));
|
|
1030
|
-
|
|
1031
|
-
if (pathname.slice(-1) === '/') {
|
|
1032
|
-
pathname = pathname.substring(1);
|
|
1033
|
-
segments.push({
|
|
1034
|
-
type: 'pathname',
|
|
1035
|
-
value: '/'
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
return segments;
|
|
1040
|
-
}
|
|
1041
|
-
function interpolatePath(path, params, leaveWildcard) {
|
|
1042
|
-
const interpolatedPathSegments = parsePathname(path);
|
|
1043
|
-
return joinPaths(interpolatedPathSegments.map(segment => {
|
|
1044
|
-
if (segment.value === '*' && !leaveWildcard) {
|
|
1045
|
-
return '';
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
if (segment.type === 'param') {
|
|
1049
|
-
var _segment$value$substr;
|
|
1050
|
-
|
|
1051
|
-
return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
return segment.value;
|
|
1055
|
-
}));
|
|
1056
|
-
}
|
|
1057
|
-
function matchPathname(currentPathname, matchLocation) {
|
|
1058
|
-
const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
|
|
1059
|
-
|
|
1060
|
-
if (matchLocation.to && !pathParams) {
|
|
1061
|
-
return;
|
|
1062
|
-
} // if (matchLocation.search && !searchMatched) {
|
|
1063
|
-
// return
|
|
1064
|
-
// }
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
return pathParams != null ? pathParams : {};
|
|
1068
|
-
}
|
|
1069
|
-
function matchByPath(from, matchLocation) {
|
|
1070
|
-
var _matchLocation$to;
|
|
1071
|
-
|
|
1072
|
-
const baseSegments = parsePathname(from);
|
|
1073
|
-
const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
|
|
1074
|
-
const params = {};
|
|
1075
|
-
|
|
1076
|
-
let isMatch = (() => {
|
|
1077
|
-
for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
|
|
1078
|
-
const baseSegment = baseSegments[i];
|
|
1079
|
-
const routeSegment = routeSegments[i];
|
|
1080
|
-
const isLastRouteSegment = i === routeSegments.length - 1;
|
|
1081
|
-
const isLastBaseSegment = i === baseSegments.length - 1;
|
|
1082
|
-
|
|
1083
|
-
if (routeSegment) {
|
|
1084
|
-
if (routeSegment.type === 'wildcard') {
|
|
1085
|
-
if (baseSegment != null && baseSegment.value) {
|
|
1086
|
-
params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
|
|
1087
|
-
return true;
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
return false;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
if (routeSegment.type === 'pathname') {
|
|
1094
|
-
if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
|
|
1095
|
-
return true;
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
if (baseSegment) {
|
|
1099
|
-
if (matchLocation.caseSensitive) {
|
|
1100
|
-
if (routeSegment.value !== baseSegment.value) {
|
|
1101
|
-
return false;
|
|
1102
|
-
}
|
|
1103
|
-
} else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
|
|
1104
|
-
return false;
|
|
1105
|
-
}
|
|
828
|
+
this.__store = new Store(getInitialRouterState(), {
|
|
829
|
+
onUpdate: () => {
|
|
830
|
+
const prev = this.state;
|
|
831
|
+
this.state = this.__store.state;
|
|
832
|
+
const matchesByIdChanged = prev.matchesById !== this.state.matchesById;
|
|
833
|
+
let matchesChanged;
|
|
834
|
+
let pendingMatchesChanged;
|
|
835
|
+
if (!matchesByIdChanged) {
|
|
836
|
+
matchesChanged = prev.matchIds.length !== this.state.matchIds.length || prev.matchIds.some((d, i) => d !== this.state.matchIds[i]);
|
|
837
|
+
pendingMatchesChanged = prev.pendingMatchIds.length !== this.state.pendingMatchIds.length || prev.pendingMatchIds.some((d, i) => d !== this.state.pendingMatchIds[i]);
|
|
1106
838
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
if (routeSegment.type === 'param') {
|
|
1114
|
-
if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
|
|
1115
|
-
return false;
|
|
839
|
+
if (matchesByIdChanged || matchesChanged) {
|
|
840
|
+
this.state.matches = this.state.matchIds.map(id => {
|
|
841
|
+
return this.state.matchesById[id];
|
|
842
|
+
});
|
|
1116
843
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
844
|
+
if (matchesByIdChanged || pendingMatchesChanged) {
|
|
845
|
+
this.state.pendingMatches = this.state.pendingMatchIds.map(id => {
|
|
846
|
+
return this.state.matchesById[id];
|
|
847
|
+
});
|
|
1120
848
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
849
|
+
this.state.isFetching = [...this.state.matches, ...this.state.pendingMatches].some(d => d.isFetching);
|
|
850
|
+
},
|
|
851
|
+
defaultPriority: 'low'
|
|
852
|
+
});
|
|
853
|
+
this.state = this.__store.state;
|
|
854
|
+
this.update(options);
|
|
855
|
+
const next = this.buildNext({
|
|
856
|
+
hash: true,
|
|
857
|
+
fromCurrent: true,
|
|
858
|
+
search: true,
|
|
859
|
+
state: true
|
|
860
|
+
});
|
|
861
|
+
if (this.state.location.href !== next.href) {
|
|
862
|
+
this.#commitLocation({
|
|
863
|
+
...next,
|
|
864
|
+
replace: true
|
|
865
|
+
});
|
|
1126
866
|
}
|
|
1127
867
|
}
|
|
868
|
+
reset = () => {
|
|
869
|
+
this.__store.setState(s => Object.assign(s, getInitialRouterState()));
|
|
870
|
+
};
|
|
871
|
+
mount = () => {
|
|
872
|
+
// If the router matches are empty, start loading the matches
|
|
873
|
+
// if (!this.state.matches.length) {
|
|
874
|
+
this.safeLoad();
|
|
875
|
+
// }
|
|
876
|
+
};
|
|
1128
877
|
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
// 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.
|
|
1137
|
-
function encode(obj, pfx) {
|
|
1138
|
-
var k,
|
|
1139
|
-
i,
|
|
1140
|
-
tmp,
|
|
1141
|
-
str = '';
|
|
1142
|
-
|
|
1143
|
-
for (k in obj) {
|
|
1144
|
-
if ((tmp = obj[k]) !== void 0) {
|
|
1145
|
-
if (Array.isArray(tmp)) {
|
|
1146
|
-
for (i = 0; i < tmp.length; i++) {
|
|
1147
|
-
str && (str += '&');
|
|
1148
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
878
|
+
update = opts => {
|
|
879
|
+
this.options = {
|
|
880
|
+
...this.options,
|
|
881
|
+
...opts,
|
|
882
|
+
context: {
|
|
883
|
+
...this.options.context,
|
|
884
|
+
...opts?.context
|
|
1149
885
|
}
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
return (pfx || '') + str;
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
function toValue(mix) {
|
|
1161
|
-
if (!mix) return '';
|
|
1162
|
-
var str = decodeURIComponent(mix);
|
|
1163
|
-
if (str === 'false') return false;
|
|
1164
|
-
if (str === 'true') return true;
|
|
1165
|
-
if (str.charAt(0) === '0') return str;
|
|
1166
|
-
return +str * 0 === 0 ? +str : str;
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
function decode(str) {
|
|
1170
|
-
var tmp,
|
|
1171
|
-
k,
|
|
1172
|
-
out = {},
|
|
1173
|
-
arr = str.split('&');
|
|
1174
|
-
|
|
1175
|
-
while (tmp = arr.shift()) {
|
|
1176
|
-
tmp = tmp.split('=');
|
|
1177
|
-
k = tmp.shift();
|
|
1178
|
-
|
|
1179
|
-
if (out[k] !== void 0) {
|
|
1180
|
-
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1181
|
-
} else {
|
|
1182
|
-
out[k] = toValue(tmp.shift());
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
return out;
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
function _extends() {
|
|
1190
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
1191
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
1192
|
-
var source = arguments[i];
|
|
1193
|
-
|
|
1194
|
-
for (var key in source) {
|
|
1195
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1196
|
-
target[key] = source[key];
|
|
886
|
+
};
|
|
887
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
888
|
+
if (this.#unsubHistory) {
|
|
889
|
+
this.#unsubHistory();
|
|
1197
890
|
}
|
|
891
|
+
this.history = this.options.history ?? (isServer ? createMemoryHistory() : createBrowserHistory());
|
|
892
|
+
const parsedLocation = this.#parseLocation();
|
|
893
|
+
this.__store.setState(s => ({
|
|
894
|
+
...s,
|
|
895
|
+
resolvedLocation: parsedLocation,
|
|
896
|
+
location: parsedLocation
|
|
897
|
+
}));
|
|
898
|
+
this.#unsubHistory = this.history.listen(() => {
|
|
899
|
+
this.safeLoad({
|
|
900
|
+
next: this.#parseLocation(this.state.location)
|
|
901
|
+
});
|
|
902
|
+
});
|
|
1198
903
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
function createRoute(routeConfig, options, parent, router) {
|
|
1207
|
-
const {
|
|
1208
|
-
id,
|
|
1209
|
-
routeId,
|
|
1210
|
-
path: routePath,
|
|
1211
|
-
fullPath
|
|
1212
|
-
} = routeConfig;
|
|
1213
|
-
|
|
1214
|
-
const action = router.state.actions[id] || (() => {
|
|
1215
|
-
router.state.actions[id] = {
|
|
1216
|
-
submissions: [],
|
|
1217
|
-
submit: async (submission, actionOpts) => {
|
|
1218
|
-
var _actionOpts$invalidat;
|
|
1219
|
-
|
|
1220
|
-
if (!route) {
|
|
1221
|
-
return;
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
|
|
1225
|
-
|
|
1226
|
-
if (!(actionOpts != null && actionOpts.multi)) {
|
|
1227
|
-
action.submissions = action.submissions.filter(d => d.isMulti);
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
const actionState = {
|
|
1231
|
-
submittedAt: Date.now(),
|
|
1232
|
-
status: 'pending',
|
|
1233
|
-
submission,
|
|
1234
|
-
isMulti: !!(actionOpts != null && actionOpts.multi)
|
|
1235
|
-
};
|
|
1236
|
-
action.current = actionState;
|
|
1237
|
-
action.latest = actionState;
|
|
1238
|
-
action.submissions.push(actionState);
|
|
1239
|
-
router.notify();
|
|
1240
|
-
|
|
1241
|
-
try {
|
|
1242
|
-
const res = await (route.options.action == null ? void 0 : route.options.action(submission));
|
|
1243
|
-
actionState.data = res;
|
|
1244
|
-
|
|
1245
|
-
if (invalidate) {
|
|
1246
|
-
router.invalidateRoute({
|
|
1247
|
-
to: '.',
|
|
1248
|
-
fromCurrent: true
|
|
1249
|
-
});
|
|
1250
|
-
await router.reload();
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
actionState.status = 'success';
|
|
1254
|
-
return res;
|
|
1255
|
-
} catch (err) {
|
|
1256
|
-
console.error(err);
|
|
1257
|
-
actionState.error = err;
|
|
1258
|
-
actionState.status = 'error';
|
|
1259
|
-
} finally {
|
|
1260
|
-
router.notify();
|
|
1261
|
-
}
|
|
904
|
+
const {
|
|
905
|
+
basepath,
|
|
906
|
+
routeTree
|
|
907
|
+
} = this.options;
|
|
908
|
+
this.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
|
|
909
|
+
if (routeTree && routeTree !== this.routeTree) {
|
|
910
|
+
this.#buildRouteTree(routeTree);
|
|
1262
911
|
}
|
|
912
|
+
return this;
|
|
1263
913
|
};
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
if (!route) {
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
const loaderState = {
|
|
1276
|
-
loadedAt: Date.now(),
|
|
1277
|
-
loaderContext
|
|
1278
|
-
};
|
|
1279
|
-
loader.current = loaderState;
|
|
1280
|
-
loader.latest = loaderState;
|
|
1281
|
-
loader.pending.push(loaderState); // router.state = {
|
|
1282
|
-
// ...router.state,
|
|
1283
|
-
// currentAction: loaderState,
|
|
1284
|
-
// latestAction: loaderState,
|
|
1285
|
-
// }
|
|
1286
|
-
|
|
1287
|
-
router.notify();
|
|
1288
|
-
|
|
1289
|
-
try {
|
|
1290
|
-
return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
|
|
1291
|
-
} finally {
|
|
1292
|
-
loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
|
|
1293
|
-
|
|
1294
|
-
router.notify();
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
914
|
+
buildNext = opts => {
|
|
915
|
+
const next = this.#buildLocation(opts);
|
|
916
|
+
const __matches = this.matchRoutes(next.pathname, next.search);
|
|
917
|
+
return this.#buildLocation({
|
|
918
|
+
...opts,
|
|
919
|
+
__matches
|
|
920
|
+
});
|
|
1297
921
|
};
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
from: fullPath
|
|
1320
|
-
}));
|
|
1321
|
-
},
|
|
1322
|
-
matchRoute: (matchLocation, opts) => {
|
|
1323
|
-
return router.matchRoute(_extends({}, matchLocation, {
|
|
1324
|
-
from: fullPath
|
|
1325
|
-
}), opts);
|
|
1326
|
-
}
|
|
1327
|
-
};
|
|
1328
|
-
router.options.createRoute == null ? void 0 : router.options.createRoute({
|
|
1329
|
-
router,
|
|
1330
|
-
route
|
|
1331
|
-
});
|
|
1332
|
-
return route;
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
const rootRouteId = '__root__';
|
|
1336
|
-
const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
|
|
1337
|
-
if (options === void 0) {
|
|
1338
|
-
options = {};
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
if (isRoot === void 0) {
|
|
1342
|
-
isRoot = true;
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
if (isRoot) {
|
|
1346
|
-
options.path = rootRouteId;
|
|
1347
|
-
} // Strip the root from parentIds
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
if (parentId === rootRouteId) {
|
|
1351
|
-
parentId = '';
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
|
|
1355
|
-
|
|
1356
|
-
if (path && path !== '/') {
|
|
1357
|
-
path = trimPath(path);
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
const routeId = path || options.id;
|
|
1361
|
-
let id = joinPaths([parentId, routeId]);
|
|
1362
|
-
|
|
1363
|
-
if (path === rootRouteId) {
|
|
1364
|
-
path = '/';
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
if (id !== rootRouteId) {
|
|
1368
|
-
id = joinPaths(['/', id]);
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
|
|
1372
|
-
return {
|
|
1373
|
-
id: id,
|
|
1374
|
-
routeId: routeId,
|
|
1375
|
-
path: path,
|
|
1376
|
-
fullPath: fullPath,
|
|
1377
|
-
options: options,
|
|
1378
|
-
children,
|
|
1379
|
-
createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
|
|
1380
|
-
addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
|
|
1381
|
-
createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
|
|
1382
|
-
};
|
|
1383
|
-
};
|
|
1384
|
-
|
|
1385
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1386
|
-
function createRouteMatch(router, route, opts) {
|
|
1387
|
-
const routeMatch = _extends({}, route, opts, {
|
|
1388
|
-
router,
|
|
1389
|
-
routeSearch: {},
|
|
1390
|
-
search: {},
|
|
1391
|
-
childMatches: [],
|
|
1392
|
-
status: 'idle',
|
|
1393
|
-
routeLoaderData: {},
|
|
1394
|
-
loaderData: {},
|
|
1395
|
-
isFetching: false,
|
|
1396
|
-
isInvalid: false,
|
|
1397
|
-
invalidAt: Infinity,
|
|
1398
|
-
// pendingActions: [],
|
|
1399
|
-
getIsInvalid: () => {
|
|
1400
|
-
const now = Date.now();
|
|
1401
|
-
return routeMatch.isInvalid || routeMatch.invalidAt < now;
|
|
1402
|
-
},
|
|
1403
|
-
__: {
|
|
1404
|
-
abortController: new AbortController(),
|
|
1405
|
-
latestId: '',
|
|
1406
|
-
resolve: () => {},
|
|
1407
|
-
notify: () => {
|
|
1408
|
-
routeMatch.__.resolve();
|
|
1409
|
-
|
|
1410
|
-
routeMatch.router.notify();
|
|
1411
|
-
},
|
|
1412
|
-
validate: () => {
|
|
1413
|
-
var _routeMatch$parentMat, _routeMatch$parentMat2;
|
|
1414
|
-
|
|
1415
|
-
// Validate the search params and stabilize them
|
|
1416
|
-
const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
|
|
1417
|
-
|
|
1418
|
-
try {
|
|
1419
|
-
var _validator;
|
|
1420
|
-
|
|
1421
|
-
const prevSearch = routeMatch.routeSearch;
|
|
1422
|
-
const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
|
|
1423
|
-
let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {}); // Invalidate route matches when search param stability changes
|
|
922
|
+
cancelMatches = () => {
|
|
923
|
+
this.state.matches.forEach(match => {
|
|
924
|
+
this.cancelMatch(match.id);
|
|
925
|
+
});
|
|
926
|
+
};
|
|
927
|
+
cancelMatch = id => {
|
|
928
|
+
this.getRouteMatch(id)?.abortController?.abort();
|
|
929
|
+
};
|
|
930
|
+
safeLoad = opts => {
|
|
931
|
+
return this.load(opts).catch(err => {
|
|
932
|
+
// console.warn(err)
|
|
933
|
+
// invariant(false, 'Encountered an error during router.load()! ☝️.')
|
|
934
|
+
});
|
|
935
|
+
};
|
|
936
|
+
latestLoadPromise = Promise.resolve();
|
|
937
|
+
load = async opts => {
|
|
938
|
+
const promise = new Promise(async (resolve, reject) => {
|
|
939
|
+
let latestPromise;
|
|
940
|
+
const checkLatest = () => {
|
|
941
|
+
return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
|
|
942
|
+
};
|
|
1424
943
|
|
|
1425
|
-
|
|
1426
|
-
|
|
944
|
+
// Cancel any pending matches
|
|
945
|
+
// this.cancelMatches()
|
|
946
|
+
|
|
947
|
+
let pendingMatches;
|
|
948
|
+
this.__store.batch(() => {
|
|
949
|
+
if (opts?.next) {
|
|
950
|
+
// Ingest the new location
|
|
951
|
+
this.__store.setState(s => ({
|
|
952
|
+
...s,
|
|
953
|
+
location: opts.next
|
|
954
|
+
}));
|
|
1427
955
|
}
|
|
1428
956
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
if (typeof routeMatch.__[type] !== 'function') {
|
|
1435
|
-
routeMatch.__[type] = component;
|
|
1436
|
-
}
|
|
1437
|
-
});
|
|
1438
|
-
} catch (err) {
|
|
1439
|
-
console.error(err);
|
|
1440
|
-
const error = new Error('Invalid search params found', {
|
|
1441
|
-
cause: err
|
|
957
|
+
// Match the routes
|
|
958
|
+
pendingMatches = this.matchRoutes(this.state.location.pathname, this.state.location.search, {
|
|
959
|
+
throwOnError: opts?.throwOnError,
|
|
960
|
+
debug: true
|
|
1442
961
|
});
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
},
|
|
1451
|
-
cancel: () => {
|
|
1452
|
-
var _routeMatch$__$abortC;
|
|
1453
|
-
|
|
1454
|
-
(_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
|
|
1455
|
-
},
|
|
1456
|
-
invalidate: () => {
|
|
1457
|
-
routeMatch.isInvalid = true;
|
|
1458
|
-
},
|
|
1459
|
-
hasLoaders: () => {
|
|
1460
|
-
return !!(route.options.loader || componentTypes.some(d => {
|
|
1461
|
-
var _route$options$d;
|
|
1462
|
-
|
|
1463
|
-
return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
|
|
1464
|
-
}));
|
|
1465
|
-
},
|
|
1466
|
-
load: async loaderOpts => {
|
|
1467
|
-
const now = Date.now();
|
|
1468
|
-
const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
|
|
1469
|
-
|
|
1470
|
-
if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
|
|
1471
|
-
// If the match is currently active, don't preload it
|
|
1472
|
-
if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
|
|
1473
|
-
return;
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
router.matchCache[routeMatch.matchId] = {
|
|
1477
|
-
gc: now + loaderOpts.gcMaxAge,
|
|
1478
|
-
match: routeMatch
|
|
1479
|
-
};
|
|
1480
|
-
} // If the match is invalid, errored or idle, trigger it to load
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
|
|
1484
|
-
const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
|
|
1485
|
-
await routeMatch.fetch({
|
|
1486
|
-
maxAge
|
|
1487
|
-
});
|
|
1488
|
-
}
|
|
1489
|
-
},
|
|
1490
|
-
fetch: async opts => {
|
|
1491
|
-
const id = '' + Date.now() + Math.random();
|
|
1492
|
-
routeMatch.__.latestId = id; // If the match was in an error state, set it
|
|
1493
|
-
// to a loading state again. Otherwise, keep it
|
|
1494
|
-
// as loading or resolved
|
|
1495
|
-
|
|
1496
|
-
if (routeMatch.status === 'idle') {
|
|
1497
|
-
routeMatch.status = 'loading';
|
|
1498
|
-
} // We started loading the route, so it's no longer invalid
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
routeMatch.isInvalid = false;
|
|
1502
|
-
routeMatch.__.loadPromise = new Promise(async resolve => {
|
|
1503
|
-
// We are now fetching, even if it's in the background of a
|
|
1504
|
-
// resolved state
|
|
1505
|
-
routeMatch.isFetching = true;
|
|
1506
|
-
routeMatch.__.resolve = resolve;
|
|
1507
|
-
|
|
1508
|
-
routeMatch.__.componentsPromise = (async () => {
|
|
1509
|
-
// then run all component and data loaders in parallel
|
|
1510
|
-
// For each component type, potentially load it asynchronously
|
|
1511
|
-
await Promise.all(componentTypes.map(async type => {
|
|
1512
|
-
var _routeMatch$__$type;
|
|
1513
|
-
|
|
1514
|
-
const component = routeMatch.options[type];
|
|
1515
|
-
|
|
1516
|
-
if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
|
|
1517
|
-
routeMatch.__[type] = await router.options.loadComponent(component);
|
|
1518
|
-
}
|
|
962
|
+
this.__store.setState(s => ({
|
|
963
|
+
...s,
|
|
964
|
+
status: 'pending',
|
|
965
|
+
pendingMatchIds: pendingMatches.map(d => d.id),
|
|
966
|
+
matchesById: this.#mergeMatches(s.matchesById, pendingMatches)
|
|
1519
967
|
}));
|
|
1520
|
-
})();
|
|
1521
|
-
|
|
1522
|
-
routeMatch.__.dataPromise = Promise.resolve().then(async () => {
|
|
1523
|
-
try {
|
|
1524
|
-
var _ref, _ref2, _opts$maxAge;
|
|
1525
|
-
|
|
1526
|
-
if (routeMatch.options.loader) {
|
|
1527
|
-
const data = await routeMatch.options.loader({
|
|
1528
|
-
params: routeMatch.params,
|
|
1529
|
-
search: routeMatch.routeSearch,
|
|
1530
|
-
signal: routeMatch.__.abortController.signal
|
|
1531
|
-
});
|
|
1532
|
-
|
|
1533
|
-
if (id !== routeMatch.__.latestId) {
|
|
1534
|
-
return routeMatch.__.loadPromise;
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
routeMatch.error = undefined;
|
|
1541
|
-
routeMatch.status = 'success';
|
|
1542
|
-
routeMatch.updatedAt = Date.now();
|
|
1543
|
-
routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
|
|
1544
|
-
} catch (err) {
|
|
1545
|
-
if (id !== routeMatch.__.latestId) {
|
|
1546
|
-
return routeMatch.__.loadPromise;
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
{
|
|
1550
|
-
console.error(err);
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
routeMatch.error = err;
|
|
1554
|
-
routeMatch.status = 'error';
|
|
1555
|
-
routeMatch.updatedAt = Date.now();
|
|
1556
|
-
}
|
|
1557
968
|
});
|
|
1558
|
-
|
|
1559
969
|
try {
|
|
1560
|
-
|
|
970
|
+
// Load the matches
|
|
971
|
+
await this.loadMatches(pendingMatches);
|
|
1561
972
|
|
|
1562
|
-
|
|
1563
|
-
|
|
973
|
+
// Only apply the latest transition
|
|
974
|
+
if (latestPromise = checkLatest()) {
|
|
975
|
+
return await latestPromise;
|
|
1564
976
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
977
|
+
const prevLocation = this.state.resolvedLocation;
|
|
978
|
+
this.__store.setState(s => ({
|
|
979
|
+
...s,
|
|
980
|
+
status: 'idle',
|
|
981
|
+
resolvedLocation: s.location,
|
|
982
|
+
matchIds: s.pendingMatchIds,
|
|
983
|
+
pendingMatchIds: []
|
|
984
|
+
}));
|
|
985
|
+
if (prevLocation.href !== this.state.location.href) {
|
|
986
|
+
this.options.onRouteChange?.();
|
|
1568
987
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
});
|
|
1575
|
-
await routeMatch.__.loadPromise;
|
|
1576
|
-
|
|
1577
|
-
if (id !== routeMatch.__.latestId) {
|
|
1578
|
-
return routeMatch.__.loadPromise;
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
delete routeMatch.__.loadPromise;
|
|
1582
|
-
}
|
|
1583
|
-
});
|
|
1584
|
-
|
|
1585
|
-
if (!routeMatch.hasLoaders()) {
|
|
1586
|
-
routeMatch.status = 'success';
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
return routeMatch;
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1593
|
-
const defaultStringifySearch = stringifySearchWith(JSON.stringify);
|
|
1594
|
-
function parseSearchWith(parser) {
|
|
1595
|
-
return searchStr => {
|
|
1596
|
-
if (searchStr.substring(0, 1) === '?') {
|
|
1597
|
-
searchStr = searchStr.substring(1);
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
let query = decode(searchStr); // Try to parse any query params that might be json
|
|
1601
|
-
|
|
1602
|
-
for (let key in query) {
|
|
1603
|
-
const value = query[key];
|
|
1604
|
-
|
|
1605
|
-
if (typeof value === 'string') {
|
|
1606
|
-
try {
|
|
1607
|
-
query[key] = parser(value);
|
|
1608
|
-
} catch (err) {//
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
return query;
|
|
1614
|
-
};
|
|
1615
|
-
}
|
|
1616
|
-
function stringifySearchWith(stringify) {
|
|
1617
|
-
return search => {
|
|
1618
|
-
search = _extends({}, search);
|
|
1619
|
-
|
|
1620
|
-
if (search) {
|
|
1621
|
-
Object.keys(search).forEach(key => {
|
|
1622
|
-
const val = search[key];
|
|
1623
|
-
|
|
1624
|
-
if (typeof val === 'undefined' || val === undefined) {
|
|
1625
|
-
delete search[key];
|
|
1626
|
-
} else if (val && typeof val === 'object' && val !== null) {
|
|
1627
|
-
try {
|
|
1628
|
-
search[key] = stringify(val);
|
|
1629
|
-
} catch (err) {// silent
|
|
988
|
+
resolve();
|
|
989
|
+
} catch (err) {
|
|
990
|
+
// Only apply the latest transition
|
|
991
|
+
if (latestPromise = checkLatest()) {
|
|
992
|
+
return await latestPromise;
|
|
1630
993
|
}
|
|
994
|
+
reject(err);
|
|
1631
995
|
}
|
|
1632
996
|
});
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
var _window$document;
|
|
1641
|
-
// Detect if we're in the DOM
|
|
1642
|
-
const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
|
|
1643
|
-
|
|
1644
|
-
const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
|
|
1645
|
-
|
|
1646
|
-
function getInitialRouterState() {
|
|
1647
|
-
return {
|
|
1648
|
-
status: 'idle',
|
|
1649
|
-
location: null,
|
|
1650
|
-
matches: [],
|
|
1651
|
-
actions: {},
|
|
1652
|
-
loaders: {},
|
|
1653
|
-
lastUpdated: Date.now(),
|
|
1654
|
-
isFetching: false,
|
|
1655
|
-
isPreloading: false
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
function createRouter(userOptions) {
|
|
1660
|
-
var _userOptions$stringif, _userOptions$parseSea;
|
|
1661
|
-
|
|
1662
|
-
const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
|
|
1663
|
-
|
|
1664
|
-
const originalOptions = _extends({
|
|
1665
|
-
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
1666
|
-
defaultLoaderMaxAge: 0,
|
|
1667
|
-
defaultPreloadMaxAge: 2000,
|
|
1668
|
-
defaultPreloadDelay: 50
|
|
1669
|
-
}, userOptions, {
|
|
1670
|
-
stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
|
|
1671
|
-
parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
|
|
1672
|
-
});
|
|
1673
|
-
|
|
1674
|
-
let router = {
|
|
1675
|
-
history,
|
|
1676
|
-
options: originalOptions,
|
|
1677
|
-
listeners: [],
|
|
1678
|
-
// Resolved after construction
|
|
1679
|
-
basepath: '',
|
|
1680
|
-
routeTree: undefined,
|
|
1681
|
-
routesById: {},
|
|
1682
|
-
location: undefined,
|
|
1683
|
-
allRouteInfo: undefined,
|
|
1684
|
-
//
|
|
1685
|
-
navigationPromise: Promise.resolve(),
|
|
1686
|
-
resolveNavigation: () => {},
|
|
1687
|
-
matchCache: {},
|
|
1688
|
-
state: getInitialRouterState(),
|
|
1689
|
-
reset: () => {
|
|
1690
|
-
router.state = getInitialRouterState();
|
|
1691
|
-
router.notify();
|
|
1692
|
-
},
|
|
1693
|
-
startedLoadingAt: Date.now(),
|
|
1694
|
-
subscribe: listener => {
|
|
1695
|
-
router.listeners.push(listener);
|
|
1696
|
-
return () => {
|
|
1697
|
-
router.listeners = router.listeners.filter(x => x !== listener);
|
|
1698
|
-
};
|
|
1699
|
-
},
|
|
1700
|
-
getRoute: id => {
|
|
1701
|
-
return router.routesById[id];
|
|
1702
|
-
},
|
|
1703
|
-
notify: () => {
|
|
1704
|
-
const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
|
|
1705
|
-
const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
|
|
1706
|
-
|
|
1707
|
-
if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
|
|
1708
|
-
router.state = _extends({}, router.state, {
|
|
1709
|
-
isFetching,
|
|
1710
|
-
isPreloading
|
|
1711
|
-
});
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
cascadeLoaderData(router.state.matches);
|
|
1715
|
-
router.listeners.forEach(listener => listener(router));
|
|
1716
|
-
},
|
|
1717
|
-
dehydrateState: () => {
|
|
1718
|
-
return _extends({}, pick(router.state, ['status', 'location', 'lastUpdated']), {
|
|
1719
|
-
matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
|
|
1720
|
-
});
|
|
1721
|
-
},
|
|
1722
|
-
hydrateState: dehydratedState => {
|
|
1723
|
-
// Match the routes
|
|
1724
|
-
const matches = router.matchRoutes(router.location.pathname, {
|
|
1725
|
-
strictParseParams: true
|
|
1726
|
-
});
|
|
1727
|
-
matches.forEach((match, index) => {
|
|
1728
|
-
const dehydratedMatch = dehydratedState.matches[index];
|
|
1729
|
-
invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
|
|
1730
|
-
Object.assign(match, dehydratedMatch);
|
|
1731
|
-
});
|
|
1732
|
-
matches.forEach(match => match.__.validate());
|
|
1733
|
-
router.state = _extends({}, router.state, dehydratedState, {
|
|
1734
|
-
matches
|
|
1735
|
-
});
|
|
1736
|
-
},
|
|
1737
|
-
mount: () => {
|
|
1738
|
-
const next = router.__.buildLocation({
|
|
1739
|
-
to: '.',
|
|
1740
|
-
search: true,
|
|
1741
|
-
hash: true
|
|
1742
|
-
}); // If the current location isn't updated, trigger a navigation
|
|
1743
|
-
// to the current location. Otherwise, load the current location.
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
if (next.href !== router.location.href) {
|
|
1747
|
-
router.__.commitLocation(next, true);
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
if (!router.state.matches.length) {
|
|
1751
|
-
router.load();
|
|
1752
|
-
}
|
|
1753
|
-
|
|
1754
|
-
const unsub = router.history.listen(event => {
|
|
1755
|
-
router.load(router.__.parseLocation(event.location, router.location));
|
|
1756
|
-
}); // addEventListener does not exist in React Native, but window does
|
|
1757
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1758
|
-
|
|
1759
|
-
if (!isServer && window.addEventListener) {
|
|
1760
|
-
// Listen to visibillitychange and focus
|
|
1761
|
-
window.addEventListener('visibilitychange', router.onFocus, false);
|
|
1762
|
-
window.addEventListener('focus', router.onFocus, false);
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
return () => {
|
|
1766
|
-
unsub();
|
|
1767
|
-
|
|
1768
|
-
if (!isServer && window.removeEventListener) {
|
|
1769
|
-
// Be sure to unsubscribe if a new handler is set
|
|
1770
|
-
window.removeEventListener('visibilitychange', router.onFocus);
|
|
1771
|
-
window.removeEventListener('focus', router.onFocus);
|
|
1772
|
-
}
|
|
997
|
+
this.latestLoadPromise = promise;
|
|
998
|
+
return this.latestLoadPromise;
|
|
999
|
+
};
|
|
1000
|
+
#mergeMatches = (prevMatchesById, nextMatches) => {
|
|
1001
|
+
const nextMatchesById = {
|
|
1002
|
+
...prevMatchesById
|
|
1773
1003
|
};
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
|
|
1780
|
-
|
|
1781
|
-
if (!router.location || newHistory) {
|
|
1782
|
-
if (opts != null && opts.history) {
|
|
1783
|
-
router.history = opts.history;
|
|
1004
|
+
let hadNew = false;
|
|
1005
|
+
nextMatches.forEach(match => {
|
|
1006
|
+
if (!nextMatchesById[match.id]) {
|
|
1007
|
+
hadNew = true;
|
|
1008
|
+
nextMatchesById[match.id] = match;
|
|
1784
1009
|
}
|
|
1785
|
-
|
|
1786
|
-
router.location = router.__.parseLocation(router.history.location);
|
|
1787
|
-
router.state.location = router.location;
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
Object.assign(router.options, opts);
|
|
1791
|
-
const {
|
|
1792
|
-
basepath,
|
|
1793
|
-
routeConfig
|
|
1794
|
-
} = router.options;
|
|
1795
|
-
router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
|
|
1796
|
-
|
|
1797
|
-
if (routeConfig) {
|
|
1798
|
-
router.routesById = {};
|
|
1799
|
-
router.routeTree = router.__.buildRouteTree(routeConfig);
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
return router;
|
|
1803
|
-
},
|
|
1804
|
-
cancelMatches: () => {
|
|
1805
|
-
var _router$state$pending, _router$state$pending2;
|
|
1806
|
-
[...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
|
|
1807
|
-
match.cancel();
|
|
1808
1010
|
});
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
const id = Math.random();
|
|
1812
|
-
router.startedLoadingAt = id;
|
|
1813
|
-
|
|
1814
|
-
if (next) {
|
|
1815
|
-
// Ingest the new location
|
|
1816
|
-
router.location = next;
|
|
1817
|
-
} // Cancel any pending matches
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
router.cancelMatches(); // Match the routes
|
|
1821
|
-
|
|
1822
|
-
const matches = router.matchRoutes(router.location.pathname, {
|
|
1823
|
-
strictParseParams: true
|
|
1824
|
-
});
|
|
1825
|
-
|
|
1826
|
-
if (typeof document !== 'undefined') {
|
|
1827
|
-
router.state = _extends({}, router.state, {
|
|
1828
|
-
pending: {
|
|
1829
|
-
matches: matches,
|
|
1830
|
-
location: router.location
|
|
1831
|
-
},
|
|
1832
|
-
status: 'loading'
|
|
1833
|
-
});
|
|
1834
|
-
} else {
|
|
1835
|
-
router.state = _extends({}, router.state, {
|
|
1836
|
-
matches: matches,
|
|
1837
|
-
location: router.location,
|
|
1838
|
-
status: 'loading'
|
|
1839
|
-
});
|
|
1011
|
+
if (!hadNew) {
|
|
1012
|
+
return prevMatchesById;
|
|
1840
1013
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
const exiting = [],
|
|
1853
|
-
staying = [];
|
|
1854
|
-
previousMatches.forEach(d => {
|
|
1855
|
-
if (matches.find(dd => dd.matchId === d.matchId)) {
|
|
1856
|
-
staying.push(d);
|
|
1857
|
-
} else {
|
|
1858
|
-
exiting.push(d);
|
|
1859
|
-
}
|
|
1014
|
+
return nextMatchesById;
|
|
1015
|
+
};
|
|
1016
|
+
getRoute = id => {
|
|
1017
|
+
const route = this.routesById[id];
|
|
1018
|
+
invariant(route, `Route with id "${id}" not found`);
|
|
1019
|
+
return route;
|
|
1020
|
+
};
|
|
1021
|
+
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
1022
|
+
const next = this.buildNext(navigateOpts);
|
|
1023
|
+
const matches = this.matchRoutes(next.pathname, next.search, {
|
|
1024
|
+
throwOnError: true
|
|
1860
1025
|
});
|
|
1861
|
-
|
|
1862
|
-
return
|
|
1026
|
+
this.__store.setState(s => {
|
|
1027
|
+
return {
|
|
1028
|
+
...s,
|
|
1029
|
+
matchesById: this.#mergeMatches(s.matchesById, matches)
|
|
1030
|
+
};
|
|
1031
|
+
});
|
|
1032
|
+
await this.loadMatches(matches, {
|
|
1033
|
+
preload: true,
|
|
1034
|
+
maxAge: navigateOpts.maxAge
|
|
1863
1035
|
});
|
|
1036
|
+
return matches;
|
|
1037
|
+
};
|
|
1038
|
+
cleanMatches = () => {
|
|
1864
1039
|
const now = Date.now();
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
if (gc > 0) {
|
|
1881
|
-
router.matchCache[d.matchId] = {
|
|
1882
|
-
gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
|
|
1883
|
-
match: d
|
|
1040
|
+
const outdatedMatchIds = Object.values(this.state.matchesById).filter(match => {
|
|
1041
|
+
const route = this.getRoute(match.routeId);
|
|
1042
|
+
return !this.state.matchIds.includes(match.id) && !this.state.pendingMatchIds.includes(match.id) && match.preloadInvalidAt < now && (route.options.gcMaxAge ? match.updatedAt + route.options.gcMaxAge < now : true);
|
|
1043
|
+
}).map(d => d.id);
|
|
1044
|
+
if (outdatedMatchIds.length) {
|
|
1045
|
+
this.__store.setState(s => {
|
|
1046
|
+
const matchesById = {
|
|
1047
|
+
...s.matchesById
|
|
1048
|
+
};
|
|
1049
|
+
outdatedMatchIds.forEach(id => {
|
|
1050
|
+
delete matchesById[id];
|
|
1051
|
+
});
|
|
1052
|
+
return {
|
|
1053
|
+
...s,
|
|
1054
|
+
matchesById
|
|
1884
1055
|
};
|
|
1885
|
-
}
|
|
1886
|
-
});
|
|
1887
|
-
staying.forEach(d => {
|
|
1888
|
-
d.options.onTransition == null ? void 0 : d.options.onTransition({
|
|
1889
|
-
params: d.params,
|
|
1890
|
-
search: d.routeSearch
|
|
1891
|
-
});
|
|
1892
|
-
});
|
|
1893
|
-
entering.forEach(d => {
|
|
1894
|
-
d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
|
|
1895
|
-
params: d.params,
|
|
1896
|
-
search: d.search
|
|
1897
1056
|
});
|
|
1898
|
-
delete router.matchCache[d.matchId];
|
|
1899
|
-
});
|
|
1900
|
-
|
|
1901
|
-
if (router.startedLoadingAt !== id) {
|
|
1902
|
-
// Ignore side-effects of match loading
|
|
1903
|
-
return;
|
|
1904
1057
|
}
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1058
|
+
};
|
|
1059
|
+
matchRoutes = (pathname, locationSearch, opts) => {
|
|
1060
|
+
let routeParams = {};
|
|
1061
|
+
let foundRoute = this.flatRoutes.find(route => {
|
|
1062
|
+
const matchedParams = matchPathname(this.basepath, pathname, {
|
|
1063
|
+
to: route.fullPath,
|
|
1064
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive
|
|
1065
|
+
});
|
|
1066
|
+
if (matchedParams) {
|
|
1067
|
+
routeParams = matchedParams;
|
|
1068
|
+
return true;
|
|
1911
1069
|
}
|
|
1070
|
+
return false;
|
|
1912
1071
|
});
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
});
|
|
1919
|
-
router.notify();
|
|
1920
|
-
router.resolveNavigation();
|
|
1921
|
-
},
|
|
1922
|
-
cleanMatchCache: () => {
|
|
1923
|
-
const now = Date.now();
|
|
1924
|
-
Object.keys(router.matchCache).forEach(matchId => {
|
|
1925
|
-
const entry = router.matchCache[matchId]; // Don't remove loading matches
|
|
1926
|
-
|
|
1927
|
-
if (entry.match.status === 'loading') {
|
|
1928
|
-
return;
|
|
1929
|
-
} // Do not remove successful matches that are still valid
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
if (entry.gc > 0 && entry.gc > now) {
|
|
1933
|
-
return;
|
|
1934
|
-
} // Everything else gets removed
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
delete router.matchCache[matchId];
|
|
1938
|
-
});
|
|
1939
|
-
},
|
|
1940
|
-
loadRoute: async function loadRoute(navigateOpts) {
|
|
1941
|
-
if (navigateOpts === void 0) {
|
|
1942
|
-
navigateOpts = router.location;
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
const next = router.buildNext(navigateOpts);
|
|
1946
|
-
const matches = router.matchRoutes(next.pathname, {
|
|
1947
|
-
strictParseParams: true
|
|
1948
|
-
});
|
|
1949
|
-
await router.loadMatches(matches);
|
|
1950
|
-
return matches;
|
|
1951
|
-
},
|
|
1952
|
-
preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
|
|
1953
|
-
var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
|
|
1954
|
-
|
|
1955
|
-
if (navigateOpts === void 0) {
|
|
1956
|
-
navigateOpts = router.location;
|
|
1072
|
+
let routeCursor = foundRoute || this.routesById['__root__'];
|
|
1073
|
+
let matchedRoutes = [routeCursor];
|
|
1074
|
+
while (routeCursor?.parentRoute) {
|
|
1075
|
+
routeCursor = routeCursor.parentRoute;
|
|
1076
|
+
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1957
1077
|
}
|
|
1958
1078
|
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
preload: true,
|
|
1965
|
-
maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
|
|
1966
|
-
gcMaxAge: (_ref5 = (_ref6 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref6 : router.options.defaultLoaderGcMaxAge) != null ? _ref5 : 0
|
|
1967
|
-
});
|
|
1968
|
-
return matches;
|
|
1969
|
-
},
|
|
1970
|
-
matchRoutes: (pathname, opts) => {
|
|
1971
|
-
var _router$state$pending3, _router$state$pending4;
|
|
1972
|
-
|
|
1973
|
-
router.cleanMatchCache();
|
|
1974
|
-
const matches = [];
|
|
1975
|
-
|
|
1976
|
-
if (!router.routeTree) {
|
|
1977
|
-
return matches;
|
|
1978
|
-
}
|
|
1079
|
+
// Alright, by now we should have all of our
|
|
1080
|
+
// matching routes and their param pairs, let's
|
|
1081
|
+
// Turn them into actual `Match` objects and
|
|
1082
|
+
// accumulate the params into a single params bag
|
|
1083
|
+
let allParams = {};
|
|
1979
1084
|
|
|
1980
|
-
|
|
1085
|
+
// Existing matches are matches that are already loaded along with
|
|
1086
|
+
// pending matches that are still loading
|
|
1981
1087
|
|
|
1982
|
-
const
|
|
1983
|
-
|
|
1088
|
+
const matches = matchedRoutes.map(route => {
|
|
1089
|
+
let parsedParams;
|
|
1090
|
+
let parsedParamsError;
|
|
1091
|
+
try {
|
|
1092
|
+
parsedParams = route.options.parseParams?.(routeParams) ?? routeParams;
|
|
1093
|
+
// (typeof route.options.parseParams === 'object' &&
|
|
1094
|
+
// route.options.parseParams.parse
|
|
1095
|
+
// ? route.options.parseParams.parse(routeParams)
|
|
1096
|
+
// : (route.options.parseParams as any)?.(routeParams!)) ?? routeParams
|
|
1097
|
+
} catch (err) {
|
|
1098
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1099
|
+
cause: err
|
|
1100
|
+
});
|
|
1101
|
+
if (opts?.throwOnError) {
|
|
1102
|
+
throw parsedParamsError;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1984
1105
|
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
const
|
|
1988
|
-
|
|
1106
|
+
// Add the parsed params to the accumulated params bag
|
|
1107
|
+
Object.assign(allParams, parsedParams);
|
|
1108
|
+
const interpolatedPath = interpolatePath(route.path, allParams);
|
|
1109
|
+
const key = route.options.key ? route.options.key({
|
|
1110
|
+
params: allParams,
|
|
1111
|
+
search: locationSearch
|
|
1112
|
+
}) ?? '' : '';
|
|
1113
|
+
const stringifiedKey = key ? JSON.stringify(key) : '';
|
|
1114
|
+
const matchId = interpolatePath(route.id, allParams, true) + stringifiedKey;
|
|
1115
|
+
|
|
1116
|
+
// Waste not, want not. If we already have a match for this route,
|
|
1117
|
+
// reuse it. This is important for layout routes, which might stick
|
|
1118
|
+
// around between navigation actions that only change leaf routes.
|
|
1119
|
+
const existingMatch = this.getRouteMatch(matchId);
|
|
1120
|
+
if (existingMatch) {
|
|
1121
|
+
return {
|
|
1122
|
+
...existingMatch
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1989
1125
|
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1126
|
+
// Create a fresh route match
|
|
1127
|
+
const hasLoaders = !!(route.options.loader || componentTypes.some(d => route.options[d]?.preload));
|
|
1128
|
+
const routeMatch = {
|
|
1129
|
+
id: matchId,
|
|
1130
|
+
key: stringifiedKey,
|
|
1131
|
+
routeId: route.id,
|
|
1132
|
+
params: allParams,
|
|
1133
|
+
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1134
|
+
updatedAt: Date.now(),
|
|
1135
|
+
invalidAt: Infinity,
|
|
1136
|
+
preloadInvalidAt: Infinity,
|
|
1137
|
+
routeSearch: {},
|
|
1138
|
+
search: {},
|
|
1139
|
+
status: hasLoaders ? 'idle' : 'success',
|
|
1140
|
+
isFetching: false,
|
|
1141
|
+
invalid: false,
|
|
1142
|
+
error: undefined,
|
|
1143
|
+
paramsError: parsedParamsError,
|
|
1144
|
+
searchError: undefined,
|
|
1145
|
+
loaderData: undefined,
|
|
1146
|
+
loadPromise: Promise.resolve(),
|
|
1147
|
+
routeContext: undefined,
|
|
1148
|
+
context: undefined,
|
|
1149
|
+
abortController: new AbortController(),
|
|
1150
|
+
fetchedAt: 0
|
|
1151
|
+
};
|
|
1152
|
+
return routeMatch;
|
|
1153
|
+
});
|
|
1993
1154
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1155
|
+
// Take each match and resolve its search params and context
|
|
1156
|
+
// This has to happen after the matches are created or found
|
|
1157
|
+
// so that we can use the parent match's search params and context
|
|
1158
|
+
matches.forEach((match, i) => {
|
|
1159
|
+
const parentMatch = matches[i - 1];
|
|
1160
|
+
const route = this.getRoute(match.routeId);
|
|
1161
|
+
const searchInfo = (() => {
|
|
1162
|
+
// Validate the search params and stabilize them
|
|
1163
|
+
const parentSearchInfo = {
|
|
1164
|
+
search: parentMatch?.search ?? locationSearch,
|
|
1165
|
+
routeSearch: parentMatch?.routeSearch ?? locationSearch
|
|
1166
|
+
};
|
|
1167
|
+
try {
|
|
1168
|
+
const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
|
|
1169
|
+
const routeSearch = validator?.(parentSearchInfo.search) ?? {};
|
|
1170
|
+
const search = {
|
|
1171
|
+
...parentSearchInfo.search,
|
|
1172
|
+
...routeSearch
|
|
1173
|
+
};
|
|
1174
|
+
return {
|
|
1175
|
+
routeSearch: replaceEqualDeep(match.routeSearch, routeSearch),
|
|
1176
|
+
search: replaceEqualDeep(match.search, search)
|
|
1177
|
+
};
|
|
1178
|
+
} catch (err) {
|
|
1179
|
+
match.searchError = new SearchParamError(err.message, {
|
|
1180
|
+
cause: err
|
|
1181
|
+
});
|
|
1182
|
+
if (opts?.throwOnError) {
|
|
1183
|
+
throw match.searchError;
|
|
1996
1184
|
}
|
|
1185
|
+
return parentSearchInfo;
|
|
1186
|
+
}
|
|
1187
|
+
})();
|
|
1188
|
+
const contextInfo = (() => {
|
|
1189
|
+
try {
|
|
1190
|
+
const routeContext = route.options.getContext?.({
|
|
1191
|
+
parentContext: parentMatch?.routeContext ?? {},
|
|
1192
|
+
context: parentMatch?.context ?? this?.options.context ?? {},
|
|
1193
|
+
params: match.params,
|
|
1194
|
+
search: match.search
|
|
1195
|
+
}) || {};
|
|
1196
|
+
const context = {
|
|
1197
|
+
...(parentMatch?.context ?? this?.options.context),
|
|
1198
|
+
...routeContext
|
|
1199
|
+
};
|
|
1200
|
+
return {
|
|
1201
|
+
context,
|
|
1202
|
+
routeContext
|
|
1203
|
+
};
|
|
1204
|
+
} catch (err) {
|
|
1205
|
+
route.options.onError?.(err);
|
|
1206
|
+
throw err;
|
|
1207
|
+
}
|
|
1208
|
+
})();
|
|
1209
|
+
Object.assign(match, {
|
|
1210
|
+
...searchInfo,
|
|
1211
|
+
...contextInfo
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1214
|
+
return matches;
|
|
1215
|
+
};
|
|
1216
|
+
loadMatches = async (resolvedMatches, opts) => {
|
|
1217
|
+
this.cleanMatches();
|
|
1218
|
+
let firstBadMatchIndex;
|
|
1997
1219
|
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
1220
|
+
// Check each match middleware to see if the route can be accessed
|
|
1221
|
+
try {
|
|
1222
|
+
await Promise.all(resolvedMatches.map(async (match, index) => {
|
|
1223
|
+
const route = this.getRoute(match.routeId);
|
|
1224
|
+
if (!opts?.preload) {
|
|
1225
|
+
// Update each match with its latest url data
|
|
1226
|
+
this.setRouteMatch(match.id, s => ({
|
|
1227
|
+
...s,
|
|
1228
|
+
routeSearch: match.routeSearch,
|
|
1229
|
+
search: match.search,
|
|
1230
|
+
routeContext: match.routeContext,
|
|
1231
|
+
context: match.context,
|
|
1232
|
+
error: match.error,
|
|
1233
|
+
paramsError: match.paramsError,
|
|
1234
|
+
searchError: match.searchError,
|
|
1235
|
+
params: match.params
|
|
1236
|
+
}));
|
|
1237
|
+
}
|
|
1238
|
+
const handleError = (err, handler) => {
|
|
1239
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
1240
|
+
handler = handler || route.options.onError;
|
|
1241
|
+
if (isRedirect(err)) {
|
|
1242
|
+
throw err;
|
|
1243
|
+
}
|
|
1244
|
+
try {
|
|
1245
|
+
handler?.(err);
|
|
1246
|
+
} catch (errorHandlerErr) {
|
|
1247
|
+
err = errorHandlerErr;
|
|
1248
|
+
if (isRedirect(errorHandlerErr)) {
|
|
1249
|
+
throw errorHandlerErr;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
this.setRouteMatch(match.id, s => ({
|
|
1253
|
+
...s,
|
|
1254
|
+
error: err,
|
|
1255
|
+
status: 'error',
|
|
1256
|
+
updatedAt: Date.now()
|
|
1257
|
+
}));
|
|
1258
|
+
};
|
|
1259
|
+
if (match.paramsError) {
|
|
1260
|
+
handleError(match.paramsError, route.options.onParseParamsError);
|
|
1261
|
+
}
|
|
1262
|
+
if (match.searchError) {
|
|
1263
|
+
handleError(match.searchError, route.options.onValidateSearchError);
|
|
1264
|
+
}
|
|
1265
|
+
try {
|
|
1266
|
+
await route.options.beforeLoad?.({
|
|
1267
|
+
...match,
|
|
1268
|
+
preload: !!opts?.preload
|
|
2003
1269
|
});
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
1270
|
+
} catch (err) {
|
|
1271
|
+
handleError(err, route.options.onBeforeLoadError);
|
|
1272
|
+
}
|
|
1273
|
+
}));
|
|
1274
|
+
} catch (err) {
|
|
1275
|
+
if (!opts?.preload) {
|
|
1276
|
+
this.navigate(err);
|
|
1277
|
+
}
|
|
1278
|
+
throw err;
|
|
1279
|
+
}
|
|
1280
|
+
const validResolvedMatches = resolvedMatches.slice(0, firstBadMatchIndex);
|
|
1281
|
+
const matchPromises = [];
|
|
1282
|
+
validResolvedMatches.forEach((match, index) => {
|
|
1283
|
+
matchPromises.push((async () => {
|
|
1284
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
1285
|
+
const route = this.getRoute(match.routeId);
|
|
1286
|
+
if (match.isFetching || match.status === 'success' && !this.getIsInvalid({
|
|
1287
|
+
matchId: match.id,
|
|
1288
|
+
preload: opts?.preload
|
|
1289
|
+
})) {
|
|
1290
|
+
return this.getRouteMatch(match.id)?.loadPromise;
|
|
1291
|
+
}
|
|
1292
|
+
const fetchedAt = Date.now();
|
|
1293
|
+
const checkLatest = () => {
|
|
1294
|
+
const latest = this.getRouteMatch(match.id);
|
|
1295
|
+
return latest && latest.fetchedAt !== fetchedAt ? latest.loadPromise : undefined;
|
|
1296
|
+
};
|
|
1297
|
+
const loadPromise = (async () => {
|
|
1298
|
+
let latestPromise;
|
|
1299
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
1300
|
+
const component = route.options[type];
|
|
1301
|
+
if (component?.preload) {
|
|
1302
|
+
await component.preload();
|
|
1303
|
+
}
|
|
1304
|
+
}));
|
|
1305
|
+
const loaderPromise = route.options.loader?.({
|
|
1306
|
+
...match,
|
|
1307
|
+
preload: !!opts?.preload,
|
|
1308
|
+
parentMatchPromise
|
|
1309
|
+
});
|
|
1310
|
+
const handleError = err => {
|
|
1311
|
+
if (isRedirect(err)) {
|
|
1312
|
+
if (!opts?.preload) {
|
|
1313
|
+
this.navigate(err);
|
|
1314
|
+
}
|
|
1315
|
+
return true;
|
|
1316
|
+
}
|
|
1317
|
+
return false;
|
|
1318
|
+
};
|
|
1319
|
+
try {
|
|
1320
|
+
const [_, loader] = await Promise.all([componentsPromise, loaderPromise]);
|
|
1321
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1322
|
+
this.setRouteMatchData(match.id, () => loader, opts);
|
|
1323
|
+
} catch (err) {
|
|
1324
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1325
|
+
if (handleError(err)) {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const errorHandler = route.options.onLoadError ?? route.options.onError;
|
|
1329
|
+
let caughtError = err;
|
|
2008
1330
|
try {
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
throw err;
|
|
1331
|
+
errorHandler?.(err);
|
|
1332
|
+
} catch (errorHandlerErr) {
|
|
1333
|
+
caughtError = errorHandlerErr;
|
|
1334
|
+
if (handleError(errorHandlerErr)) {
|
|
1335
|
+
return;
|
|
2015
1336
|
}
|
|
2016
1337
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
1338
|
+
this.setRouteMatch(match.id, s => ({
|
|
1339
|
+
...s,
|
|
1340
|
+
error: caughtError,
|
|
1341
|
+
status: 'error',
|
|
1342
|
+
isFetching: false,
|
|
1343
|
+
updatedAt: Date.now()
|
|
1344
|
+
}));
|
|
2019
1345
|
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
if (!foundRoutes.length) {
|
|
2033
|
-
return;
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
foundRoutes.forEach(foundRoute => {
|
|
2037
|
-
var _router$matchCache$ma;
|
|
2038
|
-
|
|
2039
|
-
const interpolatedPath = interpolatePath(foundRoute.routePath, params);
|
|
2040
|
-
const matchId = interpolatePath(foundRoute.routeId, params, true);
|
|
2041
|
-
const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
|
|
2042
|
-
matchId,
|
|
2043
|
-
params,
|
|
2044
|
-
pathname: joinPaths([pathname, interpolatedPath])
|
|
2045
|
-
});
|
|
2046
|
-
matches.push(match);
|
|
2047
|
-
});
|
|
2048
|
-
const foundRoute = last(foundRoutes);
|
|
2049
|
-
|
|
2050
|
-
if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
|
|
2051
|
-
recurse(foundRoute.childRoutes);
|
|
2052
|
-
}
|
|
2053
|
-
};
|
|
2054
|
-
|
|
2055
|
-
recurse([router.routeTree]);
|
|
2056
|
-
cascadeLoaderData(matches);
|
|
2057
|
-
return matches;
|
|
2058
|
-
},
|
|
2059
|
-
loadMatches: async (resolvedMatches, loaderOpts) => {
|
|
2060
|
-
const matchPromises = resolvedMatches.map(async match => {
|
|
2061
|
-
// Validate the match (loads search params etc)
|
|
2062
|
-
match.__.validate();
|
|
2063
|
-
|
|
2064
|
-
match.load(loaderOpts);
|
|
2065
|
-
|
|
2066
|
-
if (match.__.loadPromise) {
|
|
2067
|
-
// Wait for the first sign of activity from the match
|
|
2068
|
-
await match.__.loadPromise;
|
|
2069
|
-
}
|
|
1346
|
+
})();
|
|
1347
|
+
this.setRouteMatch(match.id, s => ({
|
|
1348
|
+
...s,
|
|
1349
|
+
status: s.status !== 'success' ? 'pending' : s.status,
|
|
1350
|
+
isFetching: true,
|
|
1351
|
+
loadPromise,
|
|
1352
|
+
fetchedAt,
|
|
1353
|
+
invalid: false
|
|
1354
|
+
}));
|
|
1355
|
+
await loadPromise;
|
|
1356
|
+
})());
|
|
2070
1357
|
});
|
|
2071
|
-
router.notify();
|
|
2072
1358
|
await Promise.all(matchPromises);
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
[...router.state.matches, ...((_router$state$pending5 = (_router$state$pending6 = router.state.pending) == null ? void 0 : _router$state$pending6.matches) != null ? _router$state$pending5 : [])].forEach(match => {
|
|
2080
|
-
if (unloadedMatchIds.includes(match.matchId)) {
|
|
2081
|
-
match.invalidate();
|
|
2082
|
-
}
|
|
2083
|
-
});
|
|
2084
|
-
},
|
|
2085
|
-
reload: () => router.__.navigate({
|
|
2086
|
-
fromCurrent: true,
|
|
2087
|
-
replace: true,
|
|
2088
|
-
search: true
|
|
2089
|
-
}),
|
|
2090
|
-
resolvePath: (from, path) => {
|
|
2091
|
-
return resolvePath(router.basepath, from, cleanPath(path));
|
|
2092
|
-
},
|
|
2093
|
-
matchRoute: (location, opts) => {
|
|
2094
|
-
var _location$from;
|
|
2095
|
-
|
|
2096
|
-
// const location = router.buildNext(opts)
|
|
2097
|
-
location = _extends({}, location, {
|
|
2098
|
-
to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
|
|
1359
|
+
};
|
|
1360
|
+
reload = () => {
|
|
1361
|
+
return this.navigate({
|
|
1362
|
+
fromCurrent: true,
|
|
1363
|
+
replace: true,
|
|
1364
|
+
search: true
|
|
2099
1365
|
});
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
|
|
2115
|
-
to: next.pathname
|
|
2116
|
-
}));
|
|
2117
|
-
},
|
|
2118
|
-
navigate: async _ref7 => {
|
|
2119
|
-
let {
|
|
2120
|
-
from,
|
|
2121
|
-
to = '.',
|
|
2122
|
-
search,
|
|
2123
|
-
hash,
|
|
2124
|
-
replace,
|
|
2125
|
-
params
|
|
2126
|
-
} = _ref7;
|
|
1366
|
+
};
|
|
1367
|
+
resolvePath = (from, path) => {
|
|
1368
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1369
|
+
};
|
|
1370
|
+
navigate = async ({
|
|
1371
|
+
from,
|
|
1372
|
+
to = '',
|
|
1373
|
+
search,
|
|
1374
|
+
hash,
|
|
1375
|
+
replace,
|
|
1376
|
+
params
|
|
1377
|
+
}) => {
|
|
2127
1378
|
// If this link simply reloads the current route,
|
|
2128
1379
|
// make sure it has a new key so it will trigger a data refresh
|
|
1380
|
+
|
|
2129
1381
|
// If this `to` is a valid external URL, return
|
|
2130
1382
|
// null for LinkUtils
|
|
2131
1383
|
const toString = String(to);
|
|
2132
|
-
const fromString = String(from);
|
|
1384
|
+
const fromString = typeof from === 'undefined' ? from : String(from);
|
|
2133
1385
|
let isExternal;
|
|
2134
|
-
|
|
2135
1386
|
try {
|
|
2136
|
-
new URL(
|
|
1387
|
+
new URL(`${toString}`);
|
|
2137
1388
|
isExternal = true;
|
|
2138
1389
|
} catch (e) {}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
return router.__.navigate({
|
|
1390
|
+
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1391
|
+
return this.#commitLocation({
|
|
2142
1392
|
from: fromString,
|
|
2143
1393
|
to: toString,
|
|
2144
1394
|
search,
|
|
@@ -2146,38 +1396,58 @@
|
|
|
2146
1396
|
replace,
|
|
2147
1397
|
params
|
|
2148
1398
|
});
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
1399
|
+
};
|
|
1400
|
+
matchRoute = (location, opts) => {
|
|
1401
|
+
location = {
|
|
1402
|
+
...location,
|
|
1403
|
+
to: location.to ? this.resolvePath(location.from ?? '', location.to) : undefined
|
|
1404
|
+
};
|
|
1405
|
+
const next = this.buildNext(location);
|
|
1406
|
+
if (opts?.pending && this.state.status !== 'pending') {
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1409
|
+
const baseLocation = opts?.pending ? this.state.location : this.state.resolvedLocation;
|
|
1410
|
+
if (!baseLocation) {
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
1414
|
+
...opts,
|
|
1415
|
+
to: next.pathname
|
|
1416
|
+
});
|
|
1417
|
+
if (!match) {
|
|
1418
|
+
return false;
|
|
1419
|
+
}
|
|
1420
|
+
if (opts?.includeSearch ?? true) {
|
|
1421
|
+
return partialDeepEqual(baseLocation.search, next.search) ? match : false;
|
|
1422
|
+
}
|
|
1423
|
+
return match;
|
|
1424
|
+
};
|
|
1425
|
+
buildLink = ({
|
|
1426
|
+
from,
|
|
1427
|
+
to = '.',
|
|
1428
|
+
search,
|
|
1429
|
+
params,
|
|
1430
|
+
hash,
|
|
1431
|
+
target,
|
|
1432
|
+
replace,
|
|
1433
|
+
activeOptions,
|
|
1434
|
+
preload,
|
|
1435
|
+
preloadDelay: userPreloadDelay,
|
|
1436
|
+
disabled
|
|
1437
|
+
}) => {
|
|
2169
1438
|
// If this link simply reloads the current route,
|
|
2170
1439
|
// make sure it has a new key so it will trigger a data refresh
|
|
1440
|
+
|
|
2171
1441
|
// If this `to` is a valid external URL, return
|
|
2172
1442
|
// null for LinkUtils
|
|
1443
|
+
|
|
2173
1444
|
try {
|
|
2174
|
-
new URL(
|
|
1445
|
+
new URL(`${to}`);
|
|
2175
1446
|
return {
|
|
2176
1447
|
type: 'external',
|
|
2177
1448
|
href: to
|
|
2178
1449
|
};
|
|
2179
1450
|
} catch (e) {}
|
|
2180
|
-
|
|
2181
1451
|
const nextOpts = {
|
|
2182
1452
|
from,
|
|
2183
1453
|
to,
|
|
@@ -2186,71 +1456,69 @@
|
|
|
2186
1456
|
hash,
|
|
2187
1457
|
replace
|
|
2188
1458
|
};
|
|
2189
|
-
const next =
|
|
2190
|
-
preload =
|
|
2191
|
-
const preloadDelay =
|
|
1459
|
+
const next = this.buildNext(nextOpts);
|
|
1460
|
+
preload = preload ?? this.options.defaultPreload;
|
|
1461
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
2192
1462
|
|
|
2193
|
-
|
|
2194
|
-
const currentPathSplit =
|
|
1463
|
+
// Compare path/hash for matches
|
|
1464
|
+
const currentPathSplit = this.state.location.pathname.split('/');
|
|
2195
1465
|
const nextPathSplit = next.pathname.split('/');
|
|
2196
1466
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2197
|
-
|
|
1467
|
+
// Combine the matches based on user options
|
|
1468
|
+
const pathTest = activeOptions?.exact ? this.state.location.pathname === next.pathname : pathIsFuzzyEqual;
|
|
1469
|
+
const hashTest = activeOptions?.includeHash ? this.state.location.hash === next.hash : true;
|
|
1470
|
+
const searchTest = activeOptions?.includeSearch ?? true ? partialDeepEqual(this.state.location.search, next.search) : true;
|
|
2198
1471
|
|
|
2199
|
-
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
const isActive = pathTest && hashTest; // The click handler
|
|
1472
|
+
// The final "active" test
|
|
1473
|
+
const isActive = pathTest && hashTest && searchTest;
|
|
2203
1474
|
|
|
1475
|
+
// The click handler
|
|
2204
1476
|
const handleClick = e => {
|
|
2205
1477
|
if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
|
|
2206
1478
|
e.preventDefault();
|
|
2207
1479
|
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
} // All is well? Navigate!)
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
router.__.navigate(nextOpts);
|
|
1480
|
+
// All is well? Navigate!
|
|
1481
|
+
this.#commitLocation(nextOpts);
|
|
2214
1482
|
}
|
|
2215
|
-
};
|
|
2216
|
-
|
|
1483
|
+
};
|
|
2217
1484
|
|
|
1485
|
+
// The click handler
|
|
2218
1486
|
const handleFocus = e => {
|
|
2219
1487
|
if (preload) {
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
1488
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
1489
|
+
console.warn(err);
|
|
1490
|
+
console.warn('Error preloading route! ☝️');
|
|
2223
1491
|
});
|
|
2224
1492
|
}
|
|
2225
1493
|
};
|
|
2226
|
-
|
|
1494
|
+
const handleTouchStart = e => {
|
|
1495
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
1496
|
+
console.warn(err);
|
|
1497
|
+
console.warn('Error preloading route! ☝️');
|
|
1498
|
+
});
|
|
1499
|
+
};
|
|
2227
1500
|
const handleEnter = e => {
|
|
2228
1501
|
const target = e.target || {};
|
|
2229
|
-
|
|
2230
1502
|
if (preload) {
|
|
2231
1503
|
if (target.preloadTimeout) {
|
|
2232
1504
|
return;
|
|
2233
1505
|
}
|
|
2234
|
-
|
|
2235
1506
|
target.preloadTimeout = setTimeout(() => {
|
|
2236
1507
|
target.preloadTimeout = null;
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
1508
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
1509
|
+
console.warn(err);
|
|
1510
|
+
console.warn('Error preloading route! ☝️');
|
|
2240
1511
|
});
|
|
2241
1512
|
}, preloadDelay);
|
|
2242
1513
|
}
|
|
2243
1514
|
};
|
|
2244
|
-
|
|
2245
1515
|
const handleLeave = e => {
|
|
2246
1516
|
const target = e.target || {};
|
|
2247
|
-
|
|
2248
1517
|
if (target.preloadTimeout) {
|
|
2249
1518
|
clearTimeout(target.preloadTimeout);
|
|
2250
1519
|
target.preloadTimeout = null;
|
|
2251
1520
|
}
|
|
2252
1521
|
};
|
|
2253
|
-
|
|
2254
1522
|
return {
|
|
2255
1523
|
type: 'internal',
|
|
2256
1524
|
next,
|
|
@@ -2258,224 +1526,399 @@
|
|
|
2258
1526
|
handleClick,
|
|
2259
1527
|
handleEnter,
|
|
2260
1528
|
handleLeave,
|
|
1529
|
+
handleTouchStart,
|
|
2261
1530
|
isActive,
|
|
2262
1531
|
disabled
|
|
2263
1532
|
};
|
|
2264
|
-
}
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
return router.__.buildLocation(_extends({}, opts, {
|
|
2283
|
-
__preSearchFilters,
|
|
2284
|
-
__postSearchFilters
|
|
2285
|
-
}));
|
|
2286
|
-
},
|
|
2287
|
-
__: {
|
|
2288
|
-
buildRouteTree: rootRouteConfig => {
|
|
2289
|
-
const recurseRoutes = (routeConfigs, parent) => {
|
|
2290
|
-
return routeConfigs.map(routeConfig => {
|
|
2291
|
-
const routeOptions = routeConfig.options;
|
|
2292
|
-
const route = createRoute(routeConfig, routeOptions, parent, router);
|
|
2293
|
-
const existingRoute = router.routesById[route.routeId];
|
|
2294
|
-
|
|
2295
|
-
if (existingRoute) {
|
|
2296
|
-
{
|
|
2297
|
-
console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
throw new Error();
|
|
2301
|
-
}
|
|
2302
|
-
router.routesById[route.routeId] = route;
|
|
2303
|
-
const children = routeConfig.children;
|
|
2304
|
-
route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
|
|
2305
|
-
return route;
|
|
2306
|
-
});
|
|
2307
|
-
};
|
|
2308
|
-
|
|
2309
|
-
const routes = recurseRoutes([rootRouteConfig]);
|
|
2310
|
-
return routes[0];
|
|
2311
|
-
},
|
|
2312
|
-
parseLocation: (location, previousLocation) => {
|
|
2313
|
-
var _location$hash$split$;
|
|
2314
|
-
|
|
2315
|
-
const parsedSearch = router.options.parseSearch(location.search);
|
|
1533
|
+
};
|
|
1534
|
+
dehydrate = () => {
|
|
1535
|
+
return {
|
|
1536
|
+
state: pick(this.state, ['location', 'status', 'lastUpdated'])
|
|
1537
|
+
};
|
|
1538
|
+
};
|
|
1539
|
+
hydrate = async __do_not_use_server_ctx => {
|
|
1540
|
+
let _ctx = __do_not_use_server_ctx;
|
|
1541
|
+
// Client hydrates from window
|
|
1542
|
+
if (typeof document !== 'undefined') {
|
|
1543
|
+
_ctx = window.__TSR_DEHYDRATED__;
|
|
1544
|
+
}
|
|
1545
|
+
invariant(_ctx, 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?');
|
|
1546
|
+
const ctx = _ctx;
|
|
1547
|
+
this.dehydratedData = ctx.payload;
|
|
1548
|
+
this.options.hydrate?.(ctx.payload);
|
|
1549
|
+
this.__store.setState(s => {
|
|
2316
1550
|
return {
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
|
|
2321
|
-
href: "" + location.pathname + location.search + location.hash,
|
|
2322
|
-
state: location.state,
|
|
2323
|
-
key: location.key
|
|
1551
|
+
...s,
|
|
1552
|
+
...ctx.router.state,
|
|
1553
|
+
resolvedLocation: ctx.router.state.location
|
|
2324
1554
|
};
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
1555
|
+
});
|
|
1556
|
+
await this.load();
|
|
1557
|
+
return;
|
|
1558
|
+
};
|
|
1559
|
+
injectedHtml = [];
|
|
1560
|
+
injectHtml = async html => {
|
|
1561
|
+
this.injectedHtml.push(html);
|
|
1562
|
+
};
|
|
1563
|
+
dehydrateData = (key, getData) => {
|
|
1564
|
+
if (typeof document === 'undefined') {
|
|
1565
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
1566
|
+
this.injectHtml(async () => {
|
|
1567
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
1568
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
1569
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
1570
|
+
;(() => {
|
|
1571
|
+
var el = document.getElementById('${id}')
|
|
1572
|
+
el.parentElement.removeChild(el)
|
|
1573
|
+
})()
|
|
1574
|
+
</script>`;
|
|
2345
1575
|
});
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
1576
|
+
return () => this.hydrateData(key);
|
|
1577
|
+
}
|
|
1578
|
+
return () => undefined;
|
|
1579
|
+
};
|
|
1580
|
+
hydrateData = key => {
|
|
1581
|
+
if (typeof document !== 'undefined') {
|
|
1582
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
1583
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
1584
|
+
}
|
|
1585
|
+
return undefined;
|
|
1586
|
+
};
|
|
2351
1587
|
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
1588
|
+
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
1589
|
+
// this.state.matches
|
|
1590
|
+
// .find((d) => d.id === matchId)
|
|
1591
|
+
// ?.__promisesByKey[key]?.resolve(value)
|
|
1592
|
+
// }
|
|
1593
|
+
|
|
1594
|
+
#buildRouteTree = routeTree => {
|
|
1595
|
+
this.routeTree = routeTree;
|
|
1596
|
+
this.routesById = {};
|
|
1597
|
+
this.routesByPath = {};
|
|
1598
|
+
this.flatRoutes = [];
|
|
1599
|
+
const recurseRoutes = routes => {
|
|
1600
|
+
routes.forEach((route, i) => {
|
|
1601
|
+
route.init({
|
|
1602
|
+
originalIndex: i,
|
|
1603
|
+
router: this
|
|
2355
1604
|
});
|
|
1605
|
+
const existingRoute = this.routesById[route.id];
|
|
1606
|
+
invariant(!existingRoute, `Duplicate routes found with id: ${String(route.id)}`);
|
|
1607
|
+
this.routesById[route.id] = route;
|
|
1608
|
+
if (!route.isRoot && route.path) {
|
|
1609
|
+
const trimmedFullPath = trimPathRight(route.fullPath);
|
|
1610
|
+
if (!this.routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {
|
|
1611
|
+
this.routesByPath[trimmedFullPath] = route;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
const children = route.children;
|
|
1615
|
+
if (children?.length) {
|
|
1616
|
+
recurseRoutes(children);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
};
|
|
1620
|
+
recurseRoutes([routeTree]);
|
|
1621
|
+
this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
|
|
1622
|
+
const trimmed = trimPath(d.fullPath);
|
|
1623
|
+
const parsed = parsePathname(trimmed);
|
|
1624
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1625
|
+
parsed.shift();
|
|
2356
1626
|
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
2368
|
-
const search = replaceEqualDeep(router.location.search, postFilteredSearch);
|
|
2369
|
-
const searchStr = router.options.stringifySearch(search);
|
|
2370
|
-
let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
|
|
2371
|
-
hash = hash ? "#" + hash : '';
|
|
1627
|
+
const score = parsed.map(d => {
|
|
1628
|
+
if (d.type === 'param') {
|
|
1629
|
+
return 0.5;
|
|
1630
|
+
}
|
|
1631
|
+
if (d.type === 'wildcard') {
|
|
1632
|
+
return 0.25;
|
|
1633
|
+
}
|
|
1634
|
+
return 1;
|
|
1635
|
+
});
|
|
2372
1636
|
return {
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
href: "" + pathname + searchStr + hash,
|
|
2379
|
-
key: dest.key
|
|
1637
|
+
child: d,
|
|
1638
|
+
trimmed,
|
|
1639
|
+
parsed,
|
|
1640
|
+
index: i,
|
|
1641
|
+
score
|
|
2380
1642
|
};
|
|
2381
|
-
},
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
if (
|
|
2388
|
-
|
|
1643
|
+
}).sort((a, b) => {
|
|
1644
|
+
let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
|
|
1645
|
+
if (isIndex !== 0) return isIndex;
|
|
1646
|
+
const length = Math.min(a.score.length, b.score.length);
|
|
1647
|
+
|
|
1648
|
+
// Sort by length of score
|
|
1649
|
+
if (a.score.length !== b.score.length) {
|
|
1650
|
+
return b.score.length - a.score.length;
|
|
2389
1651
|
}
|
|
2390
1652
|
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
1653
|
+
// Sort by min available score
|
|
1654
|
+
for (let i = 0; i < length; i++) {
|
|
1655
|
+
if (a.score[i] !== b.score[i]) {
|
|
1656
|
+
return b.score[i] - a.score[i];
|
|
1657
|
+
}
|
|
2395
1658
|
}
|
|
2396
1659
|
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
}, {
|
|
2403
|
-
id
|
|
2404
|
-
});
|
|
2405
|
-
} else {
|
|
2406
|
-
history.push({
|
|
2407
|
-
pathname: next.pathname,
|
|
2408
|
-
hash: next.hash,
|
|
2409
|
-
search: next.searchStr
|
|
2410
|
-
}, {
|
|
2411
|
-
id
|
|
2412
|
-
});
|
|
1660
|
+
// Sort by min available parsed value
|
|
1661
|
+
for (let i = 0; i < length; i++) {
|
|
1662
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
1663
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
1664
|
+
}
|
|
2413
1665
|
}
|
|
2414
1666
|
|
|
2415
|
-
|
|
2416
|
-
|
|
1667
|
+
// Sort by length of trimmed full path
|
|
1668
|
+
if (a.trimmed !== b.trimmed) {
|
|
1669
|
+
return a.trimmed > b.trimmed ? 1 : -1;
|
|
1670
|
+
}
|
|
2417
1671
|
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
1672
|
+
// Sort by original index
|
|
1673
|
+
return a.index - b.index;
|
|
1674
|
+
}).map((d, i) => {
|
|
1675
|
+
d.child.rank = i;
|
|
1676
|
+
return d.child;
|
|
1677
|
+
});
|
|
1678
|
+
};
|
|
1679
|
+
#parseLocation = previousLocation => {
|
|
1680
|
+
let {
|
|
1681
|
+
pathname,
|
|
1682
|
+
search,
|
|
1683
|
+
hash,
|
|
1684
|
+
state
|
|
1685
|
+
} = this.history.location;
|
|
1686
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1687
|
+
return {
|
|
1688
|
+
pathname: pathname,
|
|
1689
|
+
searchStr: search,
|
|
1690
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1691
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1692
|
+
href: `${pathname}${search}${hash}`,
|
|
1693
|
+
state: state,
|
|
1694
|
+
key: state?.key || '__init__'
|
|
1695
|
+
};
|
|
1696
|
+
};
|
|
1697
|
+
#buildLocation = (dest = {}) => {
|
|
1698
|
+
dest.fromCurrent = dest.fromCurrent ?? dest.to === '';
|
|
1699
|
+
const fromPathname = dest.fromCurrent ? this.state.location.pathname : dest.from ?? this.state.location.pathname;
|
|
1700
|
+
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? ''}`);
|
|
1701
|
+
const fromMatches = this.matchRoutes(this.state.location.pathname, this.state.location.search);
|
|
1702
|
+
const prevParams = {
|
|
1703
|
+
...last(fromMatches)?.params
|
|
1704
|
+
};
|
|
1705
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1706
|
+
if (nextParams) {
|
|
1707
|
+
dest.__matches?.map(d => this.getRoute(d.routeId).options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1708
|
+
nextParams = {
|
|
1709
|
+
...nextParams,
|
|
1710
|
+
...fn(nextParams)
|
|
2421
1711
|
};
|
|
2422
1712
|
});
|
|
2423
|
-
return router.navigationPromise;
|
|
2424
1713
|
}
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
1714
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1715
|
+
const preSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1716
|
+
const postSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1717
|
+
|
|
1718
|
+
// Pre filters first
|
|
1719
|
+
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), this.state.location.search) : this.state.location.search;
|
|
1720
|
+
|
|
1721
|
+
// Then the link/navigate function
|
|
1722
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1723
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1724
|
+
: preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1725
|
+
: {};
|
|
1726
|
+
|
|
1727
|
+
// Then post filters
|
|
1728
|
+
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1729
|
+
const search = replaceEqualDeep(this.state.location.search, postFilteredSearch);
|
|
1730
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1731
|
+
const hash = dest.hash === true ? this.state.location.hash : functionalUpdate(dest.hash, this.state.location.hash);
|
|
1732
|
+
const hashStr = hash ? `#${hash}` : '';
|
|
1733
|
+
const nextState = dest.state === true ? this.state.location.state : functionalUpdate(dest.state, this.state.location.state);
|
|
1734
|
+
return {
|
|
1735
|
+
pathname,
|
|
1736
|
+
search,
|
|
1737
|
+
searchStr,
|
|
1738
|
+
state: nextState,
|
|
1739
|
+
hash,
|
|
1740
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1741
|
+
key: dest.key
|
|
1742
|
+
};
|
|
1743
|
+
};
|
|
1744
|
+
#commitLocation = async location => {
|
|
1745
|
+
const next = this.buildNext(location);
|
|
1746
|
+
const id = '' + Date.now() + Math.random();
|
|
1747
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1748
|
+
let nextAction = 'replace';
|
|
1749
|
+
if (!location.replace) {
|
|
1750
|
+
nextAction = 'push';
|
|
1751
|
+
}
|
|
1752
|
+
const isSameUrl = this.state.location.href === next.href;
|
|
1753
|
+
if (isSameUrl && !next.key) {
|
|
1754
|
+
nextAction = 'replace';
|
|
1755
|
+
}
|
|
1756
|
+
const href = `${next.pathname}${next.searchStr}${next.hash ? `#${next.hash}` : ''}`;
|
|
1757
|
+
this.history[nextAction === 'push' ? 'push' : 'replace'](href, {
|
|
1758
|
+
id,
|
|
1759
|
+
...next.state
|
|
1760
|
+
});
|
|
1761
|
+
return this.latestLoadPromise;
|
|
1762
|
+
};
|
|
1763
|
+
getRouteMatch = id => {
|
|
1764
|
+
return this.state.matchesById[id];
|
|
1765
|
+
};
|
|
1766
|
+
setRouteMatch = (id, updater) => {
|
|
1767
|
+
this.__store.setState(prev => ({
|
|
1768
|
+
...prev,
|
|
1769
|
+
matchesById: {
|
|
1770
|
+
...prev.matchesById,
|
|
1771
|
+
[id]: updater(prev.matchesById[id])
|
|
1772
|
+
}
|
|
1773
|
+
}));
|
|
1774
|
+
};
|
|
1775
|
+
setRouteMatchData = (id, updater, opts) => {
|
|
1776
|
+
const match = this.getRouteMatch(id);
|
|
1777
|
+
if (!match) return;
|
|
1778
|
+
const route = this.getRoute(match.routeId);
|
|
1779
|
+
const updatedAt = opts?.updatedAt ?? Date.now();
|
|
1780
|
+
const preloadInvalidAt = updatedAt + (opts?.maxAge ?? route.options.preloadMaxAge ?? this.options.defaultPreloadMaxAge ?? 5000);
|
|
1781
|
+
const invalidAt = updatedAt + (opts?.maxAge ?? route.options.maxAge ?? this.options.defaultMaxAge ?? Infinity);
|
|
1782
|
+
this.setRouteMatch(id, s => ({
|
|
1783
|
+
...s,
|
|
1784
|
+
error: undefined,
|
|
1785
|
+
status: 'success',
|
|
1786
|
+
isFetching: false,
|
|
1787
|
+
updatedAt: Date.now(),
|
|
1788
|
+
loaderData: functionalUpdate(updater, s.loaderData),
|
|
1789
|
+
preloadInvalidAt,
|
|
1790
|
+
invalidAt
|
|
1791
|
+
}));
|
|
1792
|
+
if (this.state.matches.find(d => d.id === id)) ;
|
|
1793
|
+
};
|
|
1794
|
+
invalidate = async opts => {
|
|
1795
|
+
if (opts?.matchId) {
|
|
1796
|
+
this.setRouteMatch(opts.matchId, s => ({
|
|
1797
|
+
...s,
|
|
1798
|
+
invalid: true
|
|
1799
|
+
}));
|
|
1800
|
+
const matchIndex = this.state.matches.findIndex(d => d.id === opts.matchId);
|
|
1801
|
+
const childMatch = this.state.matches[matchIndex + 1];
|
|
1802
|
+
if (childMatch) {
|
|
1803
|
+
return this.invalidate({
|
|
1804
|
+
matchId: childMatch.id,
|
|
1805
|
+
reload: false
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
} else {
|
|
1809
|
+
this.__store.batch(() => {
|
|
1810
|
+
Object.values(this.state.matchesById).forEach(match => {
|
|
1811
|
+
this.setRouteMatch(match.id, s => ({
|
|
1812
|
+
...s,
|
|
1813
|
+
invalid: true
|
|
1814
|
+
}));
|
|
1815
|
+
});
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
if (opts?.reload ?? true) {
|
|
1819
|
+
return this.reload();
|
|
1820
|
+
}
|
|
1821
|
+
};
|
|
1822
|
+
getIsInvalid = opts => {
|
|
1823
|
+
if (!opts?.matchId) {
|
|
1824
|
+
return !!this.state.matches.find(d => this.getIsInvalid({
|
|
1825
|
+
matchId: d.id,
|
|
1826
|
+
preload: opts?.preload
|
|
1827
|
+
}));
|
|
1828
|
+
}
|
|
1829
|
+
const match = this.getRouteMatch(opts?.matchId);
|
|
1830
|
+
if (!match) {
|
|
1831
|
+
return false;
|
|
1832
|
+
}
|
|
1833
|
+
const now = Date.now();
|
|
1834
|
+
return match.invalid || (opts?.preload ? match.preloadInvalidAt : match.invalidAt) < now;
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
2432
1837
|
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
1838
|
+
// Detect if we're in the DOM
|
|
1839
|
+
const isServer = typeof window === 'undefined' || !window.document.createElement;
|
|
1840
|
+
function getInitialRouterState() {
|
|
1841
|
+
return {
|
|
1842
|
+
status: 'idle',
|
|
1843
|
+
isFetching: false,
|
|
1844
|
+
resolvedLocation: null,
|
|
1845
|
+
location: null,
|
|
1846
|
+
matchesById: {},
|
|
1847
|
+
matchIds: [],
|
|
1848
|
+
pendingMatchIds: [],
|
|
1849
|
+
matches: [],
|
|
1850
|
+
pendingMatches: [],
|
|
1851
|
+
lastUpdated: Date.now()
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function isCtrlEvent(e) {
|
|
1855
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1856
|
+
}
|
|
1857
|
+
function redirect(opts) {
|
|
1858
|
+
opts.isRedirect = true;
|
|
1859
|
+
return opts;
|
|
1860
|
+
}
|
|
1861
|
+
function isRedirect(obj) {
|
|
1862
|
+
return !!obj?.isRedirect;
|
|
1863
|
+
}
|
|
1864
|
+
class SearchParamError extends Error {}
|
|
1865
|
+
class PathParamError extends Error {}
|
|
1866
|
+
function escapeJSON(jsonString) {
|
|
1867
|
+
return jsonString.replace(/\\/g, '\\\\') // Escape backslashes
|
|
1868
|
+
.replace(/'/g, "\\'") // Escape single quotes
|
|
1869
|
+
.replace(/"/g, '\\"'); // Escape double quotes
|
|
1870
|
+
}
|
|
2436
1871
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
1872
|
+
// A function that takes an import() argument which is a function and returns a new function that will
|
|
1873
|
+
// proxy arguments from the caller to the imported function, retaining all type
|
|
1874
|
+
// information along the way
|
|
1875
|
+
function lazyFn(fn, key) {
|
|
1876
|
+
return async (...args) => {
|
|
1877
|
+
const imported = await fn();
|
|
1878
|
+
return imported[key || 'default'](...args);
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
2440
1881
|
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
1882
|
+
exports.PathParamError = PathParamError;
|
|
1883
|
+
exports.RootRoute = RootRoute;
|
|
1884
|
+
exports.Route = Route;
|
|
1885
|
+
exports.Router = Router;
|
|
1886
|
+
exports.RouterContext = RouterContext;
|
|
1887
|
+
exports.SearchParamError = SearchParamError;
|
|
1888
|
+
exports.cleanPath = cleanPath;
|
|
1889
|
+
exports.componentTypes = componentTypes;
|
|
1890
|
+
exports.createBrowserHistory = createBrowserHistory;
|
|
1891
|
+
exports.createHashHistory = createHashHistory;
|
|
1892
|
+
exports.createMemoryHistory = createMemoryHistory;
|
|
1893
|
+
exports.decode = decode;
|
|
1894
|
+
exports.defaultParseSearch = defaultParseSearch;
|
|
1895
|
+
exports.defaultStringifySearch = defaultStringifySearch;
|
|
1896
|
+
exports.encode = encode;
|
|
1897
|
+
exports.functionalUpdate = functionalUpdate;
|
|
1898
|
+
exports.interpolatePath = interpolatePath;
|
|
1899
|
+
exports.invariant = invariant;
|
|
1900
|
+
exports.isPlainObject = isPlainObject;
|
|
1901
|
+
exports.isRedirect = isRedirect;
|
|
1902
|
+
exports.joinPaths = joinPaths;
|
|
1903
|
+
exports.last = last;
|
|
1904
|
+
exports.lazyFn = lazyFn;
|
|
1905
|
+
exports.matchByPath = matchByPath;
|
|
1906
|
+
exports.matchPathname = matchPathname;
|
|
1907
|
+
exports.parsePathname = parsePathname;
|
|
1908
|
+
exports.parseSearchWith = parseSearchWith;
|
|
1909
|
+
exports.partialDeepEqual = partialDeepEqual;
|
|
1910
|
+
exports.pick = pick;
|
|
1911
|
+
exports.redirect = redirect;
|
|
1912
|
+
exports.replaceEqualDeep = replaceEqualDeep;
|
|
1913
|
+
exports.resolvePath = resolvePath;
|
|
1914
|
+
exports.rootRouteId = rootRouteId;
|
|
1915
|
+
exports.stringifySearchWith = stringifySearchWith;
|
|
1916
|
+
exports.trimPath = trimPath;
|
|
1917
|
+
exports.trimPathLeft = trimPathLeft;
|
|
1918
|
+
exports.trimPathRight = trimPathRight;
|
|
1919
|
+
exports.warning = warning;
|
|
1920
|
+
|
|
1921
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2479
1922
|
|
|
2480
1923
|
}));
|
|
2481
1924
|
//# sourceMappingURL=index.development.js.map
|