@tanstack/react-router 0.0.1-alpha.0 → 0.0.1-alpha.10

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,1602 @@ 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')) {
1267
- router.notify();
1268
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
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);
1269
1161
  }
1162
+ }
1163
+ }
1270
1164
 
1271
- if (router.startedLoadingAt !== id) {
1272
- // Ignore side-effects of match loading
1273
- return;
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
+ }
1274
1205
  }
1206
+ }
1275
1207
 
1276
- router.notify();
1277
- router.resolveNavigation();
1278
- },
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
1208
+ return target;
1209
+ };
1210
+ return _extends.apply(this, arguments);
1211
+ }
1283
1212
 
1284
- if (entry.match.status === 'loading') {
1285
- return;
1286
- } // Do not remove successful matches that are still valid
1213
+ function createRoute(routeConfig, options, parent, router) {
1214
+ const {
1215
+ id,
1216
+ routeId,
1217
+ path: routePath,
1218
+ fullPath
1219
+ } = routeConfig;
1287
1220
 
1221
+ const action = router.state.actions[id] || (() => {
1222
+ router.state.actions[id] = {
1223
+ pending: [],
1224
+ submit: async (submission, actionOpts) => {
1225
+ var _actionOpts$invalidat;
1288
1226
 
1289
- if (entry.match.updatedAt && entry.match.updatedAt + entry.maxAge > now) {
1227
+ if (!route) {
1290
1228
  return;
1291
- } // Everything else gets removed
1229
+ }
1292
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
+ });
1244
+ router.notify();
1293
1245
 
1294
- delete router.preloadCache[matchId];
1295
- });
1296
- },
1297
- loadRoute: async function loadRoute(navigateOpts, loaderOpts) {
1298
- if (navigateOpts === void 0) {
1299
- navigateOpts = router.location;
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
+ }
1300
1272
  }
1273
+ };
1274
+ return router.state.actions[id];
1275
+ })();
1301
1276
 
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;
1277
+ let route = {
1278
+ routeId: id,
1279
+ routeRouteId: routeId,
1280
+ routePath,
1281
+ fullPath,
1282
+ options,
1283
+ router,
1284
+ childRoutes: undefined,
1285
+ parentRoute: parent,
1286
+ action,
1287
+ buildLink: options => {
1288
+ return router.buildLink(_extends({}, options, {
1289
+ from: fullPath
1290
+ }));
1311
1291
  },
1312
- matchRoutes: (pathname, opts) => {
1313
- var _router$state$pending3, _router$state$pending4;
1314
-
1315
- router.cleanPreloadCache();
1316
- const matches = [];
1292
+ navigate: options => {
1293
+ return router.navigate(_extends({}, options, {
1294
+ from: fullPath
1295
+ }));
1296
+ },
1297
+ matchRoute: (matchLocation, opts) => {
1298
+ return router.matchRoute(_extends({}, matchLocation, {
1299
+ from: fullPath
1300
+ }), opts);
1301
+ }
1302
+ };
1303
+ router.options.createRoute == null ? void 0 : router.options.createRoute({
1304
+ router,
1305
+ route
1306
+ });
1307
+ return route;
1308
+ }
1309
+ function cascadeLoaderData(matches) {
1310
+ matches.forEach((match, index) => {
1311
+ const parent = matches[index - 1];
1317
1312
 
1318
- if (!router.routeTree) {
1319
- return matches;
1320
- }
1313
+ if (parent) {
1314
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1315
+ }
1316
+ });
1317
+ }
1321
1318
 
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 : [])];
1319
+ const rootRouteId = '__root__';
1320
+ const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1321
+ if (options === void 0) {
1322
+ options = {};
1323
+ }
1323
1324
 
1324
- const recurse = async (routes, parentMatch) => {
1325
- var _parentMatch$params, _router$options$filte, _router$preloadCache$, _route$childRoutes2;
1325
+ if (isRoot === void 0) {
1326
+ isRoot = true;
1327
+ }
1326
1328
 
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
- });
1329
+ if (isRoot) {
1330
+ options.path = rootRouteId;
1331
+ } // Strip the root from parentIds
1338
1332
 
1339
- if (matchParams) {
1340
- let parsedParams;
1341
1333
 
1342
- try {
1343
- var _route$options$parseP;
1334
+ if (parentId === rootRouteId) {
1335
+ parentId = '';
1336
+ }
1344
1337
 
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
- }
1338
+ let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1351
1339
 
1352
- params = _extends$1({}, params, parsedParams);
1353
- }
1340
+ if (path && path !== '/') {
1341
+ path = trimPath(path);
1342
+ }
1354
1343
 
1355
- return !!matchParams;
1356
- });
1344
+ const routeId = path || options.id;
1345
+ let id = joinPaths([parentId, routeId]);
1357
1346
 
1358
- if (!route) {
1359
- return;
1360
- }
1347
+ if (path === rootRouteId) {
1348
+ path = '/';
1349
+ }
1361
1350
 
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);
1351
+ if (id !== rootRouteId) {
1352
+ id = joinPaths(['/', id]);
1353
+ }
1370
1354
 
1371
- if ((_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length) {
1372
- recurse(route.childRoutes, match);
1373
- }
1374
- };
1355
+ const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1356
+ return {
1357
+ id: id,
1358
+ routeId: routeId,
1359
+ path: path,
1360
+ fullPath: fullPath,
1361
+ options: options,
1362
+ children,
1363
+ createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1364
+ addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1365
+ createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1366
+ };
1367
+ };
1375
1368
 
