@tanstack/router-core 0.0.1-beta.173 → 0.0.1-beta.175
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 +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +60 -36
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +59 -36
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +158 -191
- package/build/types/defer.d.ts +19 -0
- package/build/types/fileRoute.d.ts +35 -0
- package/build/types/history.d.ts +31 -0
- package/build/types/index.d.ts +12 -780
- package/build/types/link.d.ts +92 -0
- package/build/types/path.d.ts +16 -0
- package/build/types/qss.d.ts +2 -0
- package/build/types/route.d.ts +234 -0
- package/build/types/routeInfo.d.ts +22 -0
- package/build/types/router.d.ts +251 -0
- package/build/types/scroll-restoration.d.ts +6 -0
- package/build/types/searchParams.d.ts +5 -0
- package/build/types/utils.d.ts +53 -0
- package/build/umd/index.development.js +60 -36
- 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 +3 -3
- package/src/route.ts +12 -16
- package/src/router.ts +122 -79
package/build/esm/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import invariant from 'tiny-invariant';
|
|
12
12
|
export { default as invariant } from 'tiny-invariant';
|
|
13
13
|
export { default as warning } from 'tiny-warning';
|
|
14
|
-
import { Store } from '@tanstack/
|
|
14
|
+
import { Store } from '@tanstack/store';
|
|
15
15
|
|
|
16
16
|
// While the public API was clearly inspired by the "history" npm package,
|
|
17
17
|
// This implementation attempts to be more lightweight by
|
|
@@ -709,6 +709,8 @@ function stringifySearchWith(stringify, parser) {
|
|
|
709
709
|
//
|
|
710
710
|
|
|
711
711
|
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
712
|
+
const visibilityChangeEvent = 'visibilitychange';
|
|
713
|
+
const focusEvent = 'focus';
|
|
712
714
|
class Router {
|
|
713
715
|
#unsubHistory;
|
|
714
716
|
resetNextScroll = false;
|
|
@@ -785,12 +787,26 @@ class Router {
|
|
|
785
787
|
this.__store.setState(s => Object.assign(s, getInitialRouterState()));
|
|
786
788
|
};
|
|
787
789
|
mount = () => {
|
|
788
|
-
//
|
|
789
|
-
//
|
|
790
|
+
// addEventListener does not exist in React Native, but window does
|
|
791
|
+
// In the future, we might need to invert control here for more adapters
|
|
792
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
793
|
+
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
794
|
+
window.addEventListener(visibilityChangeEvent, this.#onFocus, false);
|
|
795
|
+
window.addEventListener(focusEvent, this.#onFocus, false);
|
|
796
|
+
}
|
|
790
797
|
this.safeLoad();
|
|
791
|
-
|
|
798
|
+
return () => {
|
|
799
|
+
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
800
|
+
window.removeEventListener(visibilityChangeEvent, this.#onFocus);
|
|
801
|
+
window.removeEventListener(focusEvent, this.#onFocus);
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
};
|
|
805
|
+
#onFocus = () => {
|
|
806
|
+
if (this.options.refetchOnWindowFocus ?? true) {
|
|
807
|
+
this.reload();
|
|
808
|
+
}
|
|
792
809
|
};
|
|
793
|
-
|
|
794
810
|
update = opts => {
|
|
795
811
|
this.options = {
|
|
796
812
|
...this.options,
|
|
@@ -861,7 +877,6 @@ class Router {
|
|
|
861
877
|
};
|
|
862
878
|
|
|
863
879
|
// Cancel any pending matches
|
|
864
|
-
// this.cancelMatches()
|
|
865
880
|
|
|
866
881
|
let pendingMatches;
|
|
867
882
|
this.#emit({
|
|
@@ -904,6 +919,9 @@ class Router {
|
|
|
904
919
|
if (latestPromise = checkLatest()) {
|
|
905
920
|
return latestPromise;
|
|
906
921
|
}
|
|
922
|
+
const exitingMatchIds = this.state.matchIds.filter(id => !this.state.pendingMatchIds.includes(id));
|
|
923
|
+
const enteringMatchIds = this.state.pendingMatchIds.filter(id => !this.state.matchIds.includes(id));
|
|
924
|
+
const stayingMatchIds = this.state.matchIds.filter(id => this.state.pendingMatchIds.includes(id));
|
|
907
925
|
this.__store.setState(s => ({
|
|
908
926
|
...s,
|
|
909
927
|
status: 'idle',
|
|
@@ -911,6 +929,13 @@ class Router {
|
|
|
911
929
|
matchIds: s.pendingMatchIds,
|
|
912
930
|
pendingMatchIds: []
|
|
913
931
|
}));
|
|
932
|
+
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matchIds, hook]) => {
|
|
933
|
+
matchIds.forEach(id => {
|
|
934
|
+
const match = this.getRouteMatch(id);
|
|
935
|
+
const route = this.getRoute(match.routeId);
|
|
936
|
+
route.options[hook]?.(match);
|
|
937
|
+
});
|
|
938
|
+
});
|
|
914
939
|
this.#emit({
|
|
915
940
|
type: 'onLoad',
|
|
916
941
|
from: prevLocation,
|
|
@@ -927,6 +952,9 @@ class Router {
|
|
|
927
952
|
}
|
|
928
953
|
});
|
|
929
954
|
this.latestLoadPromise = promise;
|
|
955
|
+
this.latestLoadPromise.then(() => {
|
|
956
|
+
this.cleanMatches();
|
|
957
|
+
});
|
|
930
958
|
return this.latestLoadPromise;
|
|
931
959
|
};
|
|
932
960
|
#mergeMatches = (prevMatchesById, nextMatches) => {
|
|
@@ -971,7 +999,7 @@ class Router {
|
|
|
971
999
|
const now = Date.now();
|
|
972
1000
|
const outdatedMatchIds = Object.values(this.state.matchesById).filter(match => {
|
|
973
1001
|
const route = this.getRoute(match.routeId);
|
|
974
|
-
return !this.state.matchIds.includes(match.id) && !this.state.pendingMatchIds.includes(match.id) && match.
|
|
1002
|
+
return !this.state.matchIds.includes(match.id) && !this.state.pendingMatchIds.includes(match.id) && (match.preloadMaxAge > -1 ? match.updatedAt + match.preloadMaxAge < now : true) && (route.options.gcMaxAge ? match.updatedAt + route.options.gcMaxAge < now : true);
|
|
975
1003
|
}).map(d => d.id);
|
|
976
1004
|
if (outdatedMatchIds.length) {
|
|
977
1005
|
this.__store.setState(s => {
|
|
@@ -1059,8 +1087,8 @@ class Router {
|
|
|
1059
1087
|
params: routeParams,
|
|
1060
1088
|
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1061
1089
|
updatedAt: Date.now(),
|
|
1062
|
-
|
|
1063
|
-
|
|
1090
|
+
maxAge: -1,
|
|
1091
|
+
preloadMaxAge: -1,
|
|
1064
1092
|
routeSearch: {},
|
|
1065
1093
|
search: {},
|
|
1066
1094
|
status: hasLoaders ? 'pending' : 'success',
|
|
@@ -1156,11 +1184,13 @@ class Router {
|
|
|
1156
1184
|
paramsError: match.paramsError,
|
|
1157
1185
|
searchError: match.searchError,
|
|
1158
1186
|
params: match.params,
|
|
1159
|
-
|
|
1187
|
+
preloadMaxAge: 0
|
|
1160
1188
|
}));
|
|
1161
1189
|
});
|
|
1190
|
+
} else {
|
|
1191
|
+
// If we're preloading, clean preload matches before we try and use them
|
|
1192
|
+
this.cleanMatches();
|
|
1162
1193
|
}
|
|
1163
|
-
this.cleanMatches();
|
|
1164
1194
|
let firstBadMatchIndex;
|
|
1165
1195
|
|
|
1166
1196
|
// Check each match middleware to see if the route can be accessed
|
|
@@ -1222,8 +1252,7 @@ class Router {
|
|
|
1222
1252
|
matchPromises.push((async () => {
|
|
1223
1253
|
const parentMatchPromise = matchPromises[index - 1];
|
|
1224
1254
|
const route = this.getRoute(match.routeId);
|
|
1225
|
-
if (match.isFetching || match.status === 'success' && !
|
|
1226
|
-
matchId: match.id,
|
|
1255
|
+
if (match.isFetching || match.status === 'success' && !isMatchInvalid(match, {
|
|
1227
1256
|
preload: opts?.preload
|
|
1228
1257
|
})) {
|
|
1229
1258
|
return this.getRouteMatch(match.id)?.loadPromise;
|
|
@@ -1296,7 +1325,6 @@ class Router {
|
|
|
1296
1325
|
})());
|
|
1297
1326
|
});
|
|
1298
1327
|
await Promise.all(matchPromises);
|
|
1299
|
-
this.cleanMatches();
|
|
1300
1328
|
};
|
|
1301
1329
|
reload = () => {
|
|
1302
1330
|
return this.navigate({
|
|
@@ -1481,7 +1509,7 @@ class Router {
|
|
|
1481
1509
|
dehydrate = () => {
|
|
1482
1510
|
return {
|
|
1483
1511
|
state: {
|
|
1484
|
-
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', '
|
|
1512
|
+
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', 'preloadMaxAge', 'maxAge', 'id', 'loaderData', 'status', 'updatedAt']))
|
|
1485
1513
|
}
|
|
1486
1514
|
};
|
|
1487
1515
|
};
|
|
@@ -1720,7 +1748,6 @@ class Router {
|
|
|
1720
1748
|
...next.state
|
|
1721
1749
|
});
|
|
1722
1750
|
this.resetNextScroll = location.resetScroll ?? true;
|
|
1723
|
-
console.log('resetScroll', this.resetNextScroll);
|
|
1724
1751
|
return this.latestLoadPromise;
|
|
1725
1752
|
};
|
|
1726
1753
|
getRouteMatch = id => {
|
|
@@ -1745,17 +1772,17 @@ class Router {
|
|
|
1745
1772
|
if (!match) return;
|
|
1746
1773
|
const route = this.getRoute(match.routeId);
|
|
1747
1774
|
const updatedAt = opts?.updatedAt ?? Date.now();
|
|
1748
|
-
const
|
|
1749
|
-
const
|
|
1775
|
+
const preloadMaxAge = opts?.maxAge ?? route.options.preloadMaxAge ?? this.options.defaultPreloadMaxAge ?? 5000;
|
|
1776
|
+
const maxAge = opts?.maxAge ?? route.options.maxAge ?? this.options.defaultMaxAge ?? -1;
|
|
1750
1777
|
this.setRouteMatch(id, s => ({
|
|
1751
1778
|
...s,
|
|
1752
1779
|
error: undefined,
|
|
1753
1780
|
status: 'success',
|
|
1754
1781
|
isFetching: false,
|
|
1755
|
-
updatedAt:
|
|
1782
|
+
updatedAt: updatedAt,
|
|
1756
1783
|
loaderData: functionalUpdate(updater, s.loaderData),
|
|
1757
|
-
|
|
1758
|
-
|
|
1784
|
+
preloadMaxAge,
|
|
1785
|
+
maxAge
|
|
1759
1786
|
}));
|
|
1760
1787
|
};
|
|
1761
1788
|
invalidate = async opts => {
|
|
@@ -1786,20 +1813,6 @@ class Router {
|
|
|
1786
1813
|
return this.reload();
|
|
1787
1814
|
}
|
|
1788
1815
|
};
|
|
1789
|
-
getIsInvalid = opts => {
|
|
1790
|
-
if (!opts?.matchId) {
|
|
1791
|
-
return !!this.state.matches.find(d => this.getIsInvalid({
|
|
1792
|
-
matchId: d.id,
|
|
1793
|
-
preload: opts?.preload
|
|
1794
|
-
}));
|
|
1795
|
-
}
|
|
1796
|
-
const match = this.getRouteMatch(opts?.matchId);
|
|
1797
|
-
if (!match) {
|
|
1798
|
-
return false;
|
|
1799
|
-
}
|
|
1800
|
-
const now = Date.now();
|
|
1801
|
-
return match.invalid || (opts?.preload ? match.preloadInvalidAt : match.invalidAt) < now;
|
|
1802
|
-
};
|
|
1803
1816
|
}
|
|
1804
1817
|
|
|
1805
1818
|
// Detect if we're in the DOM
|
|
@@ -1845,6 +1858,16 @@ function lazyFn(fn, key) {
|
|
|
1845
1858
|
return imported[key || 'default'](...args);
|
|
1846
1859
|
};
|
|
1847
1860
|
}
|
|
1861
|
+
function isMatchInvalid(match, opts) {
|
|
1862
|
+
const now = Date.now();
|
|
1863
|
+
if (match.invalid) {
|
|
1864
|
+
return true;
|
|
1865
|
+
}
|
|
1866
|
+
if (opts?.preload) {
|
|
1867
|
+
return match.preloadMaxAge < 0 ? false : match.updatedAt + match.preloadMaxAge < now;
|
|
1868
|
+
}
|
|
1869
|
+
return match.maxAge < 0 ? false : match.updatedAt + match.maxAge < now;
|
|
1870
|
+
}
|
|
1848
1871
|
|
|
1849
1872
|
const windowKey = 'window';
|
|
1850
1873
|
const delimiter = '___';
|
|
@@ -1990,5 +2013,5 @@ function isDehydratedDeferred(obj) {
|
|
|
1990
2013
|
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
1991
2014
|
}
|
|
1992
2015
|
|
|
1993
|
-
export { FileRoute, PathParamError, RootRoute, Route, Router, RouterContext, SearchParamError, cleanPath, componentTypes, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultParseSearch, defaultStringifySearch, defer, encode, functionalUpdate, interpolatePath, isDehydratedDeferred, isPlainObject, isRedirect, joinPaths, last, lazyFn, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, restoreScrollPositions, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, watchScrollPositions };
|
|
2016
|
+
export { FileRoute, PathParamError, RootRoute, Route, Router, RouterContext, SearchParamError, cleanPath, componentTypes, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultParseSearch, defaultStringifySearch, defer, encode, functionalUpdate, interpolatePath, isDehydratedDeferred, isMatchInvalid, isPlainObject, isRedirect, joinPaths, last, lazyFn, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, restoreScrollPositions, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, watchScrollPositions };
|
|
1994
2017
|
//# sourceMappingURL=index.js.map
|