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