1376
- recurse([router.routeTree]);
1377
- return matches;
1369
+ const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1370
+ function createRouteMatch(router, route, opts) {
1371
+ const routeMatch = _extends({}, route, opts, {
1372
+ router,
1373
+ routeSearch: {},
1374
+ search: {},
1375
+ childMatches: [],
1376
+ status: 'idle',
1377
+ routeLoaderData: {},
1378
+ loaderData: {},
1379
+ isPending: false,
1380
+ isFetching: false,
1381
+ isInvalid: false,
1382
+ invalidAt: Infinity,
1383
+ getIsInvalid: () => {
1384
+ const now = Date.now();
1385
+ return routeMatch.isInvalid || routeMatch.invalidAt < now;
1378
1386
  },
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
1387
+ __: {
1388
+ abortController: new AbortController(),
1389
+ latestId: '',
1390
+ resolve: () => {},
1391
+ notify: () => {
1392
+ routeMatch.__.resolve();
1383
1393
 
1394
+ routeMatch.router.notify();
1395
+ },
1396
+ startPending: () => {
1397
+ var _routeMatch$options$p, _routeMatch$options$p2;
1384
1398
 
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
1399
+ const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1400
+ const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1391
1401
 
1402
+ if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1403
+ return;
1404
+ }
1392
1405
 
1393
- if (match.status === 'success' && match.isInvalid || match.status === 'error' || match.status === 'idle') {
1394
- match.load();
1395
- } // If requested, start the pending timers
1406
+ routeMatch.__.pendingTimeout = setTimeout(() => {
1407
+ routeMatch.isPending = true;
1396
1408
 
1409
+ routeMatch.__.resolve();
1397
1410
 
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
1411
+ if (typeof pendingMinMs !== 'undefined') {
1412
+ routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1413
+ }
1414
+ }, pendingMs);
1415
+ },
1416
+ cancelPending: () => {
1417
+ routeMatch.isPending = false;
1418
+ clearTimeout(routeMatch.__.pendingTimeout);
1419
+ clearTimeout(routeMatch.__.pendingMinTimeout);
1420
+ delete routeMatch.__.pendingMinPromise;
1421
+ },
1422
+ // setParentMatch: (parentMatch?: RouteMatch) => {
1423
+ // routeMatch.parentMatch = parentMatch
1424
+ // },
1425
+ // addChildMatch: (childMatch: RouteMatch) => {
1426
+ // if (
1427
+ // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1428
+ // ) {
1429
+ // return
1430
+ // }
1431
+ // routeMatch.childMatches.push(childMatch)
1432
+ // },
1433
+ validate: () => {
1434
+ var _routeMatch$parentMat, _routeMatch$parentMat2;
1400
1435
 
1401
- await match.__.loadPromise;
1402
- });
1403
- router.notify();
1404
- await Promise.all(matchPromises);
1405
- return resolvedMatches;
1406
- },
1407
- invalidateRoute: opts => {
1408
- var _router$state$pending5, _router$state$pending6;
1436
+ // Validate the search params and stabilize them
1437
+ const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1409
1438
 
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
- });
1417
- },
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));
1425
- },
1426
- matchRoute: (location, opts) => {
1427
- var _location$from;
1439
+ try {
1440
+ const prevSearch = routeMatch.routeSearch;
1441
+ const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1442
+ let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1428
1443
 
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);
1444
+ if (prevSearch !== nextSearch) {
1445
+ routeMatch.isInvalid = true;
1446
+ }
1434
1447
 
1435
- if (opts != null && opts.pending) {
1436
- var _router$state$pending7;
1448
+ routeMatch.routeSearch = nextSearch;
1449
+ routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1450
+ } catch (err) {
1451
+ console.error(err);
1452
+ const error = new Error('Invalid search params found', {
1453
+ cause: err
1454
+ });
1455
+ error.code = 'INVALID_SEARCH_PARAMS';
1456
+ routeMatch.status = 'error';
1457
+ routeMatch.error = error; // Do not proceed with loading the route
1437
1458
 
1438
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
1439
- return false;
1459
+ return;
1440
1460
  }
1441
-
1442
- return !!matchPathname(router.state.pending.location.pathname, _extends$1({}, opts, {
1443
- to: next.pathname
1444
- }));
1445
1461
  }
1462
+ },
1463
+ cancel: () => {
1464
+ var _routeMatch$__$abortC;
1446
1465
 
1447
- return !!matchPathname(router.state.location.pathname, _extends$1({}, opts, {
1448
- to: next.pathname
1449
- }));
1466
+ (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1467
+
1468
+ routeMatch.__.cancelPending();
1450
1469
  },
1451
- _navigate: location => {
1452
- const next = router.buildNext(location);
1453
- return router.commitLocation(next, location.replace);
1470
+ invalidate: () => {
1471
+ routeMatch.isInvalid = true;
1454
1472
  },
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;
1473
+ hasLoaders: () => {
1474
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1475
+ },
1476
+ load: async opts => {
1477
+ const id = '' + Date.now() + Math.random();
1478
+ routeMatch.__.latestId = id; // If the match was in an error state, set it
1479
+ // to a loading state again. Otherwise, keep it
1480
+ // as loading or resolved
1470
1481
 
1471
- try {
1472
- new URL("" + toString);
1473
- isExternal = true;
1474
- } catch (e) {}
1482
+ if (routeMatch.status === 'idle') {
1483
+ routeMatch.status = 'loading';
1484
+ } // We started loading the route, so it's no longer invalid
1475
1485
 
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
1486
 
1481
- return;
1482
- }
1487
+ routeMatch.isInvalid = false;
1488
+ routeMatch.__.loadPromise = new Promise(async resolve => {
1489
+ // We are now fetching, even if it's in the background of a
1490
+ // resolved state
1491
+ routeMatch.isFetching = true;
1492
+ routeMatch.__.resolve = resolve;
1483
1493
 
1484
- return router._navigate({
1485
- from: fromString,
1486
- to: toString,
1487
- search,
1488
- hash
1489
- });
1490
- },
1491
- buildLink: _ref2 => {
1492
- var _preload, _ref3, _ref4;
1494
+ const loaderPromise = (async () => {
1495
+ // Load the elements and data in parallel
1496
+ routeMatch.__.elementsPromise = (async () => {
1497
+ // then run all element and data loaders in parallel
1498
+ // For each element type, potentially load it asynchronously
1499
+ await Promise.all(elementTypes.map(async type => {
1500
+ const routeElement = routeMatch.options[type];
1493
1501
 
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;
1502
+ if (routeMatch.__[type]) {
1503
+ return;
1504
+ }
1508
1505
 
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) {}
1506
+ if (typeof routeElement === 'function') {
1507
+ const res = await routeElement(routeMatch);
1508
+ routeMatch.__[type] = res;
1509
+ } else {
1510
+ routeMatch.__[type] = routeMatch.options[type];
1511
+ }
1512
+ }));
1513
+ })();
1514
+
1515
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1516
+ try {
1517
+ var _ref, _ref2, _opts$maxAge;
1520
1518
 
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
1519
+ if (routeMatch.options.loader) {
1520
+ const data = await routeMatch.options.loader({
1521
+ params: routeMatch.params,
1522
+ search: routeMatch.routeSearch,
1523
+ signal: routeMatch.__.abortController.signal
1524
+ });
1533
1525
 
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
1526
+ if (id !== routeMatch.__.latestId) {
1527
+ return routeMatch.__.loaderPromise;
1528
+ }
1539
1529
 
1540
- const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
1541
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
1530
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1531
+ }
1542
1532
 
1543
- const isActive = pathTest && hashTest; // The click handler
1533
+ routeMatch.error = undefined;
1534
+ routeMatch.status = 'success';
1535
+ routeMatch.updatedAt = Date.now();
1536
+ 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);
1537
+ } catch (err) {
1538
+ if (id !== routeMatch.__.latestId) {
1539
+ return routeMatch.__.loaderPromise;
1540
+ }
1544
1541
 
1545
- const handleClick = e => {
1546
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1547
- e.preventDefault();
1542
+ if (process.env.NODE_ENV !== 'production') {
1543
+ console.error(err);
1544
+ }
1548
1545
 
1549
- if (pathIsEqual && !search && !hash) {
1550
- router.invalidateRoute(nextOpts);
1551
- } // All is well? Navigate!)
1546
+ routeMatch.error = err;
1547
+ routeMatch.status = 'error';
1548
+ routeMatch.updatedAt = Date.now();
1549
+ }
1550
+ });
1552
1551
 
1552
+ try {
1553
+ await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1553
1554
 
1554
- router._navigate(nextOpts);
1555
- }
1556
- }; // The click handler
1555
+ if (id !== routeMatch.__.latestId) {
1556
+ return routeMatch.__.loaderPromise;
1557
+ }
1557
1558
 
1559
+ if (routeMatch.__.pendingMinPromise) {
1560
+ await routeMatch.__.pendingMinPromise;
1561
+ delete routeMatch.__.pendingMinPromise;
1562
+ }
1563
+ } finally {
1564
+ if (id !== routeMatch.__.latestId) {
1565
+ return routeMatch.__.loaderPromise;
1566
+ }
1558
1567
 
1559
- const handleFocus = e => {
1560
- if (preload && preloadMaxAge > 0) {
1561
- router.loadRoute(nextOpts, {
1562
- maxAge: preloadMaxAge
1563
- });
1564
- }
1565
- };
1568
+ routeMatch.__.cancelPending();
1566
1569
 
1567
- const handleEnter = e => {
1568
- const target = e.target || {};
1570
+ routeMatch.isPending = false;
1571
+ routeMatch.isFetching = false;
1569
1572
 
1570
- if (preload && preloadMaxAge > 0) {
1571
- if (target.preloadTimeout) {
1572
- return;
1573
+ routeMatch.__.notify();
1573
1574
  }
1575
+ })();
1574
1576
 
1575
- target.preloadTimeout = setTimeout(() => {
1576
- target.preloadTimeout = null;
1577
- router.loadRoute(nextOpts, {
1578
- maxAge: preloadMaxAge
1579
- });
1580
- }, preloadDelay);
1581
- }
1582
- };
1583
-
1584
- const handleLeave = e => {
1585
- const target = e.target || {};
1577
+ routeMatch.__.loaderPromise = loaderPromise;
1578
+ await loaderPromise;
1586
1579
 
1587
- if (target.preloadTimeout) {
1588
- clearTimeout(target.preloadTimeout);
1589
- target.preloadTimeout = null;
1580
+ if (id !== routeMatch.__.latestId) {
1581
+ return routeMatch.__.loaderPromise;
1590
1582
  }
1591
- };
1592
1583
 
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
- })
1584
+ delete routeMatch.__.loaderPromise;
1616
1585
  });
