@tanstack/react-router 0.0.1-alpha.1 → 0.0.1-alpha.11

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.
@@ -70,23 +70,6 @@ function _extends$1() {
70
70
  return _extends$1.apply(this, arguments);
71
71
  }
72
72
 
73
- function _extends() {
74
- _extends = Object.assign ? Object.assign.bind() : function (target) {
75
- for (var i = 1; i < arguments.length; i++) {
76
- var source = arguments[i];
77
-
78
- for (var key in source) {
79
- if (Object.prototype.hasOwnProperty.call(source, key)) {
80
- target[key] = source[key];
81
- }
82
- }
83
- }
84
-
85
- return target;
86
- };
87
- return _extends.apply(this, arguments);
88
- }
89
-
90
73
  /**
91
74
  * Actions represent the type of change to a location value.
92
75
  *
@@ -230,7 +213,7 @@ function createBrowserHistory(options) {
230
213
 
231
214
  if (index == null) {
232
215
  index = 0;
233
- globalHistory.replaceState(_extends({}, globalHistory.state, {
216
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
234
217
  idx: index
235
218
  }), '');
236
219
  }
@@ -245,7 +228,7 @@ function createBrowserHistory(options) {
245
228
  state = null;
246
229
  }
247
230
 
248
- return readOnly(_extends({
231
+ return readOnly(_extends$1({
249
232
  pathname: location.pathname,
250
233
  hash: '',
251
234
  search: ''
@@ -479,7 +462,7 @@ function createHashHistory(options) {
479
462
 
480
463
  if (index == null) {
481
464
  index = 0;
482
- globalHistory.replaceState(_extends({}, globalHistory.state, {
465
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
483
466
  idx: index
484
467
  }), '');
485
468
  }
@@ -506,7 +489,7 @@ function createHashHistory(options) {
506
489
  state = null;
507
490
  }
508
491
 
509
- return readOnly(_extends({
492
+ return readOnly(_extends$1({
510
493
  pathname: location.pathname,
511
494
  hash: '',
512
495
  search: ''
@@ -658,7 +641,7 @@ function createMemoryHistory(options) {
658
641
  initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
659
642
  initialIndex = _options3.initialIndex;
660
643
  var entries = initialEntries.map(function (entry) {
661
- var location = readOnly(_extends({
644
+ var location = readOnly(_extends$1({
662
645
  pathname: '/',
663
646
  search: '',
664
647
  hash: '',
@@ -683,7 +666,7 @@ function createMemoryHistory(options) {
683
666
  state = null;
684
667
  }
685
668
 
686
- return readOnly(_extends({
669
+ return readOnly(_extends$1({
687
670
  pathname: location.pathname,
688
671
  search: '',
689
672
  hash: ''
@@ -880,799 +863,394 @@ function parsePath(path) {
880
863
  return parsedPath;
881
864
  }
882
865
 
883
- // @ts-nocheck
884
- // We're inlining qss here for compression's sake, but we've included it as a hard dependency for the MIT license it requires.
885
- function encode(obj, pfx) {
886
- var k,
887
- i,
888
- tmp,
889
- str = '';
890
-
891
- for (k in obj) {
892
- if ((tmp = obj[k]) !== void 0) {
893
- if (Array.isArray(tmp)) {
894
- for (i = 0; i < tmp.length; i++) {
895
- str && (str += '&');
896
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
897
- }
898
- } else {
899
- str && (str += '&');
900
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
901
- }
866
+ var isProduction = process.env.NODE_ENV === 'production';
867
+ var prefix = 'Invariant failed';
868
+ function invariant(condition, message) {
869
+ if (condition) {
870
+ return;
902
871
  }
903
- }
904
-
905
- return (pfx || '') + str;
906
- }
907
-
908
- function toValue(mix) {
909
- if (!mix) return '';
910
- var str = decodeURIComponent(mix);
911
- if (str === 'false') return false;
912
- if (str === 'true') return true;
913
- return +str * 0 === 0 ? +str : str;
914
- }
915
-
916
- function decode(str) {
917
- var tmp,
918
- k,
919
- out = {},
920
- arr = str.split('&');
921
-
922
- while (tmp = arr.shift()) {
923
- tmp = tmp.split('=');
924
- k = tmp.shift();
925
-
926
- if (out[k] !== void 0) {
927
- out[k] = [].concat(out[k], toValue(tmp.shift()));
928
- } else {
929
- out[k] = toValue(tmp.shift());
872
+ if (isProduction) {
873
+ throw new Error(prefix);
930
874
  }
931
- }
932
-
933
- return out;
875
+ var provided = typeof message === 'function' ? message() : message;
876
+ var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
877
+ throw new Error(value);
934
878
  }
935
879
 
936
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId) {
937
- if (options === void 0) {
938
- options = {};
939
- }
940
-
941
- if (isRoot === void 0) {
942
- isRoot = true;
943
- }
944
-
945
- if (isRoot) {
946
- options.path = rootRouteId;
947
- } else {
948
- warning(!options.path, 'Routes must have a path property.');
949
- } // Strip the root from parentIds
950
-
880
+ // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
881
+ // k: infer I,
882
+ // ) => any
883
+ // ? I
884
+ // : never
951
885
 
952
- if (parentId === rootRouteId) {
953
- parentId = '';
886
+ /**
887
+ * This function returns `a` if `b` is deeply equal.
888
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
889
+ * This can be used for structural sharing between JSON values for example.
890
+ */
891
+ function replaceEqualDeep(prev, next) {
892
+ if (prev === next) {
893
+ return prev;
954
894
  }
955
895
 
956
- let path = String(isRoot ? rootRouteId : options.path); // If the path is anything other than an index path, trim it up
896
+ const array = Array.isArray(prev) && Array.isArray(next);
957
897
 
958
- if (path !== '/') {
959
- path = trimPath(path);
960
- }
898
+ if (array || isPlainObject(prev) && isPlainObject(next)) {
899
+ const aSize = array ? prev.length : Object.keys(prev).length;
900
+ const bItems = array ? next : Object.keys(next);
901
+ const bSize = bItems.length;
902
+ const copy = array ? [] : {};
903
+ let equalItems = 0;
961
904
 
962
- let id = joinPaths([parentId, path]);
905
+ for (let i = 0; i < bSize; i++) {
906
+ const key = array ? i : bItems[i];
907
+ copy[key] = replaceEqualDeep(prev[key], next[key]);
963
908
 
964
- if (path === rootRouteId) {
965
- path = '/';
966
- }
909
+ if (copy[key] === prev[key]) {
910
+ equalItems++;
911
+ }
912
+ }
967
913
 
968
- if (id !== rootRouteId) {
969
- id = joinPaths(['/', id]);
914
+ return aSize === bSize && equalItems === aSize ? prev : copy;
970
915
  }
971
916
 
972
- const fullPath = id === rootRouteId ? '/' : trimPathRight(id);
973
- return {
974
- id: id,
975
- path: path,
976
- fullPath: fullPath,
977
- options: options,
978
- children,
979
- addChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id)), false, parentId)
980
- };
981
- };
982
- const rootRouteId = '__root__';
983
- // Source
984
- // Detect if we're in the DOM
985
- const isDOM$1 = Boolean(typeof window !== 'undefined' && window.document && window.document.createElement); // This is the default history object if none is defined
986
-
987
- const createDefaultHistory = () => isDOM$1 ? createBrowserHistory() : createMemoryHistory();
988
-
989
- function createRouter(userOptions) {
990
- var _userOptions$stringif, _userOptions$parseSea;
991
-
992
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
993
-
994
- const originalOptions = _extends$1({}, userOptions, {
995
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
996
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
997
- });
998
-
999
- let router = {
1000
- options: originalOptions,
1001
- listeners: [],
1002
- // Resolved after construction
1003
- basepath: '',
1004
- routeTree: undefined,
1005
- routesById: {},
1006
- location: undefined,
1007
- allRouteInfo: undefined,
1008
- //
1009
- navigationPromise: Promise.resolve(),
1010
- resolveNavigation: () => {},
1011
- preloadCache: {},
1012
- state: {
1013
- status: 'idle',
1014
- location: null,
1015
- matches: [],
1016
- actions: {},
1017
- loaderData: {},
1018
- lastUpdated: Date.now()
1019
- },
1020
- startedLoadingAt: Date.now(),
1021
- subscribe: listener => {
1022
- router.listeners.push(listener);
1023
- return () => {
1024
- router.listeners = router.listeners.filter(x => x !== listener);
1025
- };
1026
- },
1027
- getRoute: id => {
1028
- return router.routesById[id];
1029
- },
1030
- notify: () => {
1031
- router.state = _extends$1({}, router.state);
1032
- router.listeners.forEach(listener => listener());
1033
- },
1034
- mount: () => {
1035
- const next = router.buildLocation({
1036
- to: '.',
1037
- search: true,
1038
- hash: true
1039
- }); // If the current location isn't updated, trigger a navigation
1040
- // to the current location. Otherwise, load the current location.
1041
-
1042
- if (next.href !== router.location.href) {
1043
- return router.commitLocation(next, true);
1044
- } else {
1045
- return router.loadLocation();
1046
- }
1047
- },
1048
- update: opts => {
1049
- Object.assign(router.options, opts);
1050
- const {
1051
- basepath,
1052
- routeConfig
1053
- } = router.options;
1054
- router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1055
-
1056
- if (routeConfig) {
1057
- router.routesById = {};
1058
- router.routeTree = router.buildRouteTree(routeConfig);
1059
- }
917
+ return next;
918
+ } // Copied from: https://github.com/jonschlinkert/is-plain-object
1060
919
 
1061
- return router;
1062
- },
1063
- destroy: history.listen(event => {
1064
- router.loadLocation(router.parseLocation(event.location, router.location));
1065
- }),
1066
- buildRouteTree: rootRouteConfig => {
1067
- const recurseRoutes = (routeConfigs, parent) => {
1068
- return routeConfigs.map(routeConfig => {
1069
- const routeOptions = routeConfig.options;
1070
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1071
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1072
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1073
- // }
1074
-
1075
- const existingRoute = router.routesById[route.routeId];
1076
-
1077
- if (existingRoute) {
1078
- if (process.env.NODE_ENV !== 'production') {
1079
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1080
- }
920
+ function isPlainObject(o) {
921
+ if (!hasObjectPrototype(o)) {
922
+ return false;
923
+ } // If has modified constructor
1081
924
 
1082
- throw new Error();
1083
- }
1084
- router.routesById[route.routeId] = route;
1085
- const children = routeConfig.children;
1086
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1087
- return route;
1088
- });
1089
- };
1090
925
 
1091
- const routes = recurseRoutes([rootRouteConfig]);
1092
- return routes[0];
1093
- },
1094
- parseLocation: (location, previousLocation) => {
1095
- var _location$hash$split$;
926
+ const ctor = o.constructor;
1096
927
 
1097
- const parsedSearch = router.options.parseSearch(location.search);
1098
- return {
1099
- pathname: location.pathname,
1100
- searchStr: location.search,
1101
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1102
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1103
- href: "" + location.pathname + location.search + location.hash,
1104
- state: location.state,
1105
- key: location.key
1106
- };
1107
- },
1108
- buildLocation: function buildLocation(dest) {
1109
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
928
+ if (typeof ctor === 'undefined') {
929
+ return true;
930
+ } // If has modified prototype
1110
931
 
1111
- if (dest === void 0) {
1112
- dest = {};
1113
- }
1114
932
 
1115
- // const resolvedFrom: Location = {
1116
- // ...router.location,
1117
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
933
+ const prot = ctor.prototype;
1118
934
 
1119
- let pathname = _resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
935
+ if (!hasObjectPrototype(prot)) {
936
+ return false;
937
+ } // If constructor does not have an Object-specific method
1120
938
 
1121
- const fromMatches = router.matchRoutes(router.location.pathname, {
1122
- strictParseParams: true
1123
- });
1124
- const toMatches = router.matchRoutes(pathname);
1125
- const prevParams = (_last = last(fromMatches)) == null ? void 0 : _last.params;
1126
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1127
939
 
1128
- if (nextParams) {
1129
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1130
- Object.assign(nextParams, fn(nextParams));
1131
- });
1132
- }
940
+ if (!prot.hasOwnProperty('isPrototypeOf')) {
941
+ return false;
942
+ } // Most likely a plain Object
1133
943
 
1134
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1135
944
 
1136
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
945
+ return true;
946
+ }
1137
947
 
1138
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1139
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1140
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1141
- : {}; // Then post filters
948
+ function hasObjectPrototype(o) {
949
+ return Object.prototype.toString.call(o) === '[object Object]';
950
+ }
1142
951
 
