@tanstack/react-router 0.0.1-beta.185 → 0.0.1-beta.187
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/index.js +2 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/react.js +71 -53
- package/build/cjs/react.js.map +1 -1
- package/build/esm/index.js +70 -54
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +98 -98
- package/build/types/react.d.ts +43 -14
- package/build/umd/index.development.js +324 -175
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +4 -4
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/react.tsx +197 -104
|
@@ -236,11 +236,13 @@
|
|
|
236
236
|
};
|
|
237
237
|
},
|
|
238
238
|
push: (path, state) => {
|
|
239
|
+
assignKey(state);
|
|
239
240
|
queueTask(() => {
|
|
240
241
|
opts.pushState(path, state);
|
|
241
242
|
});
|
|
242
243
|
},
|
|
243
244
|
replace: (path, state) => {
|
|
245
|
+
assignKey(state);
|
|
244
246
|
queueTask(() => {
|
|
245
247
|
opts.replaceState(path, state);
|
|
246
248
|
});
|
|
@@ -277,6 +279,16 @@
|
|
|
277
279
|
}
|
|
278
280
|
};
|
|
279
281
|
}
|
|
282
|
+
function assignKey(state) {
|
|
283
|
+
state.key = createRandomKey();
|
|
284
|
+
// if (state.__actualLocation) {
|
|
285
|
+
// state.__actualLocation.state = {
|
|
286
|
+
// ...state.__actualLocation.state,
|
|
287
|
+
// key,
|
|
288
|
+
// }
|
|
289
|
+
// }
|
|
290
|
+
}
|
|
291
|
+
|
|
280
292
|
function createBrowserHistory(opts) {
|
|
281
293
|
const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.search}${window.location.hash}`);
|
|
282
294
|
const createHref = opts?.createHref ?? (path => path);
|
|
@@ -306,16 +318,10 @@
|
|
|
306
318
|
};
|
|
307
319
|
},
|
|
308
320
|
pushState: (path, state) => {
|
|
309
|
-
window.history.pushState(
|
|
310
|
-
...state,
|
|
311
|
-
key: createRandomKey()
|
|
312
|
-
}, '', createHref(path));
|
|
321
|
+
window.history.pushState(state, '', createHref(path));
|
|
313
322
|
},
|
|
314
323
|
replaceState: (path, state) => {
|
|
315
|
-
window.history.replaceState(
|
|
316
|
-
...state,
|
|
317
|
-
key: createRandomKey()
|
|
318
|
-
}, '', createHref(path));
|
|
324
|
+
window.history.replaceState(state, '', createHref(path));
|
|
319
325
|
},
|
|
320
326
|
back: () => window.history.back(),
|
|
321
327
|
forward: () => window.history.forward(),
|
|
@@ -334,24 +340,20 @@
|
|
|
334
340
|
}) {
|
|
335
341
|
const entries = opts.initialEntries;
|
|
336
342
|
let index = opts.initialIndex ?? entries.length - 1;
|
|
337
|
-
let currentState = {
|
|
343
|
+
let currentState = {
|
|
344
|
+
key: createRandomKey()
|
|
345
|
+
};
|
|
338
346
|
const getLocation = () => parseLocation(entries[index], currentState);
|
|
339
347
|
return createHistory({
|
|
340
348
|
getLocation,
|
|
341
349
|
subscriber: false,
|
|
342
350
|
pushState: (path, state) => {
|
|
343
|
-
currentState =
|
|
344
|
-
...state,
|
|
345
|
-
key: createRandomKey()
|
|
346
|
-
};
|
|
351
|
+
currentState = state;
|
|
347
352
|
entries.push(path);
|
|
348
353
|
index++;
|
|
349
354
|
},
|
|
350
355
|
replaceState: (path, state) => {
|
|
351
|
-
currentState =
|
|
352
|
-
...state,
|
|
353
|
-
key: createRandomKey()
|
|
354
|
-
};
|
|
356
|
+
currentState = state;
|
|
355
357
|
entries[index] = path;
|
|
356
358
|
},
|
|
357
359
|
back: () => {
|
|
@@ -372,7 +374,7 @@
|
|
|
372
374
|
pathname: href.substring(0, hashIndex > 0 ? searchIndex > 0 ? Math.min(hashIndex, searchIndex) : hashIndex : searchIndex > 0 ? searchIndex : href.length),
|
|
373
375
|
hash: hashIndex > -1 ? href.substring(hashIndex) : '',
|
|
374
376
|
search: searchIndex > -1 ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex) : '',
|
|
375
|
-
state
|
|
377
|
+
state: state || {}
|
|
376
378
|
};
|
|
377
379
|
}
|
|
378
380
|
|
|
@@ -381,6 +383,21 @@
|
|
|
381
383
|
return (Math.random() + 1).toString(36).substring(7);
|
|
382
384
|
}
|
|
383
385
|
|
|
386
|
+
// type Compute<T> = { [K in keyof T]: T[K] } | never
|
|
387
|
+
|
|
388
|
+
// type AllKeys<T> = T extends any ? keyof T : never
|
|
389
|
+
|
|
390
|
+
// export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<
|
|
391
|
+
// {
|
|
392
|
+
// [K in Keys]: T[Keys]
|
|
393
|
+
// } & {
|
|
394
|
+
// [K in AllKeys<T>]?: T extends any
|
|
395
|
+
// ? K extends keyof T
|
|
396
|
+
// ? T[K]
|
|
397
|
+
// : never
|
|
398
|
+
// : never
|
|
399
|
+
// }
|
|
400
|
+
// >
|
|
384
401
|
function last(arr) {
|
|
385
402
|
return arr[arr.length - 1];
|
|
386
403
|
}
|
|
@@ -790,6 +807,9 @@
|
|
|
790
807
|
super(options);
|
|
791
808
|
}
|
|
792
809
|
}
|
|
810
|
+
function createRouteMask(opts) {
|
|
811
|
+
return opts;
|
|
812
|
+
}
|
|
793
813
|
|
|
794
814
|
class FileRoute {
|
|
795
815
|
constructor(path) {
|
|
@@ -873,6 +893,9 @@
|
|
|
873
893
|
class Router {
|
|
874
894
|
#unsubHistory;
|
|
875
895
|
resetNextScroll = false;
|
|
896
|
+
tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
|
|
897
|
+
// nextTemporaryLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
898
|
+
|
|
876
899
|
constructor(options) {
|
|
877
900
|
this.options = {
|
|
878
901
|
defaultPreloadDelay: 50,
|
|
@@ -921,15 +944,15 @@
|
|
|
921
944
|
});
|
|
922
945
|
this.state = this.__store.state;
|
|
923
946
|
this.update(options);
|
|
924
|
-
const
|
|
925
|
-
hash: true,
|
|
926
|
-
fromCurrent: true,
|
|
947
|
+
const nextLocation = this.buildLocation({
|
|
927
948
|
search: true,
|
|
949
|
+
params: true,
|
|
950
|
+
hash: true,
|
|
928
951
|
state: true
|
|
929
952
|
});
|
|
930
|
-
if (this.state.location.href !==
|
|
953
|
+
if (this.state.location.href !== nextLocation.href) {
|
|
931
954
|
this.#commitLocation({
|
|
932
|
-
...
|
|
955
|
+
...nextLocation,
|
|
933
956
|
replace: true
|
|
934
957
|
});
|
|
935
958
|
}
|
|
@@ -972,8 +995,10 @@
|
|
|
972
995
|
};
|
|
973
996
|
};
|
|
974
997
|
#onFocus = () => {
|
|
975
|
-
if (this.options.
|
|
976
|
-
this.invalidate(
|
|
998
|
+
if (this.options.reloadOnWindowFocus ?? true) {
|
|
999
|
+
this.invalidate({
|
|
1000
|
+
__fromFocus: true
|
|
1001
|
+
});
|
|
977
1002
|
}
|
|
978
1003
|
};
|
|
979
1004
|
update = opts => {
|
|
@@ -1012,14 +1037,6 @@
|
|
|
1012
1037
|
}
|
|
1013
1038
|
return this;
|
|
1014
1039
|
};
|
|
1015
|
-
buildNext = opts => {
|
|
1016
|
-
const next = this.#buildLocation(opts);
|
|
1017
|
-
const __matches = this.matchRoutes(next.pathname, next.search);
|
|
1018
|
-
return this.#buildLocation({
|
|
1019
|
-
...opts,
|
|
1020
|
-
__matches
|
|
1021
|
-
});
|
|
1022
|
-
};
|
|
1023
1040
|
cancelMatches = () => {
|
|
1024
1041
|
this.state.matches.forEach(match => {
|
|
1025
1042
|
this.cancelMatch(match.id);
|
|
@@ -1078,7 +1095,7 @@
|
|
|
1078
1095
|
try {
|
|
1079
1096
|
// Load the matches
|
|
1080
1097
|
try {
|
|
1081
|
-
await this.loadMatches(pendingMatches);
|
|
1098
|
+
await this.loadMatches(pendingMatches.map(d => d.id));
|
|
1082
1099
|
} catch (err) {
|
|
1083
1100
|
// swallow this error, since we'll display the
|
|
1084
1101
|
// errors on the route components
|
|
@@ -1127,10 +1144,19 @@
|
|
|
1127
1144
|
return this.latestLoadPromise;
|
|
1128
1145
|
};
|
|
1129
1146
|
#mergeMatches = (prevMatchesById, nextMatches) => {
|
|
1130
|
-
|
|
1131
|
-
...prevMatchesById
|
|
1132
|
-
...Object.fromEntries(nextMatches.map(match => [match.id, match]))
|
|
1147
|
+
let matchesById = {
|
|
1148
|
+
...prevMatchesById
|
|
1133
1149
|
};
|
|
1150
|
+
nextMatches.forEach(match => {
|
|
1151
|
+
if (!matchesById[match.id]) {
|
|
1152
|
+
matchesById[match.id] = match;
|
|
1153
|
+
}
|
|
1154
|
+
matchesById[match.id] = {
|
|
1155
|
+
...matchesById[match.id],
|
|
1156
|
+
...match
|
|
1157
|
+
};
|
|
1158
|
+
});
|
|
1159
|
+
return matchesById;
|
|
1134
1160
|
};
|
|
1135
1161
|
getRoute = id => {
|
|
1136
1162
|
const route = this.routesById[id];
|
|
@@ -1138,7 +1164,7 @@
|
|
|
1138
1164
|
return route;
|
|
1139
1165
|
};
|
|
1140
1166
|
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
1141
|
-
|
|
1167
|
+
let next = this.buildLocation(navigateOpts);
|
|
1142
1168
|
const matches = this.matchRoutes(next.pathname, next.search, {
|
|
1143
1169
|
throwOnError: true
|
|
1144
1170
|
});
|
|
@@ -1148,11 +1174,11 @@
|
|
|
1148
1174
|
matchesById: this.#mergeMatches(s.matchesById, matches)
|
|
1149
1175
|
};
|
|
1150
1176
|
});
|
|
1151
|
-
await this.loadMatches(matches, {
|
|
1177
|
+
await this.loadMatches(matches.map(d => d.id), {
|
|
1152
1178
|
preload: true,
|
|
1153
1179
|
maxAge: navigateOpts.maxAge
|
|
1154
1180
|
});
|
|
1155
|
-
return matches;
|
|
1181
|
+
return [last(matches), matches];
|
|
1156
1182
|
};
|
|
1157
1183
|
cleanMatches = () => {
|
|
1158
1184
|
const now = Date.now();
|
|
@@ -1306,8 +1332,8 @@
|
|
|
1306
1332
|
});
|
|
1307
1333
|
return matches;
|
|
1308
1334
|
};
|
|
1309
|
-
loadMatches = async (
|
|
1310
|
-
const getFreshMatches = () =>
|
|
1335
|
+
loadMatches = async (matchIds, opts) => {
|
|
1336
|
+
const getFreshMatches = () => matchIds.map(d => this.getRouteMatch(d));
|
|
1311
1337
|
if (!opts?.preload) {
|
|
1312
1338
|
getFreshMatches().forEach(match => {
|
|
1313
1339
|
// Update each match with its latest route data
|
|
@@ -1387,8 +1413,9 @@
|
|
|
1387
1413
|
}
|
|
1388
1414
|
}
|
|
1389
1415
|
} catch (err) {
|
|
1390
|
-
if (
|
|
1391
|
-
this.navigate(err);
|
|
1416
|
+
if (isRedirect(err)) {
|
|
1417
|
+
if (!opts?.preload) this.navigate(err);
|
|
1418
|
+
return;
|
|
1392
1419
|
}
|
|
1393
1420
|
throw err;
|
|
1394
1421
|
}
|
|
@@ -1497,13 +1524,13 @@
|
|
|
1497
1524
|
isExternal = true;
|
|
1498
1525
|
} catch (e) {}
|
|
1499
1526
|
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1500
|
-
return this.#
|
|
1527
|
+
return this.#buildAndCommitLocation({
|
|
1501
1528
|
from: fromString,
|
|
1502
1529
|
to: toString,
|
|
1503
1530
|
search,
|
|
1504
1531
|
hash,
|
|
1505
|
-
replace,
|
|
1506
1532
|
params,
|
|
1533
|
+
replace,
|
|
1507
1534
|
resetScroll
|
|
1508
1535
|
});
|
|
1509
1536
|
};
|
|
@@ -1512,7 +1539,7 @@
|
|
|
1512
1539
|
...location,
|
|
1513
1540
|
to: location.to ? this.resolvePath(location.from ?? '', location.to) : undefined
|
|
1514
1541
|
};
|
|
1515
|
-
const next = this.
|
|
1542
|
+
const next = this.buildLocation(location);
|
|
1516
1543
|
if (opts?.pending && this.state.status !== 'pending') {
|
|
1517
1544
|
return false;
|
|
1518
1545
|
}
|
|
@@ -1545,6 +1572,7 @@
|
|
|
1545
1572
|
preloadDelay: userPreloadDelay,
|
|
1546
1573
|
disabled,
|
|
1547
1574
|
state,
|
|
1575
|
+
mask,
|
|
1548
1576
|
resetScroll
|
|
1549
1577
|
}) => {
|
|
1550
1578
|
// If this link simply reloads the current route,
|
|
@@ -1568,9 +1596,10 @@
|
|
|
1568
1596
|
hash,
|
|
1569
1597
|
replace,
|
|
1570
1598
|
state,
|
|
1599
|
+
mask,
|
|
1571
1600
|
resetScroll
|
|
1572
1601
|
};
|
|
1573
|
-
const next = this.
|
|
1602
|
+
const next = this.buildLocation(nextOpts);
|
|
1574
1603
|
preload = preload ?? this.options.defaultPreload;
|
|
1575
1604
|
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
1576
1605
|
|
|
@@ -1592,7 +1621,11 @@
|
|
|
1592
1621
|
e.preventDefault();
|
|
1593
1622
|
|
|
1594
1623
|
// All is well? Navigate!
|
|
1595
|
-
this.#commitLocation(
|
|
1624
|
+
this.#commitLocation({
|
|
1625
|
+
...next,
|
|
1626
|
+
replace,
|
|
1627
|
+
resetScroll
|
|
1628
|
+
});
|
|
1596
1629
|
}
|
|
1597
1630
|
};
|
|
1598
1631
|
|
|
@@ -1805,84 +1838,180 @@
|
|
|
1805
1838
|
});
|
|
1806
1839
|
};
|
|
1807
1840
|
#parseLocation = previousLocation => {
|
|
1808
|
-
|
|
1841
|
+
const parse = ({
|
|
1809
1842
|
pathname,
|
|
1810
1843
|
search,
|
|
1811
1844
|
hash,
|
|
1812
1845
|
state
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1846
|
+
}) => {
|
|
1847
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1848
|
+
return {
|
|
1849
|
+
pathname: pathname,
|
|
1850
|
+
searchStr: search,
|
|
1851
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1852
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1853
|
+
href: `${pathname}${search}${hash}`,
|
|
1854
|
+
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1855
|
+
};
|
|
1823
1856
|
};
|
|
1857
|
+
const location = parse(this.history.location);
|
|
1858
|
+
let {
|
|
1859
|
+
__tempLocation,
|
|
1860
|
+
__tempKey
|
|
1861
|
+
} = location.state;
|
|
1862
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
1863
|
+
// Sync up the location keys
|
|
1864
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
1865
|
+
parsedTempLocation.state.key = location.state.key;
|
|
1866
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
1867
|
+
return {
|
|
1868
|
+
...parsedTempLocation,
|
|
1869
|
+
maskedLocation: location
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
return location;
|
|
1824
1873
|
};
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1874
|
+
buildLocation = (opts = {}) => {
|
|
1875
|
+
const build = (dest = {}, matches) => {
|
|
1876
|
+
const from = this.state.location;
|
|
1877
|
+
const fromPathname = dest.from ?? from.pathname;
|
|
1878
|
+
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? ''}`);
|
|
1879
|
+
const fromMatches = this.matchRoutes(fromPathname, from.search);
|
|
1880
|
+
const prevParams = {
|
|
1881
|
+
...last(fromMatches)?.params
|
|
1882
|
+
};
|
|
1883
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1884
|
+
if (nextParams) {
|
|
1885
|
+
matches?.map(d => this.getRoute(d.routeId).options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1886
|
+
nextParams = {
|
|
1887
|
+
...nextParams,
|
|
1888
|
+
...fn(nextParams)
|
|
1889
|
+
};
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1893
|
+
const preSearchFilters = matches?.map(match => this.getRoute(match.routeId).options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1894
|
+
const postSearchFilters = matches?.map(match => this.getRoute(match.routeId).options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1895
|
+
|
|
1896
|
+
// Pre filters first
|
|
1897
|
+
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
|
|
1898
|
+
|
|
1899
|
+
// Then the link/navigate function
|
|
1900
|
+
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1901
|
+
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1902
|
+
: preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1903
|
+
: {};
|
|
1904
|
+
|
|
1905
|
+
// Then post filters
|
|
1906
|
+
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1907
|
+
const search = replaceEqualDeep(from.search, postFilteredSearch);
|
|
1908
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1909
|
+
const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
|
|
1910
|
+
const hashStr = hash ? `#${hash}` : '';
|
|
1911
|
+
let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
|
|
1912
|
+
nextState = replaceEqualDeep(from.state, nextState);
|
|
1913
|
+
return {
|
|
1914
|
+
pathname,
|
|
1915
|
+
search,
|
|
1916
|
+
searchStr,
|
|
1917
|
+
state: nextState,
|
|
1918
|
+
hash,
|
|
1919
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1920
|
+
unmaskOnReload: dest.unmaskOnReload
|
|
1921
|
+
};
|
|
1832
1922
|
};
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1923
|
+
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
1924
|
+
let next = build(dest);
|
|
1925
|
+
let maskedNext = maskedDest ? build(maskedDest) : undefined;
|
|
1926
|
+
if (!maskedNext) {
|
|
1927
|
+
let params = {};
|
|
1928
|
+
let foundMask = this.options.routeMasks?.find(d => {
|
|
1929
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1930
|
+
to: d.from,
|
|
1931
|
+
fuzzy: false
|
|
1932
|
+
});
|
|
1933
|
+
if (match) {
|
|
1934
|
+
params = match;
|
|
1935
|
+
return true;
|
|
1936
|
+
}
|
|
1937
|
+
return false;
|
|
1938
|
+
});
|
|
1939
|
+
if (foundMask) {
|
|
1940
|
+
foundMask = {
|
|
1941
|
+
...foundMask,
|
|
1942
|
+
from: interpolatePath(foundMask.from, params)
|
|
1943
|
+
};
|
|
1944
|
+
maskedDest = foundMask;
|
|
1945
|
+
maskedNext = build(maskedDest);
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1949
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1950
|
+
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1951
|
+
const final = build(dest, nextMatches);
|
|
1952
|
+
if (maskedFinal) {
|
|
1953
|
+
final.maskedLocation = maskedFinal;
|
|
1954
|
+
}
|
|
1955
|
+
return final;
|
|
1956
|
+
};
|
|
1957
|
+
if (opts.mask) {
|
|
1958
|
+
return buildWithMatches(opts, {
|
|
1959
|
+
...pick(opts, ['from']),
|
|
1960
|
+
...opts.mask
|
|
1840
1961
|
});
|
|
1841
1962
|
}
|
|
1842
|
-
|
|
1843
|
-
const preSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1844
|
-
const postSearchFilters = dest.__matches?.map(match => this.getRoute(match.routeId).options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1845
|
-
|
|
1846
|
-
// Pre filters first
|
|
1847
|
-
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), this.state.location.search) : this.state.location.search;
|
|
1848
|
-
|
|
1849
|
-
// Then the link/navigate function
|
|
1850
|
-
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
1851
|
-
: dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
|
|
1852
|
-
: preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
|
|
1853
|
-
: {};
|
|
1854
|
-
|
|
1855
|
-
// Then post filters
|
|
1856
|
-
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1857
|
-
const search = replaceEqualDeep(this.state.location.search, postFilteredSearch);
|
|
1858
|
-
const searchStr = this.options.stringifySearch(search);
|
|
1859
|
-
const hash = dest.hash === true ? this.state.location.hash : functionalUpdate(dest.hash, this.state.location.hash);
|
|
1860
|
-
const hashStr = hash ? `#${hash}` : '';
|
|
1861
|
-
const nextState = dest.state === true ? this.state.location.state : functionalUpdate(dest.state, this.state.location.state);
|
|
1862
|
-
return {
|
|
1863
|
-
pathname,
|
|
1864
|
-
search,
|
|
1865
|
-
searchStr,
|
|
1866
|
-
state: nextState,
|
|
1867
|
-
hash,
|
|
1868
|
-
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1869
|
-
key: dest.key
|
|
1870
|
-
};
|
|
1963
|
+
return buildWithMatches(opts);
|
|
1871
1964
|
};
|
|
1872
|
-
#
|
|
1873
|
-
|
|
1965
|
+
#buildAndCommitLocation = ({
|
|
1966
|
+
replace,
|
|
1967
|
+
resetScroll,
|
|
1968
|
+
...rest
|
|
1969
|
+
} = {}) => {
|
|
1970
|
+
const location = this.buildLocation(rest);
|
|
1971
|
+
return this.#commitLocation({
|
|
1972
|
+
...location,
|
|
1973
|
+
replace,
|
|
1974
|
+
resetScroll
|
|
1975
|
+
});
|
|
1976
|
+
};
|
|
1977
|
+
#commitLocation = async next => {
|
|
1874
1978
|
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1875
1979
|
let nextAction = 'replace';
|
|
1876
|
-
if (!
|
|
1980
|
+
if (!next.replace) {
|
|
1877
1981
|
nextAction = 'push';
|
|
1878
1982
|
}
|
|
1879
1983
|
const isSameUrl = this.state.location.href === next.href;
|
|
1880
|
-
if (isSameUrl
|
|
1984
|
+
if (isSameUrl) {
|
|
1881
1985
|
nextAction = 'replace';
|
|
1882
1986
|
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1987
|
+
let {
|
|
1988
|
+
maskedLocation,
|
|
1989
|
+
...nextHistory
|
|
1990
|
+
} = next;
|
|
1991
|
+
if (maskedLocation) {
|
|
1992
|
+
nextHistory = {
|
|
1993
|
+
...maskedLocation,
|
|
1994
|
+
state: {
|
|
1995
|
+
...maskedLocation.state,
|
|
1996
|
+
__tempKey: undefined,
|
|
1997
|
+
__tempLocation: {
|
|
1998
|
+
...nextHistory,
|
|
1999
|
+
search: nextHistory.searchStr,
|
|
2000
|
+
state: {
|
|
2001
|
+
...nextHistory.state,
|
|
2002
|
+
__tempKey: undefined,
|
|
2003
|
+
__tempLocation: undefined,
|
|
2004
|
+
key: undefined
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
2010
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
this.history[nextAction === 'push' ? 'push' : 'replace'](nextHistory.href, nextHistory.state);
|
|
2014
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
1886
2015
|
return this.latestLoadPromise;
|
|
1887
2016
|
};
|
|
1888
2017
|
getRouteMatch = id => {
|
|
@@ -1931,25 +2060,26 @@
|
|
|
1931
2060
|
if (childMatch) {
|
|
1932
2061
|
return this.invalidate({
|
|
1933
2062
|
matchId: childMatch.id,
|
|
1934
|
-
reload: false
|
|
2063
|
+
reload: false,
|
|
2064
|
+
__fromFocus: opts.__fromFocus
|
|
1935
2065
|
});
|
|
1936
2066
|
}
|
|
1937
2067
|
} else {
|
|
1938
2068
|
this.__store.batch(() => {
|
|
1939
2069
|
Object.values(this.state.matchesById).forEach(match => {
|
|
1940
|
-
this.
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2070
|
+
const route = this.getRoute(match.routeId);
|
|
2071
|
+
const shouldInvalidate = opts?.__fromFocus ? route.options.reloadOnWindowFocus ?? true : true;
|
|
2072
|
+
if (shouldInvalidate) {
|
|
2073
|
+
this.setRouteMatch(match.id, s => ({
|
|
2074
|
+
...s,
|
|
2075
|
+
invalid: true
|
|
2076
|
+
}));
|
|
2077
|
+
}
|
|
1944
2078
|
});
|
|
1945
2079
|
});
|
|
1946
2080
|
}
|
|
1947
2081
|
if (opts?.reload ?? true) {
|
|
1948
|
-
return this.
|
|
1949
|
-
fromCurrent: true,
|
|
1950
|
-
replace: true,
|
|
1951
|
-
search: true
|
|
1952
|
-
});
|
|
2082
|
+
return this.load();
|
|
1953
2083
|
}
|
|
1954
2084
|
};
|
|
1955
2085
|
}
|
|
@@ -2016,7 +2146,7 @@
|
|
|
2016
2146
|
let cache;
|
|
2017
2147
|
let pathDidChange = false;
|
|
2018
2148
|
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2019
|
-
const defaultGetKey = location => location.key;
|
|
2149
|
+
const defaultGetKey = location => location.state.key;
|
|
2020
2150
|
function watchScrollPositions(router, opts) {
|
|
2021
2151
|
const getKey = opts?.getKey || defaultGetKey;
|
|
2022
2152
|
if (sessionsStorage) {
|
|
@@ -2252,6 +2382,8 @@
|
|
|
2252
2382
|
search,
|
|
2253
2383
|
params,
|
|
2254
2384
|
to = '.',
|
|
2385
|
+
state,
|
|
2386
|
+
mask,
|
|
2255
2387
|
preload,
|
|
2256
2388
|
preloadDelay,
|
|
2257
2389
|
replace,
|
|
@@ -2307,7 +2439,7 @@
|
|
|
2307
2439
|
...resolvedActiveProps,
|
|
2308
2440
|
...resolvedInactiveProps,
|
|
2309
2441
|
...rest,
|
|
2310
|
-
href: disabled ? undefined : next.href,
|
|
2442
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
2311
2443
|
onClick: composeHandlers([onClick, handleReactClick]),
|
|
2312
2444
|
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
2313
2445
|
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
@@ -2374,11 +2506,25 @@
|
|
|
2374
2506
|
return state.renderedMatchIds;
|
|
2375
2507
|
}
|
|
2376
2508
|
});
|
|
2509
|
+
const locationKey = useRouterState({
|
|
2510
|
+
select: d => d.resolvedLocation.state?.key
|
|
2511
|
+
});
|
|
2512
|
+
const route = router.getRoute(rootRouteId);
|
|
2513
|
+
const errorComponent = React__namespace.useCallback(props => {
|
|
2514
|
+
return /*#__PURE__*/React__namespace.createElement(ErrorComponent, {
|
|
2515
|
+
...props,
|
|
2516
|
+
useMatch: route.useMatch,
|
|
2517
|
+
useContext: route.useContext,
|
|
2518
|
+
useRouteContext: route.useRouteContext,
|
|
2519
|
+
useSearch: route.useSearch,
|
|
2520
|
+
useParams: route.useParams
|
|
2521
|
+
});
|
|
2522
|
+
}, [route]);
|
|
2377
2523
|
return /*#__PURE__*/React__namespace.createElement(matchIdsContext.Provider, {
|
|
2378
2524
|
value: [undefined, ...matchIds]
|
|
2379
2525
|
}, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
|
|
2380
|
-
|
|
2381
|
-
|
|
2526
|
+
resetKey: locationKey,
|
|
2527
|
+
errorComponent: errorComponent,
|
|
2382
2528
|
onCatch: () => {
|
|
2383
2529
|
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
2384
2530
|
}
|
|
@@ -2502,10 +2648,23 @@
|
|
|
2502
2648
|
const matchId = matchIds[0];
|
|
2503
2649
|
const routeId = router.getRouteMatch(matchId).routeId;
|
|
2504
2650
|
const route = router.getRoute(routeId);
|
|
2651
|
+
const locationKey = useRouterState({
|
|
2652
|
+
select: s => s.resolvedLocation.state?.key
|
|
2653
|
+
});
|
|
2505
2654
|
const PendingComponent = route.options.pendingComponent ?? router.options.defaultPendingComponent ?? defaultPending;
|
|
2506
|
-
const
|
|
2655
|
+
const routeErrorComponent = route.options.errorComponent ?? router.options.defaultErrorComponent ?? ErrorComponent;
|
|
2507
2656
|
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? !route.isRoot ? React__namespace.Suspense : SafeFragment;
|
|
2508
|
-
const ResolvedCatchBoundary = !!
|
|
2657
|
+
const ResolvedCatchBoundary = !!routeErrorComponent ? CatchBoundary : SafeFragment;
|
|
2658
|
+
const errorComponent = React__namespace.useCallback(props => {
|
|
2659
|
+
return /*#__PURE__*/React__namespace.createElement(routeErrorComponent, {
|
|
2660
|
+
...props,
|
|
2661
|
+
useMatch: route.useMatch,
|
|
2662
|
+
useContext: route.useContext,
|
|
2663
|
+
useRouteContext: route.useRouteContext,
|
|
2664
|
+
useSearch: route.useSearch,
|
|
2665
|
+
useParams: route.useParams
|
|
2666
|
+
});
|
|
2667
|
+
}, [route]);
|
|
2509
2668
|
return /*#__PURE__*/React__namespace.createElement(matchIdsContext.Provider, {
|
|
2510
2669
|
value: matchIds
|
|
2511
2670
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
|
|
@@ -2517,9 +2676,8 @@
|
|
|
2517
2676
|
useParams: route.useParams
|
|
2518
2677
|
})
|
|
2519
2678
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
|
|
2520
|
-
|
|
2679
|
+
resetKey: locationKey,
|
|
2521
2680
|
errorComponent: errorComponent,
|
|
2522
|
-
route: route,
|
|
2523
2681
|
onCatch: () => {
|
|
2524
2682
|
warning(false, `Error in route match: ${matchId}`);
|
|
2525
2683
|
}
|
|
@@ -2595,57 +2753,45 @@
|
|
|
2595
2753
|
// there has to be a better way to reset error boundaries when the
|
|
2596
2754
|
// router's location key changes.
|
|
2597
2755
|
|
|
2598
|
-
|
|
2599
|
-
state = {
|
|
2600
|
-
error: false,
|
|
2601
|
-
info: undefined
|
|
2602
|
-
};
|
|
2603
|
-
componentDidCatch(error, info) {
|
|
2604
|
-
this.props.onCatch(error, info);
|
|
2605
|
-
this.setState({
|
|
2606
|
-
error,
|
|
2607
|
-
info
|
|
2608
|
-
});
|
|
2609
|
-
}
|
|
2610
|
-
render() {
|
|
2611
|
-
return /*#__PURE__*/React__namespace.createElement(CatchBoundaryInner, _extends({}, this.props, {
|
|
2612
|
-
errorState: this.state,
|
|
2613
|
-
reset: () => this.setState({})
|
|
2614
|
-
}));
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
function CatchBoundaryInner(props) {
|
|
2618
|
-
const locationKey = useRouterState({
|
|
2619
|
-
select: d => d.resolvedLocation.key
|
|
2620
|
-
});
|
|
2621
|
-
const [activeErrorState, setActiveErrorState] = React__namespace.useState(props.errorState);
|
|
2756
|
+
function CatchBoundary(props) {
|
|
2622
2757
|
const errorComponent = props.errorComponent ?? ErrorComponent;
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2758
|
+
return /*#__PURE__*/React__namespace.createElement(CatchBoundaryImpl, {
|
|
2759
|
+
resetKey: props.resetKey,
|
|
2760
|
+
onCatch: props.onCatch,
|
|
2761
|
+
children: ({
|
|
2762
|
+
error
|
|
2763
|
+
}) => {
|
|
2764
|
+
if (error) {
|
|
2765
|
+
return /*#__PURE__*/React__namespace.createElement(errorComponent, {
|
|
2766
|
+
error
|
|
2767
|
+
});
|
|
2628
2768
|
}
|
|
2769
|
+
return props.children;
|
|
2629
2770
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
}
|
|
2771
|
+
});
|
|
2772
|
+
}
|
|
2773
|
+
class CatchBoundaryImpl extends React__namespace.Component {
|
|
2774
|
+
state = {
|
|
2775
|
+
error: null
|
|
2776
|
+
};
|
|
2777
|
+
static getDerivedStateFromError(error) {
|
|
2778
|
+
return {
|
|
2779
|
+
error
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
componentDidUpdate(prevProps, prevState) {
|
|
2783
|
+
if (prevState.error && prevProps.resetKey !== this.props.resetKey) {
|
|
2784
|
+
this.setState({
|
|
2785
|
+
error: null
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
componentDidCatch(error) {
|
|
2790
|
+
this.props.onCatch?.(error);
|
|
2791
|
+
}
|
|
2792
|
+
render() {
|
|
2793
|
+
return this.props.children(this.state);
|
|
2647
2794
|
}
|
|
2648
|
-
return props.children;
|
|
2649
2795
|
}
|
|
2650
2796
|
function ErrorComponent({
|
|
2651
2797
|
error
|
|
@@ -2773,6 +2919,8 @@
|
|
|
2773
2919
|
|
|
2774
2920
|
exports.Await = Await;
|
|
2775
2921
|
exports.Block = Block;
|
|
2922
|
+
exports.CatchBoundary = CatchBoundary;
|
|
2923
|
+
exports.CatchBoundaryImpl = CatchBoundaryImpl;
|
|
2776
2924
|
exports.ErrorComponent = ErrorComponent;
|
|
2777
2925
|
exports.FileRoute = FileRoute;
|
|
2778
2926
|
exports.Link = Link;
|
|
@@ -2792,6 +2940,7 @@
|
|
|
2792
2940
|
exports.createBrowserHistory = createBrowserHistory;
|
|
2793
2941
|
exports.createHashHistory = createHashHistory;
|
|
2794
2942
|
exports.createMemoryHistory = createMemoryHistory;
|
|
2943
|
+
exports.createRouteMask = createRouteMask;
|
|
2795
2944
|
exports.decode = decode;
|
|
2796
2945
|
exports.defaultParseSearch = defaultParseSearch;
|
|
2797
2946
|
exports.defaultStringifySearch = defaultStringifySearch;
|