@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.
@@ -39,23 +39,6 @@ function _extends$1() {
39
39
  return _extends$1.apply(this, arguments);
40
40
  }
41
41
 
42
- function _extends() {
43
- _extends = Object.assign ? Object.assign.bind() : function (target) {
44
- for (var i = 1; i < arguments.length; i++) {
45
- var source = arguments[i];
46
-
47
- for (var key in source) {
48
- if (Object.prototype.hasOwnProperty.call(source, key)) {
49
- target[key] = source[key];
50
- }
51
- }
52
- }
53
-
54
- return target;
55
- };
56
- return _extends.apply(this, arguments);
57
- }
58
-
59
42
  /**
60
43
  * Actions represent the type of change to a location value.
61
44
  *
@@ -199,7 +182,7 @@ function createBrowserHistory(options) {
199
182
 
200
183
  if (index == null) {
201
184
  index = 0;
202
- globalHistory.replaceState(_extends({}, globalHistory.state, {
185
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
203
186
  idx: index
204
187
  }), '');
205
188
  }
@@ -214,7 +197,7 @@ function createBrowserHistory(options) {
214
197
  state = null;
215
198
  }
216
199
 
217
- return readOnly(_extends({
200
+ return readOnly(_extends$1({
218
201
  pathname: location.pathname,
219
202
  hash: '',
220
203
  search: ''
@@ -448,7 +431,7 @@ function createHashHistory(options) {
448
431
 
449
432
  if (index == null) {
450
433
  index = 0;
451
- globalHistory.replaceState(_extends({}, globalHistory.state, {
434
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
452
435
  idx: index
453
436
  }), '');
454
437
  }
@@ -475,7 +458,7 @@ function createHashHistory(options) {
475
458
  state = null;
476
459
  }
477
460
 
478
- return readOnly(_extends({
461
+ return readOnly(_extends$1({
479
462
  pathname: location.pathname,
480
463
  hash: '',
481
464
  search: ''
@@ -627,7 +610,7 @@ function createMemoryHistory(options) {
627
610
  initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
628
611
  initialIndex = _options3.initialIndex;
629
612
  var entries = initialEntries.map(function (entry) {
630
- var location = readOnly(_extends({
613
+ var location = readOnly(_extends$1({
631
614
  pathname: '/',
632
615
  search: '',
633
616
  hash: '',
@@ -652,7 +635,7 @@ function createMemoryHistory(options) {
652
635
  state = null;
653
636
  }
654
637
 
655
- return readOnly(_extends({
638
+ return readOnly(_extends$1({
656
639
  pathname: location.pathname,
657
640
  search: '',
658
641
  hash: ''
@@ -849,1464 +832,1636 @@ function parsePath(path) {
849
832
  return parsedPath;
850
833
  }
851
834
 
852
- // @ts-nocheck
853
- // We're inlining qss here for compression's sake, but we've included it as a hard dependency for the MIT license it requires.
854
- function encode(obj, pfx) {
855
- var k,
856
- i,
857
- tmp,
858
- str = '';
859
-
860
- for (k in obj) {
861
- if ((tmp = obj[k]) !== void 0) {
862
- if (Array.isArray(tmp)) {
863
- for (i = 0; i < tmp.length; i++) {
864
- str && (str += '&');
865
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
866
- }
867
- } else {
868
- str && (str += '&');
869
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
870
- }
835
+ var isProduction = process.env.NODE_ENV === 'production';
836
+ var prefix = 'Invariant failed';
837
+ function invariant(condition, message) {
838
+ if (condition) {
839
+ return;
871
840
  }
872
- }
873
-
874
- return (pfx || '') + str;
875
- }
876
-
877
- function toValue(mix) {
878
- if (!mix) return '';
879
- var str = decodeURIComponent(mix);
880
- if (str === 'false') return false;
881
- if (str === 'true') return true;
882
- return +str * 0 === 0 ? +str : str;
883
- }
884
-
885
- function decode(str) {
886
- var tmp,
887
- k,
888
- out = {},
889
- arr = str.split('&');
890
-
891
- while (tmp = arr.shift()) {
892
- tmp = tmp.split('=');
893
- k = tmp.shift();
894
-
895
- if (out[k] !== void 0) {
896
- out[k] = [].concat(out[k], toValue(tmp.shift()));
897
- } else {
898
- out[k] = toValue(tmp.shift());
841
+ if (isProduction) {
842
+ throw new Error(prefix);
899
843
  }
900
- }
901
-
902
- return out;
844
+ var provided = typeof message === 'function' ? message() : message;
845
+ var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
846
+ throw new Error(value);
903
847
  }
904
848
 
905
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId) {
906
- if (options === void 0) {
907
- options = {};
908
- }
909
-
910
- if (isRoot === void 0) {
911
- isRoot = true;
912
- }
913
-
914
- if (isRoot) {
915
- options.path = rootRouteId;
916
- } else {
917
- warning(!options.path, 'Routes must have a path property.');
918
- } // Strip the root from parentIds
919
-
849
+ // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
850
+ // k: infer I,
851
+ // ) => any
852
+ // ? I
853
+ // : never
920
854
 
921
- if (parentId === rootRouteId) {
922
- parentId = '';
855
+ /**
856
+ * This function returns `a` if `b` is deeply equal.
857
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
858
+ * This can be used for structural sharing between JSON values for example.
859
+ */
860
+ function replaceEqualDeep(prev, next) {
861
+ if (prev === next) {
862
+ return prev;
923
863
  }
924
864
 
925
- let path = String(isRoot ? rootRouteId : options.path); // If the path is anything other than an index path, trim it up
865
+ const array = Array.isArray(prev) && Array.isArray(next);
926
866
 
927
- if (path !== '/') {
928
- path = trimPath(path);
929
- }
867
+ if (array || isPlainObject(prev) && isPlainObject(next)) {
868
+ const aSize = array ? prev.length : Object.keys(prev).length;
869
+ const bItems = array ? next : Object.keys(next);
870
+ const bSize = bItems.length;
871
+ const copy = array ? [] : {};
872
+ let equalItems = 0;
930
873
 
931
- let id = joinPaths([parentId, path]);
874
+ for (let i = 0; i < bSize; i++) {
875
+ const key = array ? i : bItems[i];
876
+ copy[key] = replaceEqualDeep(prev[key], next[key]);
932
877
 
933
- if (path === rootRouteId) {
934
- path = '/';
935
- }
878
+ if (copy[key] === prev[key]) {
879
+ equalItems++;
880
+ }
881
+ }
936
882
 
937
- if (id !== rootRouteId) {
938
- id = joinPaths(['/', id]);
883
+ return aSize === bSize && equalItems === aSize ? prev : copy;
939
884
  }
940
885
 
941
- const fullPath = id === rootRouteId ? '/' : trimPathRight(id);
942
- return {
943
- id: id,
944
- path: path,
945
- fullPath: fullPath,
946
- options: options,
947
- children,
948
- addChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id)), false, parentId)
949
- };
950
- };
951
- const rootRouteId = '__root__';
952
- // Source
953
- // Detect if we're in the DOM
954
- const isDOM = Boolean(typeof window !== 'undefined' && window.document && window.document.createElement); // This is the default history object if none is defined
955
-
956
- const createDefaultHistory = () => isDOM ? createBrowserHistory() : createMemoryHistory();
957
-
958
- function createRouter(userOptions) {
959
- var _userOptions$stringif, _userOptions$parseSea;
960
-
961
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
962
-
963
- const originalOptions = _extends$1({}, userOptions, {
964
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
965
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
966
- });
967
-
968
- let router = {
969
- options: originalOptions,
970
- listeners: [],
971
- // Resolved after construction
972
- basepath: '',
973
- routeTree: undefined,
974
- routesById: {},
975
- location: undefined,
976
- allRouteInfo: undefined,
977
- //
978
- navigationPromise: Promise.resolve(),
979
- resolveNavigation: () => {},
980
- preloadCache: {},
981
- state: {
982
- status: 'idle',
983
- location: null,
984
- matches: [],
985
- actions: {},
986
- loaderData: {},
987
- lastUpdated: Date.now()
988
- },
989
- startedLoadingAt: Date.now(),
990
- subscribe: listener => {
991
- router.listeners.push(listener);
992
- return () => {
993
- router.listeners = router.listeners.filter(x => x !== listener);
994
- };
995
- },
996
- getRoute: id => {
997
- return router.routesById[id];
998
- },
999
- notify: () => {
1000
- router.state = _extends$1({}, router.state);
1001
- router.listeners.forEach(listener => listener());
1002
- },
1003
- mount: () => {
1004
- const next = router.buildLocation({
1005
- to: '.',
1006
- search: true,
1007
- hash: true
1008
- }); // If the current location isn't updated, trigger a navigation
1009
- // to the current location. Otherwise, load the current location.
1010
-
1011
- if (next.href !== router.location.href) {
1012
- return router.commitLocation(next, true);
1013
- } else {
1014
- return router.loadLocation();
1015
- }
1016
- },
1017
- update: opts => {
1018
- Object.assign(router.options, opts);
1019
- const {
1020
- basepath,
1021
- routeConfig
1022
- } = router.options;
1023
- router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1024
-
1025
- if (routeConfig) {
1026
- router.routesById = {};
1027
- router.routeTree = router.buildRouteTree(routeConfig);
1028
- }
886
+ return next;
887
+ } // Copied from: https://github.com/jonschlinkert/is-plain-object
1029
888
 
1030
- return router;
1031
- },
1032
- destroy: history.listen(event => {
1033
- router.loadLocation(router.parseLocation(event.location, router.location));
1034
- }),
1035
- buildRouteTree: rootRouteConfig => {
1036
- const recurseRoutes = (routeConfigs, parent) => {
1037
- return routeConfigs.map(routeConfig => {
1038
- const routeOptions = routeConfig.options;
1039
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1040
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1041
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1042
- // }
1043
-
1044
- const existingRoute = router.routesById[route.routeId];
1045
-
1046
- if (existingRoute) {
1047
- if (process.env.NODE_ENV !== 'production') {
1048
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1049
- }
889
+ function isPlainObject(o) {
890
+ if (!hasObjectPrototype(o)) {
891
+ return false;
892
+ } // If has modified constructor
1050
893
 
1051
- throw new Error();
1052
- }
1053
- router.routesById[route.routeId] = route;
1054
- const children = routeConfig.children;
1055
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1056
- return route;
1057
- });
1058
- };
1059
894
 
1060
- const routes = recurseRoutes([rootRouteConfig]);
1061
- return routes[0];
1062
- },
1063
- parseLocation: (location, previousLocation) => {
1064
- var _location$hash$split$;
895
+ const ctor = o.constructor;
1065
896
 
1066
- const parsedSearch = router.options.parseSearch(location.search);
1067
- return {
1068
- pathname: location.pathname,
1069
- searchStr: location.search,
1070
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1071
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1072
- href: "" + location.pathname + location.search + location.hash,
1073
- state: location.state,
1074
- key: location.key
1075
- };
1076
- },
1077
- buildLocation: function buildLocation(dest) {
1078
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
897
+ if (typeof ctor === 'undefined') {
898
+ return true;
899
+ } // If has modified prototype
1079
900
 
1080
- if (dest === void 0) {
1081
- dest = {};
1082
- }
1083
901
 
1084
- // const resolvedFrom: Location = {
1085
- // ...router.location,
1086
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
902
+ const prot = ctor.prototype;
1087
903
 
1088
- let pathname = _resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
904
+ if (!hasObjectPrototype(prot)) {
905
+ return false;
906
+ } // If constructor does not have an Object-specific method
1089
907
 
1090
- const fromMatches = router.matchRoutes(router.location.pathname, {
1091
- strictParseParams: true
1092
- });
1093
- const toMatches = router.matchRoutes(pathname);
1094
- const prevParams = (_last = last(fromMatches)) == null ? void 0 : _last.params;
1095
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1096
908
 
1097
- if (nextParams) {
1098
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1099
- Object.assign(nextParams, fn(nextParams));
1100
- });
1101
- }
909
+ if (!prot.hasOwnProperty('isPrototypeOf')) {
910
+ return false;
911
+ } // Most likely a plain Object
1102
912
 
1103
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1104
913
 
1105
- 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
914
+ return true;
915
+ }
1106
916
 
