@tanstack/router-core 0.0.1-alpha.0 → 0.0.1-alpha.10

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