@tanstack/router-core 0.0.1-alpha.1 → 0.0.1-alpha.11

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