@tanstack/react-router 0.0.1-alpha.1 → 0.0.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,23 +70,6 @@ function _extends$1() {
70
70
  return _extends$1.apply(this, arguments);
71
71
  }
72
72
 
73
- function _extends() {
74
- _extends = Object.assign ? Object.assign.bind() : function (target) {
75
- for (var i = 1; i < arguments.length; i++) {
76
- var source = arguments[i];
77
-
78
- for (var key in source) {
79
- if (Object.prototype.hasOwnProperty.call(source, key)) {
80
- target[key] = source[key];
81
- }
82
- }
83
- }
84
-
85
- return target;
86
- };
87
- return _extends.apply(this, arguments);
88
- }
89
-
90
73
  /**
91
74
  * Actions represent the type of change to a location value.
92
75
  *
@@ -230,7 +213,7 @@ function createBrowserHistory(options) {
230
213
 
231
214
  if (index == null) {
232
215
  index = 0;
233
- globalHistory.replaceState(_extends({}, globalHistory.state, {
216
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
234
217
  idx: index
235
218
  }), '');
236
219
  }
@@ -245,7 +228,7 @@ function createBrowserHistory(options) {
245
228
  state = null;
246
229
  }
247
230
 
248
- return readOnly(_extends({
231
+ return readOnly(_extends$1({
249
232
  pathname: location.pathname,
250
233
  hash: '',
251
234
  search: ''
@@ -479,7 +462,7 @@ function createHashHistory(options) {
479
462
 
480
463
  if (index == null) {
481
464
  index = 0;
482
- globalHistory.replaceState(_extends({}, globalHistory.state, {
465
+ globalHistory.replaceState(_extends$1({}, globalHistory.state, {
483
466
  idx: index
484
467
  }), '');
485
468
  }
@@ -506,7 +489,7 @@ function createHashHistory(options) {
506
489
  state = null;
507
490
  }
508
491
 
509
- return readOnly(_extends({
492
+ return readOnly(_extends$1({
510
493
  pathname: location.pathname,
511
494
  hash: '',
512
495
  search: ''
@@ -658,7 +641,7 @@ function createMemoryHistory(options) {
658
641
  initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
659
642
  initialIndex = _options3.initialIndex;
660
643
  var entries = initialEntries.map(function (entry) {
661
- var location = readOnly(_extends({
644
+ var location = readOnly(_extends$1({
662
645
  pathname: '/',
663
646
  search: '',
664
647
  hash: '',
@@ -683,7 +666,7 @@ function createMemoryHistory(options) {
683
666
  state = null;
684
667
  }
685
668
 
686
- return readOnly(_extends({
669
+ return readOnly(_extends$1({
687
670
  pathname: location.pathname,
688
671
  search: '',
689
672
  hash: ''
@@ -880,1464 +863,1600 @@ function parsePath(path) {
880
863
  return parsedPath;
881
864
  }
882
865
 
883
- // @ts-nocheck
884
- // We're inlining qss here for compression's sake, but we've included it as a hard dependency for the MIT license it requires.
885
- function encode(obj, pfx) {
886
- var k,
887
- i,
888
- tmp,
889
- str = '';
890
-
891
- for (k in obj) {
892
- if ((tmp = obj[k]) !== void 0) {
893
- if (Array.isArray(tmp)) {
894
- for (i = 0; i < tmp.length; i++) {
895
- str && (str += '&');
896
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
897
- }
898
- } else {
899
- str && (str += '&');
900
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
901
- }
866
+ var isProduction = process.env.NODE_ENV === 'production';
867
+ var prefix = 'Invariant failed';
868
+ function invariant(condition, message) {
869
+ if (condition) {
870
+ return;
902
871
  }
903
- }
904
-
905
- return (pfx || '') + str;
906
- }
907
-
908
- function toValue(mix) {
909
- if (!mix) return '';
910
- var str = decodeURIComponent(mix);
911
- if (str === 'false') return false;
912
- if (str === 'true') return true;
913
- return +str * 0 === 0 ? +str : str;
914
- }
915
-
916
- function decode(str) {
917
- var tmp,
918
- k,
919
- out = {},
920
- arr = str.split('&');
921
-
922
- while (tmp = arr.shift()) {
923
- tmp = tmp.split('=');
924
- k = tmp.shift();
925
-
926
- if (out[k] !== void 0) {
927
- out[k] = [].concat(out[k], toValue(tmp.shift()));
928
- } else {
929
- out[k] = toValue(tmp.shift());
872
+ if (isProduction) {
873
+ throw new Error(prefix);
930
874
  }
931
- }
932
-
933
- return out;
875
+ var provided = typeof message === 'function' ? message() : message;
876
+ var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
877
+ throw new Error(value);
934
878
  }
935
879
 
936
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId) {
937
- if (options === void 0) {
938
- options = {};
939
- }
940
-
941
- if (isRoot === void 0) {
942
- isRoot = true;
943
- }
944
-
945
- if (isRoot) {
946
- options.path = rootRouteId;
947
- } else {
948
- warning(!options.path, 'Routes must have a path property.');
949
- } // Strip the root from parentIds
950
-
880
+ // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
881
+ // k: infer I,
882
+ // ) => any
883
+ // ? I
884
+ // : never
951
885
 
952
- if (parentId === rootRouteId) {
953
- parentId = '';
886
+ /**
887
+ * This function returns `a` if `b` is deeply equal.
888
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
889
+ * This can be used for structural sharing between JSON values for example.
890
+ */
891
+ function replaceEqualDeep(prev, next) {
892
+ if (prev === next) {
893
+ return prev;
954
894
  }
955
895
 
956
- let path = String(isRoot ? rootRouteId : options.path); // If the path is anything other than an index path, trim it up
896
+ const array = Array.isArray(prev) && Array.isArray(next);
957
897
 
958
- if (path !== '/') {
959
- path = trimPath(path);
960
- }
898
+ if (array || isPlainObject(prev) && isPlainObject(next)) {
899
+ const aSize = array ? prev.length : Object.keys(prev).length;
900
+ const bItems = array ? next : Object.keys(next);
901
+ const bSize = bItems.length;
902
+ const copy = array ? [] : {};
903
+ let equalItems = 0;
961
904
 
962
- let id = joinPaths([parentId, path]);
905
+ for (let i = 0; i < bSize; i++) {
906
+ const key = array ? i : bItems[i];
907
+ copy[key] = replaceEqualDeep(prev[key], next[key]);
963
908
 
964
- if (path === rootRouteId) {
965
- path = '/';
966
- }
909
+ if (copy[key] === prev[key]) {
910
+ equalItems++;
911
+ }
912
+ }
967
913
 
968
- if (id !== rootRouteId) {
969
- id = joinPaths(['/', id]);
914
+ return aSize === bSize && equalItems === aSize ? prev : copy;
970
915
  }
971
916
 
972
- const fullPath = id === rootRouteId ? '/' : trimPathRight(id);
973
- return {
974
- id: id,
975
- path: path,
976
- fullPath: fullPath,
977
- options: options,
978
- children,
979
- addChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id)), false, parentId)
980
- };
981
- };
982
- const rootRouteId = '__root__';
983
- // Source
984
- // Detect if we're in the DOM
985
- const isDOM$1 = Boolean(typeof window !== 'undefined' && window.document && window.document.createElement); // This is the default history object if none is defined
986
-
987
- const createDefaultHistory = () => isDOM$1 ? createBrowserHistory() : createMemoryHistory();
988
-
989
- function createRouter(userOptions) {
990
- var _userOptions$stringif, _userOptions$parseSea;
991
-
992
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
993
-
994
- const originalOptions = _extends$1({}, userOptions, {
995
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
996
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
997
- });
998
-
999
- let router = {
1000
- options: originalOptions,
1001
- listeners: [],
1002
- // Resolved after construction
1003
- basepath: '',
1004
- routeTree: undefined,
1005
- routesById: {},
1006
- location: undefined,
1007
- allRouteInfo: undefined,
1008
- //
1009
- navigationPromise: Promise.resolve(),
1010
- resolveNavigation: () => {},
1011
- preloadCache: {},
1012
- state: {
1013
- status: 'idle',
1014
- location: null,
1015
- matches: [],
1016
- actions: {},
1017
- loaderData: {},
1018
- lastUpdated: Date.now()
1019
- },
1020
- startedLoadingAt: Date.now(),
1021
- subscribe: listener => {
1022
- router.listeners.push(listener);
1023
- return () => {
1024
- router.listeners = router.listeners.filter(x => x !== listener);
1025
- };
1026
- },
1027
- getRoute: id => {
1028
- return router.routesById[id];
1029
- },
1030
- notify: () => {
1031
- router.state = _extends$1({}, router.state);
1032
- router.listeners.forEach(listener => listener());
1033
- },
1034
- mount: () => {
1035
- const next = router.buildLocation({
1036
- to: '.',
1037
- search: true,
1038
- hash: true
1039
- }); // If the current location isn't updated, trigger a navigation
1040
- // to the current location. Otherwise, load the current location.
1041
-
1042
- if (next.href !== router.location.href) {
1043
- return router.commitLocation(next, true);
1044
- } else {
1045
- return router.loadLocation();
1046
- }
1047
- },
1048
- update: opts => {
1049
- Object.assign(router.options, opts);
1050
- const {
1051
- basepath,
1052
- routeConfig
1053
- } = router.options;
1054
- router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1055
-
1056
- if (routeConfig) {
1057
- router.routesById = {};
1058
- router.routeTree = router.buildRouteTree(routeConfig);
1059
- }
917
+ return next;
918
+ } // Copied from: https://github.com/jonschlinkert/is-plain-object
1060
919
 
1061
- return router;
1062
- },
1063
- destroy: history.listen(event => {
1064
- router.loadLocation(router.parseLocation(event.location, router.location));
1065
- }),
1066
- buildRouteTree: rootRouteConfig => {
1067
- const recurseRoutes = (routeConfigs, parent) => {
1068
- return routeConfigs.map(routeConfig => {
1069
- const routeOptions = routeConfig.options;
1070
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1071
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1072
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1073
- // }
1074
-
1075
- const existingRoute = router.routesById[route.routeId];
1076
-
1077
- if (existingRoute) {
1078
- if (process.env.NODE_ENV !== 'production') {
1079
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1080
- }
920
+ function isPlainObject(o) {
921
+ if (!hasObjectPrototype(o)) {
922
+ return false;
923
+ } // If has modified constructor
1081
924
 
1082
- throw new Error();
1083
- }
1084
- router.routesById[route.routeId] = route;
1085
- const children = routeConfig.children;
1086
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1087
- return route;
1088
- });
1089
- };
1090
925
 
1091
- const routes = recurseRoutes([rootRouteConfig]);
1092
- return routes[0];
1093
- },
1094
- parseLocation: (location, previousLocation) => {
1095
- var _location$hash$split$;
926
+ const ctor = o.constructor;
1096
927
 
1097
- const parsedSearch = router.options.parseSearch(location.search);
1098
- return {
1099
- pathname: location.pathname,
1100
- searchStr: location.search,
1101
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1102
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1103
- href: "" + location.pathname + location.search + location.hash,
1104
- state: location.state,
1105
- key: location.key
1106
- };
1107
- },
1108
- buildLocation: function buildLocation(dest) {
1109
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
928
+ if (typeof ctor === 'undefined') {
929
+ return true;
930
+ } // If has modified prototype
1110
931
 
1111
- if (dest === void 0) {
1112
- dest = {};
1113
- }
1114
932
 
1115
- // const resolvedFrom: Location = {
1116
- // ...router.location,
1117
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
933
+ const prot = ctor.prototype;
1118
934
 
1119
- let pathname = _resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
935
+ if (!hasObjectPrototype(prot)) {
936
+ return false;
937
+ } // If constructor does not have an Object-specific method
1120
938
 
1121
- const fromMatches = router.matchRoutes(router.location.pathname, {
1122
- strictParseParams: true
1123
- });
1124
- const toMatches = router.matchRoutes(pathname);
1125
- const prevParams = (_last = last(fromMatches)) == null ? void 0 : _last.params;
1126
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1127
939
 
1128
- if (nextParams) {
1129
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1130
- Object.assign(nextParams, fn(nextParams));
1131
- });
1132
- }
940
+ if (!prot.hasOwnProperty('isPrototypeOf')) {
941
+ return false;
942
+ } // Most likely a plain Object
1133
943
 
1134
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1135
944
 
1136
- 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
945
+ return true;
946
+ }
1137
947
 
1138
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1139
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1140
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1141
- : {}; // Then post filters
948
+ function hasObjectPrototype(o) {
949
+ return Object.prototype.toString.call(o) === '[object Object]';
950
+ }
1142
951
 