1586
+ return await routeMatch.__.loadPromise;
1617
1587
  }
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
1588
+ });
1623
1589
 
1624
- router.options.createRouter == null ? void 0 : router.options.createRouter(router); // router.mount()
1590
+ if (!routeMatch.hasLoaders()) {
1591
+ routeMatch.status = 'success';
1592
+ }
1625
1593
 
1626
- return router;
1594
+ return routeMatch;
1627
1595
  }
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
1596
 
1643
- const action = router.state.actions[routeId] || (() => {
1644
- router.state.actions[routeId] = {
1645
- pending: [],
1646
- submit: async (submission, actionOpts) => {
1647
- var _actionOpts$invalidat;
1597
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1598
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify);
1599
+ function parseSearchWith(parser) {
1600
+ return searchStr => {
1601
+ if (searchStr.substring(0, 1) === '?') {
1602
+ searchStr = searchStr.substring(1);
1603
+ }
1648
1604
 
1649
- if (!route) {
1650
- return;
1651
- }
1605
+ let query = decode(searchStr); // Try to parse any query params that might be json
1652
1606
 
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();
1607
+ for (let key in query) {
1608
+ const value = query[key];
1665
1609
 
1610
+ if (typeof value === 'string') {
1666
1611
  try {
1667
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1668
- actionState.data = res;
1612
+ query[key] = parser(value);
1613
+ } catch (err) {//
1614
+ }
1615
+ }
1616
+ }
1669
1617
 
1670
- if (invalidate) {
1671
- router.invalidateRoute({
1672
- to: '.',
1673
- fromCurrent: true
1674
- });
1675
- await router.reload();
1676
- }
1618
+ return query;
1619
+ };
1620
+ }
1621
+ function stringifySearchWith(stringify) {
1622
+ return search => {
1623
+ search = _extends({}, search);
1677
1624
 
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);
1625
+ if (search) {
1626
+ Object.keys(search).forEach(key => {
1627
+ const val = search[key];
1686
1628
 
1687
- if (actionState === router.state.action) {
1688
- router.state.action = undefined;
1629
+ if (typeof val === 'undefined' || val === undefined) {
1630
+ delete search[key];
1631
+ } else if (val && typeof val === 'object' && val !== null) {
1632
+ try {
1633
+ search[key] = stringify(val);
1634
+ } catch (err) {// silent
1689
1635
  }
1690
-
1691
- router.notify();
1692
1636
  }
1693
- }
1694
- };
1695
- return router.state.actions[routeId];
1696
- })();
1637
+ });
1638
+ }
1697
1639
 
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
- }));
1640
+ const searchStr = encode(search).toString();
1641
+ return searchStr ? "?" + searchStr : '';
1642
+ };
1643
+ }
1644
+
1645
+ var _window$document;
1646
+ // Detect if we're in the DOM
1647
+ const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1648
+
1649
+ const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1650
+
1651
+ function createRouter(userOptions) {
1652
+ var _userOptions$stringif, _userOptions$parseSea;
1653
+
1654
+ const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1655
+
1656
+ const originalOptions = _extends({
1657
+ defaultLoaderGcMaxAge: 5 * 60 * 1000,
1658
+ defaultLoaderMaxAge: 0,
1659
+ defaultPreloadMaxAge: 2000,
1660
+ defaultPreloadDelay: 50
1661
+ }, userOptions, {
1662
+ stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1663
+ parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1664
+ });
1665
+
1666
+ let router = {
1667
+ history,
1668
+ options: originalOptions,
1669
+ listeners: [],
1670
+ removeActionQueue: [],
1671
+ // Resolved after construction
1672
+ basepath: '',
1673
+ routeTree: undefined,
1674
+ routesById: {},
1675
+ location: undefined,
1676
+ allRouteInfo: undefined,
1677
+ //
1678
+ navigationPromise: Promise.resolve(),
1679
+ resolveNavigation: () => {},
1680
+ matchCache: {},
1681
+ state: {
1682
+ status: 'idle',
1683
+ location: null,
1684
+ matches: [],
1685
+ actions: {},
1686
+ loaderData: {},
1687
+ lastUpdated: Date.now(),
1688
+ isFetching: false,
1689
+ isPreloading: false
1690
+ },
1691
+ startedLoadingAt: Date.now(),
1692
+ subscribe: listener => {
1693
+ router.listeners.push(listener);
1694
+ return () => {
1695
+ router.listeners = router.listeners.filter(x => x !== listener);
1696
+ };
1697
+ },
1698
+ getRoute: id => {
1699
+ return router.routesById[id];
1700
+ },
1701
+ notify: () => {
1702
+ router.state = _extends({}, router.state, {
1703
+ isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1704
+ isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1705
+ });
1706
+ cascadeLoaderData(router.state.matches);
1707
+ router.listeners.forEach(listener => listener());
1708
+ },
1709
+ mount: () => {
1710
+ const next = router.__.buildLocation({
1711
+ to: '.',
1712
+ search: true,
1713
+ hash: true
1714
+ }); // If the current location isn't updated, trigger a navigation
1715
+ // to the current location. Otherwise, load the current location.
1716
+
1717
+
1718
+ if (next.href !== router.location.href) {
1719
+ router.__.commitLocation(next, true);
1720
+ } else {
1721
+ router.loadLocation();
1722
+ }
1723
+
1724
+ const unsub = history.listen(event => {
1725
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1726
+ }); // addEventListener does not exist in React Native, but window does
1727
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1728
+
1729
+ if (!isServer && window.addEventListener) {
1730
+ // Listen to visibillitychange and focus
1731
+ window.addEventListener('visibilitychange', router.onFocus, false);
1732
+ window.addEventListener('focus', router.onFocus, false);
1733
+ }
1734
+
1735
+ return () => {
1736
+ unsub(); // Be sure to unsubscribe if a new handler is set
1737
+
1738
+ window.removeEventListener('visibilitychange', router.onFocus);
1739
+ window.removeEventListener('focus', router.onFocus);
1740
+ };
1711
1741
  },
1712
- navigate: options => {
1713
- return router.navigate(_extends$1({}, options, {
1714
- from: fullPath
1715
- }));
1742
+ onFocus: () => {
1743
+ router.loadLocation();
1716
1744
  },
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();
1745
+ update: opts => {
1746
+ Object.assign(router.options, opts);
1747
+ const {
1748
+ basepath,
1749
+ routeConfig
1750
+ } = router.options;
1751
+ router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1747
1752
 
1748
- routeMatch.router.notify();
1749
- },
1750
- startPending: () => {
1751
- var _routeMatch$options$p, _routeMatch$options$p2;
1753
+ if (routeConfig) {
1754
+ router.routesById = {};
1755
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1756
+ }
1752
1757
 
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;
1758
+ return router;
1759
+ },
1760
+ cancelMatches: () => {
1761
+ var _router$state$pending, _router$state$pending2;
1762
+ [...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 => {
1763
+ match.cancel();
1764
+ });
1765
+ },
1766
+ loadLocation: async next => {
1767
+ const id = Math.random();
1768
+ router.startedLoadingAt = id;
1755
1769
 
1756
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1757
- return;
1758
- }
1770
+ if (next) {
1771
+ // Ingest the new location
1772
+ router.location = next;
1773
+ } // Clear out old actions
1759
1774
 
1760
- routeMatch.__.pendingTimeout = setTimeout(() => {
1761
- routeMatch.isPending = true;
1762
1775
 
1763
- routeMatch.__.resolve();
1776
+ router.removeActionQueue.forEach(_ref => {
1777
+ let {
1778
+ action,
1779
+ actionState
1780
+ } = _ref;
1764
1781
 
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
+ if (router.state.currentAction === actionState) {
1783
+ router.state.currentAction = undefined;
1782
1784
  }
1783
1785
 
1784
- routeMatch.childMatches.push(childMatch);
1785
- },
1786
- validate: () => {
1787
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1788
-
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;
1786
+ if (action.current === actionState) {
1787
+ action.current = undefined;
1788
+ }
1789
+ });
1790
+ router.removeActionQueue = []; // Cancel any pending matches
1791
1791
 
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
1792
+ router.cancelMatches(); // Match the routes
1795
1793
 
1796
- if (prevSearch !== nextSearch) {
1797
- routeMatch.isInvalid = true;
1798
- }
1794
+ const matches = router.matchRoutes(location.pathname, {
1795
+ strictParseParams: true
1796
+ });
1797
+ router.state = _extends({}, router.state, {
1798
+ pending: {
1799
+ matches: matches,
1800
+ location: router.location
1801
+ },
1802
+ status: 'loading'
1803
+ });
1804
+ router.notify(); // Load the matches
1799
1805
 
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
1806
+ await router.loadMatches(matches, {
1807
+ withPending: true
1808
+ });
1810
1809
 
1811
- return;
1812
- }
1810
+ if (router.startedLoadingAt !== id) {
1811
+ // Ignore side-effects of match loading
1812
+ return router.navigationPromise;
1813
1813
  }
1814
- },
1815
- cancel: () => {
1816
- var _routeMatch$__$abortC;
1817
-
1818
- (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1819
1814
 
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
1815
+ const previousMatches = router.state.matches;
1816
+ const exiting = [],
1817
+ staying = [];
1818
+ previousMatches.forEach(d => {
1819
+ if (matches.find(dd => dd.matchId === d.matchId)) {
1820
+ staying.push(d);
1821
+ } else {
1822
+ exiting.push(d);
1823
+ }
1824
+ });
1825
+ const now = Date.now();
1826
+ exiting.forEach(d => {
1827
+ var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1827
1828
 
1828
- if (routeMatch.status === 'error' || routeMatch.status === 'idle') {
1829
- routeMatch.status = 'loading';
1830
- } // We started loading the route, so it's no longer invalid
1829
+ d.__.onExit == null ? void 0 : d.__.onExit({
1830
+ params: d.params,
1831
+ search: d.routeSearch
1832
+ }); // Clear idle error states when match leaves
1831
1833
 
1834
+ if (d.status === 'error' && !d.isFetching) {
1835
+ d.status = 'idle';
1836
+ d.error = undefined;
1837
+ }
1832
1838
 
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;
1839
+ 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);
1839
1840
 
1840
- const loaderPromise = (async () => {
1841
- const importer = routeMatch.options.import; // First, run any importers
1841
+ if (gc > 0) {
1842
+ router.matchCache[d.matchId] = {
1843
+ gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1844
+ match: d
1845
+ };
1846
+ }
1847
+ });
1848
+ staying.forEach(d => {
1849
+ d.options.onTransition == null ? void 0 : d.options.onTransition({
1850
+ params: d.params,
1851
+ search: d.routeSearch
1852
+ });
1853
+ });
1854
+ const entering = matches.filter(d => {
1855
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
1856
+ });
1857
+ entering.forEach(d => {
1858
+ d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1859
+ params: d.params,
1860
+ search: d.search
1861
+ });
1862
+ delete router.matchCache[d.matchId];
1863
+ });
1842
1864
 
1843
- if (importer) {
1844
- routeMatch.__.importPromise = importer({
1845
- params: routeMatch.params // search: routeMatch.search,
1865
+ if (matches.some(d => d.status === 'loading')) {
1866
+ router.notify();
1867
+ await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1868
+ }
1846
1869
 
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
1870
+ if (router.startedLoadingAt !== id) {
1871
+ // Ignore side-effects of match loading
1872
+ return;
1873
+ }
1852
1874
 
1875
+ router.state = _extends({}, router.state, {
1876
+ location: router.location,
1877
+ matches,
1878
+ pending: undefined,
1879
+ status: 'idle'
1880
+ });
1881
+ router.notify();
1882
+ router.resolveNavigation();
1883
+ },
1884
+ cleanMatchCache: () => {
1885
+ const now = Date.now();
1886
+ Object.keys(router.matchCache).forEach(matchId => {
1887
+ const entry = router.matchCache[matchId]; // Don't remove loading matches
1853
1888
 
1854
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1889
+ if (entry.match.status === 'loading') {
1890
+ return;
1891
+ } // Do not remove successful matches that are still valid
1855
1892
 
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];
1862
1893
 
1863
- if (routeMatch.__[type]) {
1864
- return;
1865
- }
1894
+ if (entry.gc > 0 && entry.gc > now) {
1895
+ return;
1896
+ } // Everything else gets removed
1866
1897
 
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
- })();
1875
1898
 
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
- }));
1899
+ delete router.matchCache[matchId];
1900
+ });
1901
+ },
1902
+ loadRoute: async function loadRoute(navigateOpts) {
1903
+ if (navigateOpts === void 0) {
1904
+ navigateOpts = router.location;
1905
+ }
1883
1906
 
1884
- if (id !== routeMatch.__.latestId) {
1885
- return routeMatch.__.loaderPromise;
1886
- }
1907
+ const next = router.buildNext(navigateOpts);
1908
+ const matches = router.matchRoutes(next.pathname, {
1909
+ strictParseParams: true
1910
+ });
1911
+ await router.loadMatches(matches);
1912
+ return matches;
1913
+ },
1914
+ preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1915
+ var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
1887
1916
 
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
- }
1917
+ if (navigateOpts === void 0) {
1918
+ navigateOpts = router.location;
1919
+ }
1897
1920
 
