@tanstack/react-router 0.0.1-alpha.6 → 0.0.1-alpha.7

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