1107
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1108
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1109
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1110
- : {}; // Then post filters
917
+ function hasObjectPrototype(o) {
918
+ return Object.prototype.toString.call(o) === '[object Object]';
919
+ }
1111
920
 
1112
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1113
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1114
- const searchStr = router.options.stringifySearch(search);
1115
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1116
- hash = hash ? "#" + hash : '';
1117
- return {
1118
- pathname,
1119
- search,
1120
- searchStr,
1121
- state: router.location.state,
1122
- hash,
1123
- href: "" + pathname + searchStr + hash,
1124
- key: dest.key
1125
- };
1126
- },
1127
- commitLocation: (next, replace) => {
1128
- const id = '' + Date.now() + Math.random();
1129
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1130
- let nextAction = 'replace';
921
+ function last(arr) {
922
+ return arr[arr.length - 1];
923
+ }
924
+ function warning(cond, message) {
925
+ if (cond) {
926
+ if (typeof console !== 'undefined') console.warn(message);
1131
927
 
1132
- if (!replace) {
1133
- nextAction = 'push';
1134
- }
928
+ try {
929
+ throw new Error(message);
930
+ } catch (_unused) {}
931
+ }
1135
932
 
1136
- const isSameUrl = router.parseLocation(history.location).href === next.href;
933
+ return true;
934
+ }
1137
935
 
1138
- if (isSameUrl && !next.key) {
1139
- nextAction = 'replace';
1140
- }
936
+ function isFunction(d) {
937
+ return typeof d === 'function';
938
+ }
1141
939
 
1142
- if (nextAction === 'replace') {
1143
- history.replace({
1144
- pathname: next.pathname,
1145
- hash: next.hash,
1146
- search: next.searchStr
1147
- }, {
1148
- id
1149
- });
1150
- } else {
1151
- history.push({
1152
- pathname: next.pathname,
1153
- hash: next.hash,
1154
- search: next.searchStr
1155
- }, {
1156
- id
1157
- });
1158
- }
940
+ function functionalUpdate(updater, previous) {
941
+ if (isFunction(updater)) {
942
+ return updater(previous);
943
+ }
1159
944
 
1160
- router.navigationPromise = new Promise(resolve => {
1161
- const previousNavigationResolve = router.resolveNavigation;
945
+ return updater;
946
+ }
1162
947
 
1163
- router.resolveNavigation = () => {
1164
- previousNavigationResolve();
1165
- resolve();
1166
- };
1167
- });
1168
- return router.navigationPromise;
1169
- },
1170
- buildNext: opts => {
1171
- const next = router.buildLocation(opts);
1172
- const matches = router.matchRoutes(next.pathname);
948
+ function joinPaths(paths) {
949
+ return cleanPath(paths.filter(Boolean).join('/'));
950
+ }
951
+ function cleanPath(path) {
952
+ // remove double slashes
953
+ return path.replace(/\/{2,}/g, '/');
954
+ }
955
+ function trimPathLeft(path) {
956
+ return path === '/' ? path : path.replace(/^\/{1,}/, '');
957
+ }
958
+ function trimPathRight(path) {
959
+ return path === '/' ? path : path.replace(/\/{1,}$/, '');
960
+ }
961
+ function trimPath(path) {
962
+ return trimPathRight(trimPathLeft(path));
963
+ }
964
+ function resolvePath(basepath, base, to) {
965
+ base = base.replace(new RegExp("^" + basepath), '/');
966
+ to = to.replace(new RegExp("^" + basepath), '/');
967
+ let baseSegments = parsePathname(base);
968
+ const toSegments = parsePathname(to);
969
+ toSegments.forEach((toSegment, index) => {
970
+ if (toSegment.value === '/') {
971
+ if (!index) {
972
+ // Leading slash
973
+ baseSegments = [toSegment];
974
+ } else if (index === toSegments.length - 1) {
975
+ // Trailing Slash
976
+ baseSegments.push(toSegment);
977
+ } else ;
978
+ } else if (toSegment.value === '..') {
979
+ var _last;
1173
980
 
1174
- const __preSearchFilters = matches.map(match => {
1175
- var _match$options$preSea;
981
+ // Extra trailing slash? pop it off
982
+ if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
983
+ baseSegments.pop();
984
+ }
1176
985
 
1177
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1178
- }).flat().filter(Boolean);
986
+ baseSegments.pop();
987
+ } else if (toSegment.value === '.') {
988
+ return;
989
+ } else {
990
+ baseSegments.push(toSegment);
991
+ }
992
+ });
993
+ const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
994
+ return cleanPath(joined);
995
+ }
996
+ function parsePathname(pathname) {
997
+ if (!pathname) {
998
+ return [];
999
+ }
1179
1000
 
1180
- const __postSearchFilters = matches.map(match => {
1181
- var _match$options$postSe;
1001
+ pathname = cleanPath(pathname);
1002
+ const segments = [];
1182
1003
 
1183
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1184
- }).flat().filter(Boolean);
1004
+ if (pathname.slice(0, 1) === '/') {
1005
+ pathname = pathname.substring(1);
1006
+ segments.push({
1007
+ type: 'pathname',
1008
+ value: '/'
1009
+ });
1010
+ }
1185
1011
 
1186
- return router.buildLocation(_extends$1({}, opts, {
1187
- __preSearchFilters,
1188
- __postSearchFilters
1189
- }));
1190
- },
1191
- cancelMatches: () => {
1192
- var _router$state$pending, _router$state$pending2;
1193
- [...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 => {
1194
- match.cancel();
1195
- });
1196
- },
1197
- loadLocation: async next => {
1198
- const id = Math.random();
1199
- router.startedLoadingAt = id;
1012
+ if (!pathname) {
1013
+ return segments;
1014
+ } // Remove empty segments and '.' segments
1200
1015
 
1201
- if (next) {
1202
- // Ingest the new location
1203
- router.location = next;
1204
- } // Cancel any pending matches
1205
1016
 
1017
+ const split = pathname.split('/').filter(Boolean);
1018
+ segments.push(...split.map(part => {
1019
+ if (part.startsWith('*')) {
1020
+ return {
1021
+ type: 'wildcard',
1022
+ value: part
1023
+ };
1024
+ }
1206
1025
 
1207
- router.cancelMatches(); // Match the routes
1026
+ if (part.charAt(0) === ':') {
1027
+ return {
1028
+ type: 'param',
1029
+ value: part
1030
+ };
1031
+ }
1208
1032
 
1209
- const unloadedMatches = router.matchRoutes(location.pathname, {
1210
- strictParseParams: true
1211
- });
1212
- unloadedMatches.forEach((match, index) => {
1213
- const parent = unloadedMatches[index - 1];
1214
- const child = unloadedMatches[index + 1];
1215
- if (parent) match.__.setParentMatch(parent);
1216
- if (child) match.__.addChildMatch(child);
1217
- });
1218
- router.state = _extends$1({}, router.state, {
1219
- pending: {
1220
- matches: unloadedMatches,
1221
- location: router.location
1033
+ return {
1034
+ type: 'pathname',
1035
+ value: part
1036
+ };
1037
+ }));
1038
+
1039
+ if (pathname.slice(-1) === '/') {
1040
+ pathname = pathname.substring(1);
1041
+ segments.push({
1042
+ type: 'pathname',
1043
+ value: '/'
1044
+ });
1045
+ }
1046
+
1047
+ return segments;
1048
+ }
1049
+ function interpolatePath(path, params, leaveWildcard) {
1050
+ const interpolatedPathSegments = parsePathname(path);
1051
+ return joinPaths(interpolatedPathSegments.map(segment => {
1052
+ if (segment.value === '*' && !leaveWildcard) {
1053
+ return '';
1054
+ }
1055
+
1056
+ if (segment.type === 'param') {
1057
+ var _segment$value$substr;
1058
+
1059
+ return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
1060
+ }
1061
+
1062
+ return segment.value;
1063
+ }));
1064
+ }
1065
+ function matchPathname(currentPathname, matchLocation) {
1066
+ const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1067
+
1068
+ if (matchLocation.to && !pathParams) {
1069
+ return;
1070
+ } // if (matchLocation.search && !searchMatched) {
1071
+ // return
1072
+ // }
1073
+
1074
+
1075
+ return pathParams != null ? pathParams : {};
1076
+ }
1077
+ function matchByPath(from, matchLocation) {
1078
+ var _matchLocation$to;
1079
+
1080
+ const baseSegments = parsePathname(from);
1081
+ const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
1082
+ const params = {};
1083
+
1084
+ let isMatch = (() => {
1085
+ for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
1086
+ const baseSegment = baseSegments[i];
1087
+ const routeSegment = routeSegments[i];
1088
+ const isLastRouteSegment = i === routeSegments.length - 1;
1089
+ const isLastBaseSegment = i === baseSegments.length - 1;
1090
+
1091
+ if (routeSegment) {
1092
+ if (routeSegment.type === 'wildcard') {
1093
+ if (baseSegment != null && baseSegment.value) {
1094
+ params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
1095
+ return true;
1096
+ }
1097
+
1098
+ return false;
1222
1099
  }
1223
- });
1224
- router.notify(); // Load the matches
1225
1100
 
1226
- const matches = await router.loadMatches(unloadedMatches, {
1227
- withPending: true
1228
- });
1101
+ if (routeSegment.type === 'pathname') {
1102
+ if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
1103
+ return true;
1104
+ }
1229
1105
 
1230
- if (router.startedLoadingAt !== id) {
1231
- // Ignore side-effects of match loading
1232
- return router.navigationPromise;
1106
+ if (baseSegment) {
1107
+ if (matchLocation.caseSensitive) {
1108
+ if (routeSegment.value !== baseSegment.value) {
1109
+ return false;
1110
+ }
1111
+ } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
1112
+ return false;
1113
+ }
1114
+ }
1115
+ }
1116
+
1117
+ if (!baseSegment) {
1118
+ return false;
1119
+ }
1120
+
1121
+ if (routeSegment.type === 'param') {
1122
+ if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
1123
+ return false;
1124
+ }
1125
+
1126
+ if (!baseSegment.value.startsWith(':')) {
1127
+ params[routeSegment.value.substring(1)] = baseSegment.value;
1128
+ }
1129
+ }
1233
1130
  }
1234
1131
 
1235
- const previousMatches = router.state.matches;
1236
- previousMatches.filter(d => {
1237
- return !matches.find(dd => dd.matchId === d.matchId);
1238
- }).forEach(d => {
1239
- d.__.onExit == null ? void 0 : d.__.onExit({
1240
- params: d.params,
1241
- search: d.routeSearch
1242
- });
1243
- });
1244
- previousMatches.filter(d => {
1245
- return matches.find(dd => dd.matchId === d.matchId);
1246
- }).forEach(d => {
1247
- d.options.onTransition == null ? void 0 : d.options.onTransition({
1248
- params: d.params,
1249
- search: d.routeSearch
1250
- });
1251
- });
1252
- matches.filter(d => {
1253
- return !previousMatches.find(dd => dd.matchId === d.matchId);
1254
- }).forEach(d => {
1255
- d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1256
- params: d.params,
1257
- search: d.search
1258
- });
1259
- });
1260
- router.state = _extends$1({}, router.state, {
1261
- location: router.location,
1262
- matches,
1263
- pending: undefined
1264
- });
1132
+ if (isLastRouteSegment && !isLastBaseSegment) {
1133
+ return !!matchLocation.fuzzy;
1134
+ }
1135
+ }
1265
1136
 