1898
- if (process.env.NODE_ENV !== 'production') {
1899
- console.error(err);
1900
- }
1921
+ const next = router.buildNext(navigateOpts);
1922
+ const matches = router.matchRoutes(next.pathname, {
1923
+ strictParseParams: true
1924
+ });
1925
+ await router.loadMatches(matches, {
1926
+ preload: true,
1927
+ maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
1928
+ gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
1929
+ });
1930
+ return matches;
1931
+ },
1932
+ matchRoutes: (pathname, opts) => {
1933
+ var _router$state$pending3, _router$state$pending4;
1901
1934
 
1902
- routeMatch.error = err;
1903
- routeMatch.status = 'error';
1904
- routeMatch.updatedAt = Date.now();
1905
- }
1906
- });
1935
+ router.cleanMatchCache();
1936
+ const matches = [];
1907
1937
 
1908
- try {
1909
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1938
+ if (!router.routeTree) {
1939
+ return matches;
1940
+ }
1910
1941
 
1911
- if (id !== routeMatch.__.latestId) {
1912
- return routeMatch.__.loaderPromise;
1913
- }
1942
+ 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 : [])];
1914
1943
 
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
- }
1944
+ const recurse = async routes => {
1945
+ var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
1923
1946
 
1924
- routeMatch.__.cancelPending();
1947
+ const parentMatch = last(matches);
1948
+ let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1949
+ const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
1950
+ let foundRoutes = [];
1925
1951
 
1926
- routeMatch.isPending = false;
1927
- routeMatch.isFetching = false;
1952
+ const findMatchInRoutes = (parentRoutes, routes) => {
1953
+ routes.some(route => {
1954
+ var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
1928
1955
 
1929
- routeMatch.__.notify();
1930
- }
1931
- })();
1956
+ if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
1957
+ return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
1958
+ }
1932
1959
 