1143
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1144
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1145
- const searchStr = router.options.stringifySearch(search);
1146
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1147
- hash = hash ? "#" + hash : '';
1148
- return {
1149
- pathname,
1150
- search,
1151
- searchStr,
1152
- state: router.location.state,
1153
- hash,
1154
- href: "" + pathname + searchStr + hash,
1155
- key: dest.key
1156
- };
1157
- },
1158
- commitLocation: (next, replace) => {
1159
- const id = '' + Date.now() + Math.random();
1160
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1161
- let nextAction = 'replace';
952
+ function last(arr) {
953
+ return arr[arr.length - 1];
954
+ }
955
+ function warning(cond, message) {
956
+ if (cond) {
957
+ if (typeof console !== 'undefined') console.warn(message);
1162
958
 
1163
- if (!replace) {
1164
- nextAction = 'push';
1165
- }
959
+ try {
960
+ throw new Error(message);
961
+ } catch (_unused) {}
962
+ }
1166
963
 
1167
- const isSameUrl = router.parseLocation(history.location).href === next.href;
964
+ return true;
965
+ }
1168
966
 
1169
- if (isSameUrl && !next.key) {
1170
- nextAction = 'replace';
1171
- }
967
+ function isFunction(d) {
968
+ return typeof d === 'function';
969
+ }
1172
970
 
1173
- if (nextAction === 'replace') {
1174
- history.replace({
1175
- pathname: next.pathname,
1176
- hash: next.hash,
1177
- search: next.searchStr
1178
- }, {
1179
- id
1180
- });
1181
- } else {
1182
- history.push({
1183
- pathname: next.pathname,
1184
- hash: next.hash,
1185
- search: next.searchStr
1186
- }, {
1187
- id
1188
- });
1189
- }
971
+ function functionalUpdate(updater, previous) {
972
+ if (isFunction(updater)) {
973
+ return updater(previous);
974
+ }
1190
975
 
1191
- router.navigationPromise = new Promise(resolve => {
1192
- const previousNavigationResolve = router.resolveNavigation;
976
+ return updater;
977
+ }
1193
978
 
1194
- router.resolveNavigation = () => {
1195
- previousNavigationResolve();
1196
- resolve();
1197
- };
1198
- });
1199
- return router.navigationPromise;
1200
- },
1201
- buildNext: opts => {
1202
- const next = router.buildLocation(opts);
1203
- const matches = router.matchRoutes(next.pathname);
1204
-
1205
- const __preSearchFilters = matches.map(match => {
1206
- var _match$options$preSea;
1207
-
1208
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1209
- }).flat().filter(Boolean);
1210
-
1211
- const __postSearchFilters = matches.map(match => {
1212
- var _match$options$postSe;
1213
-
1214
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1215
- }).flat().filter(Boolean);
1216
-
1217
- return router.buildLocation(_extends$1({}, opts, {
1218
- __preSearchFilters,
1219
- __postSearchFilters
1220
- }));
1221
- },
1222
- cancelMatches: () => {
1223
- var _router$state$pending, _router$state$pending2;
1224
- [...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
1225
- match.cancel();
1226
- });
1227
- },
1228
- loadLocation: async next => {
1229
- const id = Math.random();
1230
- router.startedLoadingAt = id;
1231
-
1232
- if (next) {
1233
- // Ingest the new location
1234
- router.location = next;
1235
- } // Cancel any pending matches
1236
-
1237
-
1238
- router.cancelMatches(); // Match the routes
1239
-
1240
- const unloadedMatches = router.matchRoutes(location.pathname, {
1241
- strictParseParams: true
1242
- });
1243
- unloadedMatches.forEach((match, index) => {
1244
- const parent = unloadedMatches[index - 1];
1245
- const child = unloadedMatches[index + 1];
1246
- if (parent) match.__.setParentMatch(parent);
1247
- if (child) match.__.addChildMatch(child);
1248
- });
1249
- router.state = _extends$1({}, router.state, {
1250
- pending: {
1251
- matches: unloadedMatches,
1252
- location: router.location
1253
- }
1254
- });
1255
- router.notify(); // Load the matches
1256
-
1257
- const matches = await router.loadMatches(unloadedMatches, {
1258
- withPending: true
1259
- });
1260
-
1261
- if (router.startedLoadingAt !== id) {
1262
- // Ignore side-effects of match loading
1263
- return router.navigationPromise;
1264
- }
1265
-
1266
- const previousMatches = router.state.matches;
1267
- previousMatches.filter(d => {
1268
- return !matches.find(dd => dd.matchId === d.matchId);
1269
- }).forEach(d => {
1270
- d.__.onExit == null ? void 0 : d.__.onExit({
1271
- params: d.params,
1272
- search: d.routeSearch
1273
- });
1274
- });
1275
- previousMatches.filter(d => {
1276
- return matches.find(dd => dd.matchId === d.matchId);
1277
- }).forEach(d => {
1278
- d.options.onTransition == null ? void 0 : d.options.onTransition({
1279
- params: d.params,
1280
- search: d.routeSearch
1281
- });
1282
- });
1283
- matches.filter(d => {
1284
- return !previousMatches.find(dd => dd.matchId === d.matchId);
1285
- }).forEach(d => {
1286
- d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1287
- params: d.params,
1288
- search: d.search
1289
- });
1290
- });
1291
- router.state = _extends$1({}, router.state, {
1292
- location: router.location,
1293
- matches,
1294
- pending: undefined
1295
- });
1296
-
1297
- if (matches.some(d => d.status === 'loading')) {
1298
- router.notify();
1299
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1300
- }
1301
-
1302
- if (router.startedLoadingAt !== id) {
1303
- // Ignore side-effects of match loading
1304
- return;
1305
- }
1306
-
1307
- router.notify();
1308
- router.resolveNavigation();
1309
- },
1310
- cleanPreloadCache: () => {
1311
- const now = Date.now();
1312
- Object.keys(router.preloadCache).forEach(matchId => {
1313
- const entry = router.preloadCache[matchId]; // Don't remove loading matches
1314
-
1315
- if (entry.match.status === 'loading') {
1316
- return;
1317
- } // Do not remove successful matches that are still valid
1318
-
1319
-
1320
- if (entry.match.updatedAt && entry.match.updatedAt + entry.maxAge > now) {
1321
- return;
1322
- } // Everything else gets removed
1323
-
1324
-
1325
- delete router.preloadCache[matchId];
1326
- });
1327
- },
1328
- loadRoute: async function loadRoute(navigateOpts, loaderOpts) {
1329
- if (navigateOpts === void 0) {
1330
- navigateOpts = router.location;
1331
- }
1332
-
1333
- const next = router.buildNext(navigateOpts);
1334
- const matches = router.matchRoutes(next.pathname, {
1335
- strictParseParams: true
1336
- });
1337
- await router.loadMatches(matches, {
1338
- preload: true,
1339
- maxAge: loaderOpts.maxAge
1340
- });
1341
- return matches;
1342
- },
1343
- matchRoutes: (pathname, opts) => {
1344
- var _router$state$pending3, _router$state$pending4;
1345
-
1346
- router.cleanPreloadCache();
1347
- const matches = [];
979
+ function joinPaths(paths) {
980
+ return cleanPath(paths.filter(Boolean).join('/'));
981
+ }
982
+ function cleanPath(path) {
983
+ // remove double slashes
984
+ return path.replace(/\/{2,}/g, '/');
985
+ }
986
+ function trimPathLeft(path) {
987
+ return path === '/' ? path : path.replace(/^\/{1,}/, '');
988
+ }
989
+ function trimPathRight(path) {
990
+ return path === '/' ? path : path.replace(/\/{1,}$/, '');
991
+ }
992
+ function trimPath(path) {
993
+ return trimPathRight(trimPathLeft(path));
994
+ }
995
+ function resolvePath(basepath, base, to) {
996
+ base = base.replace(new RegExp("^" + basepath), '/');
997
+ to = to.replace(new RegExp("^" + basepath), '/');
998
+ let baseSegments = parsePathname(base);
999
+ const toSegments = parsePathname(to);
1000
+ toSegments.forEach((toSegment, index) => {
1001
+ if (toSegment.value === '/') {
1002
+ if (!index) {
1003
+ // Leading slash
1004
+ baseSegments = [toSegment];
1005
+ } else if (index === toSegments.length - 1) {
1006
+ // Trailing Slash
1007
+ baseSegments.push(toSegment);
1008
+ } else ;
1009
+ } else if (toSegment.value === '..') {
1010
+ var _last;
1348
1011
 
1349
- if (!router.routeTree) {
1350
- return matches;
1012
+ // Extra trailing slash? pop it off
1013
+ if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
1014
+ baseSegments.pop();
1351
1015
  }
1352
1016
 
1353
- const existingMatches = [...router.state.matches, ...((_router$state$pending3 = (_router$state$pending4 = router.state.pending) == null ? void 0 : _router$state$pending4.matches) != null ? _router$state$pending3 : [])];
1354
-
1355
- const recurse = async (routes, parentMatch) => {
1356
- var _parentMatch$params, _router$options$filte, _router$preloadCache$, _route$childRoutes2;
1357
-
1358
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1359
- const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
1360
- const route = filteredRoutes == null ? void 0 : filteredRoutes.find(route => {
1361
- var _route$childRoutes, _route$options$caseSe;
1362
-
1363
- const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length);
1364
- const matchParams = matchPathname(pathname, {
1365
- to: route.fullPath,
1366
- fuzzy,
1367
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
1368
- });
1369
-
1370
- if (matchParams) {
1371
- let parsedParams;
1372
-
1373
- try {
1374
- var _route$options$parseP;
1375
-
1376
- parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
1377
- } catch (err) {
1378
- if (opts != null && opts.strictParseParams) {
1379
- throw err;
1380
- }
1381
- }
1017
+ baseSegments.pop();
1018
+ } else if (toSegment.value === '.') {
1019
+ return;
1020
+ } else {
1021
+ baseSegments.push(toSegment);
1022
+ }
1023
+ });
1024
+ const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
1025
+ return cleanPath(joined);
1026
+ }
1027
+ function parsePathname(pathname) {
1028
+ if (!pathname) {
1029
+ return [];
1030
+ }
1382
1031
 
1383
- params = _extends$1({}, params, parsedParams);
1384
- }
1032
+ pathname = cleanPath(pathname);
1033
+ const segments = [];
1385
1034
 
1386
- return !!matchParams;
1387
- });
1035
+ if (pathname.slice(0, 1) === '/') {
1036
+ pathname = pathname.substring(1);
1037
+ segments.push({
1038
+ type: 'pathname',
1039
+ value: '/'
1040
+ });
1041
+ }
1388
1042
 
1389
- if (!route) {
1390
- return;
1391
- }
1043
+ if (!pathname) {
1044
+ return segments;
1045
+ } // Remove empty segments and '.' segments
1392
1046
 
1393
- const interpolatedPath = interpolatePath(route.routePath, params);
1394
- const matchId = interpolatePath(route.routeId, params, true);
1395
- const match = existingMatches.find(d => d.matchId === matchId) || ((_router$preloadCache$ = router.preloadCache[matchId]) == null ? void 0 : _router$preloadCache$.match) || createRouteMatch(router, route, {
1396
- matchId,
1397
- params,
1398
- pathname: joinPaths([pathname, interpolatedPath])
1399
- });
1400
- matches.push(match);
1401
1047
 
1402
- if ((_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length) {
1403
- recurse(route.childRoutes, match);
1404
- }
1048
+ const split = pathname.split('/').filter(Boolean);
1049
+ segments.push(...split.map(part => {
1050
+ if (part.startsWith('*')) {
1051
+ return {
1052
+ type: 'wildcard',
1053
+ value: part
1405
1054
  };
1055
+ }
1406
1056
 
1407
- recurse([router.routeTree]);
1408
- return matches;
1409
- },
1410
- loadMatches: async (resolvedMatches, loaderOpts) => {
1411
- const matchPromises = resolvedMatches.map(async match => {
1412
- // Validate the match (loads search params etc)
1413
- match.__.validate(); // If this is a preload, add it to the preload cache
1414
-
1415
-
1416
- if (loaderOpts != null && loaderOpts.preload) {
1417
- router.preloadCache[match.matchId] = {
1418
- maxAge: loaderOpts == null ? void 0 : loaderOpts.maxAge,
1419
- match
1420
- };
1421
- } // If the match is invalid, errored or idle, trigger it to load
1422
-
1423
-
1424
- if (match.status === 'success' && match.isInvalid || match.status === 'error' || match.status === 'idle') {
1425
- match.load();
1426
- } // If requested, start the pending timers
1427
-
1428
-
1429
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
1430
- // This might be completion, error, or a pending state
1431
-
1432
- await match.__.loadPromise;
1433
- });
1434
- router.notify();
1435
- await Promise.all(matchPromises);
1436
- return resolvedMatches;
1437
- },
1438
- invalidateRoute: opts => {
1439
- var _router$state$pending5, _router$state$pending6;
1440
-
1441
- const next = router.buildNext(opts);
1442
- const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
1443
- [...router.state.matches, ...((_router$state$pending5 = (_router$state$pending6 = router.state.pending) == null ? void 0 : _router$state$pending6.matches) != null ? _router$state$pending5 : [])].forEach(match => {
1444
- if (unloadedMatchIds.includes(match.matchId)) {
1445
- match.isInvalid = true;
1446
- }
1447
- });
1448
- },
1449
- reload: () => router._navigate({
1450
- fromCurrent: true,
1451
- replace: true,
1452
- search: true
1453
- }),
1454
- resolvePath: (from, path) => {
1455
- return _resolvePath(router.basepath, from, cleanPath(path));
1456
- },
1457
- matchRoute: (location, opts) => {
1458
- var _location$from;
1459
-
1460
- // const location = router.buildNext(opts)
1461
- location = _extends$1({}, location, {
1462
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
1463
- });
1464
- const next = router.buildNext(location);
1465
-
1466
- if (opts != null && opts.pending) {
1467
- var _router$state$pending7;
1468
-
1469
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
1470
- return false;
1471
- }
1472
-
1473
- return !!matchPathname(router.state.pending.location.pathname, _extends$1({}, opts, {
1474
- to: next.pathname
1475
- }));
1476
- }
1477
-
1478
- return !!matchPathname(router.state.location.pathname, _extends$1({}, opts, {
1479
- to: next.pathname
1480
- }));
1481
- },
1482
- _navigate: location => {
1483
- const next = router.buildNext(location);
1484
- return router.commitLocation(next, location.replace);
1485
- },
1486
- navigate: async _ref => {
1487
- let {
1488
- from,
1489
- to = '.',
1490
- search,
1491
- hash,
1492
- replace
1493
- } = _ref;
1494
- // If this link simply reloads the current route,
1495
- // make sure it has a new key so it will trigger a data refresh
1496
- // If this `to` is a valid external URL, return
1497
- // null for LinkUtils
1498
- const toString = String(to);
1499
- const fromString = String(from);
1500
- let isExternal;
1501
-
1502
- try {
1503
- new URL("" + toString);
1504
- isExternal = true;
1505
- } catch (e) {}
1057
+ if (part.charAt(0) === ':') {
1058
+ return {
1059
+ type: 'param',
1060
+ value: part
1061
+ };
1062
+ }
1506
1063
 
1507
- if (isExternal) {
1508
- if (process.env.NODE_ENV !== 'production') {
1509
- throw new Error('Attempting to navigate to external url with router.navigate!');
1510
- }
1064
+ return {
1065
+ type: 'pathname',
1066
+ value: part
1067
+ };
1068
+ }));
1511
1069
 
1512
- return;
1513
- }
1070
+ if (pathname.slice(-1) === '/') {
1071
+ pathname = pathname.substring(1);
1072
+ segments.push({
1073
+ type: 'pathname',
1074
+ value: '/'
1075
+ });
1076
+ }
1514
1077
 
1515
- return router._navigate({
1516
- from: fromString,
1517
- to: toString,
1518
- search,
1519
- hash
1520
- });
1521
- },
1522
- buildLink: _ref2 => {
1523
- var _preload, _ref3, _ref4;
1078
+ return segments;
1079
+ }
1080
+ function interpolatePath(path, params, leaveWildcard) {
1081
+ const interpolatedPathSegments = parsePathname(path);
1082
+ return joinPaths(interpolatedPathSegments.map(segment => {
1083
+ if (segment.value === '*' && !leaveWildcard) {
1084
+ return '';
1085
+ }
1524
1086
 
1525
- let {
1526
- from,
1527
- to = '.',
1528
- search,
1529
- params,
1530
- hash,
1531
- target,
1532
- replace,
1533
- activeOptions,
1534
- preload,
1535
- preloadMaxAge: userPreloadMaxAge,
1536
- preloadDelay: userPreloadDelay,
1537
- disabled
1538
- } = _ref2;
1087
+ if (segment.type === 'param') {
1088
+ var _segment$value$substr;
1539
1089
 
1540
- // If this link simply reloads the current route,
1541
- // make sure it has a new key so it will trigger a data refresh
1542
- // If this `to` is a valid external URL, return
1543
- // null for LinkUtils
1544
- try {
1545
- new URL("" + to);
1546
- return {
1547
- type: 'external',
1548
- href: to
1549
- };
1550
- } catch (e) {}
1090
+ return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
1091
+ }
1551
1092
 
1552
- const nextOpts = {
1553
- from,
1554
- to,
1555
- search,
1556
- params,
1557
- hash,
1558
- replace
1559
- };
1560
- const next = router.buildNext(nextOpts);
1561
- preload = (_preload = preload) != null ? _preload : router.options.defaultLinkPreload;
1562
- const preloadMaxAge = (_ref3 = userPreloadMaxAge != null ? userPreloadMaxAge : router.options.defaultLinkPreloadMaxAge) != null ? _ref3 : 2000;
1563
- const preloadDelay = (_ref4 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultLinkPreloadDelay) != null ? _ref4 : 50; // Compare path/hash for matches
1093
+ return segment.value;
1094
+ }));
1095
+ }
1096
+ function matchPathname(currentPathname, matchLocation) {
1097
+ const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1564
1098
 
1565
- const pathIsEqual = router.state.location.pathname === next.pathname;
1566
- const currentPathSplit = router.state.location.pathname.split('/');
1567
- const nextPathSplit = next.pathname.split('/');
1568
- const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
1569
- const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
1099
+ if (matchLocation.to && !pathParams) {
1100
+ return;
1101
+ } // if (matchLocation.search && !searchMatched) {
1102
+ // return
1103
+ // }
1570
1104
 
1571
- const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
1572
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
1573
1105
 
1574
- const isActive = pathTest && hashTest; // The click handler
1106
+ return pathParams != null ? pathParams : {};
1107
+ }
1108
+ function matchByPath(from, matchLocation) {
1109
+ var _matchLocation$to;
1575
1110
 
1576
- const handleClick = e => {
1577
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1578
- e.preventDefault();
1111
+ const baseSegments = parsePathname(from);
1112
+ const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
1113
+ const params = {};
1579
1114
 
1580
- if (pathIsEqual && !search && !hash) {
1581
- router.invalidateRoute(nextOpts);
1582
- } // All is well? Navigate!)
1115
+ let isMatch = (() => {
1116
+ for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
1117
+ const baseSegment = baseSegments[i];
1118
+ const routeSegment = routeSegments[i];
1119
+ const isLastRouteSegment = i === routeSegments.length - 1;
1120
+ const isLastBaseSegment = i === baseSegments.length - 1;
1583
1121
 
1122
+ if (routeSegment) {
1123
+ if (routeSegment.type === 'wildcard') {
1124
+ if (baseSegment != null && baseSegment.value) {
1125
+ params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
1126
+ return true;
1127
+ }
1584
1128
 
1585
- router._navigate(nextOpts);
1129
+ return false;
1586
1130
  }
1587
- }; // The click handler
1588
1131
 
1132
+ if (routeSegment.type === 'pathname') {
1133
+ if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
1134
+ return true;
1135
+ }
1589
1136
 
1590
- const handleFocus = e => {
1591
- if (preload && preloadMaxAge > 0) {
1592
- router.loadRoute(nextOpts, {
1593
- maxAge: preloadMaxAge
1594
- });
1137
+ if (baseSegment) {
1138
+ if (matchLocation.caseSensitive) {
1139
+ if (routeSegment.value !== baseSegment.value) {
1140
+ return false;
1141
+ }
1142
+ } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
1143
+ return false;
1144
+ }
1145
+ }
1595
1146
  }
1596
- };
1597
1147
 
1598
- const handleEnter = e => {
1599
- const target = e.target || {};
1148
+ if (!baseSegment) {
1149
+ return false;
1150
+ }
1600
1151
 
1601
- if (preload && preloadMaxAge > 0) {
1602
- if (target.preloadTimeout) {
1603
- return;
1152
+ if (routeSegment.type === 'param') {
1153
+ if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
1154
+ return false;
1604
1155
  }
1605
1156
 
1606
- target.preloadTimeout = setTimeout(() => {
1607
- target.preloadTimeout = null;
1608
- router.loadRoute(nextOpts, {
1609
- maxAge: preloadMaxAge
1610
- });
1611
- }, preloadDelay);
1157
+ if (!baseSegment.value.startsWith(':')) {
1158
+ params[routeSegment.value.substring(1)] = baseSegment.value;
1159
+ }
1612
1160
  }
1613
- };
1161
+ }
1614
1162
 
1615
- const handleLeave = e => {
1616
- const target = e.target || {};
1163
+ if (isLastRouteSegment && !isLastBaseSegment) {
1164
+ return !!matchLocation.fuzzy;
1165
+ }
1166
+ }
1617
1167
 
1618
- if (target.preloadTimeout) {
1619
- clearTimeout(target.preloadTimeout);
1620
- target.preloadTimeout = null;
1168
+ return true;
1169
+ })();
1170
+
1171
+ return isMatch ? params : undefined;
1172
+ }
1173
+
1174
+ // @ts-nocheck
1175
+ // 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.
1176
+ function encode(obj, pfx) {
1177
+ var k,
1178
+ i,
1179
+ tmp,
1180
+ str = '';
1181
+
1182
+ for (k in obj) {
1183
+ if ((tmp = obj[k]) !== void 0) {
1184
+ if (Array.isArray(tmp)) {
1185
+ for (i = 0; i < tmp.length; i++) {
1186
+ str && (str += '&');
1187
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1621
1188
  }
1622
- };
1189
+ } else {
1190
+ str && (str += '&');
1191
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1192
+ }
1193
+ }
1194
+ }
1623
1195
 
1624
- return {
1625
- type: 'internal',
1626
- next,
1627
- handleFocus,
1628
- handleClick,
1629
- handleEnter,
1630
- handleLeave,
1631
- isActive,
1632
- disabled
1633
- };
1634
- },
1635
- __experimental__createSnapshot: () => {
1636
- return _extends$1({}, router.state, {
1637
- matches: router.state.matches.map(_ref5 => {
1638
- let {
1639
- routeLoaderData: loaderData,
1640
- matchId
1641
- } = _ref5;
1642
- return {
1643
- matchId,
1644
- loaderData
1645
- };
1646
- })
1647
- });
1196
+ return (pfx || '') + str;
1197
+ }
1198
+
1199
+ function toValue(mix) {
1200
+ if (!mix) return '';
1201
+ var str = decodeURIComponent(mix);
1202
+ if (str === 'false') return false;
1203
+ if (str === 'true') return true;
1204
+ return +str * 0 === 0 ? +str : str;
1205
+ }
1206
+
1207
+ function decode(str) {
1208
+ var tmp,
1209
+ k,
1210
+ out = {},
1211
+ arr = str.split('&');
1212
+
1213
+ while (tmp = arr.shift()) {
1214
+ tmp = tmp.split('=');
1215
+ k = tmp.shift();
1216
+
1217
+ if (out[k] !== void 0) {
1218
+ out[k] = [].concat(out[k], toValue(tmp.shift()));
1219
+ } else {
1220
+ out[k] = toValue(tmp.shift());
1648
1221
  }
1649
- };
1650
- router.location = router.parseLocation(history.location); // router.state.location = __experimental__snapshot?.location ?? router.location
1222
+ }
1651
1223
 
1652
- router.state.location = router.location;
1653
- router.update(userOptions); // Allow frameworks to hook into the router creation
1224
+ return out;
1225
+ }
1226
+
1227
+ function _extends() {
1228
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
1229
+ for (var i = 1; i < arguments.length; i++) {
1230
+ var source = arguments[i];
1654
1231
 
1655
- router.options.createRouter == null ? void 0 : router.options.createRouter(router); // router.mount()
1232
+ for (var key in source) {
1233
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1234
+ target[key] = source[key];
1235
+ }
1236
+ }
1237
+ }
1656
1238
 