1266
- if (matches.some(d => d.status === 'loading')) {
1137
+ return true;
1138
+ })();
1139
+
1140
+ return isMatch ? params : undefined;
1141
+ }
1142
+
1143
+ // @ts-nocheck
1144
+ // 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.
1145
+ function encode(obj, pfx) {
1146
+ var k,
1147
+ i,
1148
+ tmp,
1149
+ str = '';
1150
+
1151
+ for (k in obj) {
1152
+ if ((tmp = obj[k]) !== void 0) {
1153
+ if (Array.isArray(tmp)) {
1154
+ for (i = 0; i < tmp.length; i++) {
1155
+ str && (str += '&');
1156
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1157
+ }
1158
+ } else {
1159
+ str && (str += '&');
1160
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1161
+ }
1162
+ }
1163
+ }
1164
+
1165
+ return (pfx || '') + str;
1166
+ }
1167
+
1168
+ function toValue(mix) {
1169
+ if (!mix) return '';
1170
+ var str = decodeURIComponent(mix);
1171
+ if (str === 'false') return false;
1172
+ if (str === 'true') return true;
1173
+ return +str * 0 === 0 ? +str : str;
1174
+ }
1175
+
1176
+ function decode(str) {
1177
+ var tmp,
1178
+ k,
1179
+ out = {},
1180
+ arr = str.split('&');
1181
+
1182
+ while (tmp = arr.shift()) {
1183
+ tmp = tmp.split('=');
1184
+ k = tmp.shift();
1185
+
1186
+ if (out[k] !== void 0) {
1187
+ out[k] = [].concat(out[k], toValue(tmp.shift()));
1188
+ } else {
1189
+ out[k] = toValue(tmp.shift());
1190
+ }
1191
+ }
1192
+
1193
+ return out;
1194
+ }
1195
+
1196
+ function _extends() {
1197
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
1198
+ for (var i = 1; i < arguments.length; i++) {
1199
+ var source = arguments[i];
1200
+
1201
+ for (var key in source) {
1202
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1203
+ target[key] = source[key];
1204
+ }
1205
+ }
1206
+ }
1207
+
1208
+ return target;
1209
+ };
1210
+ return _extends.apply(this, arguments);
1211
+ }
1212
+
1213
+ function createRoute(routeConfig, options, parent, router) {
1214
+ const {
1215
+ id,
1216
+ routeId,
1217
+ path: routePath,
1218
+ fullPath
1219
+ } = routeConfig;
1220
+
1221
+ const action = router.state.actions[id] || (() => {
1222
+ router.state.actions[id] = {
1223
+ pending: [],
1224
+ submit: async (submission, actionOpts) => {
1225
+ var _actionOpts$invalidat;
1226
+
1227
+ if (!route) {
1228
+ return;
1229
+ }
1230
+
1231
+ const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1232
+ const actionState = {
1233
+ submittedAt: Date.now(),
1234
+ status: 'pending',
1235
+ submission
1236
+ };
1237
+ action.current = actionState;
1238
+ action.latest = actionState;
1239
+ action.pending.push(actionState);
1240
+ router.state = _extends({}, router.state, {
1241
+ currentAction: actionState,
1242
+ latestAction: actionState
1243
+ });
1267
1244
  router.notify();
1268
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1245
+
1246
+ try {
1247
+ const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1248
+ actionState.data = res;
1249
+
1250
+ if (invalidate) {
1251
+ router.invalidateRoute({
1252
+ to: '.',
1253
+ fromCurrent: true
1254
+ });
1255
+ await router.reload();
1256
+ }
1257
+
1258
+ actionState.status = 'success';
1259
+ return res;
1260
+ } catch (err) {
1261
+ console.error(err);
1262
+ actionState.error = err;
1263
+ actionState.status = 'error';
1264
+ } finally {
1265
+ action.pending = action.pending.filter(d => d !== actionState);
1266
+ router.removeActionQueue.push({
1267
+ action,
1268
+ actionState
1269
+ });
1270
+ router.notify();
1271
+ }
1269
1272
  }
1273
+ };
1274
+ return router.state.actions[id];
1275
+ })();
1270
1276
 
1271
- if (router.startedLoadingAt !== id) {
1272
- // Ignore side-effects of match loading
1273
- return;
1277
+ const loader = router.state.loaders[id] || (() => {
1278
+ router.state.loaders[id] = {
1279
+ pending: [],
1280
+ fetch: async loaderContext => {
1281
+ if (!route) {
1282
+ return;
1283
+ }
1284
+
1285
+ const loaderState = {
1286
+ loadedAt: Date.now(),
1287
+ loaderContext
1288
+ };
1289
+ loader.current = loaderState;
1290
+ loader.latest = loaderState;
1291
+ loader.pending.push(loaderState); // router.state = {
1292
+ // ...router.state,
1293
+ // currentAction: loaderState,
1294
+ // latestAction: loaderState,
1295
+ // }
1296
+
1297
+ router.notify();
1298
+
1299
+ try {
1300
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1301
+ } finally {
1302
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1303
+
1304
+ router.notify();
1305
+ }
1274
1306
  }
1307
+ };
1308
+ return router.state.loaders[id];
1309
+ })();
1275
1310
 
1276
- router.notify();
1277
- router.resolveNavigation();
1311
+ let route = {
1312
+ routeId: id,
1313
+ routeRouteId: routeId,
1314
+ routePath,
1315
+ fullPath,
1316
+ options,
1317
+ router,
1318
+ childRoutes: undefined,
1319
+ parentRoute: parent,
1320
+ action,
1321
+ loader: loader,
1322
+ buildLink: options => {
1323
+ return router.buildLink(_extends({}, options, {
1324
+ from: fullPath
1325
+ }));
1326
+ },
1327
+ navigate: options => {
1328
+ return router.navigate(_extends({}, options, {
1329
+ from: fullPath
1330
+ }));
1278
1331
  },
1279
- cleanPreloadCache: () => {
1280
- const now = Date.now();
1281
- Object.keys(router.preloadCache).forEach(matchId => {
1282
- const entry = router.preloadCache[matchId]; // Don't remove loading matches
1283
-
1284
- if (entry.match.status === 'loading') {
1285
- return;
1286
- } // Do not remove successful matches that are still valid
1332
+ matchRoute: (matchLocation, opts) => {
1333
+ return router.matchRoute(_extends({}, matchLocation, {
1334
+ from: fullPath
1335
+ }), opts);
1336
+ }
1337
+ };
1338
+ router.options.createRoute == null ? void 0 : router.options.createRoute({
1339
+ router,
1340
+ route
1341
+ });
1342
+ return route;
1343
+ }
1344
+ function cascadeLoaderData(matches) {
1345
+ matches.forEach((match, index) => {
1346
+ const parent = matches[index - 1];
1287
1347
 
1348
+ if (parent) {
1349
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1350
+ }
1351
+ });
1352
+ }
1288
1353
 
1289
- if (entry.match.updatedAt && entry.match.updatedAt + entry.maxAge > now) {
1290
- return;
1291
- } // Everything else gets removed
1354
+ const rootRouteId = '__root__';
1355
+ const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1356
+ if (options === void 0) {
1357
+ options = {};
1358
+ }
1292
1359
 
1360
+ if (isRoot === void 0) {
1361
+ isRoot = true;
1362
+ }
1293
1363
 
1294
- delete router.preloadCache[matchId];
1295
- });
1296
- },
1297
- loadRoute: async function loadRoute(navigateOpts, loaderOpts) {
1298
- if (navigateOpts === void 0) {
1299
- navigateOpts = router.location;
1300
- }
1364
+ if (isRoot) {
1365
+ options.path = rootRouteId;
1366
+ } // Strip the root from parentIds
1301
1367
 
1302
- const next = router.buildNext(navigateOpts);
1303
- const matches = router.matchRoutes(next.pathname, {
1304
- strictParseParams: true
1305
- });
1306
- await router.loadMatches(matches, {
1307
- preload: true,
1308
- maxAge: loaderOpts.maxAge
1309
- });
1310
- return matches;
1311
- },
1312
- matchRoutes: (pathname, opts) => {
1313
- var _router$state$pending3, _router$state$pending4;
1314
1368
 
1315
- router.cleanPreloadCache();
1316
- const matches = [];
1369
+ if (parentId === rootRouteId) {
1370
+ parentId = '';
1371
+ }
1317
1372
 
1318
- if (!router.routeTree) {
1319
- return matches;
1320
- }
1373
+ let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1321
1374
 
1322
- 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 : [])];
1375
+ if (path && path !== '/') {
1376
+ path = trimPath(path);
1377
+ }
1323
1378
 