1933
- routeMatch.__.loaderPromise = loaderPromise;
1934
- await loaderPromise;
1960
+ const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
1961
+ const matchParams = matchPathname(pathname, {
1962
+ to: route.fullPath,
1963
+ fuzzy,
1964
+ caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
1965
+ });
1935
1966
 
1936
- if (id !== routeMatch.__.latestId) {
1937
- return routeMatch.__.loaderPromise;
1938
- }
1967
+ if (matchParams) {
1968
+ let parsedParams;
1939
1969
 
1940
- delete routeMatch.__.loaderPromise;
1941
- });
1942
- return await routeMatch.__.loadPromise;
1943
- }
1944
- });
1970
+ try {
1971
+ var _route$options$parseP;
1945
1972
 
1946
- return routeMatch;
1947
- }
1973
+ parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
1974
+ } catch (err) {
1975
+ if (opts != null && opts.strictParseParams) {
1976
+ throw err;
1977
+ }
1978
+ }
1948
1979
 
1949
- function cascadeLoaderData(routeMatch) {
1950
- if (routeMatch.parentMatch) {
1951
- routeMatch.loaderData = replaceEqualDeep(routeMatch.loaderData, _extends$1({}, routeMatch.parentMatch.loaderData, routeMatch.routeLoaderData));
1952
- }
1980
+ params = _extends({}, params, parsedParams);
1981
+ }
1953
1982
 
1954
- if (routeMatch.childMatches.length) {
1955
- routeMatch.childMatches.forEach(childMatch => {
1956
- cascadeLoaderData(childMatch);
1957
- });
1958
- }
1959
- }
1983
+ if (!!matchParams) {
1984
+ foundRoutes = [...parentRoutes, route];
1985
+ }
1960
1986
 
1961
- function matchPathname(currentPathname, matchLocation) {
1962
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1987
+ return !!foundRoutes.length;
1988
+ });
1989
+ return !!foundRoutes.length;
1990
+ };
1963
1991
 
1964
- if (matchLocation.to && !pathParams) {
1965
- return;
1966
- } // if (matchLocation.search && !searchMatched) {
1967
- // return
1968
- // }
1992
+ findMatchInRoutes([], filteredRoutes);
1969
1993
 
1994
+ if (!foundRoutes.length) {
1995
+ return;
1996
+ }
1970
1997
 