1657
- return router;
1239
+ return target;
1240
+ };
1241
+ return _extends.apply(this, arguments);
1658
1242
  }
1243
+
1659
1244
  function createRoute(routeConfig, options, parent, router) {
1660
- // const id = (
1661
- // options.path === rootRouteId
1662
- // ? rootRouteId
1663
- // : joinPaths([
1664
- // parent!.id,
1665
- // `${options.path?.replace(/(.)\/$/, '$1')}`,
1666
- // ]).replace(new RegExp(`^${rootRouteId}`), '')
1667
- // ) as TRouteInfo['id']
1668
1245
  const {
1669
- id: routeId,
1246
+ id,
1247
+ routeId,
1670
1248
  path: routePath,
1671
1249
  fullPath
1672
1250
  } = routeConfig;
1673
1251
 
1674
- const action = router.state.actions[routeId] || (() => {
1675
- router.state.actions[routeId] = {
1252
+ const action = router.state.actions[id] || (() => {
1253
+ router.state.actions[id] = {
1676
1254
  pending: [],
1677
1255
  submit: async (submission, actionOpts) => {
1678
1256
  var _actionOpts$invalidat;
@@ -1687,10 +1265,12 @@ function createRoute(routeConfig, options, parent, router) {
1687
1265
  status: 'pending',
1688
1266
  submission
1689
1267
  };
1268
+ action.current = actionState;
1690
1269
  action.latest = actionState;
1691
1270
  action.pending.push(actionState);
1692
- router.state = _extends$1({}, router.state, {
1693
- action: actionState
1271
+ router.state = _extends({}, router.state, {
1272
+ currentAction: actionState,
1273
+ latestAction: actionState
1694
1274
  });
1695
1275
  router.notify();
1696
1276
 
@@ -1714,20 +1294,54 @@ function createRoute(routeConfig, options, parent, router) {
1714
1294
  actionState.status = 'error';
1715
1295
  } finally {
1716
1296
  action.pending = action.pending.filter(d => d !== actionState);
1297
+ router.removeActionQueue.push({
1298
+ action,
1299
+ actionState
1300
+ });
1301
+ router.notify();
1302
+ }
1303
+ }
1304
+ };
1305
+ return router.state.actions[id];
1306
+ })();
1717
1307
 
1718
- if (actionState === router.state.action) {
1719
- router.state.action = undefined;
1720
- }
1308
+ const loader = router.state.loaders[id] || (() => {
1309
+ router.state.loaders[id] = {
1310
+ pending: [],
1311
+ fetch: async loaderContext => {
1312
+ if (!route) {
1313
+ return;
1314
+ }
1315
+
1316
+ const loaderState = {
1317
+ loadedAt: Date.now(),
1318
+ loaderContext
1319
+ };
1320
+ loader.current = loaderState;
1321
+ loader.latest = loaderState;
1322
+ loader.pending.push(loaderState); // router.state = {
1323
+ // ...router.state,
1324
+ // currentAction: loaderState,
1325
+ // latestAction: loaderState,
1326
+ // }
1327
+
1328
+ router.notify();
1329
+
1330
+ try {
1331
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1332
+ } finally {
1333
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1721
1334
 
1722
1335
  router.notify();
1723
1336
  }
1724
1337
  }
1725
1338
  };
1726
- return router.state.actions[routeId];
1339
+ return router.state.loaders[id];
1727
1340
  })();
1728
1341
 
1729
1342
  let route = {
1730
- routeId,
1343
+ routeId: id,
1344
+ routeRouteId: routeId,
1731
1345
  routePath,
1732
1346
  fullPath,
1733
1347
  options,
@@ -1735,18 +1349,19 @@ function createRoute(routeConfig, options, parent, router) {
1735
1349
  childRoutes: undefined,
1736
1350
  parentRoute: parent,
1737
1351
  action,
1352
+ loader: loader,
1738
1353
  buildLink: options => {
1739
- return router.buildLink(_extends$1({}, options, {
1354
+ return router.buildLink(_extends({}, options, {
1740
1355
  from: fullPath
1741
1356
  }));
1742
1357
  },
1743
1358
  navigate: options => {
1744
- return router.navigate(_extends$1({}, options, {
1359
+ return router.navigate(_extends({}, options, {
1745
1360
  from: fullPath
1746
1361
  }));
1747
1362
  },
1748
1363
  matchRoute: (matchLocation, opts) => {
1749
- return router.matchRoute(_extends$1({}, matchLocation, {
1364
+ return router.matchRoute(_extends({}, matchLocation, {
1750
1365
  from: fullPath
1751
1366
  }), opts);
1752
1367
  }
@@ -1757,8 +1372,69 @@ function createRoute(routeConfig, options, parent, router) {
1757
1372
  });
1758
1373
  return route;
1759
1374
  }
1375
+ function cascadeLoaderData(matches) {
1376
+ matches.forEach((match, index) => {
1377
+ const parent = matches[index - 1];
1378
+
1379
+ if (parent) {
1380
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1381
+ }
1382
+ });
1383
+ }
1384
+
1385
+ const rootRouteId = '__root__';
1386
+ const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1387
+ if (options === void 0) {
1388
+ options = {};
1389
+ }
1390
+
1391
+ if (isRoot === void 0) {
1392
+ isRoot = true;
1393
+ }
1394
+
1395
+ if (isRoot) {
1396
+ options.path = rootRouteId;
1397
+ } // Strip the root from parentIds
1398
+
1399
+
1400
+ if (parentId === rootRouteId) {
1401
+ parentId = '';
1402
+ }
1403
+
1404
+ let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1405
+
1406
+ if (path && path !== '/') {
1407
+ path = trimPath(path);
1408
+ }
1409
+
1410
+ const routeId = path || options.id;
1411
+ let id = joinPaths([parentId, routeId]);
1412
+
1413
+ if (path === rootRouteId) {
1414
+ path = '/';
1415
+ }
1416
+
1417
+ if (id !== rootRouteId) {
1418
+ id = joinPaths(['/', id]);
1419
+ }
1420
+
1421
+ const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1422
+ return {
1423
+ id: id,
1424
+ routeId: routeId,
1425
+ path: path,
1426
+ fullPath: fullPath,
1427
+ options: options,
1428
+ children,
1429
+ createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1430
+ addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1431
+ createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1432
+ };
1433
+ };
1434
+
1435
+ const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1760
1436
  function createRouteMatch(router, route, opts) {
1761
- const routeMatch = _extends$1({}, route, opts, {
1437
+ const routeMatch = _extends({}, route, opts, {
1762
1438
  router,
1763
1439
  routeSearch: {},
1764
1440
  search: {},
@@ -1769,6 +1445,11 @@ function createRouteMatch(router, route, opts) {
1769
1445
  isPending: false,
1770
1446
  isFetching: false,
1771
1447
  isInvalid: false,
1448
+ invalidAt: Infinity,
1449
+ getIsInvalid: () => {
1450
+ const now = Date.now();
1451
+ return routeMatch.isInvalid || routeMatch.invalidAt < now;
1452
+ },
1772
1453
  __: {
1773
1454
  abortController: new AbortController(),
1774
1455
  latestId: '',
@@ -1804,16 +1485,17 @@ function createRouteMatch(router, route, opts) {
1804
1485
  clearTimeout(routeMatch.__.pendingMinTimeout);
1805
1486
  delete routeMatch.__.pendingMinPromise;
1806
1487
  },
1807
- setParentMatch: parentMatch => {
1808
- routeMatch.parentMatch = parentMatch;
1809
- },
1810
- addChildMatch: childMatch => {
1811
- if (routeMatch.childMatches.find(d => d.matchId === childMatch.matchId)) {
1812
- return;
1813
- }
1814
-
1815
- routeMatch.childMatches.push(childMatch);
1816
- },
1488
+ // setParentMatch: (parentMatch?: RouteMatch) => {
1489
+ // routeMatch.parentMatch = parentMatch
1490
+ // },
1491
+ // addChildMatch: (childMatch: RouteMatch) => {
1492
+ // if (
1493
+ // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1494
+ // ) {
1495
+ // return
1496
+ // }
1497
+ // routeMatch.childMatches.push(childMatch)
1498
+ // },
1817
1499
  validate: () => {
1818
1500
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1819
1501
 
@@ -1822,14 +1504,15 @@ function createRouteMatch(router, route, opts) {
1822
1504
 
1823
1505
  try {
1824
1506
  const prevSearch = routeMatch.routeSearch;
1825
- let nextSearch = replaceEqualDeep(prevSearch, routeMatch.options.validateSearch == null ? void 0 : routeMatch.options.validateSearch(parentSearch)); // Invalidate route matches when search param stability changes
1507
+ const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1508
+ let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1826
1509
 
1827
1510
  if (prevSearch !== nextSearch) {
1828
1511
  routeMatch.isInvalid = true;
1829
1512
  }
1830
1513
 
1831
1514
  routeMatch.routeSearch = nextSearch;
1832
- routeMatch.search = replaceEqualDeep(parentSearch, _extends$1({}, parentSearch, nextSearch));
1515
+ routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1833
1516
  } catch (err) {
1834
1517
  console.error(err);
1835
1518
  const error = new Error('Invalid search params found', {
@@ -1843,501 +1526,971 @@ function createRouteMatch(router, route, opts) {
1843
1526
  }
1844
1527
  }
1845
1528
  },
1846
- cancel: () => {
1847
- var _routeMatch$__$abortC;
1848
-
1849
- (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1850
-
1851
- routeMatch.__.cancelPending();
1529
+ cancel: () => {
1530
+ var _routeMatch$__$abortC;
1531
+
1532
+ (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1533
+
1534
+ routeMatch.__.cancelPending();
1535
+ },
1536
+ invalidate: () => {
1537
+ routeMatch.isInvalid = true;
1538
+ },
1539
+ hasLoaders: () => {
1540
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1541
+ },
1542
+ load: async loaderOpts => {
1543
+ const now = Date.now();
1544
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1545
+
1546
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1547
+ // If the match is currently active, don't preload it
1548
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1549
+ return;
1550
+ }
1551
+
1552
+ router.matchCache[routeMatch.matchId] = {
1553
+ gc: now + loaderOpts.gcMaxAge,
1554
+ match: routeMatch
1555
+ };
1556
+ } // If the match is invalid, errored or idle, trigger it to load
1557
+
1558
+
1559
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1560
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1561
+ routeMatch.fetch({
1562
+ maxAge
1563
+ });
1564
+ }
1565
+ },
1566
+ fetch: async opts => {
1567
+ const id = '' + Date.now() + Math.random();
1568
+ routeMatch.__.latestId = id; // If the match was in an error state, set it
1569
+ // to a loading state again. Otherwise, keep it
1570
+ // as loading or resolved
1571
+
1572
+ if (routeMatch.status === 'idle') {
1573
+ routeMatch.status = 'loading';
1574
+ } // We started loading the route, so it's no longer invalid
1575
+
1576
+
1577
+ routeMatch.isInvalid = false;
1578
+ routeMatch.__.loadPromise = new Promise(async resolve => {
1579
+ // We are now fetching, even if it's in the background of a
1580
+ // resolved state
1581
+ routeMatch.isFetching = true;
1582
+ routeMatch.__.resolve = resolve;
1583
+
1584
+ const loaderPromise = (async () => {
1585
+ // Load the elements and data in parallel
1586
+ routeMatch.__.elementsPromise = (async () => {
1587
+ // then run all element and data loaders in parallel
1588
+ // For each element type, potentially load it asynchronously
1589
+ await Promise.all(elementTypes.map(async type => {
1590
+ const routeElement = routeMatch.options[type];
1591
+
1592
+ if (routeMatch.__[type]) {
1593
+ return;
1594
+ }
1595
+
1596
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1597
+ }));
1598
+ })();
1599
+
1600
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1601
+ try {
1602
+ var _ref, _ref2, _opts$maxAge;
1603
+
1604
+ if (routeMatch.options.loader) {
1605
+ const data = await routeMatch.options.loader({
1606
+ params: routeMatch.params,
1607
+ search: routeMatch.routeSearch,
1608
+ signal: routeMatch.__.abortController.signal
1609
+ });
1610
+
1611
+ if (id !== routeMatch.__.latestId) {
1612
+ return routeMatch.__.loaderPromise;
1613
+ }
1614
+
1615
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1616
+ }
1617
+
1618
+ routeMatch.error = undefined;
1619
+ routeMatch.status = 'success';
1620
+ routeMatch.updatedAt = Date.now();
1621
+ routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
1622
+ } catch (err) {
1623
+ if (id !== routeMatch.__.latestId) {
1624
+ return routeMatch.__.loaderPromise;
1625
+ }
1626
+
1627
+ if (process.env.NODE_ENV !== 'production') {
1628
+ console.error(err);
1629
+ }
1630
+
1631
+ routeMatch.error = err;
1632
+ routeMatch.status = 'error';
1633
+ routeMatch.updatedAt = Date.now();
1634
+ }
1635
+ });
1636
+
1637
+ try {
1638
+ await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1639
+
1640
+ if (id !== routeMatch.__.latestId) {
1641
+ return routeMatch.__.loaderPromise;
1642
+ }
1643
+
1644
+ if (routeMatch.__.pendingMinPromise) {
1645
+ await routeMatch.__.pendingMinPromise;
1646
+ delete routeMatch.__.pendingMinPromise;
1647
+ }
1648
+ } finally {
1649
+ if (id !== routeMatch.__.latestId) {
1650
+ return routeMatch.__.loaderPromise;
1651
+ }
1652
+
1653
+ routeMatch.__.cancelPending();
1654
+
1655
+ routeMatch.isPending = false;
1656
+ routeMatch.isFetching = false;
1657
+
1658
+ routeMatch.__.notify();
1659
+ }
1660
+ })();
1661
+
1662
+ routeMatch.__.loaderPromise = loaderPromise;
1663
+ await loaderPromise;
1664
+
1665
+ if (id !== routeMatch.__.latestId) {
1666
+ return routeMatch.__.loaderPromise;
1667
+ }
1668
+
1669
+ delete routeMatch.__.loaderPromise;
1670
+ });
1671
+ return await routeMatch.__.loadPromise;
1672
+ }
1673
+ });
1674
+
1675
+ if (!routeMatch.hasLoaders()) {
1676
+ routeMatch.status = 'success';
1677
+ }
1678
+
1679
+ return routeMatch;
1680
+ }
1681
+
1682
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1683
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify);
1684
+ function parseSearchWith(parser) {
1685
+ return searchStr => {
1686
+ if (searchStr.substring(0, 1) === '?') {
1687
+ searchStr = searchStr.substring(1);
1688
+ }
1689
+
1690
+ let query = decode(searchStr); // Try to parse any query params that might be json
1691
+
1692
+ for (let key in query) {
1693
+ const value = query[key];
1694
+
1695
+ if (typeof value === 'string') {
1696
+ try {
1697
+ query[key] = parser(value);
1698
+ } catch (err) {//
1699
+ }
1700
+ }
1701
+ }
1702
+
1703
+ return query;
1704
+ };
1705
+ }
1706
+ function stringifySearchWith(stringify) {
1707
+ return search => {
1708
+ search = _extends({}, search);
1709
+
1710
+ if (search) {
1711
+ Object.keys(search).forEach(key => {
1712
+ const val = search[key];
1713
+
1714
+ if (typeof val === 'undefined' || val === undefined) {
1715
+ delete search[key];
1716
+ } else if (val && typeof val === 'object' && val !== null) {
1717
+ try {
1718
+ search[key] = stringify(val);
1719
+ } catch (err) {// silent
1720
+ }
1721
+ }
1722
+ });
1723
+ }
1724
+
1725
+ const searchStr = encode(search).toString();
1726
+ return searchStr ? "?" + searchStr : '';
1727
+ };
1728
+ }
1729
+
1730
+ var _window$document;
1731
+ // Detect if we're in the DOM
1732
+ const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1733
+
1734
+ const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1735
+
1736
+ function createRouter(userOptions) {
1737
+ var _userOptions$stringif, _userOptions$parseSea;
1738
+
1739
+ const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1740
+
1741
+ const originalOptions = _extends({
1742
+ defaultLoaderGcMaxAge: 5 * 60 * 1000,
1743
+ defaultLoaderMaxAge: 0,
1744
+ defaultPreloadMaxAge: 2000,
1745
+ defaultPreloadDelay: 50
1746
+ }, userOptions, {
1747
+ stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1748
+ parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1749
+ });
1750
+
1751
+ let router = {
1752
+ history,
1753
+ options: originalOptions,
1754
+ listeners: [],
1755
+ removeActionQueue: [],
1756
+ // Resolved after construction
1757
+ basepath: '',
1758
+ routeTree: undefined,
1759
+ routesById: {},
1760
+ location: undefined,
1761
+ allRouteInfo: undefined,
1762
+ //
1763
+ navigationPromise: Promise.resolve(),
1764
+ resolveNavigation: () => {},
1765
+ matchCache: {},
1766
+ state: {
1767
+ status: 'idle',
1768
+ location: null,
1769
+ matches: [],
1770
+ actions: {},
1771
+ loaders: {},
1772
+ loaderData: {},
1773
+ lastUpdated: Date.now(),
1774
+ isFetching: false,
1775
+ isPreloading: false
1776
+ },
1777
+ startedLoadingAt: Date.now(),
1778
+ subscribe: listener => {
1779
+ router.listeners.push(listener);
1780
+ return () => {
1781
+ router.listeners = router.listeners.filter(x => x !== listener);
1782
+ };
1783
+ },
1784
+ getRoute: id => {
1785
+ return router.routesById[id];
1786
+ },
1787
+ notify: () => {
1788
+ router.state = _extends({}, router.state, {
1789
+ isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1790
+ isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1791
+ });
1792
+ cascadeLoaderData(router.state.matches);
1793
+ router.listeners.forEach(listener => listener());
1852
1794
  },
1853
- load: async () => {
1854
- const id = '' + Date.now() + Math.random();
1855
- routeMatch.__.latestId = id; // If the match was in an error state, set it
1856
- // to a loading state again. Otherwise, keep it
1857
- // as loading or resolved
1795
+ mount: () => {
1796
+ const next = router.__.buildLocation({
1797
+ to: '.',
1798
+ search: true,
1799
+ hash: true
1800
+ }); // If the current location isn't updated, trigger a navigation
1801
+ // to the current location. Otherwise, load the current location.
1858
1802
 
1859
- if (routeMatch.status === 'error' || routeMatch.status === 'idle') {
1860
- routeMatch.status = 'loading';
1861
- } // We started loading the route, so it's no longer invalid
1862
1803
 
1804
+ if (next.href !== router.location.href) {
1805
+ router.__.commitLocation(next, true);
1806
+ } else {
1807
+ router.loadLocation();
1808
+ }
1863
1809
 
1864
- routeMatch.isInvalid = false;
1865
- routeMatch.__.loadPromise = new Promise(async resolve => {
1866
- // We are now fetching, even if it's in the background of a
1867
- // resolved state
1868
- routeMatch.isFetching = true;
1869
- routeMatch.__.resolve = resolve;
1810
+ const unsub = history.listen(event => {
1811
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1812
+ }); // addEventListener does not exist in React Native, but window does
1813
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1870
1814
 
1871
- const loaderPromise = (async () => {
1872
- const importer = routeMatch.options.import; // First, run any importers
1815
+ if (!isServer && window.addEventListener) {
1816
+ // Listen to visibillitychange and focus
1817
+ window.addEventListener('visibilitychange', router.onFocus, false);
1818
+ window.addEventListener('focus', router.onFocus, false);
1819
+ }
1873
1820
 
1874
- if (importer) {
1875
- routeMatch.__.importPromise = importer({
1876
- params: routeMatch.params // search: routeMatch.search,
1821
+ return () => {
1822
+ unsub(); // Be sure to unsubscribe if a new handler is set
1877
1823
 
1878
- }).then(imported => {
1879
- routeMatch.__ = _extends$1({}, routeMatch.__, imported);
1880
- });
1881
- } // Wait for the importer to finish before
1882
- // attempting to load elements and data
1824
+ window.removeEventListener('visibilitychange', router.onFocus);
1825
+ window.removeEventListener('focus', router.onFocus);
1826
+ };
1827
+ },
1828
+ onFocus: () => {
1829
+ router.loadLocation();
1830
+ },
1831
+ update: opts => {
1832
+ Object.assign(router.options, opts);
1833
+ const {
1834
+ basepath,
1835
+ routeConfig
1836
+ } = router.options;
1837
+ router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1883
1838
 
1839
+ if (routeConfig) {
1840
+ router.routesById = {};
1841
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1842
+ }
1884
1843
 
1885
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1844
+ return router;
1845
+ },
1846
+ cancelMatches: () => {
1847
+ var _router$state$pending, _router$state$pending2;
1848
+ [...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
1849
+ match.cancel();
1850
+ });
1851
+ },
1852
+ loadLocation: async next => {
1853
+ const id = Math.random();
1854
+ router.startedLoadingAt = id;
1886
1855
 
1887
- routeMatch.__.elementsPromise = (async () => {
1888
- // then run all element and data loaders in parallel
1889
- // For each element type, potentially load it asynchronously
1890
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1891
- await Promise.all(elementTypes.map(async type => {
1892
- const routeElement = routeMatch.options[type];
1856
+ if (next) {
1857
+ // Ingest the new location
1858
+ router.location = next;
1859
+ } // Clear out old actions
1893
1860
 
1894
- if (routeMatch.__[type]) {
1895
- return;
1896
- }
1897
1861
 
1898
- if (typeof routeElement === 'function') {
1899
- const res = await routeElement(routeMatch);
1900
- routeMatch.__[type] = res;
1901
- } else {
1902
- routeMatch.__[type] = routeMatch.options[type];
1903
- }
1904
- }));
1905
- })();
1862
+ router.removeActionQueue.forEach(_ref => {
1863
+ let {
1864
+ action,
1865
+ actionState
1866
+ } = _ref;
1906
1867
 
1907
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1908
- try {
1909
- const data = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
1910
- params: routeMatch.params,
1911
- search: routeMatch.routeSearch,
1912
- signal: routeMatch.__.abortController.signal
1913
- }));
1868
+ if (router.state.currentAction === actionState) {
1869
+ router.state.currentAction = undefined;
1870
+ }
1914
1871
 
1915
- if (id !== routeMatch.__.latestId) {
1916
- return routeMatch.__.loaderPromise;
1917
- }
1872
+ if (action.current === actionState) {
1873
+ action.current = undefined;
1874
+ }
1875
+ });
1876
+ router.removeActionQueue = []; // Cancel any pending matches
1918
1877
 
1919
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1920
- cascadeLoaderData(routeMatch);
1921
- routeMatch.error = undefined;
1922
- routeMatch.status = 'success';
1923
- routeMatch.updatedAt = Date.now();
1924
- } catch (err) {
1925
- if (id !== routeMatch.__.latestId) {
1926
- return routeMatch.__.loaderPromise;
1927
- }
1878
+ router.cancelMatches(); // Match the routes
1928
1879
 
1929
- if (process.env.NODE_ENV !== 'production') {
1930
- console.error(err);
1931
- }
1880
+ const matches = router.matchRoutes(location.pathname, {
1881
+ strictParseParams: true
1882
+ });
1883
+ router.state = _extends({}, router.state, {
1884
+ pending: {
1885
+ matches: matches,
1886
+ location: router.location
1887
+ },
1888
+ status: 'loading'
1889
+ });
1890
+ router.notify(); // Load the matches
1932
1891
 
1933
- routeMatch.error = err;
1934
- routeMatch.status = 'error';
1935
- routeMatch.updatedAt = Date.now();
1936
- }
1937
- });
1892
+ await router.loadMatches(matches, {
1893
+ withPending: true
1894
+ });
1938
1895
 
1939
- try {
1940
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1896
+ if (router.startedLoadingAt !== id) {
1897
+ // Ignore side-effects of match loading
1898
+ return router.navigationPromise;
1899
+ }
1941
1900
 
1942
- if (id !== routeMatch.__.latestId) {
1943
- return routeMatch.__.loaderPromise;
1944
- }
1901
+ const previousMatches = router.state.matches;
1902
+ const exiting = [],
1903
+ staying = [];
1904
+ previousMatches.forEach(d => {
1905
+ if (matches.find(dd => dd.matchId === d.matchId)) {
1906
+ staying.push(d);
1907
+ } else {
1908
+ exiting.push(d);
1909
+ }
1910
+ });
1911
+ const now = Date.now();
1912
+ exiting.forEach(d => {
1913
+ var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1945
1914
 
1946
- if (routeMatch.__.pendingMinPromise) {
1947
- await routeMatch.__.pendingMinPromise;
1948
- delete routeMatch.__.pendingMinPromise;
1949
- }
1950
- } finally {
1951
- if (id !== routeMatch.__.latestId) {
1952
- return routeMatch.__.loaderPromise;
1953
- }
1915
+ d.__.onExit == null ? void 0 : d.__.onExit({
1916
+ params: d.params,
1917
+ search: d.routeSearch
1918
+ }); // Clear idle error states when match leaves
1954
1919
 
1955
- routeMatch.__.cancelPending();
1920
+ if (d.status === 'error' && !d.isFetching) {
1921
+ d.status = 'idle';
1922
+ d.error = undefined;
1923
+ }
1956
1924
 
1957
- routeMatch.isPending = false;
1958
- routeMatch.isFetching = false;
1925
+ const gc = Math.max((_ref2 = (_d$options$loaderGcMa = d.options.loaderGcMaxAge) != null ? _d$options$loaderGcMa : router.options.defaultLoaderGcMaxAge) != null ? _ref2 : 0, (_ref3 = (_d$options$loaderMaxA = d.options.loaderMaxAge) != null ? _d$options$loaderMaxA : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0);
1959
1926
 
1960
- routeMatch.__.notify();
1961
- }
1962
- })();
1927
+ if (gc > 0) {
1928
+ router.matchCache[d.matchId] = {
1929
+ gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1930
+ match: d
1931
+ };
1932
+ }
1933
+ });
1934
+ staying.forEach(d => {
1935
+ d.options.onTransition == null ? void 0 : d.options.onTransition({
1936
+ params: d.params,
1937
+ search: d.routeSearch
1938
+ });
1939
+ });
1940
+ const entering = matches.filter(d => {
1941
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
1942
+ });
1943
+ entering.forEach(d => {
1944
+ d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1945
+ params: d.params,
1946
+ search: d.search
1947
+ });
1948
+ delete router.matchCache[d.matchId];
1949
+ });
1963
1950
 
1964
- routeMatch.__.loaderPromise = loaderPromise;
1965
- await loaderPromise;
1951
+ if (matches.some(d => d.status === 'loading')) {
1952
+ router.notify();
1953
+ await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1954
+ }
1966
1955
 
1967
- if (id !== routeMatch.__.latestId) {
1968
- return routeMatch.__.loaderPromise;
1969
- }
1956
+ if (router.startedLoadingAt !== id) {
1957
+ // Ignore side-effects of match loading
1958
+ return;
1959
+ }
1970
1960
 
1971
- delete routeMatch.__.loaderPromise;
1961
+ router.state = _extends({}, router.state, {
1962
+ location: router.location,
1963
+ matches,
1964
+ pending: undefined,
1965
+ status: 'idle'
1972
1966
  });
1973
- return await routeMatch.__.loadPromise;
1974
- }
1975
- });
1976
-
1977
- return routeMatch;
1978
- }
1967
+ router.notify();
1968
+ router.resolveNavigation();
1969
+ },
1970
+ cleanMatchCache: () => {
1971
+ const now = Date.now();
1972
+ Object.keys(router.matchCache).forEach(matchId => {
1973
+ const entry = router.matchCache[matchId]; // Don't remove loading matches
1979
1974
 
1980
- function cascadeLoaderData(routeMatch) {
1981
- if (routeMatch.parentMatch) {
1982
- routeMatch.loaderData = replaceEqualDeep(routeMatch.loaderData, _extends$1({}, routeMatch.parentMatch.loaderData, routeMatch.routeLoaderData));
1983
- }
1975
+ if (entry.match.status === 'loading') {
1976
+ return;
1977
+ } // Do not remove successful matches that are still valid
1984
1978
 
1985
- if (routeMatch.childMatches.length) {
1986
- routeMatch.childMatches.forEach(childMatch => {
1987
- cascadeLoaderData(childMatch);
1988
- });
1989
- }
1990
- }
1991
1979
 
1992
- function matchPathname(currentPathname, matchLocation) {
1993
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1980
+ if (entry.gc > 0 && entry.gc > now) {
1981
+ return;
1982
+ } // Everything else gets removed
1994
1983
 
1995
- if (matchLocation.to && !pathParams) {
1996
- return;
1997
- } // if (matchLocation.search && !searchMatched) {
1998
- // return
1999
- // }
2000
1984
 
1985
+ delete router.matchCache[matchId];
1986
+ });
1987
+ },
1988
+ loadRoute: async function loadRoute(navigateOpts) {
1989
+ if (navigateOpts === void 0) {
1990
+ navigateOpts = router.location;
1991
+ }
2001
1992
 
2002
- return pathParams != null ? pathParams : {};
2003
- }
1993
+ const next = router.buildNext(navigateOpts);
1994
+ const matches = router.matchRoutes(next.pathname, {
1995
+ strictParseParams: true
1996
+ });
1997
+ await router.loadMatches(matches);
1998
+ return matches;
1999
+ },
2000
+ preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
2001
+ var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
2004
2002
 
2005
- function interpolatePath(path, params, leaveWildcard) {
2006
- const interpolatedPathSegments = parsePathname(path);
2007
- return joinPaths(interpolatedPathSegments.map(segment => {
2008
- if (segment.value === '*' && !leaveWildcard) {
2009
- return '';
2010
- }
2003
+ if (navigateOpts === void 0) {
2004
+ navigateOpts = router.location;
2005
+ }
2011
2006
 
2012
- if (segment.type === 'param') {
2013
- var _segment$value$substr;
2007
+ const next = router.buildNext(navigateOpts);
2008
+ const matches = router.matchRoutes(next.pathname, {
2009
+ strictParseParams: true
2010
+ });
2011
+ await router.loadMatches(matches, {
2012
+ preload: true,
2013
+ maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
2014
+ gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
2015
+ });
2016
+ return matches;
2017
+ },
2018
+ matchRoutes: (pathname, opts) => {
2019
+ var _router$state$pending3, _router$state$pending4;
2014
2020
 
2015
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
2016
- }
2021
+ router.cleanMatchCache();
2022
+ const matches = [];
2017
2023
 
2018
- return segment.value;
2019
- }));
2020
- }
2024
+ if (!router.routeTree) {
2025
+ return matches;
2026
+ }
2021
2027
 
2022
- function warning(cond, message) {
2023
- if (cond) {
2024
- if (typeof console !== 'undefined') console.warn(message);
2028
+ const existingMatches = [...router.state.matches, ...((_router$state$pending3 = (_router$state$pending4 = router.state.pending) == null ? void 0 : _router$state$pending4.matches) != null ? _router$state$pending3 : [])];
2025
2029
 
2026
- try {
2027
- throw new Error(message);
2028
- } catch (_unused) {}
2029
- }
2030
+ const recurse = async routes => {
2031
+ var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
2030
2032
 
2031
- return true;
2032
- }
2033
+ const parentMatch = last(matches);
2034
+ let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
2035
+ const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
2036
+ let foundRoutes = [];
2033
2037
 
2034
- function isFunction(d) {
2035
- return typeof d === 'function';
2036
- }
2038
+ const findMatchInRoutes = (parentRoutes, routes) => {
2039
+ routes.some(route => {
2040
+ var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
2037
2041
 
2038
- function functionalUpdate(updater, previous) {
2039
- if (isFunction(updater)) {
2040
- return updater(previous);
2041
- }
2042
+ if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
2043
+ return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
2044
+ }
2042
2045
 
2043
- return updater;
2044
- }
2046
+ const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
2047
+ const matchParams = matchPathname(pathname, {
2048
+ to: route.fullPath,
2049
+ fuzzy,
2050
+ caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2051
+ });
2045
2052
 
2046
- function joinPaths(paths) {
2047
- return cleanPath(paths.filter(Boolean).join('/'));
2048
- }
2053
+ if (matchParams) {
2054
+ let parsedParams;
2049
2055
 
2050
- function cleanPath(path) {
2051
- // remove double slashes
2052
- return path.replace(/\/{2,}/g, '/');
2053
- }
2056
+ try {
2057
+ var _route$options$parseP;
2054
2058
 
2055
- function trimPathLeft(path) {
2056
- return path === '/' ? path : path.replace(/^\/{1,}/, '');
2057
- }
2059
+ parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
2060
+ } catch (err) {
2061
+ if (opts != null && opts.strictParseParams) {
2062
+ throw err;
2063
+ }
2064
+ }
2058
2065
 
2059
- function trimPathRight(path) {
2060
- return path === '/' ? path : path.replace(/\/{1,}$/, '');
2061
- }
2066
+ params = _extends({}, params, parsedParams);
2067
+ }
2062
2068
 
2063
- function trimPath(path) {
2064
- return trimPathRight(trimPathLeft(path));
2065
- }
2069
+ if (!!matchParams) {
2070
+ foundRoutes = [...parentRoutes, route];
2071
+ }
2066
2072
 
2067
- function matchByPath(from, matchLocation) {
2068
- var _matchLocation$to;
2073
+ return !!foundRoutes.length;
2074
+ });
2075
+ return !!foundRoutes.length;
2076
+ };
2069
2077
 
2070
- const baseSegments = parsePathname(from);
2071
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
2072
- const params = {};
2078
+ findMatchInRoutes([], filteredRoutes);
2073
2079
 
2074
- let isMatch = (() => {
2075
- for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
2076
- const baseSegment = baseSegments[i];
2077
- const routeSegment = routeSegments[i];
2078
- const isLastRouteSegment = i === routeSegments.length - 1;
2079
- const isLastBaseSegment = i === baseSegments.length - 1;
2080
+ if (!foundRoutes.length) {
2081
+ return;
2082
+ }
2080
2083
 
2081
- if (routeSegment) {
2082
- if (routeSegment.type === 'wildcard') {
2083
- if (baseSegment != null && baseSegment.value) {
2084
- params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
2085
- return true;
2086
- }
2084
+ foundRoutes.forEach(foundRoute => {
2085
+ var _router$matchCache$ma;
2087
2086
 
2088
- return false;
2087
+ const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2088
+ const matchId = interpolatePath(foundRoute.routeId, params, true);
2089
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2090
+ matchId,
2091
+ params,
2092
+ pathname: joinPaths([pathname, interpolatedPath])
2093
+ });
2094
+ matches.push(match);
2095
+ });
2096
+ const foundRoute = last(foundRoutes);
2097
+
2098
+ if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2099
+ recurse(foundRoute.childRoutes);
2089
2100
  }
2101
+ };
2090
2102
 
2091
- if (routeSegment.type === 'pathname') {
2092
- if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
2093
- return true;
2094
- }
2103
+ recurse([router.routeTree]);
2104
+ cascadeLoaderData(matches);
2105
+ return matches;
2106
+ },
2107
+ loadMatches: async (resolvedMatches, loaderOpts) => {
2108
+ const matchPromises = resolvedMatches.map(async match => {
2109
+ // Validate the match (loads search params etc)
2110
+ match.__.validate();
2095
2111
 
2096
- if (baseSegment) {
2097
- if (matchLocation.caseSensitive) {
2098
- if (routeSegment.value !== baseSegment.value) {
2099
- return false;
2100
- }
2101
- } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
2102
- return false;
2103
- }
2104
- }
2112
+ match.load(loaderOpts);
2113
+
2114
+ if (match.status === 'loading') {
2115
+ // If requested, start the pending timers
2116
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2117
+ // This might be completion, error, or a pending state
2118
+
2119
+ await match.__.loadPromise;
2105
2120
  }
2121
+ });
2122
+ router.notify();
2123
+ await Promise.all(matchPromises);
2124
+ },
2125
+ invalidateRoute: opts => {
2126
+ var _router$state$pending5, _router$state$pending6;
2106
2127
 
2107
- if (!baseSegment) {
2108
- return false;
2128
+ const next = router.buildNext(opts);
2129
+ const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2130
+ [...router.state.matches, ...((_router$state$pending5 = (_router$state$pending6 = router.state.pending) == null ? void 0 : _router$state$pending6.matches) != null ? _router$state$pending5 : [])].forEach(match => {
2131
+ if (unloadedMatchIds.includes(match.matchId)) {
2132
+ match.invalidate();
2109
2133
  }
2134
+ });
2135
+ },
2136
+ reload: () => router.__.navigate({
2137
+ fromCurrent: true,
2138
+ replace: true,
2139
+ search: true
2140
+ }),
2141
+ resolvePath: (from, path) => {
2142
+ return resolvePath(router.basepath, from, cleanPath(path));
2143
+ },
2144
+ matchRoute: (location, opts) => {
2145
+ var _location$from;
2110
2146
 
2111
- if (routeSegment.type === 'param') {
2112
- if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
2113
- return false;
2114
- }
2147
+ // const location = router.buildNext(opts)
2148
+ location = _extends({}, location, {
2149
+ to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2150
+ });
2151
+ const next = router.buildNext(location);
2115
2152
 
2116
- if (!baseSegment.value.startsWith(':')) {
2117
- params[routeSegment.value.substring(1)] = baseSegment.value;
2118
- }
2153
+ if (opts != null && opts.pending) {
2154
+ var _router$state$pending7;
2155
+
2156
+ if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2157
+ return false;
2119
2158
  }
2120
- }
2121
2159
 
2122
- if (isLastRouteSegment && !isLastBaseSegment) {
2123
- return !!matchLocation.fuzzy;
2160
+ return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2161
+ to: next.pathname
2162
+ }));
2124
2163
  }
2125
- }
2126
2164
 
2127
- return true;
2128
- })();
2165
+ return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2166
+ to: next.pathname
2167
+ }));
2168
+ },
2169
+ navigate: async _ref8 => {
2170
+ let {
2171
+ from,
2172
+ to = '.',
2173
+ search,
2174
+ hash,
2175
+ replace,
2176
+ params
2177
+ } = _ref8;
2178
+ // If this link simply reloads the current route,
2179
+ // make sure it has a new key so it will trigger a data refresh
2180
+ // If this `to` is a valid external URL, return
2181
+ // null for LinkUtils
2182
+ const toString = String(to);
2183
+ const fromString = String(from);
2184
+ let isExternal;
2129
2185
 
2130
- return isMatch ? params : undefined;
2131
- } // function matchBySearch(
2132
- // search: SearchSchema,
2133
- // matchLocation: MatchLocation,
2134
- // ) {
2135
- // return !!(matchLocation.search && matchLocation.search(search))
2136
- // }
2186
+ try {
2187
+ new URL("" + toString);
2188
+ isExternal = true;
2189
+ } catch (e) {}
2137
2190
 
2138
- function parsePathname(pathname) {
2139
- if (!pathname) {
2140
- return [];
2141
- }
2191
+ invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2192
+ return router.__.navigate({
2193
+ from: fromString,
2194
+ to: toString,
2195
+ search,
2196
+ hash,
2197
+ replace,
2198
+ params
2199
+ });
2200
+ },
2201
+ buildLink: _ref9 => {
2202
+ var _preload, _ref10;
2142
2203
 
2143
- pathname = cleanPath(pathname);
2144
- const segments = [];
2204
+ let {
2205
+ from,
2206
+ to = '.',
2207
+ search,
2208
+ params,
2209
+ hash,
2210
+ target,
2211
+ replace,
2212
+ activeOptions,
2213
+ preload,
2214
+ preloadMaxAge: userPreloadMaxAge,
2215
+ preloadGcMaxAge: userPreloadGcMaxAge,
2216
+ preloadDelay: userPreloadDelay,
2217
+ disabled
2218
+ } = _ref9;
2145
2219
 
2146
- if (pathname.slice(0, 1) === '/') {
2147
- pathname = pathname.substring(1);
2148
- segments.push({
2149
- type: 'pathname',
2150
- value: '/'
2151
- });
2152
- }
2220
+ // If this link simply reloads the current route,
2221
+ // make sure it has a new key so it will trigger a data refresh
2222
+ // If this `to` is a valid external URL, return
2223
+ // null for LinkUtils
2224
+ try {
2225
+ new URL("" + to);
2226
+ return {
2227
+ type: 'external',
2228
+ href: to
2229
+ };
2230
+ } catch (e) {}
2153
2231
 
2154
- if (!pathname) {
2155
- return segments;
2156
- } // Remove empty segments and '.' segments
2232
+ const nextOpts = {
2233
+ from,
2234
+ to,
2235
+ search,
2236
+ params,
2237
+ hash,
2238
+ replace
2239
+ };
2240
+ const next = router.buildNext(nextOpts);
2241
+ preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2242
+ const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2157
2243
 
2244
+ const pathIsEqual = router.state.location.pathname === next.pathname;
2245
+ const currentPathSplit = router.state.location.pathname.split('/');
2246
+ const nextPathSplit = next.pathname.split('/');
2247
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2248
+ const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2158
2249
 
2159
- const split = pathname.split('/').filter(Boolean);
2160
- segments.push(...split.map(part => {
2161
- if (part.startsWith('*')) {
2162
- return {
2163
- type: 'wildcard',
2164
- value: part
2165
- };
2166
- }
2250
+ const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2251
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2167
2252
 
2168
- if (part.charAt(0) === ':') {
2169
- return {
2170
- type: 'param',
2171
- value: part
2172
- };
2173
- }
2253
+ const isActive = pathTest && hashTest; // The click handler
2174
2254
 
2175
- return {
2176
- type: 'pathname',
2177
- value: part
2178
- };
2179
- }));
2255
+ const handleClick = e => {
2256
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2257
+ e.preventDefault();
2180
2258
 
2181
- if (pathname.slice(-1) === '/') {
2182
- pathname = pathname.substring(1);
2183
- segments.push({
2184
- type: 'pathname',
2185
- value: '/'
2186
- });
2187
- }
2259
+ if (pathIsEqual && !search && !hash) {
2260
+ router.invalidateRoute(nextOpts);
2261
+ } // All is well? Navigate!)
2188
2262
 
2189
- return segments;
2190
- }
2191
2263
 
2192
- function _resolvePath(basepath, base, to) {
2193
- base = base.replace(new RegExp("^" + basepath), '/');
2194
- to = to.replace(new RegExp("^" + basepath), '/');
2195
- let baseSegments = parsePathname(base);
2196
- const toSegments = parsePathname(to);
2197
- toSegments.forEach((toSegment, index) => {
2198
- if (toSegment.value === '/') {
2199
- if (!index) {
2200
- // Leading slash
2201
- baseSegments = [toSegment];
2202
- } else if (index === toSegments.length - 1) {
2203
- // Trailing Slash
2204
- baseSegments.push(toSegment);
2205
- } else ;
2206
- } else if (toSegment.value === '..') {
2207
- var _last2;
2264
+ router.__.navigate(nextOpts);
2265
+ }
2266
+ }; // The click handler
2267
+
2268
+
2269
+ const handleFocus = e => {
2270
+ if (preload) {
2271
+ router.preloadRoute(nextOpts, {
2272
+ maxAge: userPreloadMaxAge,
2273
+ gcMaxAge: userPreloadGcMaxAge
2274
+ });
2275
+ }
2276
+ };
2277
+
2278
+ const handleEnter = e => {
2279
+ const target = e.target || {};
2280
+
2281
+ if (preload) {
2282
+ if (target.preloadTimeout) {
2283
+ return;
2284
+ }
2285
+
2286
+ target.preloadTimeout = setTimeout(() => {
2287
+ target.preloadTimeout = null;
2288
+ router.preloadRoute(nextOpts, {
2289
+ maxAge: userPreloadMaxAge,
2290
+ gcMaxAge: userPreloadGcMaxAge
2291
+ });
2292
+ }, preloadDelay);
2293
+ }
2294
+ };
2208
2295
 
2209
- // Extra trailing slash? pop it off
2210
- if (baseSegments.length > 1 && ((_last2 = last(baseSegments)) == null ? void 0 : _last2.value) === '/') {
2211
- baseSegments.pop();
2212
- }
2296
+ const handleLeave = e => {
2297
+ const target = e.target || {};
2213
2298
 
2214
- baseSegments.pop();
2215
- } else if (toSegment.value === '.') {
2216
- return;
2217
- } else {
2218
- baseSegments.push(toSegment);
2219
- }
2220
- });
2221
- const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
2222
- return cleanPath(joined);
2223
- }
2224
- function replaceEqualDeep(prev, next) {
2225
- if (prev === next) {
2226
- return prev;
2227
- }
2299
+ if (target.preloadTimeout) {
2300
+ clearTimeout(target.preloadTimeout);
2301
+ target.preloadTimeout = null;
2302
+ }
2303
+ };
2228
2304
 
2229
- const array = Array.isArray(prev) && Array.isArray(next);
2305
+ return {
2306
+ type: 'internal',
2307
+ next,
2308
+ handleFocus,
2309
+ handleClick,
2310
+ handleEnter,
2311
+ handleLeave,
2312
+ isActive,
2313
+ disabled
2314
+ };
2315
+ },
2316
+ buildNext: opts => {
2317
+ const next = router.__.buildLocation(opts);
2230
2318
 
2231
- if (array || isPlainObject(prev) && isPlainObject(next)) {
2232
- const aSize = array ? prev.length : Object.keys(prev).length;
2233
- const bItems = array ? next : Object.keys(next);
2234
- const bSize = bItems.length;
2235
- const copy = array ? [] : {};
2236
- let equalItems = 0;
2319
+ const matches = router.matchRoutes(next.pathname);
2237
2320
 
2238
- for (let i = 0; i < bSize; i++) {
2239
- const key = array ? i : bItems[i];
2240
- copy[key] = replaceEqualDeep(prev[key], next[key]);
2321
+ const __preSearchFilters = matches.map(match => {
2322
+ var _match$options$preSea;
2241
2323
 
2242
- if (copy[key] === prev[key]) {
2243
- equalItems++;
2244
- }
2245
- }
2324
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2325
+ }).flat().filter(Boolean);
2246
2326
 
2247
- return aSize === bSize && equalItems === aSize ? prev : copy;
2248
- }
2327
+ const __postSearchFilters = matches.map(match => {
2328
+ var _match$options$postSe;
2249
2329
 
2250
- return next;
2251
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
2330
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2331
+ }).flat().filter(Boolean);
2252
2332
 
2253
- function isPlainObject(o) {
2254
- if (!hasObjectPrototype(o)) {
2255
- return false;
2256
- } // If has modified constructor
2333
+ return router.__.buildLocation(_extends({}, opts, {
2334
+ __preSearchFilters,
2335
+ __postSearchFilters
2336
+ }));
2337
+ },
2338
+ __: {
2339
+ buildRouteTree: rootRouteConfig => {
2340
+ const recurseRoutes = (routeConfigs, parent) => {
2341
+ return routeConfigs.map(routeConfig => {
2342
+ const routeOptions = routeConfig.options;
2343
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2344
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2345
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2346
+ // }
2347
+
2348
+ const existingRoute = router.routesById[route.routeId];
2349
+
2350
+ if (existingRoute) {
2351
+ if (process.env.NODE_ENV !== 'production') {
2352
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2353
+ }
2257
2354
 
2355
+ throw new Error();
2356
+ }
2357
+ router.routesById[route.routeId] = route;
2358
+ const children = routeConfig.children;
2359
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2360
+ return route;
2361
+ });
2362
+ };
2258
2363
 
2259
- const ctor = o.constructor;
2364
+ const routes = recurseRoutes([rootRouteConfig]);
2365
+ return routes[0];
2366
+ },
2367
+ parseLocation: (location, previousLocation) => {
2368
+ var _location$hash$split$;
2260
2369
 
2261
- if (typeof ctor === 'undefined') {
2262
- return true;
2263
- } // If has modified prototype
2370
+ const parsedSearch = router.options.parseSearch(location.search);
2371
+ return {
2372
+ pathname: location.pathname,
2373
+ searchStr: location.search,
2374
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2375
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2376
+ href: "" + location.pathname + location.search + location.hash,
2377
+ state: location.state,
2378
+ key: location.key
2379
+ };
2380
+ },
2381
+ navigate: location => {
2382
+ const next = router.buildNext(location);
2383
+ return router.__.commitLocation(next, location.replace);
2384
+ },
2385
+ buildLocation: function buildLocation(dest) {
2386
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2264
2387
 
2388
+ if (dest === void 0) {
2389
+ dest = {};
2390
+ }
2265
2391
 
2266
- const prot = ctor.prototype;
2392
+ // const resolvedFrom: Location = {
2393
+ // ...router.location,
2394
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2267
2395
 
2268
- if (!hasObjectPrototype(prot)) {
2269
- return false;
2270
- } // If constructor does not have an Object-specific method
2396
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2271
2397
 
2398
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2399
+ strictParseParams: true
2400
+ });
2401
+ const toMatches = router.matchRoutes(pathname);
2272
2402
 
2273
- if (!prot.hasOwnProperty('isPrototypeOf')) {
2274
- return false;
2275
- } // Most likely a plain Object
2403
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2276
2404
 
2405
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2277
2406
 
2278
- return true;
2279
- }
2407
+ if (nextParams) {
2408
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2409
+ Object.assign({}, nextParams, fn(nextParams));
2410
+ });
2411
+ }
2280
2412
 