1324
- const recurse = async (routes, parentMatch) => {
1325
- var _parentMatch$params, _router$options$filte, _router$preloadCache$, _route$childRoutes2;
1379
+ const routeId = path || options.id;
1380
+ let id = joinPaths([parentId, routeId]);
1326
1381
 
1327
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1328
- const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
1329
- const route = filteredRoutes == null ? void 0 : filteredRoutes.find(route => {
1330
- var _route$childRoutes, _route$options$caseSe;
1331
-
1332
- const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length);
1333
- const matchParams = matchPathname(pathname, {
1334
- to: route.fullPath,
1335
- fuzzy,
1336
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
1337
- });
1382
+ if (path === rootRouteId) {
1383
+ path = '/';
1384
+ }
1338
1385
 
1339
- if (matchParams) {
1340
- let parsedParams;
1386
+ if (id !== rootRouteId) {
1387
+ id = joinPaths(['/', id]);
1388
+ }
1341
1389
 
1342
- try {
1343
- var _route$options$parseP;
1390
+ const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1391
+ return {
1392
+ id: id,
1393
+ routeId: routeId,
1394
+ path: path,
1395
+ fullPath: fullPath,
1396
+ options: options,
1397
+ children,
1398
+ createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1399
+ addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1400
+ createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1401
+ };
1402
+ };
1344
1403
 
1345
- parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
1346
- } catch (err) {
1347
- if (opts != null && opts.strictParseParams) {
1348
- throw err;
1349
- }
1350
- }
1404
+ const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1405
+ function createRouteMatch(router, route, opts) {
1406
+ const routeMatch = _extends({}, route, opts, {
1407
+ router,
1408
+ routeSearch: {},
1409
+ search: {},
1410
+ childMatches: [],
1411
+ status: 'idle',
1412
+ routeLoaderData: {},
1413
+ loaderData: {},
1414
+ isPending: false,
1415
+ isFetching: false,
1416
+ isInvalid: false,
1417
+ invalidAt: Infinity,
1418
+ getIsInvalid: () => {
1419
+ const now = Date.now();
1420
+ return routeMatch.isInvalid || routeMatch.invalidAt < now;
1421
+ },
1422
+ __: {
1423
+ abortController: new AbortController(),
1424
+ latestId: '',
1425
+ resolve: () => {},
1426
+ notify: () => {
1427
+ routeMatch.__.resolve();
1351
1428
 
1352
- params = _extends$1({}, params, parsedParams);
1353
- }
1429
+ routeMatch.router.notify();
1430
+ },
1431
+ startPending: () => {
1432
+ var _routeMatch$options$p, _routeMatch$options$p2;
1354
1433
 
1355
- return !!matchParams;
1356
- });
1434
+ const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1435
+ const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1357
1436
 
1358
- if (!route) {
1437
+ if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1359
1438
  return;
1360
1439
  }
1361
1440
 
1362
- const interpolatedPath = interpolatePath(route.routePath, params);
1363
- const matchId = interpolatePath(route.routeId, params, true);
1364
- const match = existingMatches.find(d => d.matchId === matchId) || ((_router$preloadCache$ = router.preloadCache[matchId]) == null ? void 0 : _router$preloadCache$.match) || createRouteMatch(router, route, {
1365
- matchId,
1366
- params,
1367
- pathname: joinPaths([pathname, interpolatedPath])
1368
- });
1369
- matches.push(match);
1441
+ routeMatch.__.pendingTimeout = setTimeout(() => {
1442
+ routeMatch.isPending = true;
1370
1443
 
1371
- if ((_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length) {
1372
- recurse(route.childRoutes, match);
1373
- }
1374
- };
1444
+ routeMatch.__.resolve();
1375
1445
 
1376
- recurse([router.routeTree]);
1377
- return matches;
1378
- },
1379
- loadMatches: async (resolvedMatches, loaderOpts) => {
1380
- const matchPromises = resolvedMatches.map(async match => {
1381
- // Validate the match (loads search params etc)
1382
- match.__.validate(); // If this is a preload, add it to the preload cache
1446
+ if (typeof pendingMinMs !== 'undefined') {
1447
+ routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1448
+ }
1449
+ }, pendingMs);
1450
+ },
1451
+ cancelPending: () => {
1452
+ routeMatch.isPending = false;
1453
+ clearTimeout(routeMatch.__.pendingTimeout);
1454
+ clearTimeout(routeMatch.__.pendingMinTimeout);
1455
+ delete routeMatch.__.pendingMinPromise;
1456
+ },
1457
+ // setParentMatch: (parentMatch?: RouteMatch) => {
1458
+ // routeMatch.parentMatch = parentMatch
1459
+ // },
1460
+ // addChildMatch: (childMatch: RouteMatch) => {
1461
+ // if (
1462
+ // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1463
+ // ) {
1464
+ // return
1465
+ // }
1466
+ // routeMatch.childMatches.push(childMatch)
1467
+ // },
1468
+ validate: () => {
1469
+ var _routeMatch$parentMat, _routeMatch$parentMat2;
1383
1470
 
1471
+ // Validate the search params and stabilize them
1472
+ const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1384
1473
 
1385
- if (loaderOpts != null && loaderOpts.preload) {
1386
- router.preloadCache[match.matchId] = {
1387
- maxAge: loaderOpts == null ? void 0 : loaderOpts.maxAge,
1388
- match
1389
- };
1390
- } // If the match is invalid, errored or idle, trigger it to load
1474
+ try {
1475
+ const prevSearch = routeMatch.routeSearch;
1476
+ const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1477
+ let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1391
1478
 
1479
+ if (prevSearch !== nextSearch) {
1480
+ routeMatch.isInvalid = true;
1481
+ }
1392
1482
 
1393
- if (match.status === 'success' && match.isInvalid || match.status === 'error' || match.status === 'idle') {
1394
- match.load();
1395
- } // If requested, start the pending timers
1483
+ routeMatch.routeSearch = nextSearch;
1484
+ routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1485
+ } catch (err) {
1486
+ console.error(err);
1487
+ const error = new Error('Invalid search params found', {
1488
+ cause: err
1489
+ });
1490
+ error.code = 'INVALID_SEARCH_PARAMS';
1491
+ routeMatch.status = 'error';
1492
+ routeMatch.error = error; // Do not proceed with loading the route
1396
1493
 
1494
+ return;
1495
+ }
1496
+ }
1497
+ },
1498
+ cancel: () => {
1499
+ var _routeMatch$__$abortC;
1397
1500
 
1398
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
1399
- // This might be completion, error, or a pending state
1501
+ (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1400
1502
 
1401
- await match.__.loadPromise;
1402
- });
1403
- router.notify();
1404
- await Promise.all(matchPromises);
1405
- return resolvedMatches;
1503
+ routeMatch.__.cancelPending();
1406
1504
  },
1407
- invalidateRoute: opts => {
1408
- var _router$state$pending5, _router$state$pending6;
1409
-
1410
- const next = router.buildNext(opts);
1411
- const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
1412
- [...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 => {
1413
- if (unloadedMatchIds.includes(match.matchId)) {
1414
- match.isInvalid = true;
1415
- }
1416
- });
1505
+ invalidate: () => {
1506
+ routeMatch.isInvalid = true;
1417
1507
  },
1418
- reload: () => router._navigate({
1419
- fromCurrent: true,
1420
- replace: true,
1421
- search: true
1422
- }),
1423
- resolvePath: (from, path) => {
1424
- return _resolvePath(router.basepath, from, cleanPath(path));
1508
+ hasLoaders: () => {
1509
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1425
1510
  },
1426
- matchRoute: (location, opts) => {
1427
- var _location$from;
1428
-
1429
- // const location = router.buildNext(opts)
1430
- location = _extends$1({}, location, {
1431
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
1432
- });
1433
- const next = router.buildNext(location);
1434
-
1435
- if (opts != null && opts.pending) {
1436
- var _router$state$pending7;
1511
+ load: async loaderOpts => {
1512
+ const now = Date.now();
1513
+ 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
1437
1514
 
1438
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
1439
- return false;
1515
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1516
+ // If the match is currently active, don't preload it
1517
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1518
+ return;
1440
1519
  }
1441
1520
 
1442
- return !!matchPathname(router.state.pending.location.pathname, _extends$1({}, opts, {
1443
- to: next.pathname
1444
- }));
1445
- }
1446
-
1447
- return !!matchPathname(router.state.location.pathname, _extends$1({}, opts, {
1448
- to: next.pathname
1449
- }));
1450
- },
1451
- _navigate: location => {
1452
- const next = router.buildNext(location);
1453
- return router.commitLocation(next, location.replace);
1454
- },
1455
- navigate: async _ref => {
1456
- let {
1457
- from,
1458
- to = '.',
1459
- search,
1460
- hash,
1461
- replace
1462
- } = _ref;
1463
- // If this link simply reloads the current route,
1464
- // make sure it has a new key so it will trigger a data refresh
1465
- // If this `to` is a valid external URL, return
1466
- // null for LinkUtils
1467
- const toString = String(to);
1468
- const fromString = String(from);
1469
- let isExternal;
1470
-
1471
- try {
1472
- new URL("" + toString);
1473
- isExternal = true;
1474
- } catch (e) {}
1521
+ router.matchCache[routeMatch.matchId] = {
1522
+ gc: now + loaderOpts.gcMaxAge,
1523
+ match: routeMatch
1524
+ };
1525
+ } // If the match is invalid, errored or idle, trigger it to load
1475
1526
 
1476
- if (isExternal) {
1477
- if (process.env.NODE_ENV !== 'production') {
1478
- throw new Error('Attempting to navigate to external url with router.navigate!');
1479
- }
1480
1527
 
1481
- return;
1528
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1529
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1530
+ routeMatch.fetch({
1531
+ maxAge
1532
+ });
1482
1533
  }
1483
-
1484
- return router._navigate({
1485
- from: fromString,
1486
- to: toString,
1487
- search,
1488
- hash
1489
- });
1490
1534
  },
1491
- buildLink: _ref2 => {
1492
- var _preload, _ref3, _ref4;
1535
+ fetch: async opts => {
1536
+ const id = '' + Date.now() + Math.random();
1537
+ routeMatch.__.latestId = id; // If the match was in an error state, set it
1538
+ // to a loading state again. Otherwise, keep it
1539
+ // as loading or resolved
1493
1540
 
1494
- let {
1495
- from,
1496
- to = '.',
1497
- search,
1498
- params,
1499
- hash,
1500
- target,
1501
- replace,
1502
- activeOptions,
1503
- preload,
1504
- preloadMaxAge: userPreloadMaxAge,
1505
- preloadDelay: userPreloadDelay,
1506
- disabled
1507
- } = _ref2;
1541
+ if (routeMatch.status === 'idle') {
1542
+ routeMatch.status = 'loading';
1543
+ } // We started loading the route, so it's no longer invalid
1508
1544
 
1509
- // If this link simply reloads the current route,
1510
- // make sure it has a new key so it will trigger a data refresh
1511
- // If this `to` is a valid external URL, return
1512
- // null for LinkUtils
1513
- try {
1514
- new URL("" + to);
1515
- return {
1516
- type: 'external',
1517
- href: to
1518
- };
1519
- } catch (e) {}
1520
1545
 
1521
- const nextOpts = {
1522
- from,
1523
- to,
1524
- search,
1525
- params,
1526
- hash,
1527
- replace
1528
- };
1529
- const next = router.buildNext(nextOpts);
1530
- preload = (_preload = preload) != null ? _preload : router.options.defaultLinkPreload;
1531
- const preloadMaxAge = (_ref3 = userPreloadMaxAge != null ? userPreloadMaxAge : router.options.defaultLinkPreloadMaxAge) != null ? _ref3 : 2000;
1532
- const preloadDelay = (_ref4 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultLinkPreloadDelay) != null ? _ref4 : 50; // Compare path/hash for matches
1546
+ routeMatch.isInvalid = false;
1547
+ routeMatch.__.loadPromise = new Promise(async resolve => {
1548
+ // We are now fetching, even if it's in the background of a
1549
+ // resolved state
1550
+ routeMatch.isFetching = true;
1551
+ routeMatch.__.resolve = resolve;
1552
+
1553
+ const loaderPromise = (async () => {
1554
+ // Load the elements and data in parallel
1555
+ routeMatch.__.elementsPromise = (async () => {
1556
+ // then run all element and data loaders in parallel
1557
+ // For each element type, potentially load it asynchronously
1558
+ await Promise.all(elementTypes.map(async type => {
1559
+ const routeElement = routeMatch.options[type];
1533
1560
 
1534
- const pathIsEqual = router.state.location.pathname === next.pathname;
1535
- const currentPathSplit = router.state.location.pathname.split('/');
1536
- const nextPathSplit = next.pathname.split('/');
1537
- const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
1538
- const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
1561
+ if (routeMatch.__[type]) {
1562
+ return;
1563
+ }
1539
1564
 
1540
- const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
1541
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
1565
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1566
+ }));
1567
+ })();
1542
1568
 
1543
- const isActive = pathTest && hashTest; // The click handler
1569
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1570
+ try {
1571
+ var _ref, _ref2, _opts$maxAge;
1544
1572
 
1545
- const handleClick = e => {
1546
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1547
- e.preventDefault();
1573
+ if (routeMatch.options.loader) {
1574
+ const data = await routeMatch.options.loader({
1575
+ params: routeMatch.params,
1576
+ search: routeMatch.routeSearch,
1577
+ signal: routeMatch.__.abortController.signal
1578
+ });
1548
1579
 
1549
- if (pathIsEqual && !search && !hash) {
1550
- router.invalidateRoute(nextOpts);
1551
- } // All is well? Navigate!)
1580
+ if (id !== routeMatch.__.latestId) {
1581
+ return routeMatch.__.loaderPromise;
1582
+ }
1552
1583
 
1584
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1585
+ }
1553
1586
 
1554
- router._navigate(nextOpts);
1555
- }
1556
- }; // The click handler
1587
+ routeMatch.error = undefined;
1588
+ routeMatch.status = 'success';
1589
+ routeMatch.updatedAt = Date.now();
1590
+ 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);
1591
+ } catch (err) {
1592
+ if (id !== routeMatch.__.latestId) {
1593
+ return routeMatch.__.loaderPromise;
1594
+ }
1557
1595
 
1596
+ if (process.env.NODE_ENV !== 'production') {
1597
+ console.error(err);
1598
+ }
1558
1599
 
1559
- const handleFocus = e => {
1560
- if (preload && preloadMaxAge > 0) {
1561
- router.loadRoute(nextOpts, {
1562
- maxAge: preloadMaxAge
1600
+ routeMatch.error = err;
1601
+ routeMatch.status = 'error';
1602
+ routeMatch.updatedAt = Date.now();
1603
+ }
1563
1604
  });
1564
- }
1565
- };
1566
1605
 
1567
- const handleEnter = e => {
1568
- const target = e.target || {};
1606
+ try {
1607
+ await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1569
1608
 
1570
- if (preload && preloadMaxAge > 0) {
1571
- if (target.preloadTimeout) {
1572
- return;
1573
- }
1609
+ if (id !== routeMatch.__.latestId) {
1610
+ return routeMatch.__.loaderPromise;
1611
+ }
1574
1612
 
1575
- target.preloadTimeout = setTimeout(() => {
1576
- target.preloadTimeout = null;
1577
- router.loadRoute(nextOpts, {
1578
- maxAge: preloadMaxAge
1579
- });
1580
- }, preloadDelay);
1581
- }
1582
- };
1613
+ if (routeMatch.__.pendingMinPromise) {
1614
+ await routeMatch.__.pendingMinPromise;
1615
+ delete routeMatch.__.pendingMinPromise;
1616
+ }
1617
+ } finally {
1618
+ if (id !== routeMatch.__.latestId) {
1619
+ return routeMatch.__.loaderPromise;
1620
+ }
1583
1621
 
1584
- const handleLeave = e => {
1585
- const target = e.target || {};
1622
+ routeMatch.__.cancelPending();
1586
1623
 
1587
- if (target.preloadTimeout) {
1588
- clearTimeout(target.preloadTimeout);
1589
- target.preloadTimeout = null;
1624
+ routeMatch.isPending = false;
1625
+ routeMatch.isFetching = false;
1626
+
1627
+ routeMatch.__.notify();
1628
+ }
1629
+ })();
1630
+
1631
+ routeMatch.__.loaderPromise = loaderPromise;
1632
+ await loaderPromise;
1633
+
1634
+ if (id !== routeMatch.__.latestId) {
1635
+ return routeMatch.__.loaderPromise;
1590
1636
  }
1591
- };
1592
1637
 
1593
- return {
1594
- type: 'internal',
1595
- next,
1596
- handleFocus,
1597
- handleClick,
1598
- handleEnter,
1599
- handleLeave,
1600
- isActive,
1601
- disabled
1602
- };
1603
- },
1604
- __experimental__createSnapshot: () => {
1605
- return _extends$1({}, router.state, {
1606
- matches: router.state.matches.map(_ref5 => {
1607
- let {
1608
- routeLoaderData: loaderData,
1609
- matchId
1610
- } = _ref5;
1611
- return {
1612
- matchId,
1613
- loaderData
1614
- };
1615
- })
1638
+ delete routeMatch.__.loaderPromise;
1616
1639
  });
1640
+ return await routeMatch.__.loadPromise;
1617
1641
  }
1618
- };
1619
- router.location = router.parseLocation(history.location); // router.state.location = __experimental__snapshot?.location ?? router.location
1620
-
1621
- router.state.location = router.location;
1622
- router.update(userOptions); // Allow frameworks to hook into the router creation
1642
+ });
1623
1643
 
1624
- router.options.createRouter == null ? void 0 : router.options.createRouter(router); // router.mount()
1644
+ if (!routeMatch.hasLoaders()) {
1645
+ routeMatch.status = 'success';
1646
+ }
1625
1647
 
1626
- return router;
1648
+ return routeMatch;
1627
1649
  }
1628
- function createRoute(routeConfig, options, parent, router) {
1629
- // const id = (
1630
- // options.path === rootRouteId
1631
- // ? rootRouteId
1632
- // : joinPaths([
1633
- // parent!.id,
1634
- // `${options.path?.replace(/(.)\/$/, '$1')}`,
1635
- // ]).replace(new RegExp(`^${rootRouteId}`), '')
1636
- // ) as TRouteInfo['id']
1637
- const {
1638
- id: routeId,
1639
- path: routePath,
1640
- fullPath
1641
- } = routeConfig;
1642
1650
 
1643
- const action = router.state.actions[routeId] || (() => {
1644
- router.state.actions[routeId] = {
1645
- pending: [],
1646
- submit: async (submission, actionOpts) => {
1647
- var _actionOpts$invalidat;
1651
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1652
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify);
1653
+ function parseSearchWith(parser) {
1654
+ return searchStr => {
1655
+ if (searchStr.substring(0, 1) === '?') {
1656
+ searchStr = searchStr.substring(1);
1657
+ }
1648
1658
 
1649
- if (!route) {
1650
- return;
1651
- }
1659
+ let query = decode(searchStr); // Try to parse any query params that might be json
1652
1660
 
1653
- const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1654
- const actionState = {
1655
- submittedAt: Date.now(),
1656
- status: 'pending',
1657
- submission
1658
- };
1659
- action.latest = actionState;
1660
- action.pending.push(actionState);
1661
- router.state = _extends$1({}, router.state, {
1662
- action: actionState
1663
- });
1664
- router.notify();
1661
+ for (let key in query) {
1662
+ const value = query[key];
1665
1663
 
1664
+ if (typeof value === 'string') {
1666
1665
  try {
1667
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1668
- actionState.data = res;
1666
+ query[key] = parser(value);
1667
+ } catch (err) {//
1668
+ }
1669
+ }
1670
+ }
1669
1671
 
1670
- if (invalidate) {
1671
- router.invalidateRoute({
1672
- to: '.',
1673
- fromCurrent: true
1674
- });
1675
- await router.reload();
1676
- }
1672
+ return query;
1673
+ };
1674
+ }
1675
+ function stringifySearchWith(stringify) {
1676
+ return search => {
1677
+ search = _extends({}, search);
1677
1678
 
1678
- actionState.status = 'success';
1679
- return res;
1680
- } catch (err) {
1681
- console.error(err);
1682
- actionState.error = err;
1683
- actionState.status = 'error';
1684
- } finally {
1685
- action.pending = action.pending.filter(d => d !== actionState);
1679
+ if (search) {
1680
+ Object.keys(search).forEach(key => {
1681
+ const val = search[key];
1686
1682
 
1687
- if (actionState === router.state.action) {
1688
- router.state.action = undefined;
1683
+ if (typeof val === 'undefined' || val === undefined) {
1684
+ delete search[key];
1685
+ } else if (val && typeof val === 'object' && val !== null) {
1686
+ try {
1687
+ search[key] = stringify(val);
1688
+ } catch (err) {// silent
1689
1689
  }
1690
-
1691
- router.notify();
1692
1690
  }
1693
- }
1694
- };
1695
- return router.state.actions[routeId];
1696
- })();
1691
+ });
1692
+ }
1697
1693
 
1698
- let route = {
1699
- routeId,
1700
- routePath,
1701
- fullPath,
1702
- options,
1703
- router,
1704
- childRoutes: undefined,
1705
- parentRoute: parent,
1706
- action,
1707
- buildLink: options => {
1708
- return router.buildLink(_extends$1({}, options, {
1709
- from: fullPath
1710
- }));
1694
+ const searchStr = encode(search).toString();
1695
+ return searchStr ? "?" + searchStr : '';
1696
+ };
1697
+ }
1698
+
1699
+ var _window$document;
1700
+ // Detect if we're in the DOM
1701
+ const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1702
+
1703
+ const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1704
+
1705
+ function createRouter(userOptions) {
1706
+ var _userOptions$stringif, _userOptions$parseSea;
1707
+
1708
+ const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1709
+
1710
+ const originalOptions = _extends({
1711
+ defaultLoaderGcMaxAge: 5 * 60 * 1000,
1712
+ defaultLoaderMaxAge: 0,
1713
+ defaultPreloadMaxAge: 2000,
1714
+ defaultPreloadDelay: 50
1715
+ }, userOptions, {
1716
+ stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1717
+ parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1718
+ });
1719
+
1720
+ let router = {
1721
+ history,
1722
+ options: originalOptions,
1723
+ listeners: [],
1724
+ removeActionQueue: [],
1725
+ // Resolved after construction
1726
+ basepath: '',
1727
+ routeTree: undefined,
1728
+ routesById: {},
1729
+ location: undefined,
1730
+ allRouteInfo: undefined,
1731
+ //
1732
+ navigationPromise: Promise.resolve(),
1733
+ resolveNavigation: () => {},
1734
+ matchCache: {},
1735
+ state: {
1736
+ status: 'idle',
1737
+ location: null,
1738
+ matches: [],
1739
+ actions: {},
1740
+ loaders: {},
1741
+ loaderData: {},
1742
+ lastUpdated: Date.now(),
1743
+ isFetching: false,
1744
+ isPreloading: false
1745
+ },
1746
+ startedLoadingAt: Date.now(),
1747
+ subscribe: listener => {
1748
+ router.listeners.push(listener);
1749
+ return () => {
1750
+ router.listeners = router.listeners.filter(x => x !== listener);
1751
+ };
1711
1752
  },
1712
- navigate: options => {
1713
- return router.navigate(_extends$1({}, options, {
1714
- from: fullPath
1715
- }));
1753
+ getRoute: id => {
1754
+ return router.routesById[id];
1716
1755
  },
1717
- matchRoute: (matchLocation, opts) => {
1718
- return router.matchRoute(_extends$1({}, matchLocation, {
1719
- from: fullPath
1720
- }), opts);
1721
- }
1722
- };
1723
- router.options.createRoute == null ? void 0 : router.options.createRoute({
1724
- router,
1725
- route
1726
- });
1727
- return route;
1728
- }
1729
- function createRouteMatch(router, route, opts) {
1730
- const routeMatch = _extends$1({}, route, opts, {
1731
- router,
1732
- routeSearch: {},
1733
- search: {},
1734
- childMatches: [],
1735
- status: 'idle',
1736
- routeLoaderData: {},
1737
- loaderData: {},
1738
- isPending: false,
1739
- isFetching: false,
1740
- isInvalid: false,
1741
- __: {
1742
- abortController: new AbortController(),
1743
- latestId: '',
1744
- resolve: () => {},
1745
- notify: () => {
1746
- routeMatch.__.resolve();
1756
+ notify: () => {
1757
+ router.state = _extends({}, router.state, {
1758
+ isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1759
+ isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1760
+ });
1761
+ cascadeLoaderData(router.state.matches);
1762
+ router.listeners.forEach(listener => listener());
1763
+ },
1764
+ mount: () => {
1765
+ const next = router.__.buildLocation({
1766
+ to: '.',
1767
+ search: true,
1768
+ hash: true
1769
+ }); // If the current location isn't updated, trigger a navigation
1770
+ // to the current location. Otherwise, load the current location.
1747
1771
 
1748
- routeMatch.router.notify();
1749
- },
1750
- startPending: () => {
1751
- var _routeMatch$options$p, _routeMatch$options$p2;
1752
1772
 
1753
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1754
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1773
+ if (next.href !== router.location.href) {
1774
+ router.__.commitLocation(next, true);
1775
+ } else {
1776
+ router.loadLocation();
1777
+ }
1755
1778
 
1756
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1757
- return;
1758
- }
1779
+ const unsub = history.listen(event => {
1780
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1781
+ }); // addEventListener does not exist in React Native, but window does
1782
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1759
1783
 
1760
- routeMatch.__.pendingTimeout = setTimeout(() => {
1761
- routeMatch.isPending = true;
1784
+ if (!isServer && window.addEventListener) {
1785
+ // Listen to visibillitychange and focus
1786
+ window.addEventListener('visibilitychange', router.onFocus, false);
1787
+ window.addEventListener('focus', router.onFocus, false);
1788
+ }
1762
1789
 
1763
- routeMatch.__.resolve();
1790
+ return () => {
1791
+ unsub(); // Be sure to unsubscribe if a new handler is set
1764
1792
 
1765
- if (typeof pendingMinMs !== 'undefined') {
1766
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1767
- }
1768
- }, pendingMs);
1769
- },
1770
- cancelPending: () => {
1771
- routeMatch.isPending = false;
1772
- clearTimeout(routeMatch.__.pendingTimeout);
1773
- clearTimeout(routeMatch.__.pendingMinTimeout);
1774
- delete routeMatch.__.pendingMinPromise;
1775
- },
1776
- setParentMatch: parentMatch => {
1777
- routeMatch.parentMatch = parentMatch;
1778
- },
1779
- addChildMatch: childMatch => {
1780
- if (routeMatch.childMatches.find(d => d.matchId === childMatch.matchId)) {
1781
- return;
1782
- }
1793
+ window.removeEventListener('visibilitychange', router.onFocus);
1794
+ window.removeEventListener('focus', router.onFocus);
1795
+ };
1796
+ },
1797
+ onFocus: () => {
1798
+ router.loadLocation();
1799
+ },
1800
+ update: opts => {
1801
+ Object.assign(router.options, opts);
1802
+ const {
1803
+ basepath,
1804
+ routeConfig
1805
+ } = router.options;
1806
+ router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1783
1807
 
1784
- routeMatch.childMatches.push(childMatch);
1785
- },
1786
- validate: () => {
1787
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1808
+ if (routeConfig) {
1809
+ router.routesById = {};
1810
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1811
+ }
1788
1812
 
1789
- // Validate the search params and stabilize them
1790
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1813
+ return router;
1814
+ },
1815
+ cancelMatches: () => {
1816
+ var _router$state$pending, _router$state$pending2;
1817
+ [...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 => {
1818
+ match.cancel();
1819
+ });
1820
+ },
1821
+ loadLocation: async next => {
1822
+ const id = Math.random();
1823
+ router.startedLoadingAt = id;
1791
1824
 
1792
- try {
1793
- const prevSearch = routeMatch.routeSearch;
1794
- let nextSearch = replaceEqualDeep(prevSearch, routeMatch.options.validateSearch == null ? void 0 : routeMatch.options.validateSearch(parentSearch)); // Invalidate route matches when search param stability changes
1825
+ if (next) {
1826
+ // Ingest the new location
1827
+ router.location = next;
1828
+ } // Clear out old actions
1795
1829
 
1796
- if (prevSearch !== nextSearch) {
1797
- routeMatch.isInvalid = true;
1798
- }
1799
1830
 
1800
- routeMatch.routeSearch = nextSearch;
1801
- routeMatch.search = replaceEqualDeep(parentSearch, _extends$1({}, parentSearch, nextSearch));
1802
- } catch (err) {
1803
- console.error(err);
1804
- const error = new Error('Invalid search params found', {
1805
- cause: err
1806
- });
1807
- error.code = 'INVALID_SEARCH_PARAMS';
1808
- routeMatch.status = 'error';
1809
- routeMatch.error = error; // Do not proceed with loading the route
1831
+ router.removeActionQueue.forEach(_ref => {
1832
+ let {
1833
+ action,
1834
+ actionState
1835
+ } = _ref;
1810
1836
 
1811
- return;
1837
+ if (router.state.currentAction === actionState) {
1838
+ router.state.currentAction = undefined;
1812
1839
  }
1813
- }
1814
- },
1815
- cancel: () => {
1816
- var _routeMatch$__$abortC;
1817
1840
 
1818
- (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1841
+ if (action.current === actionState) {
1842
+ action.current = undefined;
1843
+ }
1844
+ });
1845
+ router.removeActionQueue = []; // Cancel any pending matches
1819
1846
 
1820
- routeMatch.__.cancelPending();
1821
- },
1822
- load: async () => {
1823
- const id = '' + Date.now() + Math.random();
1824
- routeMatch.__.latestId = id; // If the match was in an error state, set it
1825
- // to a loading state again. Otherwise, keep it
1826
- // as loading or resolved
1847
+ router.cancelMatches(); // Match the routes
1827
1848
 
1828
- if (routeMatch.status === 'error' || routeMatch.status === 'idle') {
1829
- routeMatch.status = 'loading';
1830
- } // We started loading the route, so it's no longer invalid
1849
+ const matches = router.matchRoutes(location.pathname, {
1850
+ strictParseParams: true
1851
+ });
1852
+ router.state = _extends({}, router.state, {
1853
+ pending: {
1854
+ matches: matches,
1855
+ location: router.location
1856
+ },
1857
+ status: 'loading'
1858
+ });
1859
+ router.notify(); // Load the matches
1831
1860
 
1861
+ await router.loadMatches(matches, {
1862
+ withPending: true
1863
+ });
1832
1864
 
1833
- routeMatch.isInvalid = false;
1834
- routeMatch.__.loadPromise = new Promise(async resolve => {
1835
- // We are now fetching, even if it's in the background of a
1836
- // resolved state
1837
- routeMatch.isFetching = true;
1838
- routeMatch.__.resolve = resolve;
1865
+ if (router.startedLoadingAt !== id) {
1866
+ // Ignore side-effects of match loading
1867
+ return router.navigationPromise;
1868
+ }
1839
1869
 
1840
- const loaderPromise = (async () => {
1841
- const importer = routeMatch.options.import; // First, run any importers
1870
+ const previousMatches = router.state.matches;
1871
+ const exiting = [],
1872
+ staying = [];
1873
+ previousMatches.forEach(d => {
1874
+ if (matches.find(dd => dd.matchId === d.matchId)) {
1875
+ staying.push(d);
1876
+ } else {
1877
+ exiting.push(d);
1878
+ }
1879
+ });
1880
+ const now = Date.now();
1881
+ exiting.forEach(d => {
1882
+ var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1842
1883
 
1843
- if (importer) {
1844
- routeMatch.__.importPromise = importer({
1845
- params: routeMatch.params // search: routeMatch.search,
1884
+ d.__.onExit == null ? void 0 : d.__.onExit({
1885
+ params: d.params,
1886
+ search: d.routeSearch
1887
+ }); // Clear idle error states when match leaves
1846
1888
 
1847
- }).then(imported => {
1848
- routeMatch.__ = _extends$1({}, routeMatch.__, imported);
1849
- });
1850
- } // Wait for the importer to finish before
1851
- // attempting to load elements and data
1889
+ if (d.status === 'error' && !d.isFetching) {
1890
+ d.status = 'idle';
1891
+ d.error = undefined;
1892
+ }
1852
1893
 
1894
+ 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);
1853
1895
 
1854
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1896
+ if (gc > 0) {
1897
+ router.matchCache[d.matchId] = {
1898
+ gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1899
+ match: d
1900
+ };
1901
+ }
1902
+ });
1903
+ staying.forEach(d => {
1904
+ d.options.onTransition == null ? void 0 : d.options.onTransition({
1905
+ params: d.params,
1906
+ search: d.routeSearch
1907
+ });
1908
+ });
1909
+ const entering = matches.filter(d => {
1910
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
1911
+ });
1912
+ entering.forEach(d => {
1913
+ d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1914
+ params: d.params,
1915
+ search: d.search
1916
+ });
1917
+ delete router.matchCache[d.matchId];
1918
+ });
1855
1919
 
1856
- routeMatch.__.elementsPromise = (async () => {
1857
- // then run all element and data loaders in parallel
1858
- // For each element type, potentially load it asynchronously
1859
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1860
- await Promise.all(elementTypes.map(async type => {
1861
- const routeElement = routeMatch.options[type];
1920
+ if (matches.some(d => d.status === 'loading')) {
1921
+ router.notify();
1922
+ await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1923
+ }
1862
1924
 
1863
- if (routeMatch.__[type]) {
1864
- return;
1865
- }
1925
+ if (router.startedLoadingAt !== id) {
1926
+ // Ignore side-effects of match loading
1927
+ return;
1928
+ }
1866
1929
 
1867
- if (typeof routeElement === 'function') {
1868
- const res = await routeElement(routeMatch);
1869
- routeMatch.__[type] = res;
1870
- } else {
1871
- routeMatch.__[type] = routeMatch.options[type];
1872
- }
1873
- }));
1874
- })();
1930
+ router.state = _extends({}, router.state, {
1931
+ location: router.location,
1932
+ matches,
1933
+ pending: undefined,
1934
+ status: 'idle'
1935
+ });
1936
+ router.notify();
1937
+ router.resolveNavigation();
1938
+ },
1939
+ cleanMatchCache: () => {
1940
+ const now = Date.now();
1941
+ Object.keys(router.matchCache).forEach(matchId => {
1942
+ const entry = router.matchCache[matchId]; // Don't remove loading matches
1875
1943
 
1876
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1877
- try {
1878
- const data = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
1879
- params: routeMatch.params,
1880
- search: routeMatch.routeSearch,
1881
- signal: routeMatch.__.abortController.signal
1882
- }));
1944
+ if (entry.match.status === 'loading') {
1945
+ return;
1946
+ } // Do not remove successful matches that are still valid
1883
1947
 
1884
- if (id !== routeMatch.__.latestId) {
1885
- return routeMatch.__.loaderPromise;
1886
- }
1887
1948
 
1888
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1889
- cascadeLoaderData(routeMatch);
1890
- routeMatch.error = undefined;
1891
- routeMatch.status = 'success';
1892
- routeMatch.updatedAt = Date.now();
1893
- } catch (err) {
1894
- if (id !== routeMatch.__.latestId) {
1895
- return routeMatch.__.loaderPromise;
1896
- }
1949
+ if (entry.gc > 0 && entry.gc > now) {
1950
+ return;
1951
+ } // Everything else gets removed
1897
1952
 
1898
- if (process.env.NODE_ENV !== 'production') {
1899
- console.error(err);
1900
- }
1901
1953
 
1902
- routeMatch.error = err;
1903
- routeMatch.status = 'error';
1904
- routeMatch.updatedAt = Date.now();
1905
- }
1906
- });
1954
+ delete router.matchCache[matchId];
1955
+ });
1956
+ },
1957
+ loadRoute: async function loadRoute(navigateOpts) {
1958
+ if (navigateOpts === void 0) {
1959
+ navigateOpts = router.location;
1960
+ }
1907
1961
 
1908
- try {
1909
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1962
+ const next = router.buildNext(navigateOpts);
1963
+ const matches = router.matchRoutes(next.pathname, {
1964
+ strictParseParams: true
1965
+ });
1966
+ await router.loadMatches(matches);
1967
+ return matches;
1968
+ },
1969
+ preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1970
+ var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
1910
1971
 
1911
- if (id !== routeMatch.__.latestId) {
1912
- return routeMatch.__.loaderPromise;
1913
- }
1972
+ if (navigateOpts === void 0) {
1973
+ navigateOpts = router.location;
1974
+ }
1975
+
1976
+ const next = router.buildNext(navigateOpts);
1977
+ const matches = router.matchRoutes(next.pathname, {
1978
+ strictParseParams: true
1979
+ });
1980
+ await router.loadMatches(matches, {
1981
+ preload: true,
1982
+ maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
1983
+ gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
1984
+ });
1985
+ return matches;
1986
+ },
1987
+ matchRoutes: (pathname, opts) => {
1988
+ var _router$state$pending3, _router$state$pending4;
1914
1989
 
1915
- if (routeMatch.__.pendingMinPromise) {
1916
- await routeMatch.__.pendingMinPromise;
1917
- delete routeMatch.__.pendingMinPromise;
1918
- }
1919
- } finally {
1920
- if (id !== routeMatch.__.latestId) {
1921
- return routeMatch.__.loaderPromise;
1922
- }
1990
+ router.cleanMatchCache();
1991
+ const matches = [];
1923
1992
 
1924
- routeMatch.__.cancelPending();
1993
+ if (!router.routeTree) {
1994
+ return matches;
1995
+ }
1925
1996
 
1926
- routeMatch.isPending = false;
1927
- routeMatch.isFetching = false;
1997
+ 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 : [])];
1928
1998
 
1929
- routeMatch.__.notify();
1930
- }
1931
- })();
1999
+ const recurse = async routes => {
2000
+ var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
1932
2001
 
1933
- routeMatch.__.loaderPromise = loaderPromise;
1934
- await loaderPromise;
2002
+ const parentMatch = last(matches);
2003
+ let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
2004
+ const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
2005
+ let foundRoutes = [];
1935
2006
 
1936
- if (id !== routeMatch.__.latestId) {
1937
- return routeMatch.__.loaderPromise;
1938
- }
2007
+ const findMatchInRoutes = (parentRoutes, routes) => {
2008
+ routes.some(route => {
2009
+ var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
1939
2010
 
1940
- delete routeMatch.__.loaderPromise;
1941
- });
1942
- return await routeMatch.__.loadPromise;
1943
- }
1944
- });
2011
+ if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
2012
+ return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
2013
+ }
1945
2014
 
1946
- return routeMatch;
1947
- }
2015
+ const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
2016
+ const matchParams = matchPathname(pathname, {
2017
+ to: route.fullPath,
2018
+ fuzzy,
2019
+ caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2020
+ });
1948
2021
 