1143
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1144
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1145
- const searchStr = router.options.stringifySearch(search);
1146
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1147
- hash = hash ? "#" + hash : '';
1148
- return {
1149
- pathname,
1150
- search,
1151
- searchStr,
1152
- state: router.location.state,
1153
- hash,
1154
- href: "" + pathname + searchStr + hash,
1155
- key: dest.key
1156
- };
1157
- },
1158
- commitLocation: (next, replace) => {
1159
- const id = '' + Date.now() + Math.random();
1160
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1161
- let nextAction = 'replace';
952
+ function last(arr) {
953
+ return arr[arr.length - 1];
954
+ }
955
+ function warning(cond, message) {
956
+ if (cond) {
957
+ if (typeof console !== 'undefined') console.warn(message);
1162
958
 
1163
- if (!replace) {
1164
- nextAction = 'push';
1165
- }
959
+ try {
960
+ throw new Error(message);
961
+ } catch (_unused) {}
962
+ }
1166
963
 
1167
- const isSameUrl = router.parseLocation(history.location).href === next.href;
964
+ return true;
965
+ }
1168
966
 
1169
- if (isSameUrl && !next.key) {
1170
- nextAction = 'replace';
1171
- }
967
+ function isFunction(d) {
968
+ return typeof d === 'function';
969
+ }
1172
970
 
1173
- if (nextAction === 'replace') {
1174
- history.replace({
1175
- pathname: next.pathname,
1176
- hash: next.hash,
1177
- search: next.searchStr
1178
- }, {
1179
- id
1180
- });
1181
- } else {
1182
- history.push({
1183
- pathname: next.pathname,
1184
- hash: next.hash,
1185
- search: next.searchStr
1186
- }, {
1187
- id
1188
- });
1189
- }
971
+ function functionalUpdate(updater, previous) {
972
+ if (isFunction(updater)) {
973
+ return updater(previous);
974
+ }
1190
975
 
1191
- router.navigationPromise = new Promise(resolve => {
1192
- const previousNavigationResolve = router.resolveNavigation;
976
+ return updater;
977
+ }
1193
978
 
1194
- router.resolveNavigation = () => {
1195
- previousNavigationResolve();
1196
- resolve();
1197
- };
1198
- });
1199
- return router.navigationPromise;
1200
- },
1201
- buildNext: opts => {
1202
- const next = router.buildLocation(opts);
1203
- const matches = router.matchRoutes(next.pathname);
979
+ function joinPaths(paths) {
980
+ return cleanPath(paths.filter(Boolean).join('/'));
981
+ }
982
+ function cleanPath(path) {
983
+ // remove double slashes
984
+ return path.replace(/\/{2,}/g, '/');
985
+ }
986
+ function trimPathLeft(path) {
987
+ return path === '/' ? path : path.replace(/^\/{1,}/, '');
988
+ }
989
+ function trimPathRight(path) {
990
+ return path === '/' ? path : path.replace(/\/{1,}$/, '');
991
+ }
992
+ function trimPath(path) {
993
+ return trimPathRight(trimPathLeft(path));
994
+ }
995
+ function resolvePath(basepath, base, to) {
996
+ base = base.replace(new RegExp("^" + basepath), '/');
997
+ to = to.replace(new RegExp("^" + basepath), '/');
998
+ let baseSegments = parsePathname(base);
999
+ const toSegments = parsePathname(to);
1000
+ toSegments.forEach((toSegment, index) => {
1001
+ if (toSegment.value === '/') {
1002
+ if (!index) {
1003
+ // Leading slash
1004
+ baseSegments = [toSegment];
1005
+ } else if (index === toSegments.length - 1) {
1006
+ // Trailing Slash
1007
+ baseSegments.push(toSegment);
1008
+ } else ;
1009
+ } else if (toSegment.value === '..') {
1010
+ var _last;
1204
1011
 
1205
- const __preSearchFilters = matches.map(match => {
1206
- var _match$options$preSea;
1012
+ // Extra trailing slash? pop it off
1013
+ if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
1014
+ baseSegments.pop();
1015
+ }
1207
1016
 
1208
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1209
- }).flat().filter(Boolean);
1017
+ baseSegments.pop();
1018
+ } else if (toSegment.value === '.') {
1019
+ return;
1020
+ } else {
1021
+ baseSegments.push(toSegment);
1022
+ }
1023
+ });
1024
+ const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
1025
+ return cleanPath(joined);
1026
+ }
1027
+ function parsePathname(pathname) {
1028
+ if (!pathname) {
1029
+ return [];
1030
+ }
1210
1031
 
1211
- const __postSearchFilters = matches.map(match => {
1212
- var _match$options$postSe;
1032
+ pathname = cleanPath(pathname);
1033
+ const segments = [];
1213
1034
 
1214
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1215
- }).flat().filter(Boolean);
1035
+ if (pathname.slice(0, 1) === '/') {
1036
+ pathname = pathname.substring(1);
1037
+ segments.push({
1038
+ type: 'pathname',
1039
+ value: '/'
1040
+ });
1041
+ }
1216
1042
 
1217
- return router.buildLocation(_extends$1({}, opts, {
1218
- __preSearchFilters,
1219
- __postSearchFilters
1220
- }));
1221
- },
1222
- cancelMatches: () => {
1223
- var _router$state$pending, _router$state$pending2;
1224
- [...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 => {
1225
- match.cancel();
1226
- });
1227
- },
1228
- loadLocation: async next => {
1229
- const id = Math.random();
1230
- router.startedLoadingAt = id;
1043
+ if (!pathname) {
1044
+ return segments;
1045
+ } // Remove empty segments and '.' segments
1231
1046
 
1232
- if (next) {
1233
- // Ingest the new location
1234
- router.location = next;
1235
- } // Cancel any pending matches
1236
1047
 
1048
+ const split = pathname.split('/').filter(Boolean);
1049
+ segments.push(...split.map(part => {
1050
+ if (part.startsWith('*')) {
1051
+ return {
1052
+ type: 'wildcard',
1053
+ value: part
1054
+ };
1055
+ }
1056
+
1057
+ if (part.charAt(0) === ':') {
1058
+ return {
1059
+ type: 'param',
1060
+ value: part
1061
+ };
1062
+ }
1237
1063
 
1238
- router.cancelMatches(); // Match the routes
1064
+ return {
1065
+ type: 'pathname',
1066
+ value: part
1067
+ };
1068
+ }));
1239
1069
 
1240
- const unloadedMatches = router.matchRoutes(location.pathname, {
1241
- strictParseParams: true
1242
- });
1243
- unloadedMatches.forEach((match, index) => {
1244
- const parent = unloadedMatches[index - 1];
1245
- const child = unloadedMatches[index + 1];
1246
- if (parent) match.__.setParentMatch(parent);
1247
- if (child) match.__.addChildMatch(child);
1248
- });
1249
- router.state = _extends$1({}, router.state, {
1250
- pending: {
1251
- matches: unloadedMatches,
1252
- location: router.location
1070
+ if (pathname.slice(-1) === '/') {
1071
+ pathname = pathname.substring(1);
1072
+ segments.push({
1073
+ type: 'pathname',
1074
+ value: '/'
1075
+ });
1076
+ }
1077
+
1078
+ return segments;
1079
+ }
1080
+ function interpolatePath(path, params, leaveWildcard) {
1081
+ const interpolatedPathSegments = parsePathname(path);
1082
+ return joinPaths(interpolatedPathSegments.map(segment => {
1083
+ if (segment.value === '*' && !leaveWildcard) {
1084
+ return '';
1085
+ }
1086
+
1087
+ if (segment.type === 'param') {
1088
+ var _segment$value$substr;
1089
+
1090
+ return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
1091
+ }
1092
+
1093
+ return segment.value;
1094
+ }));
1095
+ }
1096
+ function matchPathname(currentPathname, matchLocation) {
1097
+ const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1098
+
1099
+ if (matchLocation.to && !pathParams) {
1100
+ return;
1101
+ } // if (matchLocation.search && !searchMatched) {
1102
+ // return
1103
+ // }
1104
+
1105
+
1106
+ return pathParams != null ? pathParams : {};
1107
+ }
1108
+ function matchByPath(from, matchLocation) {
1109
+ var _matchLocation$to;
1110
+
1111
+ const baseSegments = parsePathname(from);
1112
+ const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
1113
+ const params = {};
1114
+
1115
+ let isMatch = (() => {
1116
+ for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
1117
+ const baseSegment = baseSegments[i];
1118
+ const routeSegment = routeSegments[i];
1119
+ const isLastRouteSegment = i === routeSegments.length - 1;
1120
+ const isLastBaseSegment = i === baseSegments.length - 1;
1121
+
1122
+ if (routeSegment) {
1123
+ if (routeSegment.type === 'wildcard') {
1124
+ if (baseSegment != null && baseSegment.value) {
1125
+ params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
1126
+ return true;
1127
+ }
1128
+
1129
+ return false;
1253
1130
  }
1254
- });
1255
- router.notify(); // Load the matches
1256
1131
 
1257
- const matches = await router.loadMatches(unloadedMatches, {
1258
- withPending: true
1259
- });
1132
+ if (routeSegment.type === 'pathname') {
1133
+ if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
1134
+ return true;
1135
+ }
1260
1136
 
1261
- if (router.startedLoadingAt !== id) {
1262
- // Ignore side-effects of match loading
1263
- return router.navigationPromise;
1137
+ if (baseSegment) {
1138
+ if (matchLocation.caseSensitive) {
1139
+ if (routeSegment.value !== baseSegment.value) {
1140
+ return false;
1141
+ }
1142
+ } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
1143
+ return false;
1144
+ }
1145
+ }
1146
+ }
1147
+
1148
+ if (!baseSegment) {
1149
+ return false;
1150
+ }
1151
+
1152
+ if (routeSegment.type === 'param') {
1153
+ if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
1154
+ return false;
1155
+ }
1156
+
1157
+ if (!baseSegment.value.startsWith(':')) {
1158
+ params[routeSegment.value.substring(1)] = baseSegment.value;
1159
+ }
1160
+ }
1264
1161
  }
1265
1162
 
1266
- const previousMatches = router.state.matches;
1267
- previousMatches.filter(d => {
1268
- return !matches.find(dd => dd.matchId === d.matchId);
1269
- }).forEach(d => {
1270
- d.__.onExit == null ? void 0 : d.__.onExit({
1271
- params: d.params,
1272
- search: d.routeSearch
1273
- });
1274
- });
1275
- previousMatches.filter(d => {
1276
- return matches.find(dd => dd.matchId === d.matchId);
1277
- }).forEach(d => {
1278
- d.options.onTransition == null ? void 0 : d.options.onTransition({
1279
- params: d.params,
1280
- search: d.routeSearch
1281
- });
1282
- });
1283
- matches.filter(d => {
1284
- return !previousMatches.find(dd => dd.matchId === d.matchId);
1285
- }).forEach(d => {
1286
- d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1287
- params: d.params,
1288
- search: d.search
1289
- });
1290
- });
1291
- router.state = _extends$1({}, router.state, {
1292
- location: router.location,
1293
- matches,
1294
- pending: undefined
1295
- });
1163
+ if (isLastRouteSegment && !isLastBaseSegment) {
1164
+ return !!matchLocation.fuzzy;
1165
+ }
1166
+ }
1296
1167
 