2281
- function hasObjectPrototype(o) {
2282
- return Object.prototype.toString.call(o) === '[object Object]';
2283
- }
2413
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2284
2414
 
2285
- const defaultParseSearch = parseSearchWith(JSON.parse);
2286
- const defaultStringifySearch = stringifySearchWith(JSON.stringify);
2287
- function parseSearchWith(parser) {
2288
- return searchStr => {
2289
- if (searchStr.substring(0, 1) === '?') {
2290
- searchStr = searchStr.substring(1);
2291
- }
2415
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
2292
2416
 
2293
- let query = decode(searchStr); // Try to parse any query params that might be json
2417
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2418
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2419
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2420
+ : {}; // Then post filters
2294
2421
 
2295
- for (let key in query) {
2296
- const value = query[key];
2422
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2423
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2424
+ const searchStr = router.options.stringifySearch(search);
2425
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2426
+ hash = hash ? "#" + hash : '';
2427
+ return {
2428
+ pathname,
2429
+ search,
2430
+ searchStr,
2431
+ state: router.location.state,
2432
+ hash,
2433
+ href: "" + pathname + searchStr + hash,
2434
+ key: dest.key
2435
+ };
2436
+ },
2437
+ commitLocation: (next, replace) => {
2438
+ const id = '' + Date.now() + Math.random();
2439
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2440
+ let nextAction = 'replace';
2297
2441
 
2298
- if (typeof value === 'string') {
2299
- try {
2300
- query[key] = parser(value);
2301
- } catch (err) {//
2442
+ if (!replace) {
2443
+ nextAction = 'push';
2302
2444
  }
2303
- }
2304
- }
2305
2445
 
2306
- return query;
2307
- };
2308
- }
2309
- function stringifySearchWith(stringify) {
2310
- return search => {
2311
- search = _extends$1({}, search);
2446
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2312
2447
 
2313
- if (search) {
2314
- Object.keys(search).forEach(key => {
2315
- const val = search[key];
2448
+ if (isSameUrl && !next.key) {
2449
+ nextAction = 'replace';
2450
+ }
2316
2451
 
2317
- if (typeof val === 'undefined' || val === undefined) {
2318
- delete search[key];
2319
- } else if (val && typeof val === 'object' && val !== null) {
2320
- try {
2321
- search[key] = stringify(val);
2322
- } catch (err) {// silent
2323
- }
2452
+ if (nextAction === 'replace') {
2453
+ history.replace({
2454
+ pathname: next.pathname,
2455
+ hash: next.hash,
2456
+ search: next.searchStr
2457
+ }, {
2458
+ id
2459
+ });
2460
+ } else {
2461
+ history.push({
2462
+ pathname: next.pathname,
2463
+ hash: next.hash,
2464
+ search: next.searchStr
2465
+ }, {
2466
+ id
2467
+ });
2324
2468
  }
2325
- });
2326
- }
2327
2469
 
2328
- const searchStr = encode(search).toString();
2329
- return searchStr ? "?" + searchStr : '';
2470
+ router.navigationPromise = new Promise(resolve => {
2471
+ const previousNavigationResolve = router.resolveNavigation;
2472
+
2473
+ router.resolveNavigation = () => {
2474
+ previousNavigationResolve();
2475
+ resolve();
2476
+ };
2477
+ });
2478
+ return router.navigationPromise;
2479
+ }
2480
+ }
2330
2481
  };
2482
+ router.location = router.__.parseLocation(history.location);
2483
+ router.state.location = router.location;
2484
+ router.update(userOptions); // Allow frameworks to hook into the router creation
2485
+
2486
+ router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2487
+ return router;
2331
2488
  }
