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

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