1297
- if (matches.some(d => d.status === 'loading')) {
1298
- router.notify();
1299
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1168
+ return true;
1169
+ })();
1170
+
1171
+ return isMatch ? params : undefined;
1172
+ }
1173
+
1174
+ // @ts-nocheck
1175
+ // 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.
1176
+ function encode(obj, pfx) {
1177
+ var k,
1178
+ i,
1179
+ tmp,
1180
+ str = '';
1181
+
1182
+ for (k in obj) {
1183
+ if ((tmp = obj[k]) !== void 0) {
1184
+ if (Array.isArray(tmp)) {
1185
+ for (i = 0; i < tmp.length; i++) {
1186
+ str && (str += '&');
1187
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1188
+ }
1189
+ } else {
1190
+ str && (str += '&');
1191
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1300
1192
  }
1193
+ }
1194
+ }
1301
1195
 
1302
- if (router.startedLoadingAt !== id) {
1303
- // Ignore side-effects of match loading
1304
- return;
1196
+ return (pfx || '') + str;
1197
+ }
1198
+
1199
+ function toValue(mix) {
1200
+ if (!mix) return '';
1201
+ var str = decodeURIComponent(mix);
1202
+ if (str === 'false') return false;
1203
+ if (str === 'true') return true;
1204
+ return +str * 0 === 0 ? +str : str;
1205
+ }
1206
+
1207
+ function decode(str) {
1208
+ var tmp,
1209
+ k,
1210
+ out = {},
1211
+ arr = str.split('&');
1212
+
1213
+ while (tmp = arr.shift()) {
1214
+ tmp = tmp.split('=');
1215
+ k = tmp.shift();
1216
+
1217
+ if (out[k] !== void 0) {
1218
+ out[k] = [].concat(out[k], toValue(tmp.shift()));
1219
+ } else {
1220
+ out[k] = toValue(tmp.shift());
1221
+ }
1222
+ }
1223
+
1224
+ return out;
1225
+ }
1226
+
1227
+ function _extends() {
1228
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
1229
+ for (var i = 1; i < arguments.length; i++) {
1230
+ var source = arguments[i];
1231
+
1232
+ for (var key in source) {
1233
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1234
+ target[key] = source[key];
1235
+ }
1305
1236
  }
1237
+ }
1306
1238
 
1307
- router.notify();
1308
- router.resolveNavigation();
1309
- },
1310
- cleanPreloadCache: () => {
1311
- const now = Date.now();
1312
- Object.keys(router.preloadCache).forEach(matchId => {
1313
- const entry = router.preloadCache[matchId]; // Don't remove loading matches
1239
+ return target;
1240
+ };
1241
+ return _extends.apply(this, arguments);
1242
+ }
1314
1243
 
1315
- if (entry.match.status === 'loading') {
1316
- return;
1317
- } // Do not remove successful matches that are still valid
1244
+ function createRoute(routeConfig, options, parent, router) {
1245
+ const {
1246
+ id,
1247
+ routeId,
1248
+ path: routePath,
1249
+ fullPath
1250
+ } = routeConfig;
1318
1251
 
1252
+ const action = router.state.actions[id] || (() => {
1253
+ router.state.actions[id] = {
1254
+ pending: [],
1255
+ submit: async (submission, actionOpts) => {
1256
+ var _actionOpts$invalidat;
1319
1257
 
1320
- if (entry.match.updatedAt && entry.match.updatedAt + entry.maxAge > now) {
1258
+ if (!route) {
1321
1259
  return;
1322
- } // Everything else gets removed
1260
+ }
1323
1261
 
1262
+ const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1263
+ const actionState = {
1264
+ submittedAt: Date.now(),
1265
+ status: 'pending',
1266
+ submission
1267
+ };
1268
+ action.current = actionState;
1269
+ action.latest = actionState;
1270
+ action.pending.push(actionState);
1271
+ router.state = _extends({}, router.state, {
1272
+ currentAction: actionState,
1273
+ latestAction: actionState
1274
+ });
1275
+ router.notify();
1324
1276
 
1325
- delete router.preloadCache[matchId];
1326
- });
1327
- },
1328
- loadRoute: async function loadRoute(navigateOpts, loaderOpts) {
1329
- if (navigateOpts === void 0) {
1330
- navigateOpts = router.location;
1277
+ try {
1278
+ const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1279
+ actionState.data = res;
1280
+
1281
+ if (invalidate) {
1282
+ router.invalidateRoute({
1283
+ to: '.',
1284
+ fromCurrent: true
1285
+ });
1286
+ await router.reload();
1287
+ }
1288
+
1289
+ actionState.status = 'success';
1290
+ return res;
1291
+ } catch (err) {
1292
+ console.error(err);
1293
+ actionState.error = err;
1294
+ actionState.status = 'error';
1295
+ } finally {
1296
+ action.pending = action.pending.filter(d => d !== actionState);
1297
+ router.removeActionQueue.push({
1298
+ action,
1299
+ actionState
1300
+ });
1301
+ router.notify();
1302
+ }
1331
1303
  }
1304
+ };
1305
+ return router.state.actions[id];
1306
+ })();
1332
1307
 
1333
- const next = router.buildNext(navigateOpts);
1334
- const matches = router.matchRoutes(next.pathname, {
1335
- strictParseParams: true
1336
- });
1337
- await router.loadMatches(matches, {
1338
- preload: true,
1339
- maxAge: loaderOpts.maxAge
1340
- });
1341
- return matches;
1308
+ let route = {
1309
+ routeId: id,
1310
+ routeRouteId: routeId,
1311
+ routePath,
1312
+ fullPath,
1313
+ options,
1314
+ router,
1315
+ childRoutes: undefined,
1316
+ parentRoute: parent,
1317
+ action,
1318
+ buildLink: options => {
1319
+ return router.buildLink(_extends({}, options, {
1320
+ from: fullPath
1321
+ }));
1342
1322
  },
1343
- matchRoutes: (pathname, opts) => {
1344
- var _router$state$pending3, _router$state$pending4;
1323
+ navigate: options => {
1324
+ return router.navigate(_extends({}, options, {
1325
+ from: fullPath
1326
+ }));
1327
+ },
1328
+ matchRoute: (matchLocation, opts) => {
1329
+ return router.matchRoute(_extends({}, matchLocation, {
1330
+ from: fullPath
1331
+ }), opts);
1332
+ }
1333
+ };
1334
+ router.options.createRoute == null ? void 0 : router.options.createRoute({
1335
+ router,
1336
+ route
1337
+ });
1338
+ return route;
1339
+ }
1340
+ function cascadeLoaderData(matches) {
1341
+ matches.forEach((match, index) => {
1342
+ const parent = matches[index - 1];
1345
1343
 
1346
- router.cleanPreloadCache();
1347
- const matches = [];
1344
+ if (parent) {
1345
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1346
+ }
1347
+ });
1348
+ }
1349
+
1350
+ const rootRouteId = '__root__';
1351
+ const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1352
+ if (options === void 0) {
1353
+ options = {};
1354
+ }
1355
+
1356
+ if (isRoot === void 0) {
1357
+ isRoot = true;
1358
+ }
1359
+
1360
+ if (isRoot) {
1361
+ options.path = rootRouteId;
1362
+ } // Strip the root from parentIds
1363
+
1364
+
1365
+ if (parentId === rootRouteId) {
1366
+ parentId = '';
1367
+ }
1368
+
1369
+ let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1370
+
1371
+ if (path && path !== '/') {
1372
+ path = trimPath(path);
1373
+ }
1374
+
1375
+ const routeId = path || options.id;
1376
+ let id = joinPaths([parentId, routeId]);
1377
+
1378
+ if (path === rootRouteId) {
1379
+ path = '/';
1380
+ }
1381
+
1382
+ if (id !== rootRouteId) {
1383
+ id = joinPaths(['/', id]);
1384
+ }
1385
+
1386
+ const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1387
+ return {
1388
+ id: id,
1389
+ routeId: routeId,
1390
+ path: path,
1391
+ fullPath: fullPath,
1392
+ options: options,
1393
+ children,
1394
+ createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1395
+ addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1396
+ createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1397
+ };
1398
+ };
1399
+
1400
+ const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1401
+ function createRouteMatch(router, route, opts) {
1402
+ const routeMatch = _extends({}, route, opts, {
1403
+ router,
1404
+ routeSearch: {},
1405
+ search: {},
1406
+ childMatches: [],
1407
+ status: 'idle',
1408
+ routeLoaderData: {},
1409
+ loaderData: {},
1410
+ isPending: false,
1411
+ isFetching: false,
1412
+ isInvalid: false,
1413
+ invalidAt: Infinity,
1414
+ getIsInvalid: () => {
1415
+ const now = Date.now();
1416
+ return routeMatch.isInvalid || routeMatch.invalidAt < now;
1417
+ },
1418
+ __: {
1419
+ abortController: new AbortController(),
1420
+ latestId: '',
1421
+ resolve: () => {},
1422
+ notify: () => {
1423
+ routeMatch.__.resolve();
1424
+
1425
+ routeMatch.router.notify();
1426
+ },
1427
+ startPending: () => {
1428
+ var _routeMatch$options$p, _routeMatch$options$p2;
1348
1429
 
1349
- if (!router.routeTree) {
1350
- return matches;
1351
- }
1430
+ const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1431
+ const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1352
1432
 
1353
- 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 : [])];
1433
+ if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1434
+ return;
1435
+ }
1354
1436
 
1355
- const recurse = async (routes, parentMatch) => {
1356
- var _parentMatch$params, _router$options$filte, _router$preloadCache$, _route$childRoutes2;
1437
+ routeMatch.__.pendingTimeout = setTimeout(() => {
1438
+ routeMatch.isPending = true;
1357
1439
 
1358
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1359
- const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
1360
- const route = filteredRoutes == null ? void 0 : filteredRoutes.find(route => {
1361
- var _route$childRoutes, _route$options$caseSe;
1362
-
1363
- const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length);
1364
- const matchParams = matchPathname(pathname, {
1365
- to: route.fullPath,
1366
- fuzzy,
1367
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
1368
- });
1440
+ routeMatch.__.resolve();
1369
1441
 
1370
- if (matchParams) {
1371
- let parsedParams;
1442
+ if (typeof pendingMinMs !== 'undefined') {
1443
+ routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1444
+ }
1445
+ }, pendingMs);
1446
+ },
1447
+ cancelPending: () => {
1448
+ routeMatch.isPending = false;
1449
+ clearTimeout(routeMatch.__.pendingTimeout);
1450
+ clearTimeout(routeMatch.__.pendingMinTimeout);
1451
+ delete routeMatch.__.pendingMinPromise;
1452
+ },
1453
+ // setParentMatch: (parentMatch?: RouteMatch) => {
1454
+ // routeMatch.parentMatch = parentMatch
1455
+ // },
1456
+ // addChildMatch: (childMatch: RouteMatch) => {
1457
+ // if (
1458
+ // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1459
+ // ) {
1460
+ // return
1461
+ // }
1462
+ // routeMatch.childMatches.push(childMatch)
1463
+ // },
1464
+ validate: () => {
1465
+ var _routeMatch$parentMat, _routeMatch$parentMat2;
1372
1466
 
1373
- try {
1374
- var _route$options$parseP;
1467
+ // Validate the search params and stabilize them
1468
+ const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1375
1469
 
1376
- parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
1377
- } catch (err) {
1378
- if (opts != null && opts.strictParseParams) {
1379
- throw err;
1380
- }
1381
- }
1470
+ try {
1471
+ const prevSearch = routeMatch.routeSearch;
1472
+ const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1473
+ let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1382
1474
 
1383
- params = _extends$1({}, params, parsedParams);
1475
+ if (prevSearch !== nextSearch) {
1476
+ routeMatch.isInvalid = true;
1384
1477
  }
1385
1478
 
1386
- return !!matchParams;
1387
- });
1479
+ routeMatch.routeSearch = nextSearch;
1480
+ routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1481
+ } catch (err) {
1482
+ console.error(err);
1483
+ const error = new Error('Invalid search params found', {
1484
+ cause: err
1485
+ });
1486
+ error.code = 'INVALID_SEARCH_PARAMS';
1487
+ routeMatch.status = 'error';
1488
+ routeMatch.error = error; // Do not proceed with loading the route
1388
1489
 
1389
- if (!route) {
1390
1490
  return;
1391
1491
  }
1392
-
1393
- const interpolatedPath = interpolatePath(route.routePath, params);
1394
- const matchId = interpolatePath(route.routeId, params, true);
1395
- const match = existingMatches.find(d => d.matchId === matchId) || ((_router$preloadCache$ = router.preloadCache[matchId]) == null ? void 0 : _router$preloadCache$.match) || createRouteMatch(router, route, {
1396
- matchId,
1397
- params,
1398
- pathname: joinPaths([pathname, interpolatedPath])
1399
- });
1400
- matches.push(match);
1401
-
1402
- if ((_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length) {
1403
- recurse(route.childRoutes, match);
1404
- }
1405
- };
1406
-
1407
- recurse([router.routeTree]);
1408
- return matches;
1492
+ }
1409
1493
  },
1410
- loadMatches: async (resolvedMatches, loaderOpts) => {
1411
- const matchPromises = resolvedMatches.map(async match => {
1412
- // Validate the match (loads search params etc)
1413
- match.__.validate(); // If this is a preload, add it to the preload cache
1414
-
1415
-
1416
- if (loaderOpts != null && loaderOpts.preload) {
1417
- router.preloadCache[match.matchId] = {
1418
- maxAge: loaderOpts == null ? void 0 : loaderOpts.maxAge,
1419
- match
1420
- };
1421
- } // If the match is invalid, errored or idle, trigger it to load
1494
+ cancel: () => {
1495
+ var _routeMatch$__$abortC;
1422
1496
 
1497
+ (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1423
1498
 
1424
- if (match.status === 'success' && match.isInvalid || match.status === 'error' || match.status === 'idle') {
1425
- match.load();
1426
- } // If requested, start the pending timers
1499
+ routeMatch.__.cancelPending();
1500
+ },
1501
+ invalidate: () => {
1502
+ routeMatch.isInvalid = true;
1503
+ },
1504
+ hasLoaders: () => {
1505
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1506
+ },
1507
+ load: async opts => {
1508
+ const id = '' + Date.now() + Math.random();
1509
+ routeMatch.__.latestId = id; // If the match was in an error state, set it
1510
+ // to a loading state again. Otherwise, keep it
1511
+ // as loading or resolved
1427
1512
 
1513
+ if (routeMatch.status === 'idle') {
1514
+ routeMatch.status = 'loading';
1515
+ } // We started loading the route, so it's no longer invalid
1428
1516
 
1429
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
1430
- // This might be completion, error, or a pending state
1431
1517
 
1432
- await match.__.loadPromise;
1433
- });
1434
- router.notify();
1435
- await Promise.all(matchPromises);
1436
- return resolvedMatches;
1437
- },
1438
- invalidateRoute: opts => {
1439
- var _router$state$pending5, _router$state$pending6;
1518
+ routeMatch.isInvalid = false;
1519
+ routeMatch.__.loadPromise = new Promise(async resolve => {
1520
+ // We are now fetching, even if it's in the background of a
1521
+ // resolved state
1522
+ routeMatch.isFetching = true;
1523
+ routeMatch.__.resolve = resolve;
1440
1524
 
1441
- const next = router.buildNext(opts);
1442
- const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
1443
- [...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 => {
1444
- if (unloadedMatchIds.includes(match.matchId)) {
1445
- match.isInvalid = true;
1446
- }
1447
- });
1448
- },
1449
- reload: () => router._navigate({
1450
- fromCurrent: true,
1451
- replace: true,
1452
- search: true
1453
- }),
1454
- resolvePath: (from, path) => {
1455
- return _resolvePath(router.basepath, from, cleanPath(path));
1456
- },
1457
- matchRoute: (location, opts) => {
1458
- var _location$from;
1525
+ const loaderPromise = (async () => {
1526
+ // Load the elements and data in parallel
1527
+ routeMatch.__.elementsPromise = (async () => {
1528
+ // then run all element and data loaders in parallel
1529
+ // For each element type, potentially load it asynchronously
1530
+ await Promise.all(elementTypes.map(async type => {
1531
+ const routeElement = routeMatch.options[type];
1459
1532
 
1460
- // const location = router.buildNext(opts)
1461
- location = _extends$1({}, location, {
1462
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
1463
- });
1464
- const next = router.buildNext(location);
1533
+ if (routeMatch.__[type]) {
1534
+ return;
1535
+ }
1465
1536
 
1466
- if (opts != null && opts.pending) {
1467
- var _router$state$pending7;
1537
+ if (typeof routeElement === 'function') {
1538
+ const res = await routeElement(routeMatch);
1539
+ routeMatch.__[type] = res;
1540
+ } else {
1541
+ routeMatch.__[type] = routeMatch.options[type];
1542
+ }
1543
+ }));
1544
+ })();
1468
1545
 
1469
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
1470
- return false;
1471
- }
1546
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1547
+ try {
1548
+ var _ref, _ref2, _opts$maxAge;
1472
1549
 
1473
- return !!matchPathname(router.state.pending.location.pathname, _extends$1({}, opts, {
1474
- to: next.pathname
1475
- }));
1476
- }
1550
+ if (routeMatch.options.loader) {
1551
+ const data = await routeMatch.options.loader({
1552
+ params: routeMatch.params,
1553
+ search: routeMatch.routeSearch,
1554
+ signal: routeMatch.__.abortController.signal
1555
+ });
1477
1556
 
1478
- return !!matchPathname(router.state.location.pathname, _extends$1({}, opts, {
1479
- to: next.pathname
1480
- }));
1481
- },
1482
- _navigate: location => {
1483
- const next = router.buildNext(location);
1484
- return router.commitLocation(next, location.replace);
1485
- },
1486
- navigate: async _ref => {
1487
- let {
1488
- from,
1489
- to = '.',
1490
- search,
1491
- hash,
1492
- replace
1493
- } = _ref;
1494
- // If this link simply reloads the current route,
1495
- // make sure it has a new key so it will trigger a data refresh
1496
- // If this `to` is a valid external URL, return
1497
- // null for LinkUtils
1498
- const toString = String(to);
1499
- const fromString = String(from);
1500
- let isExternal;
1557
+ if (id !== routeMatch.__.latestId) {
1558
+ return routeMatch.__.loaderPromise;
1559
+ }
1501
1560
 
1502
- try {
1503
- new URL("" + toString);
1504
- isExternal = true;
1505
- } catch (e) {}
1561
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1562
+ }
1506
1563
 
1507
- if (isExternal) {
1508
- if (process.env.NODE_ENV !== 'production') {
1509
- throw new Error('Attempting to navigate to external url with router.navigate!');
1510
- }
1564
+ routeMatch.error = undefined;
1565
+ routeMatch.status = 'success';
1566
+ routeMatch.updatedAt = Date.now();
1567
+ 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);
1568
+ } catch (err) {
1569
+ if (id !== routeMatch.__.latestId) {
1570
+ return routeMatch.__.loaderPromise;
1571
+ }
1511
1572
 
1512
- return;
1513
- }
1573
+ if (process.env.NODE_ENV !== 'production') {
1574
+ console.error(err);
1575
+ }
1514
1576
 
1515
- return router._navigate({
1516
- from: fromString,
1517
- to: toString,
1518
- search,
1519
- hash
1520
- });
1521
- },
1522
- buildLink: _ref2 => {
1523
- var _preload, _ref3, _ref4;
1577
+ routeMatch.error = err;
1578
+ routeMatch.status = 'error';
1579
+ routeMatch.updatedAt = Date.now();
1580
+ }
1581
+ });
1524
1582
 
1525
- let {
1526
- from,
1527
- to = '.',
1528
- search,
1529
- params,
1530
- hash,
1531
- target,
1532
- replace,
1533
- activeOptions,
1534
- preload,
1535
- preloadMaxAge: userPreloadMaxAge,
1536
- preloadDelay: userPreloadDelay,
1537
- disabled
1538
- } = _ref2;
1583
+ try {
1584
+ await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1539
1585
 
1540
- // If this link simply reloads the current route,
1541
- // make sure it has a new key so it will trigger a data refresh
1542
- // If this `to` is a valid external URL, return
1543
- // null for LinkUtils
1544
- try {
1545
- new URL("" + to);
1546
- return {
1547
- type: 'external',
1548
- href: to
1549
- };
1550
- } catch (e) {}
1586
+ if (id !== routeMatch.__.latestId) {
1587
+ return routeMatch.__.loaderPromise;
1588
+ }
1551
1589
 
1552
- const nextOpts = {
1553
- from,
1554
- to,
1555
- search,
1556
- params,
1557
- hash,
1558
- replace
1559
- };
1560
- const next = router.buildNext(nextOpts);
1561
- preload = (_preload = preload) != null ? _preload : router.options.defaultLinkPreload;
1562
- const preloadMaxAge = (_ref3 = userPreloadMaxAge != null ? userPreloadMaxAge : router.options.defaultLinkPreloadMaxAge) != null ? _ref3 : 2000;
1563
- const preloadDelay = (_ref4 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultLinkPreloadDelay) != null ? _ref4 : 50; // Compare path/hash for matches
1590
+ if (routeMatch.__.pendingMinPromise) {
1591
+ await routeMatch.__.pendingMinPromise;
1592
+ delete routeMatch.__.pendingMinPromise;
1593
+ }
1594
+ } finally {
1595
+ if (id !== routeMatch.__.latestId) {
1596
+ return routeMatch.__.loaderPromise;
1597
+ }
1564
1598
 
1565
- const pathIsEqual = router.state.location.pathname === next.pathname;
1566
- const currentPathSplit = router.state.location.pathname.split('/');
1567
- const nextPathSplit = next.pathname.split('/');
1568
- const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
1569
- const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
1599
+ routeMatch.__.cancelPending();
1570
1600
 
1571
- const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
1572
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
1601
+ routeMatch.isPending = false;
1602
+ routeMatch.isFetching = false;
1573
1603
 
1574
- const isActive = pathTest && hashTest; // The click handler
1604
+ routeMatch.__.notify();
1605
+ }
1606
+ })();
1575
1607
 
1576
- const handleClick = e => {
1577
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1578
- e.preventDefault();
1608
+ routeMatch.__.loaderPromise = loaderPromise;
1609
+ await loaderPromise;
1579
1610
 
1580
- if (pathIsEqual && !search && !hash) {
1581
- router.invalidateRoute(nextOpts);
1582
- } // All is well? Navigate!)
1611
+ if (id !== routeMatch.__.latestId) {
1612
+ return routeMatch.__.loaderPromise;
1613
+ }
1583
1614
 
1615
+ delete routeMatch.__.loaderPromise;
1616
+ });
1617
+ return await routeMatch.__.loadPromise;
1618
+ }
1619
+ });
1584
1620
 
