@tanstack/react-router 0.0.1-beta.184 → 0.0.1-beta.186
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 +319 -176
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +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,10 +279,20 @@
|
|
|
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);
|
|
283
|
-
const getLocation = () => parseLocation(getHref(), history.state);
|
|
295
|
+
const getLocation = () => parseLocation(getHref(), window.history.state);
|
|
284
296
|
return createHistory({
|
|
285
297
|
getLocation,
|
|
286
298
|
subscriber: onUpdate => {
|
|
@@ -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,174 @@
|
|
|
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(from.pathname, 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
|
+
const foundMask = this.options.routeMasks?.find(d => {
|
|
1928
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1929
|
+
to: d.from,
|
|
1930
|
+
fuzzy: false
|
|
1931
|
+
});
|
|
1932
|
+
if (match) {
|
|
1933
|
+
return match;
|
|
1934
|
+
}
|
|
1935
|
+
return false;
|
|
1936
|
+
});
|
|
1937
|
+
if (foundMask) {
|
|
1938
|
+
maskedDest = foundMask;
|
|
1939
|
+
maskedNext = build(maskedDest);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1943
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1944
|
+
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1945
|
+
const final = build(dest, nextMatches);
|
|
1946
|
+
if (maskedFinal) {
|
|
1947
|
+
final.maskedLocation = maskedFinal;
|
|
1948
|
+
}
|
|
1949
|
+
return final;
|
|
1950
|
+
};
|
|
1951
|
+
if (opts.mask) {
|
|
1952
|
+
return buildWithMatches(opts, {
|
|
1953
|
+
...pick(opts, ['from']),
|
|
1954
|
+
...opts.mask
|
|
1840
1955
|
});
|
|
1841
1956
|
}
|
|
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
|
-
};
|
|
1957
|
+
return buildWithMatches(opts);
|
|
1871
1958
|
};
|
|
1872
|
-
#
|
|
1873
|
-
|
|
1959
|
+
#buildAndCommitLocation = ({
|
|
1960
|
+
replace,
|
|
1961
|
+
resetScroll,
|
|
1962
|
+
...rest
|
|
1963
|
+
} = {}) => {
|
|
1964
|
+
const location = this.buildLocation(rest);
|
|
1965
|
+
return this.#commitLocation({
|
|
1966
|
+
...location,
|
|
1967
|
+
replace,
|
|
1968
|
+
resetScroll
|
|
1969
|
+
});
|
|
1970
|
+
};
|
|
1971
|
+
#commitLocation = async next => {
|
|
1874
1972
|
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1875
1973
|
let nextAction = 'replace';
|
|
1876
|
-
if (!
|
|
1974
|
+
if (!next.replace) {
|
|
1877
1975
|
nextAction = 'push';
|
|
1878
1976
|
}
|
|
1879
1977
|
const isSameUrl = this.state.location.href === next.href;
|
|
1880
|
-
if (isSameUrl
|
|
1978
|
+
if (isSameUrl) {
|
|
1881
1979
|
nextAction = 'replace';
|
|
1882
1980
|
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1981
|
+
let {
|
|
1982
|
+
maskedLocation,
|
|
1983
|
+
...nextHistory
|
|
1984
|
+
} = next;
|
|
1985
|
+
if (maskedLocation) {
|
|
1986
|
+
nextHistory = {
|
|
1987
|
+
...maskedLocation,
|
|
1988
|
+
state: {
|
|
1989
|
+
...maskedLocation.state,
|
|
1990
|
+
__tempKey: undefined,
|
|
1991
|
+
__tempLocation: {
|
|
1992
|
+
...nextHistory,
|
|
1993
|
+
search: nextHistory.searchStr,
|
|
1994
|
+
state: {
|
|
1995
|
+
...nextHistory.state,
|
|
1996
|
+
__tempKey: undefined,
|
|
1997
|
+
__tempLocation: undefined,
|
|
1998
|
+
key: undefined
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
};
|
|
2003
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
2004
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
this.history[nextAction === 'push' ? 'push' : 'replace'](nextHistory.href, nextHistory.state);
|
|
2008
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
1886
2009
|
return this.latestLoadPromise;
|
|
1887
2010
|
};
|
|
1888
2011
|
getRouteMatch = id => {
|
|
@@ -1931,25 +2054,26 @@
|
|
|
1931
2054
|
if (childMatch) {
|
|
1932
2055
|
return this.invalidate({
|
|
1933
2056
|
matchId: childMatch.id,
|
|
1934
|
-
reload: false
|
|
2057
|
+
reload: false,
|
|
2058
|
+
__fromFocus: opts.__fromFocus
|
|
1935
2059
|
});
|
|
1936
2060
|
}
|
|
1937
2061
|
} else {
|
|
1938
2062
|
this.__store.batch(() => {
|
|
1939
2063
|
Object.values(this.state.matchesById).forEach(match => {
|
|
1940
|
-
this.
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2064
|
+
const route = this.getRoute(match.routeId);
|
|
2065
|
+
const shouldInvalidate = opts?.__fromFocus ? route.options.reloadOnWindowFocus ?? true : true;
|
|
2066
|
+
if (shouldInvalidate) {
|
|
2067
|
+
this.setRouteMatch(match.id, s => ({
|
|
2068
|
+
...s,
|
|
2069
|
+
invalid: true
|
|
2070
|
+
}));
|
|
2071
|
+
}
|
|
1944
2072
|
});
|
|
1945
2073
|
});
|
|
1946
2074
|
}
|
|
1947
2075
|
if (opts?.reload ?? true) {
|
|
1948
|
-
return this.
|
|
1949
|
-
fromCurrent: true,
|
|
1950
|
-
replace: true,
|
|
1951
|
-
search: true
|
|
1952
|
-
});
|
|
2076
|
+
return this.load();
|
|
1953
2077
|
}
|
|
1954
2078
|
};
|
|
1955
2079
|
}
|
|
@@ -2016,7 +2140,7 @@
|
|
|
2016
2140
|
let cache;
|
|
2017
2141
|
let pathDidChange = false;
|
|
2018
2142
|
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2019
|
-
const defaultGetKey = location => location.key;
|
|
2143
|
+
const defaultGetKey = location => location.state.key;
|
|
2020
2144
|
function watchScrollPositions(router, opts) {
|
|
2021
2145
|
const getKey = opts?.getKey || defaultGetKey;
|
|
2022
2146
|
if (sessionsStorage) {
|
|
@@ -2252,6 +2376,8 @@
|
|
|
2252
2376
|
search,
|
|
2253
2377
|
params,
|
|
2254
2378
|
to = '.',
|
|
2379
|
+
state,
|
|
2380
|
+
mask,
|
|
2255
2381
|
preload,
|
|
2256
2382
|
preloadDelay,
|
|
2257
2383
|
replace,
|
|
@@ -2307,7 +2433,7 @@
|
|
|
2307
2433
|
...resolvedActiveProps,
|
|
2308
2434
|
...resolvedInactiveProps,
|
|
2309
2435
|
...rest,
|
|
2310
|
-
href: disabled ? undefined : next.href,
|
|
2436
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
2311
2437
|
onClick: composeHandlers([onClick, handleReactClick]),
|
|
2312
2438
|
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
2313
2439
|
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
@@ -2374,11 +2500,25 @@
|
|
|
2374
2500
|
return state.renderedMatchIds;
|
|
2375
2501
|
}
|
|
2376
2502
|
});
|
|
2503
|
+
const locationKey = useRouterState({
|
|
2504
|
+
select: d => d.resolvedLocation.state?.key
|
|
2505
|
+
});
|
|
2506
|
+
const route = router.getRoute(rootRouteId);
|
|
2507
|
+
const errorComponent = React__namespace.useCallback(props => {
|
|
2508
|
+
return /*#__PURE__*/React__namespace.createElement(ErrorComponent, {
|
|
2509
|
+
...props,
|
|
2510
|
+
useMatch: route.useMatch,
|
|
2511
|
+
useContext: route.useContext,
|
|
2512
|
+
useRouteContext: route.useRouteContext,
|
|
2513
|
+
useSearch: route.useSearch,
|
|
2514
|
+
useParams: route.useParams
|
|
2515
|
+
});
|
|
2516
|
+
}, [route]);
|
|
2377
2517
|
return /*#__PURE__*/React__namespace.createElement(matchIdsContext.Provider, {
|
|
2378
2518
|
value: [undefined, ...matchIds]
|
|
2379
2519
|
}, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
|
|
2380
|
-
|
|
2381
|
-
|
|
2520
|
+
resetKey: locationKey,
|
|
2521
|
+
errorComponent: errorComponent,
|
|
2382
2522
|
onCatch: () => {
|
|
2383
2523
|
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
2384
2524
|
}
|
|
@@ -2502,10 +2642,23 @@
|
|
|
2502
2642
|
const matchId = matchIds[0];
|
|
2503
2643
|
const routeId = router.getRouteMatch(matchId).routeId;
|
|
2504
2644
|
const route = router.getRoute(routeId);
|
|
2645
|
+
const locationKey = useRouterState({
|
|
2646
|
+
select: s => s.resolvedLocation.state?.key
|
|
2647
|
+
});
|
|
2505
2648
|
const PendingComponent = route.options.pendingComponent ?? router.options.defaultPendingComponent ?? defaultPending;
|
|
2506
|
-
const
|
|
2649
|
+
const routeErrorComponent = route.options.errorComponent ?? router.options.defaultErrorComponent ?? ErrorComponent;
|
|
2507
2650
|
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? !route.isRoot ? React__namespace.Suspense : SafeFragment;
|
|
2508
|
-
const ResolvedCatchBoundary = !!
|
|
2651
|
+
const ResolvedCatchBoundary = !!routeErrorComponent ? CatchBoundary : SafeFragment;
|
|
2652
|
+
const errorComponent = React__namespace.useCallback(props => {
|
|
2653
|
+
return /*#__PURE__*/React__namespace.createElement(routeErrorComponent, {
|
|
2654
|
+
...props,
|
|
2655
|
+
useMatch: route.useMatch,
|
|
2656
|
+
useContext: route.useContext,
|
|
2657
|
+
useRouteContext: route.useRouteContext,
|
|
2658
|
+
useSearch: route.useSearch,
|
|
2659
|
+
useParams: route.useParams
|
|
2660
|
+
});
|
|
2661
|
+
}, [route]);
|
|
2509
2662
|
return /*#__PURE__*/React__namespace.createElement(matchIdsContext.Provider, {
|
|
2510
2663
|
value: matchIds
|
|
2511
2664
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
|
|
@@ -2517,9 +2670,8 @@
|
|
|
2517
2670
|
useParams: route.useParams
|
|
2518
2671
|
})
|
|
2519
2672
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
|
|
2520
|
-
|
|
2673
|
+
resetKey: locationKey,
|
|
2521
2674
|
errorComponent: errorComponent,
|
|
2522
|
-
route: route,
|
|
2523
2675
|
onCatch: () => {
|
|
2524
2676
|
warning(false, `Error in route match: ${matchId}`);
|
|
2525
2677
|
}
|
|
@@ -2595,57 +2747,45 @@
|
|
|
2595
2747
|
// there has to be a better way to reset error boundaries when the
|
|
2596
2748
|
// router's location key changes.
|
|
2597
2749
|
|
|
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);
|
|
2750
|
+
function CatchBoundary(props) {
|
|
2622
2751
|
const errorComponent = props.errorComponent ?? ErrorComponent;
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2752
|
+
return /*#__PURE__*/React__namespace.createElement(CatchBoundaryImpl, {
|
|
2753
|
+
resetKey: props.resetKey,
|
|
2754
|
+
onCatch: props.onCatch,
|
|
2755
|
+
children: ({
|
|
2756
|
+
error
|
|
2757
|
+
}) => {
|
|
2758
|
+
if (error) {
|
|
2759
|
+
return /*#__PURE__*/React__namespace.createElement(errorComponent, {
|
|
2760
|
+
error
|
|
2761
|
+
});
|
|
2628
2762
|
}
|
|
2763
|
+
return props.children;
|
|
2629
2764
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
}
|
|
2765
|
+
});
|
|
2766
|
+
}
|
|
2767
|
+
class CatchBoundaryImpl extends React__namespace.Component {
|
|
2768
|
+
state = {
|
|
2769
|
+
error: null
|
|
2770
|
+
};
|
|
2771
|
+
static getDerivedStateFromError(error) {
|
|
2772
|
+
return {
|
|
2773
|
+
error
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
componentDidUpdate(prevProps, prevState) {
|
|
2777
|
+
if (prevState.error && prevProps.resetKey !== this.props.resetKey) {
|
|
2778
|
+
this.setState({
|
|
2779
|
+
error: null
|
|
2780
|
+
});
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
componentDidCatch(error) {
|
|
2784
|
+
this.props.onCatch?.(error);
|
|
2785
|
+
}
|
|
2786
|
+
render() {
|
|
2787
|
+
return this.props.children(this.state);
|
|
2647
2788
|
}
|
|
2648
|
-
return props.children;
|
|
2649
2789
|
}
|
|
2650
2790
|
function ErrorComponent({
|
|
2651
2791
|
error
|
|
@@ -2773,6 +2913,8 @@
|
|
|
2773
2913
|
|
|
2774
2914
|
exports.Await = Await;
|
|
2775
2915
|
exports.Block = Block;
|
|
2916
|
+
exports.CatchBoundary = CatchBoundary;
|
|
2917
|
+
exports.CatchBoundaryImpl = CatchBoundaryImpl;
|
|
2776
2918
|
exports.ErrorComponent = ErrorComponent;
|
|
2777
2919
|
exports.FileRoute = FileRoute;
|
|
2778
2920
|
exports.Link = Link;
|
|
@@ -2792,6 +2934,7 @@
|
|
|
2792
2934
|
exports.createBrowserHistory = createBrowserHistory;
|
|
2793
2935
|
exports.createHashHistory = createHashHistory;
|
|
2794
2936
|
exports.createMemoryHistory = createMemoryHistory;
|
|
2937
|
+
exports.createRouteMask = createRouteMask;
|
|
2795
2938
|
exports.decode = decode;
|
|
2796
2939
|
exports.defaultParseSearch = defaultParseSearch;
|
|
2797
2940
|
exports.defaultStringifySearch = defaultStringifySearch;
|