1949
- function cascadeLoaderData(routeMatch) {
1950
- if (routeMatch.parentMatch) {
1951
- routeMatch.loaderData = replaceEqualDeep(routeMatch.loaderData, _extends$1({}, routeMatch.parentMatch.loaderData, routeMatch.routeLoaderData));
1952
- }
2022
+ if (matchParams) {
2023
+ let parsedParams;
1953
2024
 
1954
- if (routeMatch.childMatches.length) {
1955
- routeMatch.childMatches.forEach(childMatch => {
1956
- cascadeLoaderData(childMatch);
1957
- });
1958
- }
1959
- }
2025
+ try {
2026
+ var _route$options$parseP;
1960
2027
 
1961
- function matchPathname(currentPathname, matchLocation) {
1962
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
2028
+ parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
2029
+ } catch (err) {
2030
+ if (opts != null && opts.strictParseParams) {
2031
+ throw err;
2032
+ }
2033
+ }
1963
2034
 
1964
- if (matchLocation.to && !pathParams) {
1965
- return;
1966
- } // if (matchLocation.search && !searchMatched) {
1967
- // return
1968
- // }
2035
+ params = _extends({}, params, parsedParams);
2036
+ }
1969
2037
 
2038
+ if (!!matchParams) {
2039
+ foundRoutes = [...parentRoutes, route];
2040
+ }
1970
2041
 
1971
- return pathParams != null ? pathParams : {};
1972
- }
2042
+ return !!foundRoutes.length;
2043
+ });
2044
+ return !!foundRoutes.length;
2045
+ };
1973
2046
 
