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

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