@tanstack/react-router 0.0.1-beta.223 → 0.0.1-beta.224
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/RouterProvider.js +56 -958
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/fileRoute.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +953 -39
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/scroll-restoration.js +5 -9
- package/build/cjs/scroll-restoration.js.map +1 -1
- package/build/esm/index.js +887 -884
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +369 -363
- package/build/types/RouterProvider.d.ts +3 -22
- package/build/types/fileRoute.d.ts +2 -2
- package/build/types/route.d.ts +1 -0
- package/build/types/router.d.ts +50 -5
- package/build/umd/index.development.js +887 -884
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +2 -2
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/RouterProvider.tsx +57 -1314
- package/src/fileRoute.ts +1 -1
- package/src/route.ts +22 -0
- package/src/router.ts +1320 -45
- package/src/scroll-restoration.tsx +5 -5
|
@@ -1106,274 +1106,34 @@
|
|
|
1106
1106
|
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
1107
1107
|
}
|
|
1108
1108
|
|
|
1109
|
-
//
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
//
|
|
1120
|
-
|
|
1121
|
-
//
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1134
|
-
}
|
|
1135
|
-
} else {
|
|
1136
|
-
str && (str += '&');
|
|
1137
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return (pfx || '') + str;
|
|
1142
|
-
}
|
|
1143
|
-
function toValue(mix) {
|
|
1144
|
-
if (!mix) return '';
|
|
1145
|
-
var str = decodeURIComponent(mix);
|
|
1146
|
-
if (str === 'false') return false;
|
|
1147
|
-
if (str === 'true') return true;
|
|
1148
|
-
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
1149
|
-
}
|
|
1150
|
-
function decode(str) {
|
|
1151
|
-
var tmp,
|
|
1152
|
-
k,
|
|
1153
|
-
out = {},
|
|
1154
|
-
arr = str.split('&');
|
|
1155
|
-
while (tmp = arr.shift()) {
|
|
1156
|
-
tmp = tmp.split('=');
|
|
1157
|
-
k = tmp.shift();
|
|
1158
|
-
if (out[k] !== void 0) {
|
|
1159
|
-
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1160
|
-
} else {
|
|
1161
|
-
out[k] = toValue(tmp.shift());
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
return out;
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1168
|
-
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
1169
|
-
function parseSearchWith(parser) {
|
|
1170
|
-
return searchStr => {
|
|
1171
|
-
if (searchStr.substring(0, 1) === '?') {
|
|
1172
|
-
searchStr = searchStr.substring(1);
|
|
1173
|
-
}
|
|
1174
|
-
let query = decode(searchStr);
|
|
1175
|
-
|
|
1176
|
-
// Try to parse any query params that might be json
|
|
1177
|
-
for (let key in query) {
|
|
1178
|
-
const value = query[key];
|
|
1179
|
-
if (typeof value === 'string') {
|
|
1180
|
-
try {
|
|
1181
|
-
query[key] = parser(value);
|
|
1182
|
-
} catch (err) {
|
|
1183
|
-
//
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
return query;
|
|
1188
|
-
};
|
|
1189
|
-
}
|
|
1190
|
-
function stringifySearchWith(stringify, parser) {
|
|
1191
|
-
function stringifyValue(val) {
|
|
1192
|
-
if (typeof val === 'object' && val !== null) {
|
|
1193
|
-
try {
|
|
1194
|
-
return stringify(val);
|
|
1195
|
-
} catch (err) {
|
|
1196
|
-
// silent
|
|
1197
|
-
}
|
|
1198
|
-
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
1199
|
-
try {
|
|
1200
|
-
// Check if it's a valid parseable string.
|
|
1201
|
-
// If it is, then stringify it again.
|
|
1202
|
-
parser(val);
|
|
1203
|
-
return stringify(val);
|
|
1204
|
-
} catch (err) {
|
|
1205
|
-
// silent
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
return val;
|
|
1209
|
-
}
|
|
1210
|
-
return search => {
|
|
1211
|
-
search = {
|
|
1212
|
-
...search
|
|
1213
|
-
};
|
|
1214
|
-
if (search) {
|
|
1215
|
-
Object.keys(search).forEach(key => {
|
|
1216
|
-
const val = search[key];
|
|
1217
|
-
if (typeof val === 'undefined' || val === undefined) {
|
|
1218
|
-
delete search[key];
|
|
1219
|
-
} else {
|
|
1220
|
-
search[key] = stringifyValue(val);
|
|
1221
|
-
}
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
const searchStr = encode(search).toString();
|
|
1225
|
-
return searchStr ? `?${searchStr}` : '';
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
//
|
|
1230
|
-
|
|
1231
|
-
//
|
|
1232
|
-
|
|
1233
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1234
|
-
class Router {
|
|
1235
|
-
// dehydratedData?: TDehydrated
|
|
1236
|
-
// resetNextScroll = false
|
|
1237
|
-
// tempLocationKey = `${Math.round(Math.random() * 10000000)}`
|
|
1238
|
-
constructor(options) {
|
|
1239
|
-
this.options = {
|
|
1240
|
-
defaultPreloadDelay: 50,
|
|
1241
|
-
context: undefined,
|
|
1242
|
-
...options,
|
|
1243
|
-
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
1244
|
-
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
1245
|
-
};
|
|
1246
|
-
this.routeTree = this.options.routeTree;
|
|
1247
|
-
}
|
|
1248
|
-
subscribers = new Set();
|
|
1249
|
-
subscribe = (eventType, fn) => {
|
|
1250
|
-
const listener = {
|
|
1251
|
-
eventType,
|
|
1252
|
-
fn
|
|
1253
|
-
};
|
|
1254
|
-
this.subscribers.add(listener);
|
|
1255
|
-
return () => {
|
|
1256
|
-
this.subscribers.delete(listener);
|
|
1257
|
-
};
|
|
1258
|
-
};
|
|
1259
|
-
emit = routerEvent => {
|
|
1260
|
-
this.subscribers.forEach(listener => {
|
|
1261
|
-
if (listener.eventType === routerEvent.type) {
|
|
1262
|
-
listener.fn(routerEvent);
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1265
|
-
};
|
|
1266
|
-
|
|
1267
|
-
// dehydrate = (): DehydratedRouter => {
|
|
1268
|
-
// return {
|
|
1269
|
-
// state: {
|
|
1270
|
-
// dehydratedMatches: state.matches.map((d) =>
|
|
1271
|
-
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
1272
|
-
// ),
|
|
1273
|
-
// },
|
|
1274
|
-
// }
|
|
1275
|
-
// }
|
|
1276
|
-
|
|
1277
|
-
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
1278
|
-
// let _ctx = __do_not_use_server_ctx
|
|
1279
|
-
// // Client hydrates from window
|
|
1280
|
-
// if (typeof document !== 'undefined') {
|
|
1281
|
-
// _ctx = window.__TSR_DEHYDRATED__
|
|
1282
|
-
// }
|
|
1283
|
-
|
|
1284
|
-
// invariant(
|
|
1285
|
-
// _ctx,
|
|
1286
|
-
// 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
|
|
1287
|
-
// )
|
|
1288
|
-
|
|
1289
|
-
// const ctx = _ctx
|
|
1290
|
-
// this.dehydratedData = ctx.payload as any
|
|
1291
|
-
// this.options.hydrate?.(ctx.payload as any)
|
|
1292
|
-
// const dehydratedState = ctx.router.state
|
|
1293
|
-
|
|
1294
|
-
// let matches = this.matchRoutes(
|
|
1295
|
-
// state.location.pathname,
|
|
1296
|
-
// state.location.search,
|
|
1297
|
-
// ).map((match) => {
|
|
1298
|
-
// const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
1299
|
-
// (d) => d.id === match.id,
|
|
1300
|
-
// )
|
|
1301
|
-
|
|
1302
|
-
// invariant(
|
|
1303
|
-
// dehydratedMatch,
|
|
1304
|
-
// `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
1305
|
-
// )
|
|
1306
|
-
|
|
1307
|
-
// if (dehydratedMatch) {
|
|
1308
|
-
// return {
|
|
1309
|
-
// ...match,
|
|
1310
|
-
// ...dehydratedMatch,
|
|
1311
|
-
// }
|
|
1312
|
-
// }
|
|
1313
|
-
// return match
|
|
1314
|
-
// })
|
|
1315
|
-
|
|
1316
|
-
// this.setState((s) => {
|
|
1317
|
-
// return {
|
|
1318
|
-
// ...s,
|
|
1319
|
-
// matches: dehydratedState.dehydratedMatches as any,
|
|
1320
|
-
// }
|
|
1321
|
-
// })
|
|
1322
|
-
// }
|
|
1323
|
-
|
|
1324
|
-
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
1325
|
-
// state.matches
|
|
1326
|
-
// .find((d) => d.id === matchId)
|
|
1327
|
-
// ?.__promisesByKey[key]?.resolve(value)
|
|
1328
|
-
// }
|
|
1329
|
-
|
|
1330
|
-
// setRouteMatch = (
|
|
1331
|
-
// id: string,
|
|
1332
|
-
// pending: boolean,
|
|
1333
|
-
// updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
|
|
1334
|
-
// ) => {
|
|
1335
|
-
// const key = pending ? 'pendingMatches' : 'matches'
|
|
1336
|
-
|
|
1337
|
-
// this.setState((prev) => {
|
|
1338
|
-
// return {
|
|
1339
|
-
// ...prev,
|
|
1340
|
-
// [key]: prev[key].map((d) => {
|
|
1341
|
-
// if (d.id === id) {
|
|
1342
|
-
// return functionalUpdate(updater, d)
|
|
1343
|
-
// }
|
|
1344
|
-
|
|
1345
|
-
// return d
|
|
1346
|
-
// }),
|
|
1347
|
-
// }
|
|
1348
|
-
// })
|
|
1349
|
-
// }
|
|
1350
|
-
|
|
1351
|
-
// setPendingRouteMatch = (
|
|
1352
|
-
// id: string,
|
|
1353
|
-
// updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
|
|
1354
|
-
// ) => {
|
|
1355
|
-
// this.setRouteMatch(id, true, updater)
|
|
1356
|
-
// }
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
// A function that takes an import() argument which is a function and returns a new function that will
|
|
1360
|
-
// proxy arguments from the caller to the imported function, retaining all type
|
|
1361
|
-
// information along the way
|
|
1362
|
-
function lazyFn(fn, key) {
|
|
1363
|
-
return async (...args) => {
|
|
1364
|
-
const imported = await fn();
|
|
1365
|
-
return imported[key || 'default'](...args);
|
|
1366
|
-
};
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1109
|
+
// export type RouterContext<
|
|
1110
|
+
// TRouteTree extends AnyRoute,
|
|
1111
|
+
// // TDehydrated extends Record<string, any>,
|
|
1112
|
+
// > = {
|
|
1113
|
+
// buildLink: BuildLinkFn<TRouteTree>
|
|
1114
|
+
// state: RouterState<TRouteTree>
|
|
1115
|
+
// navigate: NavigateFn<TRouteTree>
|
|
1116
|
+
// matchRoute: MatchRouteFn<TRouteTree>
|
|
1117
|
+
// routeTree: TRouteTree
|
|
1118
|
+
// routesById: RoutesById<TRouteTree>
|
|
1119
|
+
// options: RouterOptions<TRouteTree>
|
|
1120
|
+
// history: RouterHistory
|
|
1121
|
+
// load: LoadFn
|
|
1122
|
+
// buildLocation: BuildLocationFn<TRouteTree>
|
|
1123
|
+
// subscribe: Router<TRouteTree>['subscribe']
|
|
1124
|
+
// resetNextScrollRef: React.MutableRefObject<boolean>
|
|
1125
|
+
// injectedHtmlRef: React.MutableRefObject<InjectedHtmlEntry[]>
|
|
1126
|
+
// injectHtml: (entry: InjectedHtmlEntry) => void
|
|
1127
|
+
// dehydrateData: <T>(
|
|
1128
|
+
// key: any,
|
|
1129
|
+
// getData: T | (() => Promise<T> | T),
|
|
1130
|
+
// ) => () => void
|
|
1131
|
+
// hydrateData: <T>(key: any) => T | undefined
|
|
1132
|
+
// }
|
|
1369
1133
|
const routerContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
1370
1134
|
if (typeof document !== 'undefined') {
|
|
1371
1135
|
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
1372
1136
|
}
|
|
1373
|
-
const preloadWarning = 'Error preloading route! ☝️';
|
|
1374
|
-
function isCtrlEvent(e) {
|
|
1375
|
-
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1376
|
-
}
|
|
1377
1137
|
class SearchParamError extends Error {}
|
|
1378
1138
|
class PathParamError extends Error {}
|
|
1379
1139
|
function getInitialRouterState(location) {
|
|
@@ -1390,66 +1150,55 @@
|
|
|
1390
1150
|
router,
|
|
1391
1151
|
...rest
|
|
1392
1152
|
}) {
|
|
1393
|
-
|
|
1153
|
+
// Allow the router to update options on the router instance
|
|
1154
|
+
router.updateOptions({
|
|
1394
1155
|
...router.options,
|
|
1395
1156
|
...rest,
|
|
1396
1157
|
context: {
|
|
1397
1158
|
...router.options.context,
|
|
1398
1159
|
...rest?.context
|
|
1399
1160
|
}
|
|
1400
|
-
};
|
|
1401
|
-
const history = React__namespace.useState(() => options.history ?? createBrowserHistory())[0];
|
|
1402
|
-
const tempLocationKeyRef = React__namespace.useRef(`${Math.round(Math.random() * 10000000)}`);
|
|
1403
|
-
const resetNextScrollRef = React__namespace.useRef(true);
|
|
1404
|
-
const navigateTimeoutRef = React__namespace.useRef(null);
|
|
1405
|
-
const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
|
|
1406
|
-
const checkLatest = promise => {
|
|
1407
|
-
return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
|
|
1408
|
-
};
|
|
1409
|
-
const parseLocation = useStableCallback(previousLocation => {
|
|
1410
|
-
const parse = ({
|
|
1411
|
-
pathname,
|
|
1412
|
-
search,
|
|
1413
|
-
hash,
|
|
1414
|
-
state
|
|
1415
|
-
}) => {
|
|
1416
|
-
const parsedSearch = options.parseSearch(search);
|
|
1417
|
-
return {
|
|
1418
|
-
pathname: pathname,
|
|
1419
|
-
searchStr: search,
|
|
1420
|
-
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1421
|
-
hash: hash.split('#').reverse()[0] ?? '',
|
|
1422
|
-
href: `${pathname}${search}${hash}`,
|
|
1423
|
-
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1424
|
-
};
|
|
1425
|
-
};
|
|
1426
|
-
const location = parse(history.location);
|
|
1427
|
-
let {
|
|
1428
|
-
__tempLocation,
|
|
1429
|
-
__tempKey
|
|
1430
|
-
} = location.state;
|
|
1431
|
-
if (__tempLocation && (!__tempKey || __tempKey === tempLocationKeyRef.current)) {
|
|
1432
|
-
// Sync up the location keys
|
|
1433
|
-
const parsedTempLocation = parse(__tempLocation);
|
|
1434
|
-
parsedTempLocation.state.key = location.state.key;
|
|
1435
|
-
delete parsedTempLocation.state.__tempLocation;
|
|
1436
|
-
return {
|
|
1437
|
-
...parsedTempLocation,
|
|
1438
|
-
maskedLocation: location
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
return location;
|
|
1442
1161
|
});
|
|
1443
|
-
const
|
|
1444
|
-
const [preState, setState] = React__namespace.useState(() => getInitialRouterState(latestLocationRef.current));
|
|
1162
|
+
const [preState, setState] = React__namespace.useState(() => router.state);
|
|
1445
1163
|
const [isTransitioning, startReactTransition] = React__namespace.useTransition();
|
|
1446
|
-
const pendingMatchesRef = React__namespace.useRef([]);
|
|
1447
1164
|
const state = React__namespace.useMemo(() => ({
|
|
1448
1165
|
...preState,
|
|
1449
1166
|
status: isTransitioning ? 'pending' : 'idle',
|
|
1450
|
-
location: isTransitioning ?
|
|
1451
|
-
pendingMatches:
|
|
1167
|
+
location: isTransitioning ? router.latestLocation : preState.location,
|
|
1168
|
+
pendingMatches: router.pendingMatches
|
|
1452
1169
|
}), [preState, isTransitioning]);
|
|
1170
|
+
router.setState = setState;
|
|
1171
|
+
router.state = state;
|
|
1172
|
+
router.startReactTransition = startReactTransition;
|
|
1173
|
+
React__namespace.useLayoutEffect(() => {
|
|
1174
|
+
const unsub = router.history.subscribe(() => {
|
|
1175
|
+
router.latestLocation = router.parseLocation(router.latestLocation);
|
|
1176
|
+
if (state.location !== router.latestLocation) {
|
|
1177
|
+
startReactTransition(() => {
|
|
1178
|
+
try {
|
|
1179
|
+
router.load();
|
|
1180
|
+
} catch (err) {
|
|
1181
|
+
console.error(err);
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
const nextLocation = router.buildLocation({
|
|
1187
|
+
search: true,
|
|
1188
|
+
params: true,
|
|
1189
|
+
hash: true,
|
|
1190
|
+
state: true
|
|
1191
|
+
});
|
|
1192
|
+
if (state.location.href !== nextLocation.href) {
|
|
1193
|
+
router.commitLocation({
|
|
1194
|
+
...nextLocation,
|
|
1195
|
+
replace: true
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
return () => {
|
|
1199
|
+
unsub();
|
|
1200
|
+
};
|
|
1201
|
+
}, [history]);
|
|
1453
1202
|
React__namespace.useLayoutEffect(() => {
|
|
1454
1203
|
if (!isTransitioning && state.resolvedLocation !== state.location) {
|
|
1455
1204
|
router.emit({
|
|
@@ -1458,135 +1207,592 @@
|
|
|
1458
1207
|
toLocation: state.location,
|
|
1459
1208
|
pathChanged: state.location.href !== state.resolvedLocation?.href
|
|
1460
1209
|
});
|
|
1461
|
-
|
|
1210
|
+
router.pendingMatches = [];
|
|
1462
1211
|
setState(s => ({
|
|
1463
1212
|
...s,
|
|
1464
1213
|
resolvedLocation: s.location
|
|
1465
1214
|
}));
|
|
1466
1215
|
}
|
|
1467
1216
|
});
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
const routesByPath = {};
|
|
1475
|
-
const recurseRoutes = routes => {
|
|
1476
|
-
routes.forEach((route, i) => {
|
|
1477
|
-
route.init({
|
|
1478
|
-
originalIndex: i
|
|
1479
|
-
});
|
|
1480
|
-
const existingRoute = routesById[route.id];
|
|
1481
|
-
invariant(!existingRoute, `Duplicate routes found with id: ${String(route.id)}`);
|
|
1482
|
-
routesById[route.id] = route;
|
|
1483
|
-
if (!route.isRoot && route.path) {
|
|
1484
|
-
const trimmedFullPath = trimPathRight(route.fullPath);
|
|
1485
|
-
if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {
|
|
1486
|
-
routesByPath[trimmedFullPath] = route;
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
const children = route.children;
|
|
1490
|
-
if (children?.length) {
|
|
1491
|
-
recurseRoutes(children);
|
|
1492
|
-
}
|
|
1493
|
-
});
|
|
1494
|
-
};
|
|
1495
|
-
recurseRoutes([router.routeTree]);
|
|
1496
|
-
return [routesById, routesByPath];
|
|
1497
|
-
}, []);
|
|
1498
|
-
const looseRoutesById = routesById;
|
|
1499
|
-
const flatRoutes = React__namespace.useMemo(() => Object.values(routesByPath).map((d, i) => {
|
|
1500
|
-
const trimmed = trimPath(d.fullPath);
|
|
1501
|
-
const parsed = parsePathname(trimmed);
|
|
1502
|
-
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1503
|
-
parsed.shift();
|
|
1504
|
-
}
|
|
1505
|
-
const score = parsed.map(d => {
|
|
1506
|
-
if (d.type === 'param') {
|
|
1507
|
-
return 0.5;
|
|
1508
|
-
}
|
|
1509
|
-
if (d.type === 'wildcard') {
|
|
1510
|
-
return 0.25;
|
|
1217
|
+
React__namespace.useLayoutEffect(() => {
|
|
1218
|
+
startReactTransition(() => {
|
|
1219
|
+
try {
|
|
1220
|
+
router.load();
|
|
1221
|
+
} catch (err) {
|
|
1222
|
+
console.error(err);
|
|
1511
1223
|
}
|
|
1512
|
-
return 1;
|
|
1513
1224
|
});
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1225
|
+
}, []);
|
|
1226
|
+
return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
|
|
1227
|
+
value: router
|
|
1228
|
+
}, /*#__PURE__*/React__namespace.createElement(Matches, null));
|
|
1229
|
+
}
|
|
1230
|
+
function getRouteMatch(state, id) {
|
|
1231
|
+
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
1232
|
+
}
|
|
1233
|
+
function useRouterState(opts) {
|
|
1234
|
+
const {
|
|
1235
|
+
state
|
|
1236
|
+
} = useRouter();
|
|
1237
|
+
// return useStore(router.__store, opts?.select as any)
|
|
1238
|
+
return opts?.select ? opts.select(state) : state;
|
|
1239
|
+
}
|
|
1240
|
+
function useRouter() {
|
|
1241
|
+
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
1242
|
+
const value = React__namespace.useContext(resolvedContext);
|
|
1243
|
+
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
1244
|
+
return value;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
function defer(_promise) {
|
|
1248
|
+
const promise = _promise;
|
|
1249
|
+
if (!promise.__deferredState) {
|
|
1250
|
+
promise.__deferredState = {
|
|
1251
|
+
uid: Math.random().toString(36).slice(2),
|
|
1252
|
+
status: 'pending'
|
|
1520
1253
|
};
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1254
|
+
const state = promise.__deferredState;
|
|
1255
|
+
promise.then(data => {
|
|
1256
|
+
state.status = 'success';
|
|
1257
|
+
state.data = data;
|
|
1258
|
+
}).catch(error => {
|
|
1259
|
+
state.status = 'error';
|
|
1260
|
+
state.error = error;
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
return promise;
|
|
1264
|
+
}
|
|
1265
|
+
function isDehydratedDeferred(obj) {
|
|
1266
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
1267
|
+
}
|
|
1530
1268
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1269
|
+
function useAwaited({
|
|
1270
|
+
promise
|
|
1271
|
+
}) {
|
|
1272
|
+
const router = useRouter();
|
|
1273
|
+
let state = promise.__deferredState;
|
|
1274
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
1275
|
+
if (isDehydratedDeferred(promise)) {
|
|
1276
|
+
state = router.hydrateData(key);
|
|
1277
|
+
promise = Promise.resolve(state.data);
|
|
1278
|
+
promise.__deferredState = state;
|
|
1279
|
+
}
|
|
1280
|
+
if (state.status === 'pending') {
|
|
1281
|
+
throw promise;
|
|
1282
|
+
}
|
|
1283
|
+
if (state.status === 'error') {
|
|
1284
|
+
throw state.error;
|
|
1285
|
+
}
|
|
1286
|
+
router.dehydrateData(key, state);
|
|
1287
|
+
return [state.data];
|
|
1288
|
+
}
|
|
1289
|
+
function Await(props) {
|
|
1290
|
+
const awaited = useAwaited(props);
|
|
1291
|
+
return props.children(...awaited);
|
|
1292
|
+
}
|
|
1537
1293
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1294
|
+
class FileRoute {
|
|
1295
|
+
constructor(path) {
|
|
1296
|
+
this.path = path;
|
|
1297
|
+
}
|
|
1298
|
+
createRoute = options => {
|
|
1299
|
+
const route = new Route(options);
|
|
1300
|
+
route.isRoot = false;
|
|
1301
|
+
return route;
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1544
1304
|
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1305
|
+
function lazyRouteComponent(importer, exportName) {
|
|
1306
|
+
let loadPromise;
|
|
1307
|
+
const load = () => {
|
|
1308
|
+
if (!loadPromise) {
|
|
1309
|
+
loadPromise = importer();
|
|
1548
1310
|
}
|
|
1311
|
+
return loadPromise;
|
|
1312
|
+
};
|
|
1313
|
+
const lazyComp = /*#__PURE__*/React__namespace.lazy(async () => {
|
|
1314
|
+
const moduleExports = await load();
|
|
1315
|
+
const comp = moduleExports[exportName ?? 'default'];
|
|
1316
|
+
return {
|
|
1317
|
+
default: comp
|
|
1318
|
+
};
|
|
1319
|
+
});
|
|
1320
|
+
lazyComp.preload = load;
|
|
1321
|
+
return lazyComp;
|
|
1322
|
+
}
|
|
1549
1323
|
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
let foundRoute = flatRoutes.find(route => {
|
|
1559
|
-
const matchedParams = matchPathname(basepath, trimPathRight(pathname), {
|
|
1560
|
-
to: route.fullPath,
|
|
1561
|
-
caseSensitive: route.options.caseSensitive ?? options.caseSensitive,
|
|
1562
|
-
fuzzy: false
|
|
1563
|
-
});
|
|
1564
|
-
if (matchedParams) {
|
|
1565
|
-
routeParams = matchedParams;
|
|
1566
|
-
return true;
|
|
1324
|
+
function _extends() {
|
|
1325
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
1326
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1327
|
+
var source = arguments[i];
|
|
1328
|
+
for (var key in source) {
|
|
1329
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1330
|
+
target[key] = source[key];
|
|
1331
|
+
}
|
|
1567
1332
|
}
|
|
1568
|
-
return false;
|
|
1569
|
-
});
|
|
1570
|
-
let routeCursor = foundRoute || routesById['__root__'];
|
|
1571
|
-
let matchedRoutes = [routeCursor];
|
|
1572
|
-
// let includingLayouts = true
|
|
1573
|
-
while (routeCursor?.parentRoute) {
|
|
1574
|
-
routeCursor = routeCursor.parentRoute;
|
|
1575
|
-
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1576
1333
|
}
|
|
1334
|
+
return target;
|
|
1335
|
+
};
|
|
1336
|
+
return _extends.apply(this, arguments);
|
|
1337
|
+
}
|
|
1577
1338
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1339
|
+
function useLinkProps(options) {
|
|
1340
|
+
const {
|
|
1341
|
+
buildLink
|
|
1342
|
+
} = useRouter();
|
|
1343
|
+
const match = useMatch({
|
|
1344
|
+
strict: false
|
|
1345
|
+
});
|
|
1346
|
+
const {
|
|
1347
|
+
// custom props
|
|
1348
|
+
type,
|
|
1349
|
+
children,
|
|
1350
|
+
target,
|
|
1351
|
+
activeProps = () => ({
|
|
1352
|
+
className: 'active'
|
|
1353
|
+
}),
|
|
1354
|
+
inactiveProps = () => ({}),
|
|
1355
|
+
activeOptions,
|
|
1356
|
+
disabled,
|
|
1357
|
+
hash,
|
|
1358
|
+
search,
|
|
1359
|
+
params,
|
|
1360
|
+
to,
|
|
1361
|
+
state,
|
|
1362
|
+
mask,
|
|
1363
|
+
preload,
|
|
1364
|
+
preloadDelay,
|
|
1365
|
+
replace,
|
|
1366
|
+
startTransition,
|
|
1367
|
+
resetScroll,
|
|
1368
|
+
// element props
|
|
1369
|
+
style,
|
|
1370
|
+
className,
|
|
1371
|
+
onClick,
|
|
1372
|
+
onFocus,
|
|
1373
|
+
onMouseEnter,
|
|
1374
|
+
onMouseLeave,
|
|
1375
|
+
onTouchStart,
|
|
1376
|
+
...rest
|
|
1377
|
+
} = options;
|
|
1378
|
+
const linkInfo = buildLink({
|
|
1379
|
+
from: options.to ? match.pathname : undefined,
|
|
1380
|
+
...options
|
|
1381
|
+
});
|
|
1382
|
+
if (linkInfo.type === 'external') {
|
|
1383
|
+
const {
|
|
1384
|
+
href
|
|
1385
|
+
} = linkInfo;
|
|
1386
|
+
return {
|
|
1387
|
+
href
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
const {
|
|
1391
|
+
handleClick,
|
|
1392
|
+
handleFocus,
|
|
1393
|
+
handleEnter,
|
|
1394
|
+
handleLeave,
|
|
1395
|
+
handleTouchStart,
|
|
1396
|
+
isActive,
|
|
1397
|
+
next
|
|
1398
|
+
} = linkInfo;
|
|
1399
|
+
const composeHandlers = handlers => e => {
|
|
1400
|
+
if (e.persist) e.persist();
|
|
1401
|
+
handlers.filter(Boolean).forEach(handler => {
|
|
1402
|
+
if (e.defaultPrevented) return;
|
|
1403
|
+
handler(e);
|
|
1404
|
+
});
|
|
1405
|
+
};
|
|
1580
1406
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1407
|
+
// Get the active props
|
|
1408
|
+
const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
|
|
1409
|
+
|
|
1410
|
+
// Get the inactive props
|
|
1411
|
+
const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
|
|
1412
|
+
return {
|
|
1413
|
+
...resolvedActiveProps,
|
|
1414
|
+
...resolvedInactiveProps,
|
|
1415
|
+
...rest,
|
|
1416
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
1417
|
+
onClick: composeHandlers([onClick, handleClick]),
|
|
1418
|
+
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
1419
|
+
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
1420
|
+
onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
|
|
1421
|
+
onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
|
|
1422
|
+
target,
|
|
1423
|
+
style: {
|
|
1424
|
+
...style,
|
|
1425
|
+
...resolvedActiveProps.style,
|
|
1426
|
+
...resolvedInactiveProps.style
|
|
1427
|
+
},
|
|
1428
|
+
className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
|
|
1429
|
+
...(disabled ? {
|
|
1430
|
+
role: 'link',
|
|
1431
|
+
'aria-disabled': true
|
|
1432
|
+
} : undefined),
|
|
1433
|
+
['data-status']: isActive ? 'active' : undefined
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
const Link = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
1437
|
+
const linkProps = useLinkProps(props);
|
|
1438
|
+
return /*#__PURE__*/React__namespace.createElement("a", _extends({
|
|
1439
|
+
ref: ref
|
|
1440
|
+
}, linkProps, {
|
|
1441
|
+
children: typeof props.children === 'function' ? props.children({
|
|
1442
|
+
isActive: linkProps['data-status'] === 'active'
|
|
1443
|
+
}) : props.children
|
|
1444
|
+
}));
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1447
|
+
// @ts-nocheck
|
|
1448
|
+
|
|
1449
|
+
// 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.
|
|
1450
|
+
|
|
1451
|
+
function encode(obj, pfx) {
|
|
1452
|
+
var k,
|
|
1453
|
+
i,
|
|
1454
|
+
tmp,
|
|
1455
|
+
str = '';
|
|
1456
|
+
for (k in obj) {
|
|
1457
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
1458
|
+
if (Array.isArray(tmp)) {
|
|
1459
|
+
for (i = 0; i < tmp.length; i++) {
|
|
1460
|
+
str && (str += '&');
|
|
1461
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1462
|
+
}
|
|
1463
|
+
} else {
|
|
1464
|
+
str && (str += '&');
|
|
1465
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return (pfx || '') + str;
|
|
1470
|
+
}
|
|
1471
|
+
function toValue(mix) {
|
|
1472
|
+
if (!mix) return '';
|
|
1473
|
+
var str = decodeURIComponent(mix);
|
|
1474
|
+
if (str === 'false') return false;
|
|
1475
|
+
if (str === 'true') return true;
|
|
1476
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
1477
|
+
}
|
|
1478
|
+
function decode(str) {
|
|
1479
|
+
var tmp,
|
|
1480
|
+
k,
|
|
1481
|
+
out = {},
|
|
1482
|
+
arr = str.split('&');
|
|
1483
|
+
while (tmp = arr.shift()) {
|
|
1484
|
+
tmp = tmp.split('=');
|
|
1485
|
+
k = tmp.shift();
|
|
1486
|
+
if (out[k] !== void 0) {
|
|
1487
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1488
|
+
} else {
|
|
1489
|
+
out[k] = toValue(tmp.shift());
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return out;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
// Detect if we're in the DOM
|
|
1496
|
+
|
|
1497
|
+
function redirect(opts) {
|
|
1498
|
+
opts.isRedirect = true;
|
|
1499
|
+
return opts;
|
|
1500
|
+
}
|
|
1501
|
+
function isRedirect(obj) {
|
|
1502
|
+
return !!obj?.isRedirect;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1506
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
1507
|
+
function parseSearchWith(parser) {
|
|
1508
|
+
return searchStr => {
|
|
1509
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
1510
|
+
searchStr = searchStr.substring(1);
|
|
1511
|
+
}
|
|
1512
|
+
let query = decode(searchStr);
|
|
1513
|
+
|
|
1514
|
+
// Try to parse any query params that might be json
|
|
1515
|
+
for (let key in query) {
|
|
1516
|
+
const value = query[key];
|
|
1517
|
+
if (typeof value === 'string') {
|
|
1518
|
+
try {
|
|
1519
|
+
query[key] = parser(value);
|
|
1520
|
+
} catch (err) {
|
|
1521
|
+
//
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
return query;
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
function stringifySearchWith(stringify, parser) {
|
|
1529
|
+
function stringifyValue(val) {
|
|
1530
|
+
if (typeof val === 'object' && val !== null) {
|
|
1531
|
+
try {
|
|
1532
|
+
return stringify(val);
|
|
1533
|
+
} catch (err) {
|
|
1534
|
+
// silent
|
|
1535
|
+
}
|
|
1536
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
1537
|
+
try {
|
|
1538
|
+
// Check if it's a valid parseable string.
|
|
1539
|
+
// If it is, then stringify it again.
|
|
1540
|
+
parser(val);
|
|
1541
|
+
return stringify(val);
|
|
1542
|
+
} catch (err) {
|
|
1543
|
+
// silent
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
return val;
|
|
1547
|
+
}
|
|
1548
|
+
return search => {
|
|
1549
|
+
search = {
|
|
1550
|
+
...search
|
|
1551
|
+
};
|
|
1552
|
+
if (search) {
|
|
1553
|
+
Object.keys(search).forEach(key => {
|
|
1554
|
+
const val = search[key];
|
|
1555
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
1556
|
+
delete search[key];
|
|
1557
|
+
} else {
|
|
1558
|
+
search[key] = stringifyValue(val);
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
const searchStr = encode(search).toString();
|
|
1563
|
+
return searchStr ? `?${searchStr}` : '';
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
//
|
|
1568
|
+
|
|
1569
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1570
|
+
const preloadWarning = 'Error preloading route! ☝️';
|
|
1571
|
+
class Router {
|
|
1572
|
+
// Option-independent properties
|
|
1573
|
+
tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
|
|
1574
|
+
resetNextScroll = true;
|
|
1575
|
+
navigateTimeout = null;
|
|
1576
|
+
latestLoadPromise = Promise.resolve();
|
|
1577
|
+
subscribers = new Set();
|
|
1578
|
+
pendingMatches = [];
|
|
1579
|
+
injectedHtml = [];
|
|
1580
|
+
|
|
1581
|
+
// Must build in constructor
|
|
1582
|
+
|
|
1583
|
+
constructor(options) {
|
|
1584
|
+
this.updateOptions({
|
|
1585
|
+
defaultPreloadDelay: 50,
|
|
1586
|
+
context: undefined,
|
|
1587
|
+
...options,
|
|
1588
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
1589
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
startReactTransition = () => {
|
|
1593
|
+
warning(false, 'startReactTransition implementation is missing. If you see this, please file an issue.');
|
|
1594
|
+
};
|
|
1595
|
+
setState = () => {
|
|
1596
|
+
warning(false, 'setState implementation is missing. If you see this, please file an issue.');
|
|
1597
|
+
};
|
|
1598
|
+
updateOptions = newOptions => {
|
|
1599
|
+
this.options;
|
|
1600
|
+
this.options = {
|
|
1601
|
+
...this.options,
|
|
1602
|
+
...newOptions
|
|
1603
|
+
};
|
|
1604
|
+
this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
|
|
1605
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
1606
|
+
this.history = this.options.history ?? createBrowserHistory();
|
|
1607
|
+
this.latestLocation = this.parseLocation();
|
|
1608
|
+
}
|
|
1609
|
+
if (this.options.routeTree !== this.routeTree) {
|
|
1610
|
+
this.routeTree = this.options.routeTree;
|
|
1611
|
+
this.buildRouteTree();
|
|
1612
|
+
}
|
|
1613
|
+
if (!this.state) {
|
|
1614
|
+
this.state = getInitialRouterState(this.latestLocation);
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
buildRouteTree = () => {
|
|
1618
|
+
this.routesById = {};
|
|
1619
|
+
this.routesByPath = {};
|
|
1620
|
+
const recurseRoutes = childRoutes => {
|
|
1621
|
+
childRoutes.forEach((childRoute, i) => {
|
|
1622
|
+
// if (typeof childRoute === 'function') {
|
|
1623
|
+
// childRoute = (childRoute as any)()
|
|
1624
|
+
// }
|
|
1625
|
+
childRoute.init({
|
|
1626
|
+
originalIndex: i
|
|
1627
|
+
});
|
|
1628
|
+
const existingRoute = this.routesById[childRoute.id];
|
|
1629
|
+
invariant(!existingRoute, `Duplicate routes found with id: ${String(childRoute.id)}`);
|
|
1630
|
+
this.routesById[childRoute.id] = childRoute;
|
|
1631
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
1632
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
1633
|
+
if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith('/')) {
|
|
1634
|
+
this.routesByPath[trimmedFullPath] = childRoute;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
const children = childRoute.children;
|
|
1638
|
+
if (children?.length) {
|
|
1639
|
+
recurseRoutes(children);
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
};
|
|
1643
|
+
recurseRoutes([this.routeTree]);
|
|
1644
|
+
this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
|
|
1645
|
+
const trimmed = trimPath(d.fullPath);
|
|
1646
|
+
const parsed = parsePathname(trimmed);
|
|
1647
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1648
|
+
parsed.shift();
|
|
1649
|
+
}
|
|
1650
|
+
const score = parsed.map(d => {
|
|
1651
|
+
if (d.type === 'param') {
|
|
1652
|
+
return 0.5;
|
|
1653
|
+
}
|
|
1654
|
+
if (d.type === 'wildcard') {
|
|
1655
|
+
return 0.25;
|
|
1656
|
+
}
|
|
1657
|
+
return 1;
|
|
1658
|
+
});
|
|
1659
|
+
return {
|
|
1660
|
+
child: d,
|
|
1661
|
+
trimmed,
|
|
1662
|
+
parsed,
|
|
1663
|
+
index: i,
|
|
1664
|
+
score
|
|
1665
|
+
};
|
|
1666
|
+
}).sort((a, b) => {
|
|
1667
|
+
let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
|
|
1668
|
+
if (isIndex !== 0) return isIndex;
|
|
1669
|
+
const length = Math.min(a.score.length, b.score.length);
|
|
1670
|
+
|
|
1671
|
+
// Sort by length of score
|
|
1672
|
+
if (a.score.length !== b.score.length) {
|
|
1673
|
+
return b.score.length - a.score.length;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
// Sort by min available score
|
|
1677
|
+
for (let i = 0; i < length; i++) {
|
|
1678
|
+
if (a.score[i] !== b.score[i]) {
|
|
1679
|
+
return b.score[i] - a.score[i];
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
// Sort by min available parsed value
|
|
1684
|
+
for (let i = 0; i < length; i++) {
|
|
1685
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
1686
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
// Sort by length of trimmed full path
|
|
1691
|
+
if (a.trimmed !== b.trimmed) {
|
|
1692
|
+
return a.trimmed > b.trimmed ? 1 : -1;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// Sort by original index
|
|
1696
|
+
return a.index - b.index;
|
|
1697
|
+
}).map((d, i) => {
|
|
1698
|
+
d.child.rank = i;
|
|
1699
|
+
return d.child;
|
|
1700
|
+
});
|
|
1701
|
+
};
|
|
1702
|
+
subscribe = (eventType, fn) => {
|
|
1703
|
+
const listener = {
|
|
1704
|
+
eventType,
|
|
1705
|
+
fn
|
|
1706
|
+
};
|
|
1707
|
+
this.subscribers.add(listener);
|
|
1708
|
+
return () => {
|
|
1709
|
+
this.subscribers.delete(listener);
|
|
1710
|
+
};
|
|
1711
|
+
};
|
|
1712
|
+
emit = routerEvent => {
|
|
1713
|
+
this.subscribers.forEach(listener => {
|
|
1714
|
+
if (listener.eventType === routerEvent.type) {
|
|
1715
|
+
listener.fn(routerEvent);
|
|
1716
|
+
}
|
|
1717
|
+
});
|
|
1718
|
+
};
|
|
1719
|
+
checkLatest = promise => {
|
|
1720
|
+
return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
|
|
1721
|
+
};
|
|
1722
|
+
parseLocation = previousLocation => {
|
|
1723
|
+
const parse = ({
|
|
1724
|
+
pathname,
|
|
1725
|
+
search,
|
|
1726
|
+
hash,
|
|
1727
|
+
state
|
|
1728
|
+
}) => {
|
|
1729
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1730
|
+
return {
|
|
1731
|
+
pathname: pathname,
|
|
1732
|
+
searchStr: search,
|
|
1733
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1734
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1735
|
+
href: `${pathname}${search}${hash}`,
|
|
1736
|
+
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1737
|
+
};
|
|
1738
|
+
};
|
|
1739
|
+
const location = parse(this.history.location);
|
|
1740
|
+
let {
|
|
1741
|
+
__tempLocation,
|
|
1742
|
+
__tempKey
|
|
1743
|
+
} = location.state;
|
|
1744
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
1745
|
+
// Sync up the location keys
|
|
1746
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
1747
|
+
parsedTempLocation.state.key = location.state.key;
|
|
1748
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
1749
|
+
return {
|
|
1750
|
+
...parsedTempLocation,
|
|
1751
|
+
maskedLocation: location
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
return location;
|
|
1755
|
+
};
|
|
1756
|
+
resolvePathWithBase = (from, path) => {
|
|
1757
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1758
|
+
};
|
|
1759
|
+
get looseRoutesById() {
|
|
1760
|
+
return this.routesById;
|
|
1761
|
+
}
|
|
1762
|
+
matchRoutes = (pathname, locationSearch, opts) => {
|
|
1763
|
+
let routeParams = {};
|
|
1764
|
+
let foundRoute = this.flatRoutes.find(route => {
|
|
1765
|
+
const matchedParams = matchPathname(this.basepath, trimPathRight(pathname), {
|
|
1766
|
+
to: route.fullPath,
|
|
1767
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
|
|
1768
|
+
fuzzy: false
|
|
1769
|
+
});
|
|
1770
|
+
if (matchedParams) {
|
|
1771
|
+
routeParams = matchedParams;
|
|
1772
|
+
return true;
|
|
1773
|
+
}
|
|
1774
|
+
return false;
|
|
1775
|
+
});
|
|
1776
|
+
let routeCursor = foundRoute || this.routesById['__root__'];
|
|
1777
|
+
let matchedRoutes = [routeCursor];
|
|
1778
|
+
// let includingLayouts = true
|
|
1779
|
+
while (routeCursor?.parentRoute) {
|
|
1780
|
+
routeCursor = routeCursor.parentRoute;
|
|
1781
|
+
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
// Existing matches are matches that are already loaded along with
|
|
1785
|
+
// pending matches that are still loading
|
|
1786
|
+
|
|
1787
|
+
const parseErrors = matchedRoutes.map(route => {
|
|
1788
|
+
let parsedParamsError;
|
|
1789
|
+
if (route.options.parseParams) {
|
|
1790
|
+
try {
|
|
1791
|
+
const parsedParams = route.options.parseParams(routeParams);
|
|
1792
|
+
// Add the parsed params to the accumulated params bag
|
|
1793
|
+
Object.assign(routeParams, parsedParams);
|
|
1794
|
+
} catch (err) {
|
|
1795
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1590
1796
|
cause: err
|
|
1591
1797
|
});
|
|
1592
1798
|
if (opts?.throwOnError) {
|
|
@@ -1604,8 +1810,8 @@
|
|
|
1604
1810
|
// Waste not, want not. If we already have a match for this route,
|
|
1605
1811
|
// reuse it. This is important for layout routes, which might stick
|
|
1606
1812
|
// around between navigation actions that only change leaf routes.
|
|
1607
|
-
const existingMatch = getRouteMatch(state, matchId);
|
|
1608
|
-
const cause = state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1813
|
+
const existingMatch = getRouteMatch(this.state, matchId);
|
|
1814
|
+
const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1609
1815
|
if (existingMatch) {
|
|
1610
1816
|
return {
|
|
1611
1817
|
...existingMatch,
|
|
@@ -1619,7 +1825,7 @@
|
|
|
1619
1825
|
id: matchId,
|
|
1620
1826
|
routeId: route.id,
|
|
1621
1827
|
params: routeParams,
|
|
1622
|
-
pathname: joinPaths([basepath, interpolatedPath]),
|
|
1828
|
+
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1623
1829
|
updatedAt: Date.now(),
|
|
1624
1830
|
routeSearch: {},
|
|
1625
1831
|
search: {},
|
|
@@ -1644,7 +1850,7 @@
|
|
|
1644
1850
|
// so that we can use the parent match's search params and context
|
|
1645
1851
|
matches.forEach((match, i) => {
|
|
1646
1852
|
const parentMatch = matches[i - 1];
|
|
1647
|
-
const route = looseRoutesById[match.routeId];
|
|
1853
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1648
1854
|
const searchInfo = (() => {
|
|
1649
1855
|
// Validate the search params and stabilize them
|
|
1650
1856
|
const parentSearchInfo = {
|
|
@@ -1678,28 +1884,28 @@
|
|
|
1678
1884
|
Object.assign(match, searchInfo);
|
|
1679
1885
|
});
|
|
1680
1886
|
return matches;
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
getRouteMatch(state, id)?.abortController?.abort();
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
state.matches.forEach(match => {
|
|
1687
|
-
cancelMatch(match.id);
|
|
1887
|
+
};
|
|
1888
|
+
cancelMatch = id => {
|
|
1889
|
+
getRouteMatch(this.state, id)?.abortController?.abort();
|
|
1890
|
+
};
|
|
1891
|
+
cancelMatches = () => {
|
|
1892
|
+
this.state.matches.forEach(match => {
|
|
1893
|
+
this.cancelMatch(match.id);
|
|
1688
1894
|
});
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1895
|
+
};
|
|
1896
|
+
buildLocation = opts => {
|
|
1691
1897
|
const build = (dest = {}, matches) => {
|
|
1692
|
-
const from =
|
|
1898
|
+
const from = this.latestLocation;
|
|
1693
1899
|
const fromPathname = dest.from ?? from.pathname;
|
|
1694
|
-
let pathname = resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1695
|
-
const fromMatches = matchRoutes(fromPathname, from.search);
|
|
1900
|
+
let pathname = this.resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1901
|
+
const fromMatches = this.matchRoutes(fromPathname, from.search);
|
|
1696
1902
|
const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
|
|
1697
1903
|
const prevParams = {
|
|
1698
1904
|
...last(fromMatches)?.params
|
|
1699
1905
|
};
|
|
1700
1906
|
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1701
1907
|
if (nextParams) {
|
|
1702
|
-
matches?.map(d => looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1908
|
+
matches?.map(d => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1703
1909
|
nextParams = {
|
|
1704
1910
|
...nextParams,
|
|
1705
1911
|
...fn(nextParams)
|
|
@@ -1707,8 +1913,8 @@
|
|
|
1707
1913
|
});
|
|
1708
1914
|
}
|
|
1709
1915
|
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1710
|
-
const preSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1711
|
-
const postSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1916
|
+
const preSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1917
|
+
const postSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1712
1918
|
|
|
1713
1919
|
// Pre filters first
|
|
1714
1920
|
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
|
|
@@ -1722,7 +1928,7 @@
|
|
|
1722
1928
|
// Then post filters
|
|
1723
1929
|
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1724
1930
|
const search = replaceEqualDeep(from.search, postFilteredSearch);
|
|
1725
|
-
const searchStr = options.stringifySearch(search);
|
|
1931
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1726
1932
|
const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
|
|
1727
1933
|
const hashStr = hash ? `#${hash}` : '';
|
|
1728
1934
|
let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
|
|
@@ -1733,7 +1939,7 @@
|
|
|
1733
1939
|
searchStr,
|
|
1734
1940
|
state: nextState,
|
|
1735
1941
|
hash,
|
|
1736
|
-
href: history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1942
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1737
1943
|
unmaskOnReload: dest.unmaskOnReload
|
|
1738
1944
|
};
|
|
1739
1945
|
};
|
|
@@ -1742,8 +1948,8 @@
|
|
|
1742
1948
|
let maskedNext = maskedDest ? build(maskedDest) : undefined;
|
|
1743
1949
|
if (!maskedNext) {
|
|
1744
1950
|
let params = {};
|
|
1745
|
-
let foundMask = options.routeMasks?.find(d => {
|
|
1746
|
-
const match = matchPathname(basepath, next.pathname, {
|
|
1951
|
+
let foundMask = this.options.routeMasks?.find(d => {
|
|
1952
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1747
1953
|
to: d.from,
|
|
1748
1954
|
caseSensitive: false,
|
|
1749
1955
|
fuzzy: false
|
|
@@ -1763,8 +1969,8 @@
|
|
|
1763
1969
|
maskedNext = build(maskedDest);
|
|
1764
1970
|
}
|
|
1765
1971
|
}
|
|
1766
|
-
const nextMatches = matchRoutes(next.pathname, next.search);
|
|
1767
|
-
const maskedMatches = maskedNext ? matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1972
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1973
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1768
1974
|
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1769
1975
|
const final = build(dest, nextMatches);
|
|
1770
1976
|
if (maskedFinal) {
|
|
@@ -1779,13 +1985,13 @@
|
|
|
1779
1985
|
});
|
|
1780
1986
|
}
|
|
1781
1987
|
return buildWithMatches(opts);
|
|
1782
|
-
}
|
|
1783
|
-
|
|
1988
|
+
};
|
|
1989
|
+
commitLocation = async ({
|
|
1784
1990
|
startTransition,
|
|
1785
1991
|
...next
|
|
1786
1992
|
}) => {
|
|
1787
|
-
if (
|
|
1788
|
-
const isSameUrl =
|
|
1993
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1994
|
+
const isSameUrl = this.latestLocation.href === next.href;
|
|
1789
1995
|
|
|
1790
1996
|
// If the next urls are the same and we're not replacing,
|
|
1791
1997
|
// do nothing
|
|
@@ -1812,37 +2018,37 @@
|
|
|
1812
2018
|
}
|
|
1813
2019
|
}
|
|
1814
2020
|
};
|
|
1815
|
-
if (nextHistory.unmaskOnReload ?? options.unmaskOnReload ?? false) {
|
|
1816
|
-
nextHistory.state.__tempKey =
|
|
2021
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
2022
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
1817
2023
|
}
|
|
1818
2024
|
}
|
|
1819
2025
|
const apply = () => {
|
|
1820
|
-
history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
2026
|
+
this.history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
1821
2027
|
};
|
|
1822
2028
|
if (startTransition ?? true) {
|
|
1823
|
-
startReactTransition(apply);
|
|
2029
|
+
this.startReactTransition(apply);
|
|
1824
2030
|
} else {
|
|
1825
2031
|
apply();
|
|
1826
2032
|
}
|
|
1827
2033
|
}
|
|
1828
|
-
|
|
1829
|
-
return
|
|
1830
|
-
}
|
|
1831
|
-
|
|
2034
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
2035
|
+
return this.latestLoadPromise;
|
|
2036
|
+
};
|
|
2037
|
+
buildAndCommitLocation = ({
|
|
1832
2038
|
replace,
|
|
1833
2039
|
resetScroll,
|
|
1834
2040
|
startTransition,
|
|
1835
2041
|
...rest
|
|
1836
2042
|
} = {}) => {
|
|
1837
|
-
const location = buildLocation(rest);
|
|
1838
|
-
return commitLocation({
|
|
2043
|
+
const location = this.buildLocation(rest);
|
|
2044
|
+
return this.commitLocation({
|
|
1839
2045
|
...location,
|
|
1840
2046
|
startTransition,
|
|
1841
2047
|
replace,
|
|
1842
2048
|
resetScroll
|
|
1843
2049
|
});
|
|
1844
|
-
}
|
|
1845
|
-
|
|
2050
|
+
};
|
|
2051
|
+
navigate = ({
|
|
1846
2052
|
from,
|
|
1847
2053
|
to = '',
|
|
1848
2054
|
...rest
|
|
@@ -1860,13 +2066,13 @@
|
|
|
1860
2066
|
isExternal = true;
|
|
1861
2067
|
} catch (e) {}
|
|
1862
2068
|
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1863
|
-
return buildAndCommitLocation({
|
|
2069
|
+
return this.buildAndCommitLocation({
|
|
1864
2070
|
...rest,
|
|
1865
2071
|
from: fromString,
|
|
1866
2072
|
to: toString
|
|
1867
2073
|
});
|
|
1868
|
-
}
|
|
1869
|
-
|
|
2074
|
+
};
|
|
2075
|
+
loadMatches = async ({
|
|
1870
2076
|
checkLatest,
|
|
1871
2077
|
matches,
|
|
1872
2078
|
preload
|
|
@@ -1878,7 +2084,7 @@
|
|
|
1878
2084
|
try {
|
|
1879
2085
|
for (let [index, match] of matches.entries()) {
|
|
1880
2086
|
const parentMatch = matches[index - 1];
|
|
1881
|
-
const route = looseRoutesById[match.routeId];
|
|
2087
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1882
2088
|
const handleError = (err, code) => {
|
|
1883
2089
|
err.routerCode = code;
|
|
1884
2090
|
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
@@ -1907,19 +2113,20 @@
|
|
|
1907
2113
|
if (match.searchError) {
|
|
1908
2114
|
handleError(match.searchError, 'VALIDATE_SEARCH');
|
|
1909
2115
|
}
|
|
1910
|
-
const parentContext = parentMatch?.context ?? options.context ?? {};
|
|
2116
|
+
const parentContext = parentMatch?.context ?? this.options.context ?? {};
|
|
1911
2117
|
const beforeLoadContext = (await route.options.beforeLoad?.({
|
|
1912
2118
|
search: match.search,
|
|
1913
2119
|
abortController: match.abortController,
|
|
1914
2120
|
params: match.params,
|
|
1915
2121
|
preload: !!preload,
|
|
1916
2122
|
context: parentContext,
|
|
1917
|
-
location: state.location,
|
|
1918
|
-
|
|
2123
|
+
location: this.state.location,
|
|
2124
|
+
// TOOD: just expose state and router, etc
|
|
2125
|
+
navigate: opts => this.navigate({
|
|
1919
2126
|
...opts,
|
|
1920
2127
|
from: match.pathname
|
|
1921
2128
|
}),
|
|
1922
|
-
buildLocation,
|
|
2129
|
+
buildLocation: this.buildLocation,
|
|
1923
2130
|
cause: match.cause
|
|
1924
2131
|
})) ?? {};
|
|
1925
2132
|
const context = {
|
|
@@ -1937,7 +2144,7 @@
|
|
|
1937
2144
|
}
|
|
1938
2145
|
} catch (err) {
|
|
1939
2146
|
if (isRedirect(err)) {
|
|
1940
|
-
if (!preload) navigate(err);
|
|
2147
|
+
if (!preload) this.navigate(err);
|
|
1941
2148
|
return matches;
|
|
1942
2149
|
}
|
|
1943
2150
|
throw err;
|
|
@@ -1947,11 +2154,11 @@
|
|
|
1947
2154
|
validResolvedMatches.forEach((match, index) => {
|
|
1948
2155
|
matchPromises.push((async () => {
|
|
1949
2156
|
const parentMatchPromise = matchPromises[index - 1];
|
|
1950
|
-
const route = looseRoutesById[match.routeId];
|
|
2157
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1951
2158
|
const handleIfRedirect = err => {
|
|
1952
2159
|
if (isRedirect(err)) {
|
|
1953
2160
|
if (!preload) {
|
|
1954
|
-
navigate(err);
|
|
2161
|
+
this.navigate(err);
|
|
1955
2162
|
}
|
|
1956
2163
|
return true;
|
|
1957
2164
|
}
|
|
@@ -1964,7 +2171,7 @@
|
|
|
1964
2171
|
invalid: false
|
|
1965
2172
|
};
|
|
1966
2173
|
if (match.isFetching) {
|
|
1967
|
-
loadPromise = getRouteMatch(state, match.id)?.loadPromise;
|
|
2174
|
+
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
1968
2175
|
} else {
|
|
1969
2176
|
const loaderContext = {
|
|
1970
2177
|
params: match.params,
|
|
@@ -1973,8 +2180,8 @@
|
|
|
1973
2180
|
parentMatchPromise,
|
|
1974
2181
|
abortController: match.abortController,
|
|
1975
2182
|
context: match.context,
|
|
1976
|
-
location: state.location,
|
|
1977
|
-
navigate: opts => navigate({
|
|
2183
|
+
location: this.state.location,
|
|
2184
|
+
navigate: opts => this.navigate({
|
|
1978
2185
|
...opts,
|
|
1979
2186
|
from: match.pathname
|
|
1980
2187
|
}),
|
|
@@ -2022,7 +2229,7 @@
|
|
|
2022
2229
|
loadPromise
|
|
2023
2230
|
};
|
|
2024
2231
|
if (!preload) {
|
|
2025
|
-
setState(s => ({
|
|
2232
|
+
this.setState(s => ({
|
|
2026
2233
|
...s,
|
|
2027
2234
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2028
2235
|
}));
|
|
@@ -2057,7 +2264,7 @@
|
|
|
2057
2264
|
};
|
|
2058
2265
|
}
|
|
2059
2266
|
if (!preload) {
|
|
2060
|
-
setState(s => ({
|
|
2267
|
+
this.setState(s => ({
|
|
2061
2268
|
...s,
|
|
2062
2269
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2063
2270
|
}));
|
|
@@ -2066,17 +2273,17 @@
|
|
|
2066
2273
|
});
|
|
2067
2274
|
await Promise.all(matchPromises);
|
|
2068
2275
|
return matches;
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2276
|
+
};
|
|
2277
|
+
load = async () => {
|
|
2071
2278
|
const promise = new Promise(async (resolve, reject) => {
|
|
2072
|
-
const next =
|
|
2073
|
-
const prevLocation = state.resolvedLocation;
|
|
2279
|
+
const next = this.latestLocation;
|
|
2280
|
+
const prevLocation = this.state.resolvedLocation;
|
|
2074
2281
|
const pathDidChange = prevLocation.href !== next.href;
|
|
2075
2282
|
let latestPromise;
|
|
2076
2283
|
|
|
2077
2284
|
// Cancel any pending matches
|
|
2078
|
-
cancelMatches(
|
|
2079
|
-
|
|
2285
|
+
this.cancelMatches();
|
|
2286
|
+
this.emit({
|
|
2080
2287
|
type: 'onBeforeLoad',
|
|
2081
2288
|
fromLocation: prevLocation,
|
|
2082
2289
|
toLocation: next,
|
|
@@ -2084,14 +2291,14 @@
|
|
|
2084
2291
|
});
|
|
2085
2292
|
|
|
2086
2293
|
// Match the routes
|
|
2087
|
-
let matches = matchRoutes(next.pathname, next.search, {
|
|
2294
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
2088
2295
|
debug: true
|
|
2089
2296
|
});
|
|
2090
|
-
|
|
2091
|
-
const previousMatches = state.matches;
|
|
2297
|
+
this.pendingMatches = matches;
|
|
2298
|
+
const previousMatches = this.state.matches;
|
|
2092
2299
|
|
|
2093
2300
|
// Ingest the new matches
|
|
2094
|
-
setState(s => ({
|
|
2301
|
+
this.setState(s => ({
|
|
2095
2302
|
...s,
|
|
2096
2303
|
status: 'pending',
|
|
2097
2304
|
location: next,
|
|
@@ -2100,9 +2307,9 @@
|
|
|
2100
2307
|
try {
|
|
2101
2308
|
try {
|
|
2102
2309
|
// Load the matches
|
|
2103
|
-
await loadMatches({
|
|
2310
|
+
await this.loadMatches({
|
|
2104
2311
|
matches,
|
|
2105
|
-
checkLatest: () => checkLatest(promise)
|
|
2312
|
+
checkLatest: () => this.checkLatest(promise)
|
|
2106
2313
|
});
|
|
2107
2314
|
} catch (err) {
|
|
2108
2315
|
// swallow this error, since we'll display the
|
|
@@ -2110,12 +2317,12 @@
|
|
|
2110
2317
|
}
|
|
2111
2318
|
|
|
2112
2319
|
// Only apply the latest transition
|
|
2113
|
-
if (latestPromise = checkLatest(promise)) {
|
|
2320
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2114
2321
|
return latestPromise;
|
|
2115
2322
|
}
|
|
2116
|
-
const exitingMatchIds = previousMatches.filter(id => !
|
|
2117
|
-
const enteringMatchIds =
|
|
2118
|
-
const stayingMatchIds = previousMatches.filter(id =>
|
|
2323
|
+
const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
|
|
2324
|
+
const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
|
|
2325
|
+
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id))
|
|
2119
2326
|
|
|
2120
2327
|
// setState((s) => ({
|
|
2121
2328
|
// ...s,
|
|
@@ -2127,10 +2334,10 @@
|
|
|
2127
2334
|
;
|
|
2128
2335
|
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matches, hook]) => {
|
|
2129
2336
|
matches.forEach(match => {
|
|
2130
|
-
looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2337
|
+
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2131
2338
|
});
|
|
2132
2339
|
});
|
|
2133
|
-
|
|
2340
|
+
this.emit({
|
|
2134
2341
|
type: 'onLoad',
|
|
2135
2342
|
fromLocation: prevLocation,
|
|
2136
2343
|
toLocation: next,
|
|
@@ -2139,28 +2346,28 @@
|
|
|
2139
2346
|
resolve();
|
|
2140
2347
|
} catch (err) {
|
|
2141
2348
|
// Only apply the latest transition
|
|
2142
|
-
if (latestPromise = checkLatest(promise)) {
|
|
2349
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
2143
2350
|
return latestPromise;
|
|
2144
2351
|
}
|
|
2145
2352
|
reject(err);
|
|
2146
2353
|
}
|
|
2147
2354
|
});
|
|
2148
|
-
|
|
2149
|
-
return
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
let next = buildLocation(navigateOpts);
|
|
2153
|
-
let matches = matchRoutes(next.pathname, next.search, {
|
|
2355
|
+
this.latestLoadPromise = promise;
|
|
2356
|
+
return this.latestLoadPromise;
|
|
2357
|
+
};
|
|
2358
|
+
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
2359
|
+
let next = this.buildLocation(navigateOpts);
|
|
2360
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
2154
2361
|
throwOnError: true
|
|
2155
2362
|
});
|
|
2156
|
-
await loadMatches({
|
|
2363
|
+
await this.loadMatches({
|
|
2157
2364
|
matches,
|
|
2158
2365
|
preload: true,
|
|
2159
2366
|
checkLatest: () => undefined
|
|
2160
2367
|
});
|
|
2161
2368
|
return [last(matches), matches];
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2369
|
+
};
|
|
2370
|
+
buildLink = dest => {
|
|
2164
2371
|
// If this link simply reloads the current route,
|
|
2165
2372
|
// make sure it has a new key so it will trigger a data refresh
|
|
2166
2373
|
|
|
@@ -2186,18 +2393,18 @@
|
|
|
2186
2393
|
};
|
|
2187
2394
|
} catch (e) {}
|
|
2188
2395
|
const nextOpts = dest;
|
|
2189
|
-
const next = buildLocation(nextOpts);
|
|
2190
|
-
const preload = userPreload ?? options.defaultPreload;
|
|
2191
|
-
const preloadDelay = userPreloadDelay ?? options.defaultPreloadDelay ?? 0;
|
|
2396
|
+
const next = this.buildLocation(nextOpts);
|
|
2397
|
+
const preload = userPreload ?? this.options.defaultPreload;
|
|
2398
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
2192
2399
|
|
|
2193
2400
|
// Compare path/hash for matches
|
|
2194
|
-
const currentPathSplit =
|
|
2401
|
+
const currentPathSplit = this.latestLocation.pathname.split('/');
|
|
2195
2402
|
const nextPathSplit = next.pathname.split('/');
|
|
2196
2403
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
2197
|
-
// Combine the matches based on user options
|
|
2198
|
-
const pathTest = activeOptions?.exact ?
|
|
2199
|
-
const hashTest = activeOptions?.includeHash ?
|
|
2200
|
-
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(
|
|
2404
|
+
// Combine the matches based on user this.options
|
|
2405
|
+
const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
|
|
2406
|
+
const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
|
|
2407
|
+
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
|
|
2201
2408
|
|
|
2202
2409
|
// The final "active" test
|
|
2203
2410
|
const isActive = pathTest && hashTest && searchTest;
|
|
@@ -2208,7 +2415,7 @@
|
|
|
2208
2415
|
e.preventDefault();
|
|
2209
2416
|
|
|
2210
2417
|
// All is well? Navigate!
|
|
2211
|
-
commitLocation({
|
|
2418
|
+
this.commitLocation({
|
|
2212
2419
|
...next,
|
|
2213
2420
|
replace,
|
|
2214
2421
|
resetScroll,
|
|
@@ -2220,384 +2427,184 @@
|
|
|
2220
2427
|
// The click handler
|
|
2221
2428
|
const handleFocus = e => {
|
|
2222
2429
|
if (preload) {
|
|
2223
|
-
preloadRoute(nextOpts).catch(err => {
|
|
2430
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2224
2431
|
console.warn(err);
|
|
2225
2432
|
console.warn(preloadWarning);
|
|
2226
2433
|
});
|
|
2227
2434
|
}
|
|
2228
2435
|
};
|
|
2229
2436
|
const handleTouchStart = e => {
|
|
2230
|
-
preloadRoute(nextOpts).catch(err => {
|
|
2437
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2231
2438
|
console.warn(err);
|
|
2232
2439
|
console.warn(preloadWarning);
|
|
2233
2440
|
});
|
|
2234
2441
|
};
|
|
2235
|
-
const handleEnter = e => {
|
|
2236
|
-
const target = e.target || {};
|
|
2237
|
-
if (preload) {
|
|
2238
|
-
if (target.preloadTimeout) {
|
|
2239
|
-
return;
|
|
2240
|
-
}
|
|
2241
|
-
target.preloadTimeout = setTimeout(() => {
|
|
2242
|
-
target.preloadTimeout = null;
|
|
2243
|
-
preloadRoute(nextOpts).catch(err => {
|
|
2244
|
-
console.warn(err);
|
|
2245
|
-
console.warn(preloadWarning);
|
|
2246
|
-
});
|
|
2247
|
-
}, preloadDelay);
|
|
2248
|
-
}
|
|
2249
|
-
};
|
|
2250
|
-
const handleLeave = e => {
|
|
2251
|
-
const target = e.target || {};
|
|
2252
|
-
if (target.preloadTimeout) {
|
|
2253
|
-
clearTimeout(target.preloadTimeout);
|
|
2254
|
-
target.preloadTimeout = null;
|
|
2255
|
-
}
|
|
2256
|
-
};
|
|
2257
|
-
return {
|
|
2258
|
-
type: 'internal',
|
|
2259
|
-
next,
|
|
2260
|
-
handleFocus,
|
|
2261
|
-
handleClick,
|
|
2262
|
-
handleEnter,
|
|
2263
|
-
handleLeave,
|
|
2264
|
-
handleTouchStart,
|
|
2265
|
-
isActive,
|
|
2266
|
-
disabled
|
|
2267
|
-
};
|
|
2268
|
-
});
|
|
2269
|
-
React__namespace.useLayoutEffect(() => {
|
|
2270
|
-
const unsub = history.subscribe(() => {
|
|
2271
|
-
latestLocationRef.current = parseLocation(latestLocationRef.current);
|
|
2272
|
-
if (state.location !== latestLocationRef.current) {
|
|
2273
|
-
startReactTransition(() => {
|
|
2274
|
-
try {
|
|
2275
|
-
load();
|
|
2276
|
-
} catch (err) {
|
|
2277
|
-
console.error(err);
|
|
2278
|
-
}
|
|
2279
|
-
});
|
|
2280
|
-
}
|
|
2281
|
-
});
|
|
2282
|
-
const nextLocation = buildLocation({
|
|
2283
|
-
search: true,
|
|
2284
|
-
params: true,
|
|
2285
|
-
hash: true,
|
|
2286
|
-
state: true
|
|
2287
|
-
});
|
|
2288
|
-
if (state.location.href !== nextLocation.href) {
|
|
2289
|
-
commitLocation({
|
|
2290
|
-
...nextLocation,
|
|
2291
|
-
replace: true
|
|
2292
|
-
});
|
|
2293
|
-
}
|
|
2294
|
-
return () => {
|
|
2295
|
-
unsub();
|
|
2296
|
-
};
|
|
2297
|
-
}, [history]);
|
|
2298
|
-
const matchRoute = useStableCallback((location, opts) => {
|
|
2299
|
-
location = {
|
|
2300
|
-
...location,
|
|
2301
|
-
to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
|
|
2302
|
-
};
|
|
2303
|
-
const next = buildLocation(location);
|
|
2304
|
-
if (opts?.pending && state.status !== 'pending') {
|
|
2305
|
-
return false;
|
|
2306
|
-
}
|
|
2307
|
-
const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
|
|
2308
|
-
|
|
2309
|
-
// const baseLocation = state.resolvedLocation
|
|
2310
|
-
|
|
2311
|
-
if (!baseLocation) {
|
|
2312
|
-
return false;
|
|
2313
|
-
}
|
|
2314
|
-
const match = matchPathname(basepath, baseLocation.pathname, {
|
|
2315
|
-
...opts,
|
|
2316
|
-
to: next.pathname
|
|
2317
|
-
});
|
|
2318
|
-
if (!match) {
|
|
2319
|
-
return false;
|
|
2320
|
-
}
|
|
2321
|
-
if (match && (opts?.includeSearch ?? true)) {
|
|
2322
|
-
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
2323
|
-
}
|
|
2324
|
-
return match;
|
|
2325
|
-
});
|
|
2326
|
-
const injectedHtmlRef = React__namespace.useRef([]);
|
|
2327
|
-
const injectHtml = useStableCallback(async html => {
|
|
2328
|
-
injectedHtmlRef.current.push(html);
|
|
2329
|
-
});
|
|
2330
|
-
const dehydrateData = useStableCallback((key, getData) => {
|
|
2331
|
-
if (typeof document === 'undefined') {
|
|
2332
|
-
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2333
|
-
injectHtml(async () => {
|
|
2334
|
-
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2335
|
-
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2336
|
-
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2337
|
-
;(() => {
|
|
2338
|
-
var el = document.getElementById('${id}')
|
|
2339
|
-
el.parentElement.removeChild(el)
|
|
2340
|
-
})()
|
|
2341
|
-
</script>`;
|
|
2342
|
-
});
|
|
2343
|
-
return () => hydrateData(key);
|
|
2344
|
-
}
|
|
2345
|
-
return () => undefined;
|
|
2346
|
-
});
|
|
2347
|
-
const hydrateData = useStableCallback(key => {
|
|
2348
|
-
if (typeof document !== 'undefined') {
|
|
2349
|
-
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2350
|
-
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2351
|
-
}
|
|
2352
|
-
return undefined;
|
|
2353
|
-
});
|
|
2354
|
-
React__namespace.useLayoutEffect(() => {
|
|
2355
|
-
startReactTransition(() => {
|
|
2356
|
-
try {
|
|
2357
|
-
load();
|
|
2358
|
-
} catch (err) {
|
|
2359
|
-
console.error(err);
|
|
2360
|
-
}
|
|
2361
|
-
});
|
|
2362
|
-
}, []);
|
|
2363
|
-
const routerContextValue = {
|
|
2364
|
-
routeTree: router.routeTree,
|
|
2365
|
-
navigate,
|
|
2366
|
-
buildLink,
|
|
2367
|
-
state,
|
|
2368
|
-
matchRoute,
|
|
2369
|
-
routesById,
|
|
2370
|
-
options,
|
|
2371
|
-
history,
|
|
2372
|
-
load,
|
|
2373
|
-
buildLocation,
|
|
2374
|
-
subscribe: router.subscribe,
|
|
2375
|
-
resetNextScrollRef,
|
|
2376
|
-
injectedHtmlRef,
|
|
2377
|
-
injectHtml,
|
|
2378
|
-
dehydrateData,
|
|
2379
|
-
hydrateData
|
|
2380
|
-
};
|
|
2381
|
-
return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
|
|
2382
|
-
value: routerContextValue
|
|
2383
|
-
}, /*#__PURE__*/React__namespace.createElement(Matches, null));
|
|
2384
|
-
}
|
|
2385
|
-
function getRouteMatch(state, id) {
|
|
2386
|
-
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
2387
|
-
}
|
|
2388
|
-
function useRouterState(opts) {
|
|
2389
|
-
const {
|
|
2390
|
-
state
|
|
2391
|
-
} = useRouter();
|
|
2392
|
-
// return useStore(router.__store, opts?.select as any)
|
|
2393
|
-
return opts?.select ? opts.select(state) : state;
|
|
2394
|
-
}
|
|
2395
|
-
function useRouter() {
|
|
2396
|
-
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
2397
|
-
const value = React__namespace.useContext(resolvedContext);
|
|
2398
|
-
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
2399
|
-
return value;
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
function defer(_promise) {
|
|
2403
|
-
const promise = _promise;
|
|
2404
|
-
if (!promise.__deferredState) {
|
|
2405
|
-
promise.__deferredState = {
|
|
2406
|
-
uid: Math.random().toString(36).slice(2),
|
|
2407
|
-
status: 'pending'
|
|
2408
|
-
};
|
|
2409
|
-
const state = promise.__deferredState;
|
|
2410
|
-
promise.then(data => {
|
|
2411
|
-
state.status = 'success';
|
|
2412
|
-
state.data = data;
|
|
2413
|
-
}).catch(error => {
|
|
2414
|
-
state.status = 'error';
|
|
2415
|
-
state.error = error;
|
|
2416
|
-
});
|
|
2417
|
-
}
|
|
2418
|
-
return promise;
|
|
2419
|
-
}
|
|
2420
|
-
function isDehydratedDeferred(obj) {
|
|
2421
|
-
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
2422
|
-
}
|
|
2423
|
-
|
|
2424
|
-
function useAwaited({
|
|
2425
|
-
promise
|
|
2426
|
-
}) {
|
|
2427
|
-
const router = useRouter();
|
|
2428
|
-
let state = promise.__deferredState;
|
|
2429
|
-
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
2430
|
-
if (isDehydratedDeferred(promise)) {
|
|
2431
|
-
state = router.hydrateData(key);
|
|
2432
|
-
promise = Promise.resolve(state.data);
|
|
2433
|
-
promise.__deferredState = state;
|
|
2434
|
-
}
|
|
2435
|
-
if (state.status === 'pending') {
|
|
2436
|
-
throw promise;
|
|
2437
|
-
}
|
|
2438
|
-
if (state.status === 'error') {
|
|
2439
|
-
throw state.error;
|
|
2440
|
-
}
|
|
2441
|
-
router.dehydrateData(key, state);
|
|
2442
|
-
return [state.data];
|
|
2443
|
-
}
|
|
2444
|
-
function Await(props) {
|
|
2445
|
-
const awaited = useAwaited(props);
|
|
2446
|
-
return props.children(...awaited);
|
|
2447
|
-
}
|
|
2448
|
-
|
|
2449
|
-
class FileRoute {
|
|
2450
|
-
constructor(path) {
|
|
2451
|
-
this.path = path;
|
|
2452
|
-
}
|
|
2453
|
-
createRoute = options => {
|
|
2454
|
-
const route = new Route(options);
|
|
2455
|
-
route.isRoot = false;
|
|
2456
|
-
return route;
|
|
2457
|
-
};
|
|
2458
|
-
}
|
|
2459
|
-
|
|
2460
|
-
function lazyRouteComponent(importer, exportName) {
|
|
2461
|
-
let loadPromise;
|
|
2462
|
-
const load = () => {
|
|
2463
|
-
if (!loadPromise) {
|
|
2464
|
-
loadPromise = importer();
|
|
2465
|
-
}
|
|
2466
|
-
return loadPromise;
|
|
2467
|
-
};
|
|
2468
|
-
const lazyComp = /*#__PURE__*/React__namespace.lazy(async () => {
|
|
2469
|
-
const moduleExports = await load();
|
|
2470
|
-
const comp = moduleExports[exportName ?? 'default'];
|
|
2471
|
-
return {
|
|
2472
|
-
default: comp
|
|
2473
|
-
};
|
|
2474
|
-
});
|
|
2475
|
-
lazyComp.preload = load;
|
|
2476
|
-
return lazyComp;
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
|
-
function _extends() {
|
|
2480
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
2481
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
2482
|
-
var source = arguments[i];
|
|
2483
|
-
for (var key in source) {
|
|
2484
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2485
|
-
target[key] = source[key];
|
|
2442
|
+
const handleEnter = e => {
|
|
2443
|
+
const target = e.target || {};
|
|
2444
|
+
if (preload) {
|
|
2445
|
+
if (target.preloadTimeout) {
|
|
2446
|
+
return;
|
|
2486
2447
|
}
|
|
2448
|
+
target.preloadTimeout = setTimeout(() => {
|
|
2449
|
+
target.preloadTimeout = null;
|
|
2450
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2451
|
+
console.warn(err);
|
|
2452
|
+
console.warn(preloadWarning);
|
|
2453
|
+
});
|
|
2454
|
+
}, preloadDelay);
|
|
2487
2455
|
}
|
|
2488
|
-
}
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
buildLink
|
|
2497
|
-
} = useRouter();
|
|
2498
|
-
const match = useMatch({
|
|
2499
|
-
strict: false
|
|
2500
|
-
});
|
|
2501
|
-
const {
|
|
2502
|
-
// custom props
|
|
2503
|
-
type,
|
|
2504
|
-
children,
|
|
2505
|
-
target,
|
|
2506
|
-
activeProps = () => ({
|
|
2507
|
-
className: 'active'
|
|
2508
|
-
}),
|
|
2509
|
-
inactiveProps = () => ({}),
|
|
2510
|
-
activeOptions,
|
|
2511
|
-
disabled,
|
|
2512
|
-
hash,
|
|
2513
|
-
search,
|
|
2514
|
-
params,
|
|
2515
|
-
to,
|
|
2516
|
-
state,
|
|
2517
|
-
mask,
|
|
2518
|
-
preload,
|
|
2519
|
-
preloadDelay,
|
|
2520
|
-
replace,
|
|
2521
|
-
startTransition,
|
|
2522
|
-
resetScroll,
|
|
2523
|
-
// element props
|
|
2524
|
-
style,
|
|
2525
|
-
className,
|
|
2526
|
-
onClick,
|
|
2527
|
-
onFocus,
|
|
2528
|
-
onMouseEnter,
|
|
2529
|
-
onMouseLeave,
|
|
2530
|
-
onTouchStart,
|
|
2531
|
-
...rest
|
|
2532
|
-
} = options;
|
|
2533
|
-
const linkInfo = buildLink({
|
|
2534
|
-
from: options.to ? match.pathname : undefined,
|
|
2535
|
-
...options
|
|
2536
|
-
});
|
|
2537
|
-
if (linkInfo.type === 'external') {
|
|
2538
|
-
const {
|
|
2539
|
-
href
|
|
2540
|
-
} = linkInfo;
|
|
2456
|
+
};
|
|
2457
|
+
const handleLeave = e => {
|
|
2458
|
+
const target = e.target || {};
|
|
2459
|
+
if (target.preloadTimeout) {
|
|
2460
|
+
clearTimeout(target.preloadTimeout);
|
|
2461
|
+
target.preloadTimeout = null;
|
|
2462
|
+
}
|
|
2463
|
+
};
|
|
2541
2464
|
return {
|
|
2542
|
-
|
|
2465
|
+
type: 'internal',
|
|
2466
|
+
next,
|
|
2467
|
+
handleFocus,
|
|
2468
|
+
handleClick,
|
|
2469
|
+
handleEnter,
|
|
2470
|
+
handleLeave,
|
|
2471
|
+
handleTouchStart,
|
|
2472
|
+
isActive,
|
|
2473
|
+
disabled
|
|
2543
2474
|
};
|
|
2544
|
-
}
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2475
|
+
};
|
|
2476
|
+
matchRoute = (location, opts) => {
|
|
2477
|
+
location = {
|
|
2478
|
+
...location,
|
|
2479
|
+
to: location.to ? this.resolvePathWithBase(location.from || '', location.to) : undefined
|
|
2480
|
+
};
|
|
2481
|
+
const next = this.buildLocation(location);
|
|
2482
|
+
if (opts?.pending && this.state.status !== 'pending') {
|
|
2483
|
+
return false;
|
|
2484
|
+
}
|
|
2485
|
+
const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
|
|
2486
|
+
|
|
2487
|
+
// const baseLocation = state.resolvedLocation
|
|
2488
|
+
|
|
2489
|
+
if (!baseLocation) {
|
|
2490
|
+
return false;
|
|
2491
|
+
}
|
|
2492
|
+
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
2493
|
+
...opts,
|
|
2494
|
+
to: next.pathname
|
|
2559
2495
|
});
|
|
2496
|
+
if (!match) {
|
|
2497
|
+
return false;
|
|
2498
|
+
}
|
|
2499
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
2500
|
+
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
2501
|
+
}
|
|
2502
|
+
return match;
|
|
2503
|
+
};
|
|
2504
|
+
injectHtml = async html => {
|
|
2505
|
+
this.injectedHtml.push(html);
|
|
2506
|
+
};
|
|
2507
|
+
dehydrateData = (key, getData) => {
|
|
2508
|
+
if (typeof document === 'undefined') {
|
|
2509
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2510
|
+
this.injectHtml(async () => {
|
|
2511
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2512
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2513
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2514
|
+
;(() => {
|
|
2515
|
+
var el = document.getElementById('${id}')
|
|
2516
|
+
el.parentElement.removeChild(el)
|
|
2517
|
+
})()
|
|
2518
|
+
</script>`;
|
|
2519
|
+
});
|
|
2520
|
+
return () => this.hydrateData(key);
|
|
2521
|
+
}
|
|
2522
|
+
return () => undefined;
|
|
2523
|
+
};
|
|
2524
|
+
hydrateData = key => {
|
|
2525
|
+
if (typeof document !== 'undefined') {
|
|
2526
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2527
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2528
|
+
}
|
|
2529
|
+
return undefined;
|
|
2560
2530
|
};
|
|
2561
2531
|
|
|
2562
|
-
//
|
|
2563
|
-
|
|
2532
|
+
// dehydrate = (): DehydratedRouter => {
|
|
2533
|
+
// return {
|
|
2534
|
+
// state: {
|
|
2535
|
+
// dehydratedMatches: this.state.matches.map((d) =>
|
|
2536
|
+
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
2537
|
+
// ),
|
|
2538
|
+
// },
|
|
2539
|
+
// }
|
|
2540
|
+
// }
|
|
2564
2541
|
|
|
2565
|
-
//
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2542
|
+
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
2543
|
+
// let _ctx = __do_not_use_server_ctx
|
|
2544
|
+
// // Client hydrates from window
|
|
2545
|
+
// if (typeof document !== 'undefined') {
|
|
2546
|
+
// _ctx = window.__TSR_DEHYDRATED__
|
|
2547
|
+
// }
|
|
2548
|
+
|
|
2549
|
+
// invariant(
|
|
2550
|
+
// _ctx,
|
|
2551
|
+
// 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
|
|
2552
|
+
// )
|
|
2553
|
+
|
|
2554
|
+
// const ctx = _ctx
|
|
2555
|
+
// this.dehydratedData = ctx.payload as any
|
|
2556
|
+
// this.options.hydrate?.(ctx.payload as any)
|
|
2557
|
+
// const dehydratedState = ctx.router.state
|
|
2558
|
+
|
|
2559
|
+
// let matches = this.matchRoutes(
|
|
2560
|
+
// this.state.location.pathname,
|
|
2561
|
+
// this.state.location.search,
|
|
2562
|
+
// ).map((match) => {
|
|
2563
|
+
// const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
2564
|
+
// (d) => d.id === match.id,
|
|
2565
|
+
// )
|
|
2566
|
+
|
|
2567
|
+
// invariant(
|
|
2568
|
+
// dehydratedMatch,
|
|
2569
|
+
// `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
2570
|
+
// )
|
|
2571
|
+
|
|
2572
|
+
// if (dehydratedMatch) {
|
|
2573
|
+
// return {
|
|
2574
|
+
// ...match,
|
|
2575
|
+
// ...dehydratedMatch,
|
|
2576
|
+
// }
|
|
2577
|
+
// }
|
|
2578
|
+
// return match
|
|
2579
|
+
// })
|
|
2580
|
+
|
|
2581
|
+
// this.setState((s) => {
|
|
2582
|
+
// return {
|
|
2583
|
+
// ...s,
|
|
2584
|
+
// matches: dehydratedState.dehydratedMatches as any,
|
|
2585
|
+
// }
|
|
2586
|
+
// })
|
|
2587
|
+
// }
|
|
2588
|
+
|
|
2589
|
+
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
2590
|
+
// state.matches
|
|
2591
|
+
// .find((d) => d.id === matchId)
|
|
2592
|
+
// ?.__promisesByKey[key]?.resolve(value)
|
|
2593
|
+
// }
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
// A function that takes an import() argument which is a function and returns a new function that will
|
|
2597
|
+
// proxy arguments from the caller to the imported function, retaining all type
|
|
2598
|
+
// information along the way
|
|
2599
|
+
function lazyFn(fn, key) {
|
|
2600
|
+
return async (...args) => {
|
|
2601
|
+
const imported = await fn();
|
|
2602
|
+
return imported[key || 'default'](...args);
|
|
2589
2603
|
};
|
|
2590
2604
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
ref: ref
|
|
2595
|
-
}, linkProps, {
|
|
2596
|
-
children: typeof props.children === 'function' ? props.children({
|
|
2597
|
-
isActive: linkProps['data-status'] === 'active'
|
|
2598
|
-
}) : props.children
|
|
2599
|
-
}));
|
|
2600
|
-
});
|
|
2605
|
+
function isCtrlEvent(e) {
|
|
2606
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
2607
|
+
}
|
|
2601
2608
|
|
|
2602
2609
|
const useLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
|
|
2603
2610
|
const windowKey = 'window';
|
|
@@ -2607,11 +2614,7 @@
|
|
|
2607
2614
|
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2608
2615
|
const defaultGetKey = location => location.state.key;
|
|
2609
2616
|
function useScrollRestoration(options) {
|
|
2610
|
-
const
|
|
2611
|
-
state,
|
|
2612
|
-
subscribe,
|
|
2613
|
-
resetNextScrollRef
|
|
2614
|
-
} = useRouter();
|
|
2617
|
+
const router = useRouter();
|
|
2615
2618
|
useLayoutEffect(() => {
|
|
2616
2619
|
const getKey = options?.getKey || defaultGetKey;
|
|
2617
2620
|
if (sessionsStorage) {
|
|
@@ -2667,7 +2670,7 @@
|
|
|
2667
2670
|
if (typeof document !== 'undefined') {
|
|
2668
2671
|
document.addEventListener('scroll', onScroll, true);
|
|
2669
2672
|
}
|
|
2670
|
-
const unsubOnBeforeLoad = subscribe('onBeforeLoad', event => {
|
|
2673
|
+
const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', event => {
|
|
2671
2674
|
if (event.pathChanged) {
|
|
2672
2675
|
const restoreKey = getKey(event.fromLocation);
|
|
2673
2676
|
for (const elementSelector in cache.state.next) {
|
|
@@ -2697,12 +2700,12 @@
|
|
|
2697
2700
|
}
|
|
2698
2701
|
}
|
|
2699
2702
|
});
|
|
2700
|
-
const unsubOnResolved = subscribe('onResolved', event => {
|
|
2703
|
+
const unsubOnResolved = router.subscribe('onResolved', event => {
|
|
2701
2704
|
if (event.pathChanged) {
|
|
2702
|
-
if (!
|
|
2705
|
+
if (!router.resetNextScroll) {
|
|
2703
2706
|
return;
|
|
2704
2707
|
}
|
|
2705
|
-
|
|
2708
|
+
router.resetNextScroll = true;
|
|
2706
2709
|
const getKey = options?.getKey || defaultGetKey;
|
|
2707
2710
|
const restoreKey = getKey(event.toLocation);
|
|
2708
2711
|
let windowRestored = false;
|