1974
- function interpolatePath(path, params, leaveWildcard) {
1975
- const interpolatedPathSegments = parsePathname(path);
1976
- return joinPaths(interpolatedPathSegments.map(segment => {
1977
- if (segment.value === '*' && !leaveWildcard) {
1978
- return '';
1979
- }
2047
+ findMatchInRoutes([], filteredRoutes);
1980
2048
 
1981
- if (segment.type === 'param') {
1982
- var _segment$value$substr;
2049
+ if (!foundRoutes.length) {
2050
+ return;
2051
+ }
1983
2052
 
1984
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
1985
- }
2053
+ foundRoutes.forEach(foundRoute => {
2054
+ var _router$matchCache$ma;
1986
2055
 
1987
- return segment.value;
1988
- }));
1989
- }
2056
+ const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2057
+ const matchId = interpolatePath(foundRoute.routeId, params, true);
2058
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2059
+ matchId,
2060
+ params,
2061
+ pathname: joinPaths([pathname, interpolatedPath])
2062
+ });
2063
+ matches.push(match);
2064
+ });
2065
+ const foundRoute = last(foundRoutes);
1990
2066
 
1991
- function warning(cond, message) {
1992
- if (cond) {
1993
- if (typeof console !== 'undefined') console.warn(message);
2067
+ if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2068
+ recurse(foundRoute.childRoutes);
2069
+ }
2070
+ };
1994
2071
 