1585
- router._navigate(nextOpts);
1586
- }
1587
- }; // The click handler
1621
+ if (!routeMatch.hasLoaders()) {
1622
+ routeMatch.status = 'success';
1623
+ }
1588
1624
 
1625
+ return routeMatch;
1626
+ }
1589
1627
 
1590
- const handleFocus = e => {
1591
- if (preload && preloadMaxAge > 0) {
1592
- router.loadRoute(nextOpts, {
1593
- maxAge: preloadMaxAge
1594
- });
1595
- }
1596
- };
1628
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1629
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify);
1630
+ function parseSearchWith(parser) {
1631
+ return searchStr => {
1632
+ if (searchStr.substring(0, 1) === '?') {
1633
+ searchStr = searchStr.substring(1);
1634
+ }
1597
1635
 
1598
- const handleEnter = e => {
1599
- const target = e.target || {};
1636
+ let query = decode(searchStr); // Try to parse any query params that might be json
1600
1637
 
1601
- if (preload && preloadMaxAge > 0) {
1602
- if (target.preloadTimeout) {
1603
- return;
1604
- }
1638
+ for (let key in query) {
1639
+ const value = query[key];
1605
1640
 
1606
- target.preloadTimeout = setTimeout(() => {
1607
- target.preloadTimeout = null;
1608
- router.loadRoute(nextOpts, {
1609
- maxAge: preloadMaxAge
1610
- });
1611
- }, preloadDelay);
1641
+ if (typeof value === 'string') {
1642
+ try {
1643
+ query[key] = parser(value);
1644
+ } catch (err) {//
1612
1645
  }
1613
- };
1646
+ }
1647
+ }
1614
1648
 
1615
- const handleLeave = e => {
1616
- const target = e.target || {};
1649
+ return query;
1650
+ };
1651
+ }
1652
+ function stringifySearchWith(stringify) {
1653
+ return search => {
1654
+ search = _extends({}, search);
1617
1655
 
1618
- if (target.preloadTimeout) {
1619
- clearTimeout(target.preloadTimeout);
1620
- target.preloadTimeout = null;
1621
- }
1622
- };
1656
+ if (search) {
1657
+ Object.keys(search).forEach(key => {
1658
+ const val = search[key];
1623
1659
 
1624
- return {
1625
- type: 'internal',
1626
- next,
1627
- handleFocus,
1628
- handleClick,
1629
- handleEnter,
1630
- handleLeave,
1631
- isActive,
1632
- disabled
1633
- };
1634
- },
1635
- __experimental__createSnapshot: () => {
1636
- return _extends$1({}, router.state, {
1637
- matches: router.state.matches.map(_ref5 => {
1638
- let {
1639
- routeLoaderData: loaderData,
1640
- matchId
1641
- } = _ref5;
1642
- return {
1643
- matchId,
1644
- loaderData
1645
- };
1646
- })
1660
+ if (typeof val === 'undefined' || val === undefined) {
1661
+ delete search[key];
1662
+ } else if (val && typeof val === 'object' && val !== null) {
1663
+ try {
1664
+ search[key] = stringify(val);
1665
+ } catch (err) {// silent
1666
+ }
1667
+ }
1647
1668
  });
1648
1669
  }
1670
+
1671
+ const searchStr = encode(search).toString();
1672
+ return searchStr ? "?" + searchStr : '';
1649
1673
  };
1650
- router.location = router.parseLocation(history.location); // router.state.location = __experimental__snapshot?.location ?? router.location
1674
+ }
1651
1675
 
1652
- router.state.location = router.location;
1653
- router.update(userOptions); // Allow frameworks to hook into the router creation
1676
+ var _window$document;
1677
+ // Detect if we're in the DOM
1678
+ const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1654
1679
 
1655
- router.options.createRouter == null ? void 0 : router.options.createRouter(router); // router.mount()
1680
+ const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1656
1681
 
1657
- return router;
1658
- }
1659
- function createRoute(routeConfig, options, parent, router) {
1660
- // const id = (
1661
- // options.path === rootRouteId
1662
- // ? rootRouteId
1663
- // : joinPaths([
1664
- // parent!.id,
1665
- // `${options.path?.replace(/(.)\/$/, '$1')}`,
1666
- // ]).replace(new RegExp(`^${rootRouteId}`), '')
1667
- // ) as TRouteInfo['id']
1668
- const {
1669
- id: routeId,
1670
- path: routePath,
1671
- fullPath
1672
- } = routeConfig;
1682
+ function createRouter(userOptions) {
1683
+ var _userOptions$stringif, _userOptions$parseSea;
1673
1684
 
1674
- const action = router.state.actions[routeId] || (() => {
1675
- router.state.actions[routeId] = {
1676
- pending: [],
1677
- submit: async (submission, actionOpts) => {
1678
- var _actionOpts$invalidat;
1685
+ const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1679
1686
 
1680
- if (!route) {
1681
- return;
1682
- }
1687
+ const originalOptions = _extends({
1688
+ defaultLoaderGcMaxAge: 5 * 60 * 1000,
1689
+ defaultLoaderMaxAge: 0,
1690
+ defaultPreloadMaxAge: 2000,
1691
+ defaultPreloadDelay: 50
1692
+ }, userOptions, {
1693
+ stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1694
+ parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1695
+ });
1683
1696
 
1684
- const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1685
- const actionState = {
1686
- submittedAt: Date.now(),
1687
- status: 'pending',
1688
- submission
1689
- };
1690
- action.latest = actionState;
1691
- action.pending.push(actionState);
1692
- router.state = _extends$1({}, router.state, {
1693
- action: actionState
1694
- });
1695
- router.notify();
1697
+ let router = {
1698
+ history,
1699
+ options: originalOptions,
1700
+ listeners: [],
1701
+ removeActionQueue: [],
1702
+ // Resolved after construction
1703
+ basepath: '',
1704
+ routeTree: undefined,
1705
+ routesById: {},
1706
+ location: undefined,
1707
+ allRouteInfo: undefined,
1708
+ //
1709
+ navigationPromise: Promise.resolve(),
1710
+ resolveNavigation: () => {},
1711
+ matchCache: {},
1712
+ state: {
1713
+ status: 'idle',
1714
+ location: null,
1715
+ matches: [],
1716
+ actions: {},
1717
+ loaderData: {},
1718
+ lastUpdated: Date.now(),
1719
+ isFetching: false,
1720
+ isPreloading: false
1721
+ },
1722
+ startedLoadingAt: Date.now(),
1723
+ subscribe: listener => {
1724
+ router.listeners.push(listener);
1725
+ return () => {
1726
+ router.listeners = router.listeners.filter(x => x !== listener);
1727
+ };
1728
+ },
1729
+ getRoute: id => {
1730
+ return router.routesById[id];
1731
+ },
1732
+ notify: () => {
1733
+ router.state = _extends({}, router.state, {
1734
+ isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1735
+ isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1736
+ });
1737
+ cascadeLoaderData(router.state.matches);
1738
+ router.listeners.forEach(listener => listener());
1739
+ },
1740
+ mount: () => {
1741
+ const next = router.__.buildLocation({
1742
+ to: '.',
1743
+ search: true,
1744
+ hash: true
1745
+ }); // If the current location isn't updated, trigger a navigation
1746
+ // to the current location. Otherwise, load the current location.
1696
1747
 
1697
- try {
1698
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1699
- actionState.data = res;
1700
1748
 
1701
- if (invalidate) {
1702
- router.invalidateRoute({
1703
- to: '.',
1704
- fromCurrent: true
1705
- });
1706
- await router.reload();
1707
- }
1749
+ if (next.href !== router.location.href) {
1750
+ router.__.commitLocation(next, true);
1751
+ } else {
1752
+ router.loadLocation();
1753
+ }
1708
1754
 
1709
- actionState.status = 'success';
1710
- return res;
1711
- } catch (err) {
1712
- console.error(err);
1713
- actionState.error = err;
1714
- actionState.status = 'error';
1715
- } finally {
1716
- action.pending = action.pending.filter(d => d !== actionState);
1755
+ const unsub = history.listen(event => {
1756
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1757
+ }); // addEventListener does not exist in React Native, but window does
1758
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1717
1759
 
1718
- if (actionState === router.state.action) {
1719
- router.state.action = undefined;
1720
- }
1760
+ if (!isServer && window.addEventListener) {
1761
+ // Listen to visibillitychange and focus
1762
+ window.addEventListener('visibilitychange', router.onFocus, false);
1763
+ window.addEventListener('focus', router.onFocus, false);
1764
+ }
1721
1765
 
1722
- router.notify();
1723
- }
1766
+ return () => {
1767
+ unsub(); // Be sure to unsubscribe if a new handler is set
1768
+
1769
+ window.removeEventListener('visibilitychange', router.onFocus);
1770
+ window.removeEventListener('focus', router.onFocus);
1771
+ };
1772
+ },
1773
+ onFocus: () => {
1774
+ router.loadLocation();
1775
+ },
1776
+ update: opts => {
1777
+ Object.assign(router.options, opts);
1778
+ const {
1779
+ basepath,
1780
+ routeConfig
1781
+ } = router.options;
1782
+ router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1783
+
1784
+ if (routeConfig) {
1785
+ router.routesById = {};
1786
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1724
1787
  }
1725
- };
1726
- return router.state.actions[routeId];
1727
- })();
1728
1788
 
1729
- let route = {
1730
- routeId,
1731
- routePath,
1732
- fullPath,
1733
- options,
1734
- router,
1735
- childRoutes: undefined,
1736
- parentRoute: parent,
1737
- action,
1738
- buildLink: options => {
1739
- return router.buildLink(_extends$1({}, options, {
1740
- from: fullPath
1741
- }));
1789
+ return router;
1742
1790
  },
1743
- navigate: options => {
1744
- return router.navigate(_extends$1({}, options, {
1745
- from: fullPath
1746
- }));
1791
+ cancelMatches: () => {
1792
+ var _router$state$pending, _router$state$pending2;
1793
+ [...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 => {
1794
+ match.cancel();
1795
+ });
1747
1796
  },
1748
- matchRoute: (matchLocation, opts) => {
1749
- return router.matchRoute(_extends$1({}, matchLocation, {
1750
- from: fullPath
1751
- }), opts);
1752
- }
1753
- };
1754
- router.options.createRoute == null ? void 0 : router.options.createRoute({
1755
- router,
1756
- route
1757
- });
1758
- return route;
1759
- }
1760
- function createRouteMatch(router, route, opts) {
1761
- const routeMatch = _extends$1({}, route, opts, {
1762
- router,
1763
- routeSearch: {},
1764
- search: {},
1765
- childMatches: [],
1766
- status: 'idle',
1767
- routeLoaderData: {},
1768
- loaderData: {},
1769
- isPending: false,
1770
- isFetching: false,
1771
- isInvalid: false,
1772
- __: {
1773
- abortController: new AbortController(),
1774
- latestId: '',
1775
- resolve: () => {},
1776
- notify: () => {
1777
- routeMatch.__.resolve();
1797
+ loadLocation: async next => {
1798
+ const id = Math.random();
1799
+ router.startedLoadingAt = id;
1800
+
1801
+ if (next) {
1802
+ // Ingest the new location
1803
+ router.location = next;
1804
+ } // Clear out old actions
1778
1805
 
1779
- routeMatch.router.notify();
1780
- },
1781
- startPending: () => {
1782
- var _routeMatch$options$p, _routeMatch$options$p2;
1783
1806
 
1784
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1785
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1807
+ router.removeActionQueue.forEach(_ref => {
1808
+ let {
1809
+ action,
1810
+ actionState
1811
+ } = _ref;
1786
1812
 
1787
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1788
- return;
1813
+ if (router.state.currentAction === actionState) {
1814
+ router.state.currentAction = undefined;
1789
1815
  }
1790
1816
 
1791
- routeMatch.__.pendingTimeout = setTimeout(() => {
1792
- routeMatch.isPending = true;
1817
+ if (action.current === actionState) {
1818
+ action.current = undefined;
1819
+ }
1820
+ });
1821
+ router.removeActionQueue = []; // Cancel any pending matches
1793
1822
 
1794
- routeMatch.__.resolve();
1823
+ router.cancelMatches(); // Match the routes
1795
1824
 
1796
- if (typeof pendingMinMs !== 'undefined') {
1797
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1798
- }
1799
- }, pendingMs);
1800
- },
1801
- cancelPending: () => {
1802
- routeMatch.isPending = false;
1803
- clearTimeout(routeMatch.__.pendingTimeout);
1804
- clearTimeout(routeMatch.__.pendingMinTimeout);
1805
- delete routeMatch.__.pendingMinPromise;
1806
- },
1807
- setParentMatch: parentMatch => {
1808
- routeMatch.parentMatch = parentMatch;
1809
- },
1810
- addChildMatch: childMatch => {
1811
- if (routeMatch.childMatches.find(d => d.matchId === childMatch.matchId)) {
1812
- return;
1813
- }
1825
+ const matches = router.matchRoutes(location.pathname, {
1826
+ strictParseParams: true
1827
+ });
1828
+ router.state = _extends({}, router.state, {
1829
+ pending: {
1830
+ matches: matches,
1831
+ location: router.location
1832
+ },
1833
+ status: 'loading'
1834
+ });
1835
+ router.notify(); // Load the matches
1814
1836
 
1815
- routeMatch.childMatches.push(childMatch);
1816
- },
1817
- validate: () => {
1818
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1837
+ await router.loadMatches(matches, {
1838
+ withPending: true
1839
+ });
1819
1840
 
1820
- // Validate the search params and stabilize them
1821
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1841
+ if (router.startedLoadingAt !== id) {
1842
+ // Ignore side-effects of match loading
1843
+ return router.navigationPromise;
1844
+ }
1822
1845
 
1823
- try {
1824
- const prevSearch = routeMatch.routeSearch;
1825
- let nextSearch = replaceEqualDeep(prevSearch, routeMatch.options.validateSearch == null ? void 0 : routeMatch.options.validateSearch(parentSearch)); // Invalidate route matches when search param stability changes
1846
+ const previousMatches = router.state.matches;
1847
+ const exiting = [],
1848
+ staying = [];
1849
+ previousMatches.forEach(d => {
1850
+ if (matches.find(dd => dd.matchId === d.matchId)) {
1851
+ staying.push(d);
1852
+ } else {
1853
+ exiting.push(d);
1854
+ }
1855
+ });
1856
+ const now = Date.now();
1857
+ exiting.forEach(d => {
1858
+ var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1826
1859
 
1827
- if (prevSearch !== nextSearch) {
1828
- routeMatch.isInvalid = true;
1829
- }
1860
+ d.__.onExit == null ? void 0 : d.__.onExit({
1861
+ params: d.params,
1862
+ search: d.routeSearch
1863
+ }); // Clear idle error states when match leaves
1830
1864
 
1831
- routeMatch.routeSearch = nextSearch;
1832
- routeMatch.search = replaceEqualDeep(parentSearch, _extends$1({}, parentSearch, nextSearch));
1833
- } catch (err) {
1834
- console.error(err);
1835
- const error = new Error('Invalid search params found', {
1836
- cause: err
1837
- });
1838
- error.code = 'INVALID_SEARCH_PARAMS';
1839
- routeMatch.status = 'error';
1840
- routeMatch.error = error; // Do not proceed with loading the route
1865
+ if (d.status === 'error' && !d.isFetching) {
1866
+ d.status = 'idle';
1867
+ d.error = undefined;
1868
+ }
1841
1869
 
1842
- return;
1870
+ 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);
1871
+
1872
+ if (gc > 0) {
1873
+ router.matchCache[d.matchId] = {
1874
+ gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1875
+ match: d
1876
+ };
1843
1877
  }
1878
+ });
1879
+ staying.forEach(d => {
1880
+ d.options.onTransition == null ? void 0 : d.options.onTransition({
1881
+ params: d.params,
1882
+ search: d.routeSearch
1883
+ });
1884
+ });
1885
+ const entering = matches.filter(d => {
1886
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
1887
+ });
1888
+ entering.forEach(d => {
1889
+ d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1890
+ params: d.params,
1891
+ search: d.search
1892
+ });
1893
+ delete router.matchCache[d.matchId];
1894
+ });
1895
+
1896
+ if (matches.some(d => d.status === 'loading')) {
1897
+ router.notify();
1898
+ await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1844
1899
  }
1845
- },
1846
- cancel: () => {
1847
- var _routeMatch$__$abortC;
1848
1900
 
1849
- (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1901
+ if (router.startedLoadingAt !== id) {
1902
+ // Ignore side-effects of match loading
1903
+ return;
1904
+ }
1850
1905
 
1851
- routeMatch.__.cancelPending();
1906
+ router.state = _extends({}, router.state, {
1907
+ location: router.location,
1908
+ matches,
1909
+ pending: undefined,
1910
+ status: 'idle'
1911
+ });
1912
+ router.notify();
1913
+ router.resolveNavigation();
1852
1914
  },
1853
- load: async () => {
1854
- const id = '' + Date.now() + Math.random();
1855
- routeMatch.__.latestId = id; // If the match was in an error state, set it
1856
- // to a loading state again. Otherwise, keep it
1857
- // as loading or resolved
1858
-
1859
- if (routeMatch.status === 'error' || routeMatch.status === 'idle') {
1860
- routeMatch.status = 'loading';
1861
- } // We started loading the route, so it's no longer invalid
1915
+ cleanMatchCache: () => {
1916
+ const now = Date.now();
1917
+ Object.keys(router.matchCache).forEach(matchId => {
1918
+ const entry = router.matchCache[matchId]; // Don't remove loading matches
1862
1919
 
1920
+ if (entry.match.status === 'loading') {
1921
+ return;
1922
+ } // Do not remove successful matches that are still valid
1863
1923
 
1864
- routeMatch.isInvalid = false;
1865
- routeMatch.__.loadPromise = new Promise(async resolve => {
1866
- // We are now fetching, even if it's in the background of a
1867
- // resolved state
1868
- routeMatch.isFetching = true;
1869
- routeMatch.__.resolve = resolve;
1870
1924
 
1871
- const loaderPromise = (async () => {
1872
- const importer = routeMatch.options.import; // First, run any importers
1925
+ if (entry.gc > 0 && entry.gc > now) {
1926
+ return;
1927
+ } // Everything else gets removed
1873
1928
 
1874
- if (importer) {
1875
- routeMatch.__.importPromise = importer({
1876
- params: routeMatch.params // search: routeMatch.search,
1877
1929
 
1878
- }).then(imported => {
1879
- routeMatch.__ = _extends$1({}, routeMatch.__, imported);
1880
- });
1881
- } // Wait for the importer to finish before
1882
- // attempting to load elements and data
1930
+ delete router.matchCache[matchId];
1931
+ });
1932
+ },
1933
+ loadRoute: async function loadRoute(navigateOpts) {
1934
+ if (navigateOpts === void 0) {
1935
+ navigateOpts = router.location;
1936
+ }
1883
1937
 
1938
+ const next = router.buildNext(navigateOpts);
1939
+ const matches = router.matchRoutes(next.pathname, {
1940
+ strictParseParams: true
1941
+ });
1942
+ await router.loadMatches(matches);
1943
+ return matches;
1944
+ },
1945
+ preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1946
+ var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
1884
1947
 
1885
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1948
+ if (navigateOpts === void 0) {
1949
+ navigateOpts = router.location;
1950
+ }
1886
1951
 
1887
- routeMatch.__.elementsPromise = (async () => {
1888
- // then run all element and data loaders in parallel
1889
- // For each element type, potentially load it asynchronously
1890
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1891
- await Promise.all(elementTypes.map(async type => {
1892
- const routeElement = routeMatch.options[type];
1952
+ const next = router.buildNext(navigateOpts);
1953
+ const matches = router.matchRoutes(next.pathname, {
1954
+ strictParseParams: true
1955
+ });
1956
+ await router.loadMatches(matches, {
1957
+ preload: true,
1958
+ maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
1959
+ gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
1960
+ });
1961
+ return matches;
1962
+ },
1963
+ matchRoutes: (pathname, opts) => {
1964
+ var _router$state$pending3, _router$state$pending4;
1893
1965
 
1894
- if (routeMatch.__[type]) {
1895
- return;
1896
- }
1966
+ router.cleanMatchCache();
1967
+ const matches = [];
1897
1968
 
1898
- if (typeof routeElement === 'function') {
1899
- const res = await routeElement(routeMatch);
1900
- routeMatch.__[type] = res;
1901
- } else {
1902
- routeMatch.__[type] = routeMatch.options[type];
1903
- }
1904
- }));
1905
- })();
1969
+ if (!router.routeTree) {
1970
+ return matches;
1971
+ }
1906
1972
 
1907
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1908
- try {
1909
- const data = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
1910
- params: routeMatch.params,
1911
- search: routeMatch.routeSearch,
1912
- signal: routeMatch.__.abortController.signal
1913
- }));
1973
+ 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
1974
 
1915
- if (id !== routeMatch.__.latestId) {
1916
- return routeMatch.__.loaderPromise;
1917
- }
1975
+ const recurse = async routes => {
1976
+ var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
1918
1977
 
1919
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1920
- cascadeLoaderData(routeMatch);
1921
- routeMatch.error = undefined;
1922
- routeMatch.status = 'success';
1923
- routeMatch.updatedAt = Date.now();
1924
- } catch (err) {
1925
- if (id !== routeMatch.__.latestId) {
1926
- return routeMatch.__.loaderPromise;
1927
- }
1978
+ const parentMatch = last(matches);
1979
+ let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1980
+ const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
1981
+ let foundRoutes = [];
1928
1982
 
1929
- if (process.env.NODE_ENV !== 'production') {
1930
- console.error(err);
1931
- }
1983
+ const findMatchInRoutes = (parentRoutes, routes) => {
1984
+ routes.some(route => {
1985
+ var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
1932
1986
 
1933
- routeMatch.error = err;
1934
- routeMatch.status = 'error';
1935
- routeMatch.updatedAt = Date.now();
1987
+ if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
1988
+ return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
1936
1989
  }
1937
- });
1938
1990
 
1939
- try {
1940
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1991
+ const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
1992
+ const matchParams = matchPathname(pathname, {
1993
+ to: route.fullPath,
1994
+ fuzzy,
1995
+ caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
1996
+ });
1941
1997
 
1942
- if (id !== routeMatch.__.latestId) {
1943
- return routeMatch.__.loaderPromise;
1944
- }
1998
+ if (matchParams) {
1999
+ let parsedParams;
1945
2000
 
1946
- if (routeMatch.__.pendingMinPromise) {
1947
- await routeMatch.__.pendingMinPromise;
1948
- delete routeMatch.__.pendingMinPromise;
1949
- }
1950
- } finally {
1951
- if (id !== routeMatch.__.latestId) {
1952
- return routeMatch.__.loaderPromise;
1953
- }
2001
+ try {
2002
+ var _route$options$parseP;
1954
2003
 
1955
- routeMatch.__.cancelPending();
2004
+ parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
2005
+ } catch (err) {
2006
+ if (opts != null && opts.strictParseParams) {
2007
+ throw err;
2008
+ }
2009
+ }
1956
2010
 
1957
- routeMatch.isPending = false;
1958
- routeMatch.isFetching = false;
2011
+ params = _extends({}, params, parsedParams);
2012
+ }
1959
2013
 
1960
- routeMatch.__.notify();
1961
- }
1962
- })();
2014
+ if (!!matchParams) {
2015
+ foundRoutes = [...parentRoutes, route];
2016
+ }
1963
2017
 
1964
- routeMatch.__.loaderPromise = loaderPromise;
1965
- await loaderPromise;
2018
+ return !!foundRoutes.length;
2019
+ });
2020
+ return !!foundRoutes.length;
2021
+ };
1966
2022
 
1967
- if (id !== routeMatch.__.latestId) {
1968
- return routeMatch.__.loaderPromise;
2023
+ findMatchInRoutes([], filteredRoutes);
2024
+
2025
+ if (!foundRoutes.length) {
2026
+ return;
1969
2027
  }
1970
2028
 
1971
- delete routeMatch.__.loaderPromise;
1972
- });
1973
- return await routeMatch.__.loadPromise;
1974
- }
1975
- });
2029
+ foundRoutes.forEach(foundRoute => {
2030
+ var _router$matchCache$ma;
1976
2031
 
1977
- return routeMatch;
1978
- }
2032
+ const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2033
+ const matchId = interpolatePath(foundRoute.routeId, params, true);
2034
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2035
+ matchId,
2036
+ params,
2037
+ pathname: joinPaths([pathname, interpolatedPath])
2038
+ });
2039
+ matches.push(match);
2040
+ });
2041
+ const foundRoute = last(foundRoutes);
1979
2042
 
1980
- function cascadeLoaderData(routeMatch) {
1981
- if (routeMatch.parentMatch) {
1982
- routeMatch.loaderData = replaceEqualDeep(routeMatch.loaderData, _extends$1({}, routeMatch.parentMatch.loaderData, routeMatch.routeLoaderData));
1983
- }
2043
+ if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2044
+ recurse(foundRoute.childRoutes);
2045
+ }
2046
+ };
1984
2047
 
1985
- if (routeMatch.childMatches.length) {
1986
- routeMatch.childMatches.forEach(childMatch => {
1987
- cascadeLoaderData(childMatch);
1988
- });
1989
- }
1990
- }
2048
+ recurse([router.routeTree]);
2049
+ cascadeLoaderData(matches);
2050
+ return matches;
2051
+ },
2052
+ loadMatches: async (resolvedMatches, loaderOpts) => {
2053
+ const now = Date.now();
2054
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2055
+ const matchPromises = resolvedMatches.map(async match => {
2056
+ // Validate the match (loads search params etc)
2057
+ match.__.validate(); // If this is a preload, add it to the preload cache
1991
2058
 
1992
- function matchPathname(currentPathname, matchLocation) {
1993
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1994
2059
 
1995
- if (matchLocation.to && !pathParams) {
1996
- return;
1997
- } // if (matchLocation.search && !searchMatched) {
1998
- // return
1999
- // }
2060
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2061
+ // If the match is currently active, don't preload it
2062
+ if (router.state.matches.find(d => d.matchId === match.matchId)) {
2063
+ return;
2064
+ }
2065
+
2066
+ router.matchCache[match.matchId] = {
2067
+ gc: now + loaderOpts.gcMaxAge,
2068
+ match
2069
+ };
2070
+ } // If the match is invalid, errored or idle, trigger it to load
2000
2071
 
2001
2072
 
2002
- return pathParams != null ? pathParams : {};
2003
- }
2073
+ if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2074
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2075
+ match.load({
2076
+ maxAge
2077
+ });
2078
+ }
2004
2079
 
2005
- function interpolatePath(path, params, leaveWildcard) {
2006
- const interpolatedPathSegments = parsePathname(path);
2007
- return joinPaths(interpolatedPathSegments.map(segment => {
2008
- if (segment.value === '*' && !leaveWildcard) {
2009
- return '';
2010
- }
2080
+ if (match.status === 'loading') {
2081
+ // If requested, start the pending timers
2082
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2083
+ // This might be completion, error, or a pending state
2011
2084
 
2012
- if (segment.type === 'param') {
2013
- var _segment$value$substr;
2085
+ await match.__.loadPromise;
2086
+ }
2087
+ });
2088
+ router.notify();
2089
+ await Promise.all(matchPromises);
2090
+ },
2091
+ invalidateRoute: opts => {
2092
+ var _router$state$pending5, _router$state$pending6;
2014
2093
 
2015
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
2016
- }
2094
+ const next = router.buildNext(opts);
2095
+ const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2096
+ [...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 => {
2097
+ if (unloadedMatchIds.includes(match.matchId)) {
2098
+ match.invalidate();
2099
+ }
2100
+ });
2101
+ },
2102
+ reload: () => router.__.navigate({
2103
+ fromCurrent: true,
2104
+ replace: true,
2105
+ search: true
2106
+ }),
2107
+ resolvePath: (from, path) => {
2108
+ return resolvePath(router.basepath, from, cleanPath(path));
2109
+ },
2110
+ matchRoute: (location, opts) => {
2111
+ var _location$from;
2017
2112
 
2018
- return segment.value;
2019
- }));
2020
- }
2113
+ // const location = router.buildNext(opts)
2114
+ location = _extends({}, location, {
2115
+ to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2116
+ });
2117
+ const next = router.buildNext(location);
2021
2118
 