1971
- return pathParams != null ? pathParams : {};
1972
- }
1998
+ foundRoutes.forEach(foundRoute => {
1999
+ var _router$matchCache$ma;
1973
2000
 
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
- }
2001
+ const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2002
+ const matchId = interpolatePath(foundRoute.routeId, params, true);
2003
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2004
+ matchId,
2005
+ params,
2006
+ pathname: joinPaths([pathname, interpolatedPath])
2007
+ });
2008
+ matches.push(match);
2009
+ });
2010
+ const foundRoute = last(foundRoutes);
1980
2011
 
1981
- if (segment.type === 'param') {
1982
- var _segment$value$substr;
2012
+ if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2013
+ recurse(foundRoute.childRoutes);
2014
+ }
2015
+ };
1983
2016
 
1984
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
1985
- }
2017
+ recurse([router.routeTree]);
2018
+ cascadeLoaderData(matches);
2019
+ return matches;
2020
+ },
2021
+ loadMatches: async (resolvedMatches, loaderOpts) => {
2022
+ const now = Date.now();
2023
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2024
+ const matchPromises = resolvedMatches.map(async match => {
2025
+ // Validate the match (loads search params etc)
2026
+ match.__.validate(); // If this is a preload, add it to the preload cache
1986
2027
 
1987
- return segment.value;
1988
- }));
1989
- }
1990
2028
 
1991
- function warning(cond, message) {
1992
- if (cond) {
1993
- if (typeof console !== 'undefined') console.warn(message);
2029
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2030
+ // If the match is currently active, don't preload it
2031
+ if (router.state.matches.find(d => d.matchId === match.matchId)) {
2032
+ return;
2033
+ }
1994
2034
 
1995
- try {
1996
- throw new Error(message);
1997
- } catch (_unused) {}
1998
- }
2035
+ router.matchCache[match.matchId] = {
2036
+ gc: now + loaderOpts.gcMaxAge,
2037
+ match
2038
+ };
2039
+ } // If the match is invalid, errored or idle, trigger it to load
1999
2040
 
2000
- return true;
2001
- }
2002
2041
 
2003
- function isFunction(d) {
2004
- return typeof d === 'function';
2005
- }
2042
+ if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2043
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2044
+ match.load({
2045
+ maxAge
2046
+ });
2047
+ }
2006
2048
 
2007
- function functionalUpdate(updater, previous) {
2008
- if (isFunction(updater)) {
2009
- return updater(previous);
2010
- }
2049
+ if (match.status === 'loading') {
2050
+ // If requested, start the pending timers
2051
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2052
+ // This might be completion, error, or a pending state
2011
2053
 
2012
- return updater;
2013
- }
2054
+ await match.__.loadPromise;
2055
+ }
2056
+ });
2057
+ router.notify();
2058
+ await Promise.all(matchPromises);
2059
+ },
2060
+ invalidateRoute: opts => {
2061
+ var _router$state$pending5, _router$state$pending6;
2014
2062
 
2015
- function joinPaths(paths) {
2016
- return cleanPath(paths.filter(Boolean).join('/'));
2017
- }
2063
+ const next = router.buildNext(opts);
2064
+ const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2065
+ [...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 => {
2066
+ if (unloadedMatchIds.includes(match.matchId)) {
2067
+ match.invalidate();
2068
+ }
2069
+ });
2070
+ },
2071
+ reload: () => router.__.navigate({
2072
+ fromCurrent: true,
2073
+ replace: true,
2074
+ search: true
2075
+ }),
2076
+ resolvePath: (from, path) => {
2077
+ return resolvePath(router.basepath, from, cleanPath(path));
2078
+ },
2079
+ matchRoute: (location, opts) => {
2080
+ var _location$from;
2018
2081
 
2019
- function cleanPath(path) {
2020
- // remove double slashes
2021
- return path.replace(/\/{2,}/g, '/');
2022
- }
2082
+ // const location = router.buildNext(opts)
2083
+ location = _extends({}, location, {
2084
+ to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2085
+ });
2086
+ const next = router.buildNext(location);
2023
2087
 
2024
- function trimPathLeft(path) {
2025
- return path === '/' ? path : path.replace(/^\/{1,}/, '');
2026
- }
2088
+ if (opts != null && opts.pending) {
2089
+ var _router$state$pending7;
2027
2090
 
2028
- function trimPathRight(path) {
2029
- return path === '/' ? path : path.replace(/\/{1,}$/, '');
2030
- }
2091
+ if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2092
+ return false;
2093
+ }
2031
2094
 
2032
- function trimPath(path) {
2033
- return trimPathRight(trimPathLeft(path));
2034
- }
2095
+ return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2096
+ to: next.pathname
2097
+ }));
2098
+ }
2035
2099
 
2036
- function matchByPath(from, matchLocation) {
2037
- var _matchLocation$to;
2100
+ return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2101
+ to: next.pathname
2102
+ }));
2103
+ },
2104
+ navigate: async _ref8 => {
2105
+ let {
2106
+ from,
2107
+ to = '.',
2108
+ search,
2109
+ hash,
2110
+ replace,
2111
+ params
2112
+ } = _ref8;
2113
+ // If this link simply reloads the current route,
2114
+ // make sure it has a new key so it will trigger a data refresh
2115
+ // If this `to` is a valid external URL, return
2116
+ // null for LinkUtils
2117
+ const toString = String(to);
2118
+ const fromString = String(from);
2119
+ let isExternal;
2038
2120
 
2039
- const baseSegments = parsePathname(from);
2040
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
2041
- const params = {};
2121
+ try {
2122
+ new URL("" + toString);
2123
+ isExternal = true;
2124
+ } catch (e) {}
2042
2125
 
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;
2126
+ invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2127
+ return router.__.navigate({
2128
+ from: fromString,
2129
+ to: toString,
2130
+ search,
2131
+ hash,
2132
+ replace,
2133
+ params
2134
+ });
2135
+ },
2136
+ buildLink: _ref9 => {
2137
+ var _preload, _ref10;
2049
2138
 
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
- }
2139
+ let {
2140
+ from,
2141
+ to = '.',
2142
+ search,
2143
+ params,
2144
+ hash,
2145
+ target,
2146
+ replace,
2147
+ activeOptions,
2148
+ preload,
2149
+ preloadMaxAge: userPreloadMaxAge,
2150
+ preloadGcMaxAge: userPreloadGcMaxAge,
2151
+ preloadDelay: userPreloadDelay,
2152
+ disabled
2153
+ } = _ref9;
2056
2154
 
2057
- return false;
2058
- }
2155
+ // If this link simply reloads the current route,
2156
+ // make sure it has a new key so it will trigger a data refresh
2157
+ // If this `to` is a valid external URL, return
2158
+ // null for LinkUtils
2159
+ try {
2160
+ new URL("" + to);
2161
+ return {
2162
+ type: 'external',
2163
+ href: to
2164
+ };
2165
+ } catch (e) {}
2059
2166
 