1995
- try {
1996
- throw new Error(message);
1997
- } catch (_unused) {}
1998
- }
2072
+ recurse([router.routeTree]);
2073
+ cascadeLoaderData(matches);
2074
+ return matches;
2075
+ },
2076
+ loadMatches: async (resolvedMatches, loaderOpts) => {
2077
+ const matchPromises = resolvedMatches.map(async match => {
2078
+ // Validate the match (loads search params etc)
2079
+ match.__.validate();
1999
2080
 
2000
- return true;
2001
- }
2081
+ match.load(loaderOpts);
2002
2082
 
2003
- function isFunction(d) {
2004
- return typeof d === 'function';
2005
- }
2083
+ if (match.status === 'loading') {
2084
+ // If requested, start the pending timers
2085
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2086
+ // This might be completion, error, or a pending state
2006
2087
 
2007
- function functionalUpdate(updater, previous) {
2008
- if (isFunction(updater)) {
2009
- return updater(previous);
2010
- }
2088
+ await match.__.loadPromise;
2089
+ }
2090
+ });
2091
+ router.notify();
2092
+ await Promise.all(matchPromises);
2093
+ },
2094
+ invalidateRoute: opts => {
2095
+ var _router$state$pending5, _router$state$pending6;
2011
2096
 
2012
- return updater;
2013
- }
2097
+ const next = router.buildNext(opts);
2098
+ const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2099
+ [...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 => {
2100
+ if (unloadedMatchIds.includes(match.matchId)) {
2101
+ match.invalidate();
2102
+ }
2103
+ });
2104
+ },
2105
+ reload: () => router.__.navigate({
2106
+ fromCurrent: true,
2107
+ replace: true,
2108
+ search: true
2109
+ }),
2110
+ resolvePath: (from, path) => {
2111
+ return resolvePath(router.basepath, from, cleanPath(path));
2112
+ },
2113
+ matchRoute: (location, opts) => {
2114
+ var _location$from;
2014
2115
 
2015
- function joinPaths(paths) {
2016
- return cleanPath(paths.filter(Boolean).join('/'));
2017
- }
2116
+ // const location = router.buildNext(opts)
2117
+ location = _extends({}, location, {
2118
+ to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2119
+ });
2120
+ const next = router.buildNext(location);
2018
2121
 
2019
- function cleanPath(path) {
2020
- // remove double slashes
2021
- return path.replace(/\/{2,}/g, '/');
2022
- }
2122
+ if (opts != null && opts.pending) {
2123
+ var _router$state$pending7;
2023
2124
 
2024
- function trimPathLeft(path) {
2025
- return path === '/' ? path : path.replace(/^\/{1,}/, '');
2026
- }
2125
+ if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2126
+ return false;
2127
+ }
2027
2128
 
2028
- function trimPathRight(path) {
2029
- return path === '/' ? path : path.replace(/\/{1,}$/, '');
2030
- }
2129
+ return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2130
+ to: next.pathname
2131
+ }));
2132
+ }
2031
2133
 
2032
- function trimPath(path) {
2033
- return trimPathRight(trimPathLeft(path));
2034
- }
2134
+ return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2135
+ to: next.pathname
2136
+ }));
2137
+ },
2138
+ navigate: async _ref8 => {
2139
+ let {
2140
+ from,
2141
+ to = '.',
2142
+ search,
2143
+ hash,
2144
+ replace,
2145
+ params
2146
+ } = _ref8;
2147
+ // If this link simply reloads the current route,
2148
+ // make sure it has a new key so it will trigger a data refresh
2149
+ // If this `to` is a valid external URL, return
2150
+ // null for LinkUtils
2151
+ const toString = String(to);
2152
+ const fromString = String(from);
2153
+ let isExternal;
2035
2154
 
2036
- function matchByPath(from, matchLocation) {
2037
- var _matchLocation$to;
2155
+ try {
2156
+ new URL("" + toString);
2157
+ isExternal = true;
2158
+ } catch (e) {}
2038
2159
 
2039
- const baseSegments = parsePathname(from);
2040
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
2041
- const params = {};
2160
+ invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2161
+ return router.__.navigate({
2162
+ from: fromString,
2163
+ to: toString,
2164
+ search,
2165
+ hash,
2166
+ replace,
2167
+ params
2168
+ });
2169
+ },
2170
+ buildLink: _ref9 => {
2171
+ var _preload, _ref10;
2042
2172
 
2043
- let isMatch = (() => {
2044
- for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
2045
- const baseSegment = baseSegments[i];
2046
- const routeSegment = routeSegments[i];
2047
- const isLastRouteSegment = i === routeSegments.length - 1;
2048
- const isLastBaseSegment = i === baseSegments.length - 1;
2173
+ let {
2174
+ from,
2175
+ to = '.',
2176
+ search,
2177
+ params,
2178
+ hash,
2179
+ target,
2180
+ replace,
2181
+ activeOptions,
2182
+ preload,
2183
+ preloadMaxAge: userPreloadMaxAge,
2184
+ preloadGcMaxAge: userPreloadGcMaxAge,
2185
+ preloadDelay: userPreloadDelay,
2186
+ disabled
2187
+ } = _ref9;
2049
2188
 
2050
- if (routeSegment) {
2051
- if (routeSegment.type === 'wildcard') {
2052
- if (baseSegment != null && baseSegment.value) {
2053
- params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
2054
- return true;
2055
- }
2189
+ // If this link simply reloads the current route,
2190
+ // make sure it has a new key so it will trigger a data refresh
2191
+ // If this `to` is a valid external URL, return
2192
+ // null for LinkUtils
2193
+ try {
2194
+ new URL("" + to);
2195
+ return {
2196
+ type: 'external',
2197
+ href: to
2198
+ };
2199
+ } catch (e) {}
2056
2200
 
2057
- return false;
2058
- }
2201
+ const nextOpts = {
2202
+ from,
2203
+ to,
2204
+ search,
2205
+ params,
2206
+ hash,
2207
+ replace
2208
+ };
2209
+ const next = router.buildNext(nextOpts);
2210
+ preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2211
+ const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2059
2212
 
2060
- if (routeSegment.type === 'pathname') {
2061
- if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
2062
- return true;
2063
- }
2213
+ const pathIsEqual = router.state.location.pathname === next.pathname;
2214
+ const currentPathSplit = router.state.location.pathname.split('/');
2215
+ const nextPathSplit = next.pathname.split('/');
2216
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2217
+ const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2064
2218
 
2065
- if (baseSegment) {
2066
- if (matchLocation.caseSensitive) {
2067
- if (routeSegment.value !== baseSegment.value) {
2068
- return false;
2069
- }
2070
- } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
2071
- return false;
2072
- }
2073
- }
2074
- }
2219
+ const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2220
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2075
2221
 
2076
- if (!baseSegment) {
2077
- return false;
2078
- }
2222
+ const isActive = pathTest && hashTest; // The click handler
2079
2223
 
2080
- if (routeSegment.type === 'param') {
2081
- if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
2082
- return false;
2083
- }
2224
+ const handleClick = e => {
2225
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2226
+ e.preventDefault();
2084
2227
 
2085
- if (!baseSegment.value.startsWith(':')) {
2086
- params[routeSegment.value.substring(1)] = baseSegment.value;
2087
- }
2088
- }
2089
- }
2228
+ if (pathIsEqual && !search && !hash) {
2229
+ router.invalidateRoute(nextOpts);
2230
+ } // All is well? Navigate!)
2090
2231
 
2091
- if (isLastRouteSegment && !isLastBaseSegment) {
2092
- return !!matchLocation.fuzzy;
2093
- }
2094
- }
2095
2232
 
2096
- return true;
2097
- })();
2233
+ router.__.navigate(nextOpts);
2234
+ }
2235
+ }; // The click handler
2098
2236
 
2099
- return isMatch ? params : undefined;
2100
- } // function matchBySearch(
2101
- // search: SearchSchema,
2102
- // matchLocation: MatchLocation,
2103
- // ) {
2104
- // return !!(matchLocation.search && matchLocation.search(search))
2105
- // }
2106
2237
 