2332
2489
 
2333
2490
  function isCtrlEvent(e) {
2334
2491
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2335
2492
  }
2336
2493
 
2337
- function last(arr) {
2338
- return arr[arr.length - 1];
2339
- }
2340
-
2341
2494
  const _excluded = ["type", "children", "target", "activeProps", "inactiveProps", "activeOptions", "disabled", "hash", "search", "params", "to", "preload", "preloadDelay", "preloadMaxAge", "replace", "style", "className", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onTouchStart", "onTouchEnd"],
2342
2495
  _excluded2 = ["pending", "caseSensitive", "children"],
2343
2496
  _excluded3 = ["children", "router"];
@@ -2356,152 +2509,166 @@ const useRouterSubscription = router => {
2356
2509
  };
2357
2510
 
2358
2511
  function createReactRouter(opts) {
2512
+ const makeRouteExt = (route, router) => {
2513
+ return {
2514
+ useRoute: function useRoute(subRouteId) {
2515
+ if (subRouteId === void 0) {
2516
+ subRouteId = '.';
2517
+ }
2518
+
2519
+ const resolvedRouteId = router.resolvePath(route.routeId, subRouteId);
2520
+ const resolvedRoute = router.getRoute(resolvedRouteId);
2521
+ useRouterSubscription(router);
2522
+ invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
2523
+ return resolvedRoute;
2524
+ },
2525
+ linkProps: options => {
2526
+ var _functionalUpdate, _functionalUpdate2;
2527
+
2528
+ const {
2529
+ // custom props
2530
+ target,
2531
+ activeProps = () => ({
2532
+ className: 'active'
2533
+ }),
2534
+ inactiveProps = () => ({}),
2535
+ disabled,
2536
+ // element props
2537
+ style,
2538
+ className,
2539
+ onClick,
2540
+ onFocus,
2541
+ onMouseEnter,
2542
+ onMouseLeave
2543
+ } = options,
2544
+ rest = _objectWithoutPropertiesLoose(options, _excluded);
2545
+
2546
+ const linkInfo = route.buildLink(options);
2547
+
2548
+ if (linkInfo.type === 'external') {
2549
+ const {
2550
+ href
2551
+ } = linkInfo;
2552
+ return {
2553
+ href
2554
+ };
2555
+ }
2556
+
2557
+ const {
2558
+ handleClick,
2559
+ handleFocus,
2560
+ handleEnter,
2561
+ handleLeave,
2562
+ isActive,
2563
+ next
2564
+ } = linkInfo;
2565
+
2566
+ const composeHandlers = handlers => e => {
2567
+ e.persist();
2568
+ handlers.forEach(handler => {
2569
+ if (handler) handler(e);
2570
+ });
2571
+ }; // Get the active props
2572
+
2573
+
2574
+ const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps, {})) != null ? _functionalUpdate : {} : {}; // Get the inactive props
2575
+
2576
+ const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
2577
+ return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2578
+ href: disabled ? undefined : next.href,
2579
+ onClick: composeHandlers([handleClick, onClick]),
2580
+ onFocus: composeHandlers([handleFocus, onFocus]),
2581
+ onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2582
+ onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
2583
+ target,
2584
+ style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
2585
+ className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
2586
+ }, disabled ? {
2587
+ role: 'link',
2588
+ 'aria-disabled': true
2589
+ } : undefined, {
2590
+ ['data-status']: isActive ? 'active' : undefined
2591
+ });
2592
+ },
2593
+ Link: /*#__PURE__*/React.forwardRef((props, ref) => {
2594
+ const linkProps = route.linkProps(props);
2595
+ useRouterSubscription(router);
2596
+ return /*#__PURE__*/React.createElement("a", _extends$2({
2597
+ ref: ref
2598
+ }, linkProps, {
2599
+ children: typeof props.children === 'function' ? props.children({
2600
+ isActive: linkProps['data-status'] === 'active'
2601
+ }) : props.children
2602
+ }));
2603
+ }),
2604
+ MatchRoute: opts => {
2605
+ const {
2606
+ pending,
2607
+ caseSensitive
2608
+ } = opts,
2609
+ rest = _objectWithoutPropertiesLoose(opts, _excluded2);
2610
+
2611
+ const params = route.matchRoute(rest, {
2612
+ pending,
2613
+ caseSensitive
2614
+ });
2615
+
2616
+ if (!params) {
2617
+ return null;
2618
+ }
2619
+
2620
+ return typeof opts.children === 'function' ? opts.children(params) : opts.children;
2621
+ }
2622
+ };
2623
+ };
2624
+
2359
2625
  const coreRouter = createRouter(_extends$2({}, opts, {
2360
2626
  createRouter: router => {
2361
2627
  const routerExt = {
2362
- useRoute: routeId => {
2363
- const route = router.getRoute(routeId);
2628
+ useState: () => {
2364
2629
  useRouterSubscription(router);
2365
-
2366
- if (!route) {
2367
- throw new Error("Could not find a route for route \"" + routeId + "\"! Did you forget to add it to your route config?");
2368
- }
2369
-
2370
- return route;
2630
+ return router.state;
2371
2631
  },
2372
2632
  useMatch: routeId => {
2373
- if (routeId === rootRouteId) {
2374
- throw new Error("\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2375
- }
2633
+ useRouterSubscription(router);
2634
+ invariant(routeId !== rootRouteId, "\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2376
2635
 
2377
2636
  const runtimeMatch = _useMatch();
2378
2637
 
2379
2638
  const match = router.state.matches.find(d => d.routeId === routeId);
2639
+ invariant(match, "Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2640
+ invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2380
2641
 
2381
2642
  if (!match) {
2382
- throw new Error("Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2383
- }
2384
-
2385
- if (runtimeMatch.routeId !== (match == null ? void 0 : match.routeId)) {
2386
- throw new Error("useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2387
- }
2388
-
2389
- useRouterSubscription(router);
2390
-
2391
- if (!match) {
2392
- throw new Error('Match not found!');
2643
+ invariant('Match not found!');
2393
2644
  }
2394
2645
 
2395
2646
  return match;
2396
2647
  }
2397
2648
  };
2398
- Object.assign(router, routerExt);
2649
+ const routeExt = makeRouteExt(router.getRoute('/'), router);
2650
+ Object.assign(router, routerExt, routeExt);
2399
2651
  },
2400
2652
  createRoute: _ref => {
2401
2653
  let {
2402
2654
  router,
2403
2655
  route
2404
2656
  } = _ref;
2405
- const routeExt = {
2406
- linkProps: options => {
2407
- var _functionalUpdate, _functionalUpdate2;
2408
-
2409
- const {
2410
- // custom props
2411
- target,
2412
- activeProps = () => ({
2413
- className: 'active'
2414
- }),
2415
- inactiveProps = () => ({}),
2416
- disabled,
2417
- // element props
2418
- style,
2419
- className,
2420
- onClick,
2421
- onFocus,
2422
- onMouseEnter,
2423
- onMouseLeave
2424
- } = options,
2425
- rest = _objectWithoutPropertiesLoose(options, _excluded);
2426
-
2427
- const linkInfo = route.buildLink(options);
2428
-
2429
- if (linkInfo.type === 'external') {
2430
- const {
2431
- href
2432
- } = linkInfo;
2433
- return {
2434
- href
2435
- };
2436
- }
2437
-
2438
- const {
2439
- handleClick,
2440
- handleFocus,
2441
- handleEnter,
2442
- handleLeave,
2443
- isActive,
2444
- next
2445
- } = linkInfo;
2446
-
2447
- const composeHandlers = handlers => e => {
2448
- e.persist();
2449
- handlers.forEach(handler => {
2450
- if (handler) handler(e);
2451
- });
2452
- }; // Get the active props
2453
-
2454
-
2455
- const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps)) != null ? _functionalUpdate : {} : {}; // Get the inactive props
2456
-
2457
- const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps)) != null ? _functionalUpdate2 : {};
2458
- return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2459
- href: disabled ? undefined : next.href,
2460
- onClick: composeHandlers([handleClick, onClick]),
2461
- onFocus: composeHandlers([handleFocus, onFocus]),
2462
- onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2463
- onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
2464
- target,
2465
- style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
2466
- className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
2467
- }, disabled ? {
2468
- role: 'link',
2469
- 'aria-disabled': true
2470
- } : undefined, {
2471
- ['data-status']: isActive ? 'active' : undefined
2472
- });
2473
- },
2474
- Link: /*#__PURE__*/React.forwardRef((props, ref) => {
2475
- const linkProps = route.linkProps(props);
2476
- useRouterSubscription(router);
2477
- return /*#__PURE__*/React.createElement("a", _extends$2({
2478
- ref: ref
2479
- }, linkProps, {
2480
- children: typeof props.children === 'function' ? props.children({
2481
- isActive: linkProps['data-status'] === 'active'
2482
- }) : props.children
2483
- }));
2484
- }),
2485
- MatchRoute: opts => {
2486
- const {
2487
- pending,
2488
- caseSensitive
2489
- } = opts,
2490
- rest = _objectWithoutPropertiesLoose(opts, _excluded2);
2491
-
2492
- const params = route.matchRoute(rest, {
2493
- pending,
2494
- caseSensitive
2495
- }); // useRouterSubscription(router)
2496
-
2497
- if (!params) {
2498
- return null;
2499
- }
2657
+ const routeExt = makeRouteExt(route, router);
2658
+ Object.assign(route, routeExt);
2659
+ },
2660
+ createElement: async element => {
2661
+ if (typeof element === 'function') {
2662
+ const res = await element(); // Support direct import() calls
2500
2663
 
2501
- return typeof opts.children === 'function' ? opts.children(params) : opts.children;
2664
+ if (typeof res === 'object' && res.default) {
2665
+ return /*#__PURE__*/React.createElement(res.default);
2666
+ } else {
2667
+ return res;
2502
2668
  }
2503
- };
2504
- Object.assign(route, routeExt);
2669
+ }
2670
+
2671
+ return element;
2505
2672
  }
2506
2673
  }));
2507
2674
  return coreRouter;
@@ -2514,10 +2681,10 @@ function RouterProvider(_ref2) {
2514
2681
  rest = _objectWithoutPropertiesLoose(_ref2, _excluded3);
2515
2682
 
2516
2683
  router.update(rest);
2517
- useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state);
2684
+ useRouterSubscription(router);
2518
2685
  useLayoutEffect(() => {
2519
- router.mount();
2520
- }, []);
2686
+ return router.mount();
2687
+ }, [router]);
2521
2688
  return /*#__PURE__*/React.createElement(routerContext.Provider, {
2522
2689
  value: {
2523
2690
  router
@@ -2526,38 +2693,43 @@ function RouterProvider(_ref2) {
2526
2693
  value: router.state.matches
2527
2694
  }, children != null ? children : /*#__PURE__*/React.createElement(Outlet, null)));
2528
2695
  }