2022
- function warning(cond, message) {
2023
- if (cond) {
2024
- if (typeof console !== 'undefined') console.warn(message);
2119
+ if (opts != null && opts.pending) {
2120
+ var _router$state$pending7;
2025
2121
 
2026
- try {
2027
- throw new Error(message);
2028
- } catch (_unused) {}
2029
- }
2122
+ if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2123
+ return false;
2124
+ }
2030
2125
 
2031
- return true;
2032
- }
2126
+ return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2127
+ to: next.pathname
2128
+ }));
2129
+ }
2033
2130
 
2034
- function isFunction(d) {
2035
- return typeof d === 'function';
2036
- }
2131
+ return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2132
+ to: next.pathname
2133
+ }));
2134
+ },
2135
+ navigate: async _ref8 => {
2136
+ let {
2137
+ from,
2138
+ to = '.',
2139
+ search,
2140
+ hash,
2141
+ replace,
2142
+ params
2143
+ } = _ref8;
2144
+ // If this link simply reloads the current route,
2145
+ // make sure it has a new key so it will trigger a data refresh
2146
+ // If this `to` is a valid external URL, return
2147
+ // null for LinkUtils
2148
+ const toString = String(to);
2149
+ const fromString = String(from);
2150
+ let isExternal;
2037
2151
 
2038
- function functionalUpdate(updater, previous) {
2039
- if (isFunction(updater)) {
2040
- return updater(previous);
2041
- }
2152
+ try {
2153
+ new URL("" + toString);
2154
+ isExternal = true;
2155
+ } catch (e) {}
2042
2156
 
2043
- return updater;
2044
- }
2157
+ invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2158
+ return router.__.navigate({
2159
+ from: fromString,
2160
+ to: toString,
2161
+ search,
2162
+ hash,
2163
+ replace,
2164
+ params
2165
+ });
2166
+ },
2167
+ buildLink: _ref9 => {
2168
+ var _preload, _ref10;
2045
2169
 
2046
- function joinPaths(paths) {
2047
- return cleanPath(paths.filter(Boolean).join('/'));
2048
- }
2170
+ let {
2171
+ from,
2172
+ to = '.',
2173
+ search,
2174
+ params,
2175
+ hash,
2176
+ target,
2177
+ replace,
2178
+ activeOptions,
2179
+ preload,
2180
+ preloadMaxAge: userPreloadMaxAge,
2181
+ preloadGcMaxAge: userPreloadGcMaxAge,
2182
+ preloadDelay: userPreloadDelay,
2183
+ disabled
2184
+ } = _ref9;
2049
2185
 
2050
- function cleanPath(path) {
2051
- // remove double slashes
2052
- return path.replace(/\/{2,}/g, '/');
2053
- }
2186
+ // If this link simply reloads the current route,
2187
+ // make sure it has a new key so it will trigger a data refresh
2188
+ // If this `to` is a valid external URL, return
2189
+ // null for LinkUtils
2190
+ try {
2191
+ new URL("" + to);
2192
+ return {
2193
+ type: 'external',
2194
+ href: to
2195
+ };
2196
+ } catch (e) {}
2054
2197
 
2055
- function trimPathLeft(path) {
2056
- return path === '/' ? path : path.replace(/^\/{1,}/, '');
2057
- }
2198
+ const nextOpts = {
2199
+ from,
2200
+ to,
2201
+ search,
2202
+ params,
2203
+ hash,
2204
+ replace
2205
+ };
2206
+ const next = router.buildNext(nextOpts);
2207
+ preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2208
+ const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2058
2209
 
2059
- function trimPathRight(path) {
2060
- return path === '/' ? path : path.replace(/\/{1,}$/, '');
2061
- }
2210
+ const pathIsEqual = router.state.location.pathname === next.pathname;
2211
+ const currentPathSplit = router.state.location.pathname.split('/');
2212
+ const nextPathSplit = next.pathname.split('/');
2213
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2214
+ const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2062
2215
 
2063
- function trimPath(path) {
2064
- return trimPathRight(trimPathLeft(path));
2065
- }
2216
+ const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2217
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2066
2218
 
2067
- function matchByPath(from, matchLocation) {
2068
- var _matchLocation$to;
2219
+ const isActive = pathTest && hashTest; // The click handler
2069
2220
 
2070
- const baseSegments = parsePathname(from);
2071
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
2072
- const params = {};
2221
+ const handleClick = e => {
2222
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2223
+ e.preventDefault();
2073
2224
 
2074
- let isMatch = (() => {
2075
- for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
2076
- const baseSegment = baseSegments[i];
2077
- const routeSegment = routeSegments[i];
2078
- const isLastRouteSegment = i === routeSegments.length - 1;
2079
- const isLastBaseSegment = i === baseSegments.length - 1;
2225
+ if (pathIsEqual && !search && !hash) {
2226
+ router.invalidateRoute(nextOpts);
2227
+ } // All is well? Navigate!)
2080
2228
 
2081
- if (routeSegment) {
2082
- if (routeSegment.type === 'wildcard') {
2083
- if (baseSegment != null && baseSegment.value) {
2084
- params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
2085
- return true;
2086
- }
2087
2229
 
2088
- return false;
2230
+ router.__.navigate(nextOpts);
2089
2231
  }
2232
+ }; // The click handler
2090
2233
 
2091
- if (routeSegment.type === 'pathname') {
2092
- if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
2093
- return true;
2094
- }
2095
2234
 
2096
- if (baseSegment) {
2097
- if (matchLocation.caseSensitive) {
2098
- if (routeSegment.value !== baseSegment.value) {
2099
- return false;
2100
- }
2101
- } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
2102
- return false;
2103
- }
2104
- }
2235
+ const handleFocus = e => {
2236
+ if (preload) {
2237
+ router.preloadRoute(nextOpts, {
2238
+ maxAge: userPreloadMaxAge,
2239
+ gcMaxAge: userPreloadGcMaxAge
2240
+ });
2105
2241
  }
2242
+ };
2106
2243
 
2107
- if (!baseSegment) {
2108
- return false;
2109
- }
2244
+ const handleEnter = e => {
2245
+ const target = e.target || {};
2110
2246
 
2111
- if (routeSegment.type === 'param') {
2112
- if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
2113
- return false;
2247
+ if (preload) {
2248
+ if (target.preloadTimeout) {
2249
+ return;
2114
2250
  }
2115
2251
 
2116
- if (!baseSegment.value.startsWith(':')) {
2117
- params[routeSegment.value.substring(1)] = baseSegment.value;
2118
- }
2252
+ target.preloadTimeout = setTimeout(() => {
2253
+ target.preloadTimeout = null;
2254
+ router.preloadRoute(nextOpts, {
2255
+ maxAge: userPreloadMaxAge,
2256
+ gcMaxAge: userPreloadGcMaxAge
2257
+ });
2258
+ }, preloadDelay);
2119
2259
  }
2120
- }
2121
-
2122
- if (isLastRouteSegment && !isLastBaseSegment) {
2123
- return !!matchLocation.fuzzy;
2124
- }
2125
- }
2126
-
2127
- return true;
2128
- })();
2129
-
2130
- return isMatch ? params : undefined;
2131
- } // function matchBySearch(
2132
- // search: SearchSchema,
2133
- // matchLocation: MatchLocation,
2134
- // ) {
2135
- // return !!(matchLocation.search && matchLocation.search(search))
2136
- // }
2137
-
2138
- function parsePathname(pathname) {
2139
- if (!pathname) {
2140
- return [];
2141
- }
2142
-
2143
- pathname = cleanPath(pathname);
2144
- const segments = [];
2145
-
2146
- if (pathname.slice(0, 1) === '/') {
2147
- pathname = pathname.substring(1);
2148
- segments.push({
2149
- type: 'pathname',
2150
- value: '/'
2151
- });
2152
- }
2153
-
2154
- if (!pathname) {
2155
- return segments;
2156
- } // Remove empty segments and '.' segments
2260
+ };
2157
2261
 
2262
+ const handleLeave = e => {
2263
+ const target = e.target || {};
2158
2264
 
2159
- const split = pathname.split('/').filter(Boolean);
2160
- segments.push(...split.map(part => {
2161
- if (part.startsWith('*')) {
2162
- return {
2163
- type: 'wildcard',
2164
- value: part
2265
+ if (target.preloadTimeout) {
2266
+ clearTimeout(target.preloadTimeout);
2267
+ target.preloadTimeout = null;
2268
+ }
2165
2269
  };
2166
- }
2167
2270
 
2168
- if (part.charAt(0) === ':') {
2169
2271
  return {
2170
- type: 'param',
2171
- value: part
2272
+ type: 'internal',
2273
+ next,
2274
+ handleFocus,
2275
+ handleClick,
2276
+ handleEnter,
2277
+ handleLeave,
2278
+ isActive,
2279
+ disabled
2172
2280
  };
2173
- }
2174
-
2175
- return {
2176
- type: 'pathname',
2177
- value: part
2178
- };
2179
- }));
2180
-
2181
- if (pathname.slice(-1) === '/') {
2182
- pathname = pathname.substring(1);
2183
- segments.push({
2184
- type: 'pathname',
2185
- value: '/'
2186
- });
2187
- }
2281
+ },
2282
+ buildNext: opts => {
2283
+ const next = router.__.buildLocation(opts);
2188
2284
 
2189
- return segments;
2190
- }
2285
+ const matches = router.matchRoutes(next.pathname);
2191
2286
 
2192
- function _resolvePath(basepath, base, to) {
2193
- base = base.replace(new RegExp("^" + basepath), '/');
2194
- to = to.replace(new RegExp("^" + basepath), '/');
2195
- let baseSegments = parsePathname(base);
2196
- const toSegments = parsePathname(to);
2197
- toSegments.forEach((toSegment, index) => {
2198
- if (toSegment.value === '/') {
2199
- if (!index) {
2200
- // Leading slash
2201
- baseSegments = [toSegment];
2202
- } else if (index === toSegments.length - 1) {
2203
- // Trailing Slash
2204
- baseSegments.push(toSegment);
2205
- } else ;
2206
- } else if (toSegment.value === '..') {
2207
- var _last2;
2287
+ const __preSearchFilters = matches.map(match => {
2288
+ var _match$options$preSea;
2208
2289
 
2209
- // Extra trailing slash? pop it off
2210
- if (baseSegments.length > 1 && ((_last2 = last(baseSegments)) == null ? void 0 : _last2.value) === '/') {
2211
- baseSegments.pop();
2212
- }
2290
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2291
+ }).flat().filter(Boolean);
2213
2292
 
2214
- baseSegments.pop();
2215
- } else if (toSegment.value === '.') {
2216
- return;
2217
- } else {
2218
- baseSegments.push(toSegment);
2219
- }
2220
- });
2221
- const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
2222
- return cleanPath(joined);
2223
- }
2224
- function replaceEqualDeep(prev, next) {
2225
- if (prev === next) {
2226
- return prev;
2227
- }
2293
+ const __postSearchFilters = matches.map(match => {
2294
+ var _match$options$postSe;
2228
2295
 
2229
- const array = Array.isArray(prev) && Array.isArray(next);
2296
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2297
+ }).flat().filter(Boolean);
2230
2298
 
2231
- if (array || isPlainObject(prev) && isPlainObject(next)) {
2232
- const aSize = array ? prev.length : Object.keys(prev).length;
2233
- const bItems = array ? next : Object.keys(next);
2234
- const bSize = bItems.length;
2235
- const copy = array ? [] : {};
2236
- let equalItems = 0;
2299
+ return router.__.buildLocation(_extends({}, opts, {
2300
+ __preSearchFilters,
2301
+ __postSearchFilters
2302
+ }));
2303
+ },
2304
+ __: {
2305
+ buildRouteTree: rootRouteConfig => {
2306
+ const recurseRoutes = (routeConfigs, parent) => {
2307
+ return routeConfigs.map(routeConfig => {
2308
+ const routeOptions = routeConfig.options;
2309
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2310
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2311
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2312
+ // }
2313
+
2314
+ const existingRoute = router.routesById[route.routeId];
2315
+
2316
+ if (existingRoute) {
2317
+ if (process.env.NODE_ENV !== 'production') {
2318
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2319
+ }
2237
2320
 
2238
- for (let i = 0; i < bSize; i++) {
2239
- const key = array ? i : bItems[i];
2240
- copy[key] = replaceEqualDeep(prev[key], next[key]);
2321
+ throw new Error();
2322
+ }
2323
+ router.routesById[route.routeId] = route;
2324
+ const children = routeConfig.children;
2325
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2326
+ return route;
2327
+ });
2328
+ };
2241
2329
 
2242
- if (copy[key] === prev[key]) {
2243
- equalItems++;
2244
- }
2245
- }
2330
+ const routes = recurseRoutes([rootRouteConfig]);
2331
+ return routes[0];
2332
+ },
2333
+ parseLocation: (location, previousLocation) => {
2334
+ var _location$hash$split$;
2246
2335
 
2247
- return aSize === bSize && equalItems === aSize ? prev : copy;
2248
- }
2336
+ const parsedSearch = router.options.parseSearch(location.search);
2337
+ return {
2338
+ pathname: location.pathname,
2339
+ searchStr: location.search,
2340
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2341
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2342
+ href: "" + location.pathname + location.search + location.hash,
2343
+ state: location.state,
2344
+ key: location.key
2345
+ };
2346
+ },
2347
+ navigate: location => {
2348
+ const next = router.buildNext(location);
2349
+ return router.__.commitLocation(next, location.replace);
2350
+ },
2351
+ buildLocation: function buildLocation(dest) {
2352
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2249
2353
 
2250
- return next;
2251
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
2354
+ if (dest === void 0) {
2355
+ dest = {};
2356
+ }
2252
2357
 
2253
- function isPlainObject(o) {
2254
- if (!hasObjectPrototype(o)) {
2255
- return false;
2256
- } // If has modified constructor
2358
+ // const resolvedFrom: Location = {
2359
+ // ...router.location,
2360
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2257
2361
 
2362
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2258
2363
 
2259
- const ctor = o.constructor;
2364
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2365
+ strictParseParams: true
2366
+ });
2367
+ const toMatches = router.matchRoutes(pathname);
2260
2368
 
2261
- if (typeof ctor === 'undefined') {
2262
- return true;
2263
- } // If has modified prototype
2369
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2264
2370
 
2371
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2265
2372
 
2266
- const prot = ctor.prototype;
2373
+ if (nextParams) {
2374
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2375
+ Object.assign({}, nextParams, fn(nextParams));
2376
+ });
2377
+ }
2267
2378
 