2060
- if (routeSegment.type === 'pathname') {
2061
- if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
2062
- return true;
2063
- }
2167
+ const nextOpts = {
2168
+ from,
2169
+ to,
2170
+ search,
2171
+ params,
2172
+ hash,
2173
+ replace
2174
+ };
2175
+ const next = router.buildNext(nextOpts);
2176
+ preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2177
+ const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2064
2178
 
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
- }
2179
+ const pathIsEqual = router.state.location.pathname === next.pathname;
2180
+ const currentPathSplit = router.state.location.pathname.split('/');
2181
+ const nextPathSplit = next.pathname.split('/');
2182
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2183
+ const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2184
+
2185
+ const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2186
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2075
2187
 
2076
- if (!baseSegment) {
2077
- return false;
2078
- }
2188
+ const isActive = pathTest && hashTest; // The click handler
2079
2189
 
2080
- if (routeSegment.type === 'param') {
2081
- if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
2082
- return false;
2083
- }
2190
+ const handleClick = e => {
2191
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2192
+ e.preventDefault();
2084
2193
 
2085
- if (!baseSegment.value.startsWith(':')) {
2086
- params[routeSegment.value.substring(1)] = baseSegment.value;
2087
- }
2088
- }
2089
- }
2194
+ if (pathIsEqual && !search && !hash) {
2195
+ router.invalidateRoute(nextOpts);
2196
+ } // All is well? Navigate!)
2090
2197
 
2091
- if (isLastRouteSegment && !isLastBaseSegment) {
2092
- return !!matchLocation.fuzzy;
2093
- }
2094
- }
2095
2198
 
2096
- return true;
2097
- })();
2199
+ router.__.navigate(nextOpts);
2200
+ }
2201
+ }; // The click handler
2098
2202
 
2099
- return isMatch ? params : undefined;
2100
- } // function matchBySearch(
2101
- // search: SearchSchema,
2102
- // matchLocation: MatchLocation,
2103
- // ) {
2104
- // return !!(matchLocation.search && matchLocation.search(search))
2105
- // }
2106
2203
 
2107
- function parsePathname(pathname) {
2108
- if (!pathname) {
2109
- return [];
2110
- }
2204
+ const handleFocus = e => {
2205
+ if (preload) {
2206
+ router.preloadRoute(nextOpts, {
2207
+ maxAge: userPreloadMaxAge,
2208
+ gcMaxAge: userPreloadGcMaxAge
2209
+ });
2210
+ }
2211
+ };
2111
2212
 
2112
- pathname = cleanPath(pathname);
2113
- const segments = [];
2213
+ const handleEnter = e => {
2214
+ const target = e.target || {};
2114
2215
 
2115
- if (pathname.slice(0, 1) === '/') {
2116
- pathname = pathname.substring(1);
2117
- segments.push({
2118
- type: 'pathname',
2119
- value: '/'
2120
- });
2121
- }
2216
+ if (preload) {
2217
+ if (target.preloadTimeout) {
2218
+ return;
2219
+ }
2122
2220
 
2123
- if (!pathname) {
2124
- return segments;
2125
- } // Remove empty segments and '.' segments
2221
+ target.preloadTimeout = setTimeout(() => {
2222
+ target.preloadTimeout = null;
2223
+ router.preloadRoute(nextOpts, {
2224
+ maxAge: userPreloadMaxAge,
2225
+ gcMaxAge: userPreloadGcMaxAge
2226
+ });
2227
+ }, preloadDelay);
2228
+ }
2229
+ };
2126
2230
 
2231
+ const handleLeave = e => {
2232
+ const target = e.target || {};
2127
2233
 
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
2234
+ if (target.preloadTimeout) {
2235
+ clearTimeout(target.preloadTimeout);
2236
+ target.preloadTimeout = null;
2237
+ }
2134
2238
  };
2135
- }
2136
2239
 
2137
- if (part.charAt(0) === ':') {
2138
2240
  return {
2139
- type: 'param',
2140
- value: part
2241
+ type: 'internal',
2242
+ next,
2243
+ handleFocus,
2244
+ handleClick,
2245
+ handleEnter,
2246
+ handleLeave,
2247
+ isActive,
2248
+ disabled
2141
2249
  };
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
- }
2250
+ },
2251
+ buildNext: opts => {
2252
+ const next = router.__.buildLocation(opts);
2157
2253
 
2158
- return segments;
2159
- }
2254
+ const matches = router.matchRoutes(next.pathname);
2160
2255
 
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;
2256
+ const __preSearchFilters = matches.map(match => {
2257
+ var _match$options$preSea;
2177
2258
 
2178
- // Extra trailing slash? pop it off
2179
- if (baseSegments.length > 1 && ((_last2 = last(baseSegments)) == null ? void 0 : _last2.value) === '/') {
2180
- baseSegments.pop();
2181
- }
2259
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2260
+ }).flat().filter(Boolean);
2182
2261
 
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
- }
2262
+ const __postSearchFilters = matches.map(match => {
2263
+ var _match$options$postSe;
2197
2264
 
2198
- const array = Array.isArray(prev) && Array.isArray(next);
2265
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2266
+ }).flat().filter(Boolean);
2199
2267
 
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;
2268
+ return router.__.buildLocation(_extends({}, opts, {
2269
+ __preSearchFilters,
2270
+ __postSearchFilters
2271
+ }));
2272
+ },
2273
+ __: {
2274
+ buildRouteTree: rootRouteConfig => {
2275
+ const recurseRoutes = (routeConfigs, parent) => {
2276
+ return routeConfigs.map(routeConfig => {
2277
+ const routeOptions = routeConfig.options;
2278
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2279
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2280
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2281
+ // }
2282
+
2283
+ const existingRoute = router.routesById[route.routeId];
2284
+
2285
+ if (existingRoute) {
2286
+ if (process.env.NODE_ENV !== 'production') {
2287
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2288
+ }
2206
2289
 
2207
- for (let i = 0; i < bSize; i++) {
2208
- const key = array ? i : bItems[i];
2209
- copy[key] = replaceEqualDeep(prev[key], next[key]);
2290
+ throw new Error();
2291
+ }
2292
+ router.routesById[route.routeId] = route;
2293
+ const children = routeConfig.children;
2294
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2295
+ return route;
2296
+ });
2297
+ };
2210
2298
 
2211
- if (copy[key] === prev[key]) {
2212
- equalItems++;
2213
- }
2214
- }
2299
+ const routes = recurseRoutes([rootRouteConfig]);
2300
+ return routes[0];
2301
+ },
2302
+ parseLocation: (location, previousLocation) => {
2303
+ var _location$hash$split$;
2215
2304
 
2216
- return aSize === bSize && equalItems === aSize ? prev : copy;
2217
- }
2305
+ const parsedSearch = router.options.parseSearch(location.search);
2306
+ return {
2307
+ pathname: location.pathname,
2308
+ searchStr: location.search,
2309
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2310
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2311
+ href: "" + location.pathname + location.search + location.hash,
2312
+ state: location.state,
2313
+ key: location.key
2314
+ };
2315
+ },
2316
+ navigate: location => {
2317
+ const next = router.buildNext(location);
2318
+ return router.__.commitLocation(next, location.replace);
2319
+ },
2320
+ buildLocation: function buildLocation(dest) {
2321
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2218
2322
 
2219
- return next;
2220
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
2323
+ if (dest === void 0) {
2324
+ dest = {};
2325
+ }
2221
2326
 
2222
- function isPlainObject(o) {
2223
- if (!hasObjectPrototype(o)) {
2224
- return false;
2225
- } // If has modified constructor
2327
+ // const resolvedFrom: Location = {
2328
+ // ...router.location,
2329
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2226
2330
 
2331
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2227
2332
 
2228
- const ctor = o.constructor;
2333
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2334
+ strictParseParams: true
2335
+ });
2336
+ const toMatches = router.matchRoutes(pathname);
2229
2337
 