2696
+
2529
2697
  function useRouter() {
2530
2698
  const value = React.useContext(routerContext);
2531
2699
  warning(!value, 'useRouter must be used inside a <Router> component!');
2532
2700
  useRouterSubscription(value.router);
2533
2701
  return value.router;
2534
2702
  }
2703
+
2535
2704
  function useMatches() {
2536
2705
  return React.useContext(matchesContext);
2537
- }
2538
- function useParentMatches() {
2539
- const router = useRouter();
2540
-
2541
- const match = _useMatch();
2706
+ } // function useParentMatches(): RouteMatch[] {
2707
+ // const router = useRouter()
2708
+ // const match = useMatch()
2709
+ // const matches = router.state.matches
2710
+ // return matches.slice(
2711
+ // 0,
2712
+ // matches.findIndex((d) => d.matchId === match.matchId) - 1,
2713
+ // )
2714
+ // }
2542
2715
 
2543
- const matches = router.state.matches;
2544
- return matches.slice(0, matches.findIndex(d => d.matchId === match.matchId) - 1);
2545
- }
2546
2716
 
2547
2717
  function _useMatch() {
2548
2718
  var _useMatches;
2549
2719
 
2550
2720
  return (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2551
2721
  }
2722
+
2552
2723
  function Outlet() {
2553
- var _ref3, _childMatch$options$c;
2724
+ var _childMatch$options$c;
2554
2725
 
2555
2726
  const router = useRouter();
2556
2727
  const [, ...matches] = useMatches();
2557
2728
  const childMatch = matches[0];
2558
2729
  if (!childMatch) return null;
2559
- const element = (_ref3 = (() => {
2560
- var _childMatch$__$errorE, _ref5;
2730
+
2731
+ const element = (() => {
2732
+ var _childMatch$__$errorE, _ref4;
2561
2733
 
2562
2734
  if (!childMatch) {
2563
2735
  return null;
@@ -2574,7 +2746,7 @@ function Outlet() {
2574
2746
  throw childMatch.error;
2575
2747
  }
2576
2748
 
2577
- return /*#__PURE__*/React.createElement(DefaultCatchBoundary, {
2749
+ return /*#__PURE__*/React.createElement(DefaultErrorBoundary, {
2578
2750
  error: childMatch.error
2579
2751
  });
2580
2752
  }
@@ -2586,17 +2758,18 @@ function Outlet() {
2586
2758
  const pendingElement = (_childMatch$__$pendin = childMatch.__.pendingElement) != null ? _childMatch$__$pendin : router.options.defaultPendingElement;
2587
2759
 
2588
2760
  if (childMatch.options.pendingMs || pendingElement) {
2589
- var _ref4;
2761
+ var _ref3;
2590
2762
 
2591
- return (_ref4 = pendingElement) != null ? _ref4 : null;
2763
+ return (_ref3 = pendingElement) != null ? _ref3 : null;
2592
2764
  }
2593
2765
  }
2594
2766
 
2595
2767
  return null;
2596
2768
  }
2597
2769
 
2598
- return (_ref5 = childMatch.__.element) != null ? _ref5 : router.options.defaultElement;
2599
- })()) != null ? _ref3 : /*#__PURE__*/React.createElement(Outlet, null);
2770
+ return (_ref4 = childMatch.__.element) != null ? _ref4 : router.options.defaultElement;
2771
+ })();
2772
+
2600
2773
  const catchElement = (_childMatch$options$c = childMatch == null ? void 0 : childMatch.options.catchElement) != null ? _childMatch$options$c : router.options.defaultCatchElement;
2601
2774
  return /*#__PURE__*/React.createElement(MatchesProvider, {
2602
2775
  value: matches,
@@ -2632,7 +2805,7 @@ class CatchBoundary extends React.Component {
2632
2805
  render() {
2633
2806
  var _this$props$catchElem;
2634
2807
 
2635
- const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultCatchBoundary;
2808
+ const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultErrorBoundary;
2636
2809
 
2637
2810
  if (this.state.error) {
2638
2811
  return typeof catchElement === 'function' ? catchElement(this.state) : catchElement;
@@ -2643,10 +2816,10 @@ class CatchBoundary extends React.Component {
2643
2816
 
2644
2817
  }
2645
2818
 
2646
- function DefaultCatchBoundary(_ref6) {
2819
+ function DefaultErrorBoundary(_ref5) {
2647
2820
  let {
2648
2821
  error
2649
- } = _ref6;
2822
+ } = _ref5;
2650
2823
  return /*#__PURE__*/React.createElement("div", {
2651
2824
  style: {
2652
2825
  padding: '.5rem',
@@ -2681,6 +2854,30 @@ function DefaultCatchBoundary(_ref6) {
2681
2854
  }
2682
2855
  }, "If you are the owner of this website, it's highly recommended that you configure your own custom Catch/Error boundaries for the router. You can optionally configure a boundary for each route."));
2683
2856
  }
2857
+ function usePrompt(message, when) {
2858
+ const router = useRouter();
2859
+ React.useEffect(() => {
2860
+ if (!when) return;
2861
+ let unblock = router.history.block(transition => {
2862
+ if (window.confirm(message)) {
2863
+ unblock();
2864
+ transition.retry();
2865
+ } else {
2866
+ router.location.pathname = window.location.pathname;
2867
+ }
2868
+ });
2869
+ return unblock;
2870
+ }, [when, location, message]);
2871
+ }
2872
+ function Prompt(_ref6) {
2873
+ let {
2874
+ message,
2875
+ when,
2876
+ children
2877
+ } = _ref6;
2878
+ usePrompt(message, when != null ? when : true);
2879
+ return children != null ? children : null;
2880
+ }
2684
2881
 
2685
- export { DefaultCatchBoundary, MatchesProvider, Outlet, RouterProvider, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, defaultParseSearch, defaultStringifySearch, functionalUpdate, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, _resolvePath as resolvePath, rootRouteId, stringifySearchWith, _useMatch as useMatch, useMatches, useParentMatches, useRouter, warning };
2882
+ export { DefaultErrorBoundary, MatchesProvider, Outlet, Prompt, RouterProvider, cascadeLoaderData, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, invariant, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, usePrompt, warning };
2686
2883
  //# sourceMappingURL=index.js.map