2107
- function parsePathname(pathname) {
2108
- if (!pathname) {
2109
- return [];
2110
- }
2238
+ const handleFocus = e => {
2239
+ if (preload) {
2240
+ router.preloadRoute(nextOpts, {
2241
+ maxAge: userPreloadMaxAge,
2242
+ gcMaxAge: userPreloadGcMaxAge
2243
+ });
2244
+ }
2245
+ };
2111
2246
 
2112
- pathname = cleanPath(pathname);
2113
- const segments = [];
2247
+ const handleEnter = e => {
2248
+ const target = e.target || {};
2114
2249
 
2115
- if (pathname.slice(0, 1) === '/') {
2116
- pathname = pathname.substring(1);
2117
- segments.push({
2118
- type: 'pathname',
2119
- value: '/'
2120
- });
2121
- }
2250
+ if (preload) {
2251
+ if (target.preloadTimeout) {
2252
+ return;
2253
+ }
2122
2254
 
2123
- if (!pathname) {
2124
- return segments;
2125
- } // Remove empty segments and '.' segments
2255
+ target.preloadTimeout = setTimeout(() => {
2256
+ target.preloadTimeout = null;
2257
+ router.preloadRoute(nextOpts, {
2258
+ maxAge: userPreloadMaxAge,
2259
+ gcMaxAge: userPreloadGcMaxAge
2260
+ });
2261
+ }, preloadDelay);
2262
+ }
2263
+ };
2126
2264
 
2265
+ const handleLeave = e => {
2266
+ const target = e.target || {};
2127
2267
 
2128
- const split = pathname.split('/').filter(Boolean);
2129
- segments.push(...split.map(part => {
2130
- if (part.startsWith('*')) {
2131
- return {
2132
- type: 'wildcard',
2133
- value: part
2268
+ if (target.preloadTimeout) {
2269
+ clearTimeout(target.preloadTimeout);
2270
+ target.preloadTimeout = null;
2271
+ }
2134
2272
  };
2135
- }
2136
2273
 
2137
- if (part.charAt(0) === ':') {
2138
2274
  return {
2139
- type: 'param',
2140
- value: part
2275
+ type: 'internal',
2276
+ next,
2277
+ handleFocus,
2278
+ handleClick,
2279
+ handleEnter,
2280
+ handleLeave,
2281
+ isActive,
2282
+ disabled
2141
2283
  };
2142
- }
2143
-
2144
- return {
2145
- type: 'pathname',
2146
- value: part
2147
- };
2148
- }));
2149
-
2150
- if (pathname.slice(-1) === '/') {
2151
- pathname = pathname.substring(1);
2152
- segments.push({
2153
- type: 'pathname',
2154
- value: '/'
2155
- });
2156
- }
2284
+ },
2285
+ buildNext: opts => {
2286
+ const next = router.__.buildLocation(opts);
2157
2287
 
2158
- return segments;
2159
- }
2288
+ const matches = router.matchRoutes(next.pathname);
2160
2289
 
2161
- function _resolvePath(basepath, base, to) {
2162
- base = base.replace(new RegExp("^" + basepath), '/');
2163
- to = to.replace(new RegExp("^" + basepath), '/');
2164
- let baseSegments = parsePathname(base);
2165
- const toSegments = parsePathname(to);
2166
- toSegments.forEach((toSegment, index) => {
2167
- if (toSegment.value === '/') {
2168
- if (!index) {
2169
- // Leading slash
2170
- baseSegments = [toSegment];
2171
- } else if (index === toSegments.length - 1) {
2172
- // Trailing Slash
2173
- baseSegments.push(toSegment);
2174
- } else ;
2175
- } else if (toSegment.value === '..') {
2176
- var _last2;
2290
+ const __preSearchFilters = matches.map(match => {
2291
+ var _match$options$preSea;
2177
2292
 
2178
- // Extra trailing slash? pop it off
2179
- if (baseSegments.length > 1 && ((_last2 = last(baseSegments)) == null ? void 0 : _last2.value) === '/') {
2180
- baseSegments.pop();
2181
- }
2293
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2294
+ }).flat().filter(Boolean);
2182
2295
 
2183
- baseSegments.pop();
2184
- } else if (toSegment.value === '.') {
2185
- return;
2186
- } else {
2187
- baseSegments.push(toSegment);
2188
- }
2189
- });
2190
- const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
2191
- return cleanPath(joined);
2192
- }
2193
- function replaceEqualDeep(prev, next) {
2194
- if (prev === next) {
2195
- return prev;
2196
- }
2296
+ const __postSearchFilters = matches.map(match => {
2297
+ var _match$options$postSe;
2197
2298
 
2198
- const array = Array.isArray(prev) && Array.isArray(next);
2299
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2300
+ }).flat().filter(Boolean);
2199
2301
 
2200
- if (array || isPlainObject(prev) && isPlainObject(next)) {
2201
- const aSize = array ? prev.length : Object.keys(prev).length;
2202
- const bItems = array ? next : Object.keys(next);
2203
- const bSize = bItems.length;
2204
- const copy = array ? [] : {};
2205
- let equalItems = 0;
2302
+ return router.__.buildLocation(_extends({}, opts, {
2303
+ __preSearchFilters,
2304
+ __postSearchFilters
2305
+ }));
2306
+ },
2307
+ __: {
2308
+ buildRouteTree: rootRouteConfig => {
2309
+ const recurseRoutes = (routeConfigs, parent) => {
2310
+ return routeConfigs.map(routeConfig => {
2311
+ const routeOptions = routeConfig.options;
2312
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2313
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2314
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2315
+ // }
2316
+
2317
+ const existingRoute = router.routesById[route.routeId];
2318
+
2319
+ if (existingRoute) {
2320
+ if (process.env.NODE_ENV !== 'production') {
2321
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2322
+ }
2206
2323
 
2207
- for (let i = 0; i < bSize; i++) {
2208
- const key = array ? i : bItems[i];
2209
- copy[key] = replaceEqualDeep(prev[key], next[key]);
2324
+ throw new Error();
2325
+ }
2326
+ router.routesById[route.routeId] = route;
2327
+ const children = routeConfig.children;
2328
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2329
+ return route;
2330
+ });
2331
+ };
2210
2332
 
2211
- if (copy[key] === prev[key]) {
2212
- equalItems++;
2213
- }
2214
- }
2333
+ const routes = recurseRoutes([rootRouteConfig]);
2334
+ return routes[0];
2335
+ },
2336
+ parseLocation: (location, previousLocation) => {
2337
+ var _location$hash$split$;
2215
2338
 
2216
- return aSize === bSize && equalItems === aSize ? prev : copy;
2217
- }
2339
+ const parsedSearch = router.options.parseSearch(location.search);
2340
+ return {
2341
+ pathname: location.pathname,
2342
+ searchStr: location.search,
2343
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2344
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2345
+ href: "" + location.pathname + location.search + location.hash,
2346
+ state: location.state,
2347
+ key: location.key
2348
+ };
2349
+ },
2350
+ navigate: location => {
2351
+ const next = router.buildNext(location);
2352
+ return router.__.commitLocation(next, location.replace);
2353
+ },
2354
+ buildLocation: function buildLocation(dest) {
2355
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2218
2356
 
2219
- return next;
2220
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
2357
+ if (dest === void 0) {
2358
+ dest = {};
2359
+ }
2221
2360
 
2222
- function isPlainObject(o) {
2223
- if (!hasObjectPrototype(o)) {
2224
- return false;
2225
- } // If has modified constructor
2361
+ // const resolvedFrom: Location = {
2362
+ // ...router.location,
2363
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2226
2364
 
2365
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2227
2366
 
2228
- const ctor = o.constructor;
2367
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2368
+ strictParseParams: true
2369
+ });
2370
+ const toMatches = router.matchRoutes(pathname);
2229
2371
 
2230
- if (typeof ctor === 'undefined') {
2231
- return true;
2232
- } // If has modified prototype
2372
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2233
2373
 
2374
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2234
2375
 
2235
- const prot = ctor.prototype;
2376
+ if (nextParams) {
2377
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2378
+ Object.assign({}, nextParams, fn(nextParams));
2379
+ });
2380
+ }
2236
2381
 
2237
- if (!hasObjectPrototype(prot)) {
2238
- return false;
2239
- } // If constructor does not have an Object-specific method
2382
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2240
2383
 
2384
+ 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
2241
2385
 
2242
- if (!prot.hasOwnProperty('isPrototypeOf')) {
2243
- return false;
2244
- } // Most likely a plain Object
2386
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2387
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2388
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2389
+ : {}; // Then post filters
2245
2390
 
2391
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2392
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2393
+ const searchStr = router.options.stringifySearch(search);
2394
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2395
+ hash = hash ? "#" + hash : '';
2396
+ return {
2397
+ pathname,
2398
+ search,
2399
+ searchStr,
2400
+ state: router.location.state,
2401
+ hash,
2402
+ href: "" + pathname + searchStr + hash,
2403
+ key: dest.key
2404
+ };
2405
+ },
2406
+ commitLocation: (next, replace) => {
2407
+ const id = '' + Date.now() + Math.random();
2408
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2409
+ let nextAction = 'replace';
2246
2410
 
2247
- return true;
2248
- }
2411
+ if (!replace) {
2412
+ nextAction = 'push';
2413
+ }
2249
2414
 
2250
- function hasObjectPrototype(o) {
2251
- return Object.prototype.toString.call(o) === '[object Object]';
2252
- }
2415
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2253
2416
 
2254
- const defaultParseSearch = parseSearchWith(JSON.parse);
2255
- const defaultStringifySearch = stringifySearchWith(JSON.stringify);
2256
- function parseSearchWith(parser) {
2257
- return searchStr => {
2258
- if (searchStr.substring(0, 1) === '?') {
2259
- searchStr = searchStr.substring(1);
2260
- }
2417
+ if (isSameUrl && !next.key) {
2418
+ nextAction = 'replace';
2419
+ }
2261
2420
 
2262
- let query = decode(searchStr); // Try to parse any query params that might be json
2421
+ if (nextAction === 'replace') {
2422
+ history.replace({
2423
+ pathname: next.pathname,
2424
+ hash: next.hash,
2425
+ search: next.searchStr
2426
+ }, {
2427
+ id
2428
+ });
2429
+ } else {
2430
+ history.push({
2431
+ pathname: next.pathname,
2432
+ hash: next.hash,
2433
+ search: next.searchStr
2434
+ }, {
2435
+ id
2436
+ });
2437
+ }
2263
2438
 
2264
- for (let key in query) {
2265
- const value = query[key];
2439
+ router.navigationPromise = new Promise(resolve => {
2440
+ const previousNavigationResolve = router.resolveNavigation;
2266
2441
 
2267
- if (typeof value === 'string') {
2268
- try {
2269
- query[key] = parser(value);
2270
- } catch (err) {//
2271
- }
2442
+ router.resolveNavigation = () => {
2443
+ previousNavigationResolve();
2444
+ resolve();
2445
+ };
2446
+ });
2447
+ return router.navigationPromise;
2272
2448
  }
2273
2449
  }
2274
-
2275
- return query;
2276
2450
  };
2277
- }
2278
- function stringifySearchWith(stringify) {
2279
- return search => {
2280
- search = _extends$1({}, search);
2281
-
2282
- if (search) {
2283
- Object.keys(search).forEach(key => {
2284
- const val = search[key];
2285
-
2286
- if (typeof val === 'undefined' || val === undefined) {
2287
- delete search[key];
2288
- } else if (val && typeof val === 'object' && val !== null) {
2289
- try {
2290
- search[key] = stringify(val);
2291
- } catch (err) {// silent
2292
- }
2293
- }
2294
- });
2295
- }
2451
+ router.location = router.__.parseLocation(history.location);
2452
+ router.state.location = router.location;
2453
+ router.update(userOptions); // Allow frameworks to hook into the router creation
2296
2454
 
2297
- const searchStr = encode(search).toString();
2298
- return searchStr ? "?" + searchStr : '';
2299
- };
2455
+ router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2456
+ return router;
2300
2457
  }
2301
2458
 
2302
2459
  function isCtrlEvent(e) {
2303
2460
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2304
2461
  }
2305
2462
 
2306
- function last(arr) {
2307
- return arr[arr.length - 1];
2308
- }
2309
-
2463
+ exports.cascadeLoaderData = cascadeLoaderData;
2464
+ exports.cleanPath = cleanPath;
2310
2465
  exports.createBrowserHistory = createBrowserHistory;
2311
2466
  exports.createHashHistory = createHashHistory;
2312
2467
  exports.createMemoryHistory = createMemoryHistory;
@@ -2314,17 +2469,25 @@ exports.createRoute = createRoute;
2314
2469
  exports.createRouteConfig = createRouteConfig;
2315
2470
  exports.createRouteMatch = createRouteMatch;
2316
2471
  exports.createRouter = createRouter;
2472
+ exports.decode = decode;
2317
2473
  exports.defaultParseSearch = defaultParseSearch;
2318
2474
  exports.defaultStringifySearch = defaultStringifySearch;
2475
+ exports.encode = encode;
2319
2476
  exports.functionalUpdate = functionalUpdate;
2477
+ exports.interpolatePath = interpolatePath;
2478
+ exports.invariant = invariant;
2479
+ exports.joinPaths = joinPaths;
2320
2480
  exports.last = last;
2321
2481
  exports.matchByPath = matchByPath;
2322
2482
  exports.matchPathname = matchPathname;
2323
2483
  exports.parsePathname = parsePathname;
2324
2484
  exports.parseSearchWith = parseSearchWith;
2325
2485
  exports.replaceEqualDeep = replaceEqualDeep;
2326
- exports.resolvePath = _resolvePath;
2486
+ exports.resolvePath = resolvePath;
2327
2487
  exports.rootRouteId = rootRouteId;
2328
2488
  exports.stringifySearchWith = stringifySearchWith;
2489
+ exports.trimPath = trimPath;
2490
+ exports.trimPathLeft = trimPathLeft;
2491
+ exports.trimPathRight = trimPathRight;
2329
2492
  exports.warning = warning;
2330
2493
  //# sourceMappingURL=index.js.map