2230
- if (typeof ctor === 'undefined') {
2231
- return true;
2232
- } // If has modified prototype
2338
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2233
2339
 
2340
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2234
2341
 
2235
- const prot = ctor.prototype;
2342
+ if (nextParams) {
2343
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2344
+ Object.assign({}, nextParams, fn(nextParams));
2345
+ });
2346
+ }
2236
2347
 
2237
- if (!hasObjectPrototype(prot)) {
2238
- return false;
2239
- } // If constructor does not have an Object-specific method
2348
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2240
2349
 
2350
+ 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
2351
 
2242
- if (!prot.hasOwnProperty('isPrototypeOf')) {
2243
- return false;
2244
- } // Most likely a plain Object
2352
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2353
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2354
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2355
+ : {}; // Then post filters
2245
2356
 
2357
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2358
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2359
+ const searchStr = router.options.stringifySearch(search);
2360
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2361
+ hash = hash ? "#" + hash : '';
2362
+ return {
2363
+ pathname,
2364
+ search,
2365
+ searchStr,
2366
+ state: router.location.state,
2367
+ hash,
2368
+ href: "" + pathname + searchStr + hash,
2369
+ key: dest.key
2370
+ };
2371
+ },
2372
+ commitLocation: (next, replace) => {
2373
+ const id = '' + Date.now() + Math.random();
2374
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2375
+ let nextAction = 'replace';
2246
2376
 
2247
- return true;
2248
- }
2377
+ if (!replace) {
2378
+ nextAction = 'push';
2379
+ }
2249
2380
 
2250
- function hasObjectPrototype(o) {
2251
- return Object.prototype.toString.call(o) === '[object Object]';
2252
- }
2381
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2253
2382
 
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
- }
2383
+ if (isSameUrl && !next.key) {
2384
+ nextAction = 'replace';
2385
+ }
2261
2386
 
2262
- let query = decode(searchStr); // Try to parse any query params that might be json
2387
+ if (nextAction === 'replace') {
2388
+ history.replace({
2389
+ pathname: next.pathname,
2390
+ hash: next.hash,
2391
+ search: next.searchStr
2392
+ }, {
2393
+ id
2394
+ });
2395
+ } else {
2396
+ history.push({
2397
+ pathname: next.pathname,
2398
+ hash: next.hash,
2399
+ search: next.searchStr
2400
+ }, {
2401
+ id
2402
+ });
2403
+ }
2263
2404
 
2264
- for (let key in query) {
2265
- const value = query[key];
2405
+ router.navigationPromise = new Promise(resolve => {
2406
+ const previousNavigationResolve = router.resolveNavigation;
2266
2407
 
2267
- if (typeof value === 'string') {
2268
- try {
2269
- query[key] = parser(value);
2270
- } catch (err) {//
2271
- }
2408
+ router.resolveNavigation = () => {
2409
+ previousNavigationResolve();
2410
+ resolve();
2411
+ };
2412
+ });
2413
+ return router.navigationPromise;
2272
2414
  }
2273
2415
  }
2274
-
2275
- return query;
2276
2416
  };
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
- }
2417
+ router.location = router.__.parseLocation(history.location);
2418
+ router.state.location = router.location;
2419
+ router.update(userOptions); // Allow frameworks to hook into the router creation
2296
2420
 
2297
- const searchStr = encode(search).toString();
2298
- return searchStr ? "?" + searchStr : '';
2299
- };
2421
+ router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2422
+ return router;
2300
2423
  }
2301
2424
 
2302
2425
  function isCtrlEvent(e) {
2303
2426
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2304
2427
  }
2305
2428
 
2306
- function last(arr) {
2307
- return arr[arr.length - 1];
2308
- }
2309
-
2429
+ exports.cascadeLoaderData = cascadeLoaderData;
2430
+ exports.cleanPath = cleanPath;
2310
2431
  exports.createBrowserHistory = createBrowserHistory;
2311
2432
  exports.createHashHistory = createHashHistory;
2312
2433
  exports.createMemoryHistory = createMemoryHistory;
@@ -2314,17 +2435,25 @@ exports.createRoute = createRoute;
2314
2435
  exports.createRouteConfig = createRouteConfig;
2315
2436
  exports.createRouteMatch = createRouteMatch;
2316
2437
  exports.createRouter = createRouter;
2438
+ exports.decode = decode;
2317
2439
  exports.defaultParseSearch = defaultParseSearch;
2318
2440
  exports.defaultStringifySearch = defaultStringifySearch;
2441
+ exports.encode = encode;
2319
2442
  exports.functionalUpdate = functionalUpdate;
2443
+ exports.interpolatePath = interpolatePath;
2444
+ exports.invariant = invariant;
2445
+ exports.joinPaths = joinPaths;
2320
2446
  exports.last = last;
2321
2447
  exports.matchByPath = matchByPath;
2322
2448
  exports.matchPathname = matchPathname;
2323
2449
  exports.parsePathname = parsePathname;
2324
2450
  exports.parseSearchWith = parseSearchWith;
2325
2451
  exports.replaceEqualDeep = replaceEqualDeep;
2326
- exports.resolvePath = _resolvePath;
2452
+ exports.resolvePath = resolvePath;
2327
2453
  exports.rootRouteId = rootRouteId;
2328
2454
  exports.stringifySearchWith = stringifySearchWith;
2455
+ exports.trimPath = trimPath;
2456
+ exports.trimPathLeft = trimPathLeft;
2457
+ exports.trimPathRight = trimPathRight;
2329
2458
  exports.warning = warning;
2330
2459
  //# sourceMappingURL=index.js.map