2268
- if (!hasObjectPrototype(prot)) {
2269
- return false;
2270
- } // If constructor does not have an Object-specific method
2379
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2271
2380
 
2381
+ 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
2272
2382
 
2273
- if (!prot.hasOwnProperty('isPrototypeOf')) {
2274
- return false;
2275
- } // Most likely a plain Object
2383
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2384
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2385
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2386
+ : {}; // Then post filters
2276
2387
 
2388
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2389
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2390
+ const searchStr = router.options.stringifySearch(search);
2391
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2392
+ hash = hash ? "#" + hash : '';
2393
+ return {
2394
+ pathname,
2395
+ search,
2396
+ searchStr,
2397
+ state: router.location.state,
2398
+ hash,
2399
+ href: "" + pathname + searchStr + hash,
2400
+ key: dest.key
2401
+ };
2402
+ },
2403
+ commitLocation: (next, replace) => {
2404
+ const id = '' + Date.now() + Math.random();
2405
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2406
+ let nextAction = 'replace';
2277
2407
 
2278
- return true;
2279
- }
2408
+ if (!replace) {
2409
+ nextAction = 'push';
2410
+ }
2280
2411
 
2281
- function hasObjectPrototype(o) {
2282
- return Object.prototype.toString.call(o) === '[object Object]';
2283
- }
2412
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2284
2413
 
