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

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