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

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