2285
- const defaultParseSearch = parseSearchWith(JSON.parse);
2286
- const defaultStringifySearch = stringifySearchWith(JSON.stringify);
2287
- function parseSearchWith(parser) {
2288
- return searchStr => {
2289
- if (searchStr.substring(0, 1) === '?') {
2290
- searchStr = searchStr.substring(1);
2291
- }
2414
+ if (isSameUrl && !next.key) {
2415
+ nextAction = 'replace';
2416
+ }
2292
2417
 
2293
- let query = decode(searchStr); // Try to parse any query params that might be json
2418
+ if (nextAction === 'replace') {
2419
+ history.replace({
2420
+ pathname: next.pathname,
2421
+ hash: next.hash,
2422
+ search: next.searchStr
2423
+ }, {
2424
+ id
2425
+ });
2426
+ } else {
2427
+ history.push({
2428
+ pathname: next.pathname,
2429
+ hash: next.hash,
2430
+ search: next.searchStr
2431
+ }, {
2432
+ id
2433
+ });
2434
+ }
2294
2435
 
2295
- for (let key in query) {
2296
- const value = query[key];
2436
+ router.navigationPromise = new Promise(resolve => {
2437
+ const previousNavigationResolve = router.resolveNavigation;
2297
2438
 
2298
- if (typeof value === 'string') {
2299
- try {
2300
- query[key] = parser(value);
2301
- } catch (err) {//
2302
- }
2439
+ router.resolveNavigation = () => {
2440
+ previousNavigationResolve();
2441
+ resolve();
2442
+ };
2443
+ });
2444
+ return router.navigationPromise;
2303
2445
  }
2304
2446
  }
2305
-
2306
- return query;
2307
2447
  };
2308
- }
2309
- function stringifySearchWith(stringify) {
2310
- return search => {
2311
- search = _extends$1({}, search);
2312
-
2313
- if (search) {
2314
- Object.keys(search).forEach(key => {
2315
- const val = search[key];
2316
-
2317
- if (typeof val === 'undefined' || val === undefined) {
2318
- delete search[key];
2319
- } else if (val && typeof val === 'object' && val !== null) {
2320
- try {
2321
- search[key] = stringify(val);
2322
- } catch (err) {// silent
2323
- }
2324
- }
2325
- });
2326
- }
2448
+ router.location = router.__.parseLocation(history.location);
2449
+ router.state.location = router.location;
2450
+ router.update(userOptions); // Allow frameworks to hook into the router creation
2327
2451
 
2328
- const searchStr = encode(search).toString();
2329
- return searchStr ? "?" + searchStr : '';
2330
- };
2452
+ router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2453
+ return router;
2331
2454
  }
2332
2455
 
2333
2456
  function isCtrlEvent(e) {
2334
2457
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2335
2458
  }
2336
2459
 
2337
- function last(arr) {
2338
- return arr[arr.length - 1];
2339
- }
2340
-
2341
2460
  const _excluded = ["type", "children", "target", "activeProps", "inactiveProps", "activeOptions", "disabled", "hash", "search", "params", "to", "preload", "preloadDelay", "preloadMaxAge", "replace", "style", "className", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onTouchStart", "onTouchEnd"],
2342
2461
  _excluded2 = ["pending", "caseSensitive", "children"],
2343
2462
  _excluded3 = ["children", "router"];
@@ -2356,151 +2475,147 @@ const useRouterSubscription = router => {
2356
2475
  };
2357
2476
 
2358
2477
  function createReactRouter(opts) {
2478
+ const makeRouteExt = (route, router) => {
2479
+ return {
2480
+ linkProps: options => {
2481
+ var _functionalUpdate, _functionalUpdate2;
2482
+
2483
+ const {
2484
+ // custom props
2485
+ target,
2486
+ activeProps = () => ({
2487
+ className: 'active'
2488
+ }),
2489
+ inactiveProps = () => ({}),
2490
+ disabled,
2491
+ // element props
2492
+ style,
2493
+ className,
2494
+ onClick,
2495
+ onFocus,
2496
+ onMouseEnter,
2497
+ onMouseLeave
2498
+ } = options,
2499
+ rest = _objectWithoutPropertiesLoose(options, _excluded);
2500
+
2501
+ const linkInfo = route.buildLink(options);
2502
+
2503
+ if (linkInfo.type === 'external') {
2504
+ const {
2505
+ href
2506
+ } = linkInfo;
2507
+ return {
2508
+ href
2509
+ };
2510
+ }
2511
+
2512
+ const {
2513
+ handleClick,
2514
+ handleFocus,
2515
+ handleEnter,
2516
+ handleLeave,
2517
+ isActive,
2518
+ next
2519
+ } = linkInfo;
2520
+
2521
+ const composeHandlers = handlers => e => {
2522
+ e.persist();
2523
+ handlers.forEach(handler => {
2524
+ if (handler) handler(e);
2525
+ });
2526
+ }; // Get the active props
2527
+
2528
+
2529
+ const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps, {})) != null ? _functionalUpdate : {} : {}; // Get the inactive props
2530
+
2531
+ const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
2532
+ return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2533
+ href: disabled ? undefined : next.href,
2534
+ onClick: composeHandlers([handleClick, onClick]),
2535
+ onFocus: composeHandlers([handleFocus, onFocus]),
2536
+ onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2537
+ onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
2538
+ target,
2539
+ style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
2540
+ className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
2541
+ }, disabled ? {
2542
+ role: 'link',
2543
+ 'aria-disabled': true
2544
+ } : undefined, {
2545
+ ['data-status']: isActive ? 'active' : undefined
2546
+ });
2547
+ },
2548
+ Link: /*#__PURE__*/React.forwardRef((props, ref) => {
2549
+ const linkProps = route.linkProps(props);
2550
+ useRouterSubscription(router);
2551
+ return /*#__PURE__*/React.createElement("a", _extends$2({
2552
+ ref: ref
2553
+ }, linkProps, {
2554
+ children: typeof props.children === 'function' ? props.children({
2555
+ isActive: linkProps['data-status'] === 'active'
2556
+ }) : props.children
2557
+ }));
2558
+ }),
2559
+ MatchRoute: opts => {
2560
+ const {
2561
+ pending,
2562
+ caseSensitive
2563
+ } = opts,
2564
+ rest = _objectWithoutPropertiesLoose(opts, _excluded2);
2565
+
2566
+ const params = route.matchRoute(rest, {
2567
+ pending,
2568
+ caseSensitive
2569
+ });
2570
+
2571
+ if (!params) {
2572
+ return null;
2573
+ }
2574
+
2575
+ return typeof opts.children === 'function' ? opts.children(params) : opts.children;
2576
+ }
2577
+ };
2578
+ };
2579
+
2359
2580
  const coreRouter = createRouter(_extends$2({}, opts, {
2360
2581
  createRouter: router => {
2361
2582
  const routerExt = {
2583
+ useState: () => {
2584
+ useRouterSubscription(router);
2585
+ return router.state;
2586
+ },
2362
2587
  useRoute: routeId => {
2363
2588
  const route = router.getRoute(routeId);
2364
2589
  useRouterSubscription(router);
2365
-
2366
- if (!route) {
2367
- throw new Error("Could not find a route for route \"" + routeId + "\"! Did you forget to add it to your route config?");
2368
- }
2369
-
2590
+ invariant(route, "Could not find a route for route \"" + routeId + "\"! Did you forget to add it to your route config?");
2370
2591
  return route;
2371
2592
  },
2372
2593
  useMatch: routeId => {
2373
- if (routeId === rootRouteId) {
2374
- throw new Error("\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2375
- }
2594
+ useRouterSubscription(router);
2595
+ invariant(routeId !== rootRouteId, "\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2376
2596
 
2377
2597
  const runtimeMatch = _useMatch();
2378
2598
 
2379
2599
  const match = router.state.matches.find(d => d.routeId === routeId);
2600
+ invariant(match, "Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2601
+ invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2380
2602
 
2381
2603
  if (!match) {
2382
- throw new Error("Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2383
- }
2384
-
2385
- if (runtimeMatch.routeId !== (match == null ? void 0 : match.routeId)) {
2386
- throw new Error("useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2387
- }
2388
-
2389
- useRouterSubscription(router);
2390
-
2391
- if (!match) {
2392
- throw new Error('Match not found!');
2604
+ invariant('Match not found!');
2393
2605
  }
2394
2606
 
2395
2607
  return match;
2396
2608
  }
2397
2609
  };
2398
- Object.assign(router, routerExt);
2610
+ const routeExt = makeRouteExt(router.getRoute('/'), router);
2611
+ Object.assign(router, routerExt, routeExt);
2399
2612
  },
2400
2613
  createRoute: _ref => {
2401
2614
  let {
2402
2615
  router,
2403
2616
  route
2404
2617
  } = _ref;
2405
- const routeExt = {
2406
- linkProps: options => {
2407
- var _functionalUpdate, _functionalUpdate2;
2408
-
2409
- const {
2410
- // custom props
2411
- target,
2412
- activeProps = () => ({
2413
- className: 'active'
2414
- }),
2415
- inactiveProps = () => ({}),
2416
- disabled,
2417
- // element props
2418
- style,
2419
- className,
2420
- onClick,
2421
- onFocus,
2422
- onMouseEnter,
2423
- onMouseLeave
2424
- } = options,
2425
- rest = _objectWithoutPropertiesLoose(options, _excluded);
2426
-
2427
- const linkInfo = route.buildLink(options);
2428
-
2429
- if (linkInfo.type === 'external') {
2430
- const {
2431
- href
2432
- } = linkInfo;
2433
- return {
2434
- href
2435
- };
2436
- }
2437
-
2438
- const {
2439
- handleClick,
2440
- handleFocus,
2441
- handleEnter,
2442
- handleLeave,
2443
- isActive,
2444
- next
2445
- } = linkInfo;
2446
-
2447
- const composeHandlers = handlers => e => {
2448
- e.persist();
2449
- handlers.forEach(handler => {
2450
- if (handler) handler(e);
2451
- });
2452
- }; // Get the active props
2453
-
2454
-
2455
- const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps)) != null ? _functionalUpdate : {} : {}; // Get the inactive props
2456
-
2457
- const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps)) != null ? _functionalUpdate2 : {};
2458
- return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2459
- href: disabled ? undefined : next.href,
2460
- onClick: composeHandlers([handleClick, onClick]),
2461
- onFocus: composeHandlers([handleFocus, onFocus]),
2462
- onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2463
- onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
2464
- target,
2465
- style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
2466
- className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
2467
- }, disabled ? {
2468
- role: 'link',
2469
- 'aria-disabled': true
2470
- } : undefined, {
2471
- ['data-status']: isActive ? 'active' : undefined
2472
- });
2473
- },
2474
- Link: /*#__PURE__*/React.forwardRef((props, ref) => {
2475
- const linkProps = route.linkProps(props);
2476
- useRouterSubscription(router);
2477
- return /*#__PURE__*/React.createElement("a", _extends$2({
2478
- ref: ref
2479
- }, linkProps, {
2480
- children: typeof props.children === 'function' ? props.children({
2481
- isActive: linkProps['data-status'] === 'active'
2482
- }) : props.children
2483
- }));
2484
- }),
2485
- MatchRoute: opts => {
2486
- const {
2487
- pending,
2488
- caseSensitive
2489
- } = opts,
2490
- rest = _objectWithoutPropertiesLoose(opts, _excluded2);
2491
-
2492
- const params = route.matchRoute(rest, {
2493
- pending,
2494
- caseSensitive
2495
- }); // useRouterSubscription(router)
2496
-
2497
- if (!params) {
2498
- return null;
2499
- }
2500
-
2501
- return typeof opts.children === 'function' ? opts.children(params) : opts.children;
2502
- }
2503
- };
2618
+ const routeExt = makeRouteExt(route, router);
2504
2619
  Object.assign(route, routeExt);
2505
2620
  }
2506
2621
  }));
@@ -2514,10 +2629,10 @@ function RouterProvider(_ref2) {
2514
2629
  rest = _objectWithoutPropertiesLoose(_ref2, _excluded3);
2515
2630
 
2516
2631
  router.update(rest);
2517
- useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state);
2632
+ useRouterSubscription(router);
2518
2633
  useLayoutEffect(() => {
2519
- router.mount();
2520
- }, []);
2634
+ return router.mount();
2635
+ }, [router]);
2521
2636
  return /*#__PURE__*/React.createElement(routerContext.Provider, {
2522
2637
  value: {
2523
2638
  router
@@ -2526,38 +2641,43 @@ function RouterProvider(_ref2) {
2526
2641
  value: router.state.matches
2527
2642
  }, children != null ? children : /*#__PURE__*/React.createElement(Outlet, null)));
2528
2643
  }
2644
+
2529
2645
  function useRouter() {
2530
2646
  const value = React.useContext(routerContext);
2531
2647
  warning(!value, 'useRouter must be used inside a <Router> component!');
2532
2648
  useRouterSubscription(value.router);
2533
2649
  return value.router;
2534
2650
  }
2651
+
2535
2652
  function useMatches() {
2536
2653
  return React.useContext(matchesContext);
2537
- }
2538
- function useParentMatches() {
2539
- const router = useRouter();
2540
-
2541
- const match = _useMatch();
2654
+ } // function useParentMatches(): RouteMatch[] {
2655
+ // const router = useRouter()
2656
+ // const match = useMatch()
2657
+ // const matches = router.state.matches
2658
+ // return matches.slice(
2659
+ // 0,
2660
+ // matches.findIndex((d) => d.matchId === match.matchId) - 1,
2661
+ // )
2662
+ // }
2542
2663
 
2543
- const matches = router.state.matches;
2544
- return matches.slice(0, matches.findIndex(d => d.matchId === match.matchId) - 1);
2545
- }
2546
2664
 
2547
2665
  function _useMatch() {
2548
2666
  var _useMatches;
2549
2667
 
2550
2668
  return (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2551
2669
  }
2670
+
2552
2671
  function Outlet() {
2553
- var _ref3, _childMatch$options$c;
2672
+ var _childMatch$options$c;
2554
2673
 
2555
2674
  const router = useRouter();
2556
2675
  const [, ...matches] = useMatches();
2557
2676
  const childMatch = matches[0];
2558
2677
  if (!childMatch) return null;
2559
- const element = (_ref3 = (() => {
2560
- var _childMatch$__$errorE, _ref5;
2678
+
2679
+ const element = (() => {
2680
+ var _childMatch$__$errorE, _ref4;
2561
2681
 
2562
2682
  if (!childMatch) {
2563
2683
  return null;
@@ -2574,7 +2694,7 @@ function Outlet() {
2574
2694
  throw childMatch.error;
2575
2695
  }
2576
2696
 
2577
- return /*#__PURE__*/React.createElement(DefaultCatchBoundary, {
2697
+ return /*#__PURE__*/React.createElement(DefaultErrorBoundary, {
2578
2698
  error: childMatch.error
2579
2699
  });
2580
2700
  }
@@ -2586,17 +2706,18 @@ function Outlet() {
2586
2706
  const pendingElement = (_childMatch$__$pendin = childMatch.__.pendingElement) != null ? _childMatch$__$pendin : router.options.defaultPendingElement;
2587
2707
 
2588
2708
  if (childMatch.options.pendingMs || pendingElement) {
2589
- var _ref4;
2709
+ var _ref3;
2590
2710
 
2591
- return (_ref4 = pendingElement) != null ? _ref4 : null;
2711
+ return (_ref3 = pendingElement) != null ? _ref3 : null;
2592
2712
  }
2593
2713
  }
2594
2714
 
2595
2715
  return null;
2596
2716
  }
2597
2717
 
2598
- return (_ref5 = childMatch.__.element) != null ? _ref5 : router.options.defaultElement;
2599
- })()) != null ? _ref3 : /*#__PURE__*/React.createElement(Outlet, null);
2718
+ return (_ref4 = childMatch.__.element) != null ? _ref4 : router.options.defaultElement;
2719
+ })();
2720
+
2600
2721
  const catchElement = (_childMatch$options$c = childMatch == null ? void 0 : childMatch.options.catchElement) != null ? _childMatch$options$c : router.options.defaultCatchElement;
2601
2722
  return /*#__PURE__*/React.createElement(MatchesProvider, {
2602
2723
  value: matches,
@@ -2632,7 +2753,7 @@ class CatchBoundary extends React.Component {
2632
2753
  render() {
2633
2754
  var _this$props$catchElem;
2634
2755
 
2635
- const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultCatchBoundary;
2756
+ const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultErrorBoundary;
2636
2757
 
2637
2758
  if (this.state.error) {
2638
2759
  return typeof catchElement === 'function' ? catchElement(this.state) : catchElement;
@@ -2643,10 +2764,10 @@ class CatchBoundary extends React.Component {
2643
2764
 
2644
2765
  }
2645
2766
 
2646
- function DefaultCatchBoundary(_ref6) {
2767
+ function DefaultErrorBoundary(_ref5) {
2647
2768
  let {
2648
2769
  error
2649
- } = _ref6;
2770
+ } = _ref5;
2650
2771
  return /*#__PURE__*/React.createElement("div", {
2651
2772
  style: {
2652
2773
  padding: '.5rem',
@@ -2681,6 +2802,30 @@ function DefaultCatchBoundary(_ref6) {
2681
2802
  }
2682
2803
  }, "If you are the owner of this website, it's highly recommended that you configure your own custom Catch/Error boundaries for the router. You can optionally configure a boundary for each route."));
2683
2804
  }
2805
+ function usePrompt(message, when) {
2806
+ const router = useRouter();
2807
+ React.useEffect(() => {
2808
+ if (!when) return;
2809
+ let unblock = router.history.block(transition => {
2810
+ if (window.confirm(message)) {
2811
+ unblock();
2812
+ transition.retry();
2813
+ } else {
2814
+ router.location.pathname = window.location.pathname;
2815
+ }
2816
+ });
2817
+ return unblock;
2818
+ }, [when, location, message]);
2819
+ }
2820
+ function Prompt(_ref6) {
2821
+ let {
2822
+ message,
2823
+ when,
2824
+ children
2825
+ } = _ref6;
2826
+ usePrompt(message, when != null ? when : true);
2827
+ return children != null ? children : null;
2828
+ }
2684
2829
 
2685
- export { DefaultCatchBoundary, MatchesProvider, Outlet, RouterProvider, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, defaultParseSearch, defaultStringifySearch, functionalUpdate, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, _resolvePath as resolvePath, rootRouteId, stringifySearchWith, _useMatch as useMatch, useMatches, useParentMatches, useRouter, warning };
2830
+ export { DefaultErrorBoundary, MatchesProvider, Outlet, Prompt, RouterProvider, cascadeLoaderData, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, invariant, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, usePrompt, warning };
2686
2831
  //# sourceMappingURL=index.js.map