@tanstack/router-core 0.0.1-beta.4 → 0.0.1-beta.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/build/cjs/{packages/router-core/src/index.js → index.js} +25 -8
  2. package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
  3. package/build/cjs/{packages/router-core/src/path.js → path.js} +19 -43
  4. package/build/cjs/path.js.map +1 -0
  5. package/build/cjs/{packages/router-core/src/qss.js → qss.js} +8 -13
  6. package/build/cjs/qss.js.map +1 -0
  7. package/build/cjs/route.js +155 -0
  8. package/build/cjs/route.js.map +1 -0
  9. package/build/cjs/{packages/router-core/src/routeConfig.js → routeConfig.js} +14 -13
  10. package/build/cjs/routeConfig.js.map +1 -0
  11. package/build/cjs/routeMatch.js +242 -0
  12. package/build/cjs/routeMatch.js.map +1 -0
  13. package/build/cjs/router.js +807 -0
  14. package/build/cjs/router.js.map +1 -0
  15. package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +10 -12
  16. package/build/cjs/searchParams.js.map +1 -0
  17. package/build/cjs/sharedClone.js +122 -0
  18. package/build/cjs/sharedClone.js.map +1 -0
  19. package/build/cjs/utils.js +47 -0
  20. package/build/cjs/utils.js.map +1 -0
  21. package/build/esm/index.js +890 -1739
  22. package/build/esm/index.js.map +1 -1
  23. package/build/stats-html.html +59 -49
  24. package/build/stats-react.json +196 -178
  25. package/build/types/index.d.ts +287 -283
  26. package/build/umd/index.development.js +1233 -922
  27. package/build/umd/index.development.js.map +1 -1
  28. package/build/umd/index.production.js +1 -1
  29. package/build/umd/index.production.js.map +1 -1
  30. package/package.json +4 -2
  31. package/src/frameworks.ts +2 -2
  32. package/src/index.ts +1 -1
  33. package/src/link.ts +86 -43
  34. package/src/path.ts +12 -8
  35. package/src/route.ts +170 -158
  36. package/src/routeConfig.ts +105 -77
  37. package/src/routeInfo.ts +26 -8
  38. package/src/routeMatch.ts +204 -217
  39. package/src/router.ts +680 -503
  40. package/src/sharedClone.ts +118 -0
  41. package/src/utils.ts +14 -72
  42. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
  43. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  44. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
  45. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
  46. package/build/cjs/node_modules/history/index.js +0 -815
  47. package/build/cjs/node_modules/history/index.js.map +0 -1
  48. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
  49. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
  50. package/build/cjs/packages/router-core/src/path.js.map +0 -1
  51. package/build/cjs/packages/router-core/src/qss.js.map +0 -1
  52. package/build/cjs/packages/router-core/src/route.js +0 -161
  53. package/build/cjs/packages/router-core/src/route.js.map +0 -1
  54. package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
  55. package/build/cjs/packages/router-core/src/routeMatch.js +0 -266
  56. package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
  57. package/build/cjs/packages/router-core/src/router.js +0 -789
  58. package/build/cjs/packages/router-core/src/router.js.map +0 -1
  59. package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
  60. package/build/cjs/packages/router-core/src/utils.js +0 -118
  61. package/build/cjs/packages/router-core/src/utils.js.map +0 -1
@@ -14,21 +14,19 @@
14
14
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RouterCore = {}));
15
15
  })(this, (function (exports) { 'use strict';
16
16
 
17
- function _extends$1() {
18
- _extends$1 = Object.assign ? Object.assign.bind() : function (target) {
17
+ function _extends() {
18
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
19
19
  for (var i = 1; i < arguments.length; i++) {
20
20
  var source = arguments[i];
21
-
22
21
  for (var key in source) {
23
22
  if (Object.prototype.hasOwnProperty.call(source, key)) {
24
23
  target[key] = source[key];
25
24
  }
26
25
  }
27
26
  }
28
-
29
27
  return target;
30
28
  };
31
- return _extends$1.apply(this, arguments);
29
+ return _extends.apply(this, arguments);
32
30
  }
33
31
 
34
32
  /**
@@ -172,7 +170,7 @@
172
170
 
173
171
  if (index == null) {
174
172
  index = 0;
175
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
173
+ globalHistory.replaceState(_extends({}, globalHistory.state, {
176
174
  idx: index
177
175
  }), '');
178
176
  }
@@ -187,7 +185,7 @@
187
185
  state = null;
188
186
  }
189
187
 
190
- return readOnly(_extends$1({
188
+ return readOnly(_extends({
191
189
  pathname: location.pathname,
192
190
  hash: '',
193
191
  search: ''
@@ -421,7 +419,7 @@
421
419
 
422
420
  if (index == null) {
423
421
  index = 0;
424
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
422
+ globalHistory.replaceState(_extends({}, globalHistory.state, {
425
423
  idx: index
426
424
  }), '');
427
425
  }
@@ -448,7 +446,7 @@
448
446
  state = null;
449
447
  }
450
448
 
451
- return readOnly(_extends$1({
449
+ return readOnly(_extends({
452
450
  pathname: location.pathname,
453
451
  hash: '',
454
452
  search: ''
@@ -600,7 +598,7 @@
600
598
  initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
601
599
  initialIndex = _options3.initialIndex;
602
600
  var entries = initialEntries.map(function (entry) {
603
- var location = readOnly(_extends$1({
601
+ var location = readOnly(_extends({
604
602
  pathname: '/',
605
603
  search: '',
606
604
  hash: '',
@@ -625,7 +623,7 @@
625
623
  state = null;
626
624
  }
627
625
 
628
- return readOnly(_extends$1({
626
+ return readOnly(_extends({
629
627
  pathname: location.pathname,
630
628
  search: '',
631
629
  hash: ''
@@ -832,104 +830,33 @@
832
830
  throw new Error(value);
833
831
  }
834
832
 
835
- // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
836
- // k: infer I,
837
- // ) => any
838
- // ? I
839
- // : never
840
-
841
- /**
842
- * This function returns `a` if `b` is deeply equal.
843
- * If not, it will replace any deeply equal children of `b` with those of `a`.
844
- * This can be used for structural sharing between JSON values for example.
845
- */
846
- function replaceEqualDeep(prev, next) {
847
- if (prev === next) {
848
- return prev;
849
- }
850
-
851
- const array = Array.isArray(prev) && Array.isArray(next);
852
-
853
- if (array || isPlainObject(prev) && isPlainObject(next)) {
854
- const aSize = array ? prev.length : Object.keys(prev).length;
855
- const bItems = array ? next : Object.keys(next);
856
- const bSize = bItems.length;
857
- const copy = array ? [] : {};
858
- let equalItems = 0;
859
-
860
- for (let i = 0; i < bSize; i++) {
861
- const key = array ? i : bItems[i];
862
- copy[key] = replaceEqualDeep(prev[key], next[key]);
863
-
864
- if (copy[key] === prev[key]) {
865
- equalItems++;
866
- }
867
- }
868
-
869
- return aSize === bSize && equalItems === aSize ? prev : copy;
870
- }
871
-
872
- return next;
873
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
874
-
875
- function isPlainObject(o) {
876
- if (!hasObjectPrototype(o)) {
877
- return false;
878
- } // If has modified constructor
879
-
880
-
881
- const ctor = o.constructor;
882
-
883
- if (typeof ctor === 'undefined') {
884
- return true;
885
- } // If has modified prototype
886
-
887
-
888
- const prot = ctor.prototype;
889
-
890
- if (!hasObjectPrototype(prot)) {
891
- return false;
892
- } // If constructor does not have an Object-specific method
893
-
894
-
895
- if (!prot.hasOwnProperty('isPrototypeOf')) {
896
- return false;
897
- } // Most likely a plain Object
898
-
899
-
900
- return true;
901
- }
902
-
903
- function hasObjectPrototype(o) {
904
- return Object.prototype.toString.call(o) === '[object Object]';
905
- }
906
-
907
833
  function last(arr) {
908
834
  return arr[arr.length - 1];
909
835
  }
910
836
  function warning(cond, message) {
911
837
  if (cond) {
912
838
  if (typeof console !== 'undefined') console.warn(message);
913
-
914
839
  try {
915
840
  throw new Error(message);
916
- } catch (_unused) {}
841
+ } catch {}
917
842
  }
918
-
919
843
  return true;
920
844
  }
921
-
922
845
  function isFunction(d) {
923
846
  return typeof d === 'function';
924
847
  }
925
-
926
848
  function functionalUpdate(updater, previous) {
927
849
  if (isFunction(updater)) {
928
850
  return updater(previous);
929
851
  }
930
-
931
852
  return updater;
932
853
  }
854
+ function pick(parent, keys) {
855
+ return keys.reduce((obj, key) => {
856
+ obj[key] = parent[key];
857
+ return obj;
858
+ }, {});
859
+ }
933
860
 
934
861
  function joinPaths(paths) {
935
862
  return cleanPath(paths.filter(Boolean).join('/'));
@@ -948,8 +875,8 @@
948
875
  return trimPathRight(trimPathLeft(path));
949
876
  }
950
877
  function resolvePath(basepath, base, to) {
951
- base = base.replace(new RegExp("^" + basepath), '/');
952
- to = to.replace(new RegExp("^" + basepath), '/');
878
+ base = base.replace(new RegExp(`^${basepath}`), '/');
879
+ to = to.replace(new RegExp(`^${basepath}`), '/');
953
880
  let baseSegments = parsePathname(base);
954
881
  const toSegments = parsePathname(to);
955
882
  toSegments.forEach((toSegment, index) => {
@@ -963,12 +890,10 @@
963
890
  } else ;
964
891
  } else if (toSegment.value === '..') {
965
892
  var _last;
966
-
967
893
  // Extra trailing slash? pop it off
968
894
  if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
969
895
  baseSegments.pop();
970
896
  }
971
-
972
897
  baseSegments.pop();
973
898
  } else if (toSegment.value === '.') {
974
899
  return;
@@ -983,10 +908,8 @@
983
908
  if (!pathname) {
984
909
  return [];
985
910
  }
986
-
987
911
  pathname = cleanPath(pathname);
988
912
  const segments = [];
989
-
990
913
  if (pathname.slice(0, 1) === '/') {
991
914
  pathname = pathname.substring(1);
992
915
  segments.push({
@@ -994,12 +917,11 @@
994
917
  value: '/'
995
918
  });
996
919
  }
997
-
998
920
  if (!pathname) {
999
921
  return segments;
1000
- } // Remove empty segments and '.' segments
1001
-
922
+ }
1002
923
 
924
+ // Remove empty segments and '.' segments
1003
925
  const split = pathname.split('/').filter(Boolean);
1004
926
  segments.push(...split.map(part => {
1005
927
  if (part.startsWith('*')) {
@@ -1008,20 +930,17 @@
1008
930
  value: part
1009
931
  };
1010
932
  }
1011
-
1012
- if (part.charAt(0) === ':') {
933
+ if (part.charAt(0) === '$') {
1013
934
  return {
1014
935
  type: 'param',
1015
936
  value: part
1016
937
  };
1017
938
  }
1018
-
1019
939
  return {
1020
940
  type: 'pathname',
1021
941
  value: part
1022
942
  };
1023
943
  }));
1024
-
1025
944
  if (pathname.slice(-1) === '/') {
1026
945
  pathname = pathname.substring(1);
1027
946
  segments.push({
@@ -1029,7 +948,6 @@
1029
948
  value: '/'
1030
949
  });
1031
950
  }
1032
-
1033
951
  return segments;
1034
952
  }
1035
953
  function interpolatePath(path, params, leaveWildcard) {
@@ -1038,57 +956,48 @@
1038
956
  if (segment.value === '*' && !leaveWildcard) {
1039
957
  return '';
1040
958
  }
1041
-
1042
959
  if (segment.type === 'param') {
1043
- var _segment$value$substr;
1044
-
1045
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
960
+ return params[segment.value.substring(1)] ?? '';
1046
961
  }
1047
-
1048
962
  return segment.value;
1049
963
  }));
1050
964
  }
1051
- function matchPathname(currentPathname, matchLocation) {
1052
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
965
+ function matchPathname(basepath, currentPathname, matchLocation) {
966
+ const pathParams = matchByPath(basepath, currentPathname, matchLocation);
967
+ // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
1053
968
 
1054
969
  if (matchLocation.to && !pathParams) {
1055
970
  return;
1056
- } // if (matchLocation.search && !searchMatched) {
1057
- // return
1058
- // }
1059
-
1060
-
1061
- return pathParams != null ? pathParams : {};
971
+ }
972
+ return pathParams ?? {};
1062
973
  }
1063
- function matchByPath(from, matchLocation) {
1064
- var _matchLocation$to;
1065
-
974
+ function matchByPath(basepath, from, matchLocation) {
975
+ if (!from.startsWith(basepath)) {
976
+ return undefined;
977
+ }
978
+ from = basepath != '/' ? from.substring(basepath.length) : from;
1066
979
  const baseSegments = parsePathname(from);
1067
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
980
+ const to = `${matchLocation.to ?? '*'}`;
981
+ const routeSegments = parsePathname(to);
1068
982
  const params = {};
1069
-
1070
983
  let isMatch = (() => {
1071
984
  for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
1072
985
  const baseSegment = baseSegments[i];
1073
986
  const routeSegment = routeSegments[i];
1074
987
  const isLastRouteSegment = i === routeSegments.length - 1;
1075
988
  const isLastBaseSegment = i === baseSegments.length - 1;
1076
-
1077
989
  if (routeSegment) {
1078
990
  if (routeSegment.type === 'wildcard') {
1079
991
  if (baseSegment != null && baseSegment.value) {
1080
992
  params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
1081
993
  return true;
1082
994
  }
1083
-
1084
995
  return false;
1085
996
  }
1086
-
1087
997
  if (routeSegment.type === 'pathname') {
1088
998
  if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
1089
999
  return true;
1090
1000
  }
1091
-
1092
1001
  if (baseSegment) {
1093
1002
  if (matchLocation.caseSensitive) {
1094
1003
  if (routeSegment.value !== baseSegment.value) {
@@ -1099,41 +1008,36 @@
1099
1008
  }
1100
1009
  }
1101
1010
  }
1102
-
1103
1011
  if (!baseSegment) {
1104
1012
  return false;
1105
1013
  }
1106
-
1107
1014
  if (routeSegment.type === 'param') {
1108
1015
  if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
1109
1016
  return false;
1110
1017
  }
1111
-
1112
- if (!baseSegment.value.startsWith(':')) {
1018
+ if (baseSegment.value.charAt(0) !== '$') {
1113
1019
  params[routeSegment.value.substring(1)] = baseSegment.value;
1114
1020
  }
1115
1021
  }
1116
1022
  }
1117
-
1118
1023
  if (isLastRouteSegment && !isLastBaseSegment) {
1119
1024
  return !!matchLocation.fuzzy;
1120
1025
  }
1121
1026
  }
1122
-
1123
1027
  return true;
1124
1028
  })();
1125
-
1126
1029
  return isMatch ? params : undefined;
1127
1030
  }
1128
1031
 
1129
1032
  // @ts-nocheck
1033
+
1130
1034
  // 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.
1035
+
1131
1036
  function encode(obj, pfx) {
1132
1037
  var k,
1133
- i,
1134
- tmp,
1135
- str = '';
1136
-
1038
+ i,
1039
+ tmp,
1040
+ str = '';
1137
1041
  for (k in obj) {
1138
1042
  if ((tmp = obj[k]) !== void 0) {
1139
1043
  if (Array.isArray(tmp)) {
@@ -1147,10 +1051,8 @@
1147
1051
  }
1148
1052
  }
1149
1053
  }
1150
-
1151
1054
  return (pfx || '') + str;
1152
1055
  }
1153
-
1154
1056
  function toValue(mix) {
1155
1057
  if (!mix) return '';
1156
1058
  var str = decodeURIComponent(mix);
@@ -1159,221 +1061,534 @@
1159
1061
  if (str.charAt(0) === '0') return str;
1160
1062
  return +str * 0 === 0 ? +str : str;
1161
1063
  }
1162
-
1163
1064
  function decode(str) {
1164
1065
  var tmp,
1165
- k,
1166
- out = {},
1167
- arr = str.split('&');
1168
-
1066
+ k,
1067
+ out = {},
1068
+ arr = str.split('&');
1169
1069
  while (tmp = arr.shift()) {
1170
1070
  tmp = tmp.split('=');
1171
1071
  k = tmp.shift();
1172
-
1173
1072
  if (out[k] !== void 0) {
1174
1073
  out[k] = [].concat(out[k], toValue(tmp.shift()));
1175
1074
  } else {
1176
1075
  out[k] = toValue(tmp.shift());
1177
1076
  }
1178
1077
  }
1179
-
1180
1078
  return out;
1181
1079
  }
1182
1080
 
1183
- function _extends() {
1184
- _extends = Object.assign ? Object.assign.bind() : function (target) {
1185
- for (var i = 1; i < arguments.length; i++) {
1186
- var source = arguments[i];
1187
-
1188
- for (var key in source) {
1189
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1190
- target[key] = source[key];
1081
+ // src/core.ts
1082
+ var CurrentReaction = void 0;
1083
+ var CurrentGets = null;
1084
+ var CurrentGetsIndex = 0;
1085
+ var EffectQueue = null;
1086
+ var CacheClean = 0;
1087
+ var CacheCheck = 1;
1088
+ var CacheDirty = 2;
1089
+ var Reactive = class {
1090
+ value;
1091
+ fn;
1092
+ observers = null;
1093
+ sources = null;
1094
+ state;
1095
+ effect;
1096
+ cleanups = null;
1097
+ alwaysUpdate = false;
1098
+ constructor(fnOrValue, type) {
1099
+ if (type != 0 /* Signal */) {
1100
+ this.fn = fnOrValue;
1101
+ this.value = void 0;
1102
+ this.state = CacheDirty;
1103
+ console.error("Memos and effects must be wrapped in a createRoot");
1104
+ this.effect = type == 2 /* Effect */;
1105
+ if (this.effect)
1106
+ this.update();
1107
+ } else {
1108
+ this.fn = void 0;
1109
+ this.value = fnOrValue;
1110
+ this.state = CacheClean;
1111
+ this.effect = false;
1112
+ }
1113
+ }
1114
+ get() {
1115
+ if (CurrentReaction) {
1116
+ if (!CurrentGets && CurrentReaction.sources && CurrentReaction.sources[CurrentGetsIndex] == this) {
1117
+ CurrentGetsIndex++;
1118
+ } else {
1119
+ if (!CurrentGets)
1120
+ CurrentGets = [this];
1121
+ else
1122
+ CurrentGets.push(this);
1123
+ }
1124
+ }
1125
+ if (this.fn)
1126
+ this.updateIfNecessary();
1127
+ return this.value;
1128
+ }
1129
+ set(value) {
1130
+ const notInBatch = !EffectQueue;
1131
+ const newValue = typeof value === "function" ? value(this.value) : value;
1132
+ if ((this.value !== newValue || this.alwaysUpdate) && this.observers) {
1133
+ for (let i = 0; i < this.observers.length; i++) {
1134
+ this.observers[i].stale(CacheDirty);
1135
+ }
1136
+ }
1137
+ this.value = newValue;
1138
+ if (notInBatch)
1139
+ stabilize();
1140
+ return newValue;
1141
+ }
1142
+ stale(state) {
1143
+ if (this.state < state) {
1144
+ if (this.state === CacheClean && this.effect) {
1145
+ if (EffectQueue)
1146
+ EffectQueue.push(this);
1147
+ else
1148
+ EffectQueue = [this];
1149
+ }
1150
+ this.state = state;
1151
+ if (this.observers) {
1152
+ for (let i = 0; i < this.observers.length; i++) {
1153
+ this.observers[i].stale(CacheCheck);
1154
+ }
1155
+ }
1156
+ }
1157
+ }
1158
+ update() {
1159
+ const oldValue = this.value;
1160
+ const prevReaction = CurrentReaction;
1161
+ const prevGets = CurrentGets;
1162
+ const prevIndex = CurrentGetsIndex;
1163
+ CurrentReaction = this;
1164
+ CurrentGets = null;
1165
+ CurrentGetsIndex = 0;
1166
+ try {
1167
+ if (this.cleanups) {
1168
+ this.cleanups.forEach((c) => c());
1169
+ this.cleanups = null;
1170
+ }
1171
+ this.value = this.fn();
1172
+ if (CurrentGets) {
1173
+ this.removeParentObservers(CurrentGetsIndex);
1174
+ if (this.sources && CurrentGetsIndex > 0) {
1175
+ this.sources.length = CurrentGetsIndex + CurrentGets.length;
1176
+ for (let i = 0; i < CurrentGets.length; i++) {
1177
+ this.sources[CurrentGetsIndex + i] = CurrentGets[i];
1178
+ }
1179
+ } else {
1180
+ this.sources = CurrentGets;
1181
+ }
1182
+ for (let i = CurrentGetsIndex; i < this.sources.length; i++) {
1183
+ const source = this.sources[i];
1184
+ if (!source.observers) {
1185
+ source.observers = [this];
1186
+ } else {
1187
+ source.observers.push(this);
1188
+ }
1189
+ }
1190
+ } else if (this.sources && CurrentGetsIndex < this.sources.length) {
1191
+ this.removeParentObservers(CurrentGetsIndex);
1192
+ this.sources.length = CurrentGetsIndex;
1193
+ }
1194
+ } finally {
1195
+ CurrentGets = prevGets;
1196
+ CurrentReaction = prevReaction;
1197
+ CurrentGetsIndex = prevIndex;
1198
+ }
1199
+ if ((oldValue !== this.value || this.alwaysUpdate) && this.observers) {
1200
+ for (let i = 0; i < this.observers.length; i++) {
1201
+ this.observers[i].state = CacheDirty;
1202
+ }
1203
+ }
1204
+ this.state = CacheClean;
1205
+ }
1206
+ updateIfNecessary() {
1207
+ if (this.state === CacheCheck) {
1208
+ for (const source of this.sources) {
1209
+ source.updateIfNecessary();
1210
+ if (this.state === CacheDirty) {
1211
+ break;
1191
1212
  }
1192
1213
  }
1193
1214
  }
1215
+ if (this.state === CacheDirty) {
1216
+ this.update();
1217
+ }
1218
+ this.state = CacheClean;
1219
+ }
1220
+ removeParentObservers(index) {
1221
+ if (!this.sources)
1222
+ return;
1223
+ for (let i = index; i < this.sources.length; i++) {
1224
+ const source = this.sources[i];
1225
+ const swap = source.observers.findIndex((v) => v === this);
1226
+ source.observers[swap] = source.observers[source.observers.length - 1];
1227
+ source.observers.pop();
1228
+ }
1229
+ }
1230
+ destroy() {
1231
+ if (this.cleanups) {
1232
+ this.cleanups.forEach((c) => c());
1233
+ this.cleanups = null;
1234
+ }
1235
+ this.removeParentObservers(0);
1236
+ }
1237
+ };
1238
+ function stabilize() {
1239
+ if (!EffectQueue)
1240
+ return;
1241
+ for (let i = 0; i < EffectQueue.length; i++) {
1242
+ EffectQueue[i].get();
1243
+ }
1244
+ EffectQueue = null;
1245
+ }
1246
+ function batch(fn) {
1247
+ EffectQueue = [];
1248
+ let out = fn();
1249
+ stabilize();
1250
+ return out;
1251
+ }
1194
1252
 
1195
- return target;
1253
+ // src/store.ts
1254
+ var $RAW = Symbol("store-raw");
1255
+ var $TRACK = Symbol("track");
1256
+ var $PROXY = Symbol("store-proxy");
1257
+ var $NODE = Symbol("store-node");
1258
+ function wrap(value) {
1259
+ let p = value[$PROXY];
1260
+ if (!p) {
1261
+ Object.defineProperty(value, $PROXY, {
1262
+ value: p = new Proxy(value, proxyTraps)
1263
+ });
1264
+ if (!Array.isArray(value)) {
1265
+ const keys = Object.keys(value);
1266
+ const desc = Object.getOwnPropertyDescriptors(value);
1267
+ for (let i = 0, l = keys.length; i < l; i++) {
1268
+ const prop = keys[i];
1269
+ if (desc[prop].get) {
1270
+ const get = desc[prop].get.bind(p);
1271
+ Object.defineProperty(value, prop, {
1272
+ enumerable: desc[prop].enumerable,
1273
+ get
1274
+ });
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ return p;
1280
+ }
1281
+ function isWrappable(obj) {
1282
+ let proto;
1283
+ return obj != null && typeof obj === "object" && (obj[$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));
1284
+ }
1285
+ function unwrap(item, set = /* @__PURE__ */ new Set()) {
1286
+ let result, unwrapped, v, prop;
1287
+ if (result = item != null && item[$RAW])
1288
+ return result;
1289
+ if (!isWrappable(item) || set.has(item))
1290
+ return item;
1291
+ if (Array.isArray(item)) {
1292
+ if (Object.isFrozen(item))
1293
+ item = item.slice(0);
1294
+ else
1295
+ set.add(item);
1296
+ for (let i = 0, l = item.length; i < l; i++) {
1297
+ v = item[i];
1298
+ if ((unwrapped = unwrap(v, set)) !== v)
1299
+ item[i] = unwrapped;
1300
+ }
1301
+ } else {
1302
+ if (Object.isFrozen(item))
1303
+ item = Object.assign({}, item);
1304
+ else
1305
+ set.add(item);
1306
+ const keys = Object.keys(item);
1307
+ const desc = Object.getOwnPropertyDescriptors(item);
1308
+ for (let i = 0, l = keys.length; i < l; i++) {
1309
+ prop = keys[i];
1310
+ if (desc[prop].get)
1311
+ continue;
1312
+ v = item[prop];
1313
+ if ((unwrapped = unwrap(v, set)) !== v)
1314
+ item[prop] = unwrapped;
1315
+ }
1316
+ }
1317
+ return item;
1318
+ }
1319
+ function getDataNodes(target) {
1320
+ let nodes = target[$NODE];
1321
+ if (!nodes)
1322
+ Object.defineProperty(target, $NODE, { value: nodes = {} });
1323
+ return nodes;
1324
+ }
1325
+ function getDataNode(nodes, property, value) {
1326
+ return nodes[property] || (nodes[property] = createDataNode(value));
1327
+ }
1328
+ function proxyDescriptor(target, property) {
1329
+ const desc = Reflect.getOwnPropertyDescriptor(target, property);
1330
+ if (!desc || desc.get || !desc.configurable || property === $PROXY || property === $NODE)
1331
+ return desc;
1332
+ delete desc.value;
1333
+ delete desc.writable;
1334
+ desc.get = () => target[$PROXY][property];
1335
+ return desc;
1336
+ }
1337
+ function trackSelf(target) {
1338
+ if (CurrentReaction) {
1339
+ const nodes = getDataNodes(target);
1340
+ (nodes._ || (nodes._ = createDataNode())).get();
1341
+ }
1342
+ }
1343
+ function ownKeys(target) {
1344
+ trackSelf(target);
1345
+ return Reflect.ownKeys(target);
1346
+ }
1347
+ function createDataNode(value) {
1348
+ const s = new Reactive(value, 0);
1349
+ s.alwaysUpdate = true;
1350
+ return s;
1351
+ }
1352
+ var Writing = false;
1353
+ var proxyTraps = {
1354
+ get(target, property, receiver) {
1355
+ if (property === $RAW)
1356
+ return target;
1357
+ if (property === $PROXY)
1358
+ return receiver;
1359
+ if (property === $TRACK) {
1360
+ trackSelf(target);
1361
+ return receiver;
1362
+ }
1363
+ const nodes = getDataNodes(target);
1364
+ const tracked = nodes.hasOwnProperty(property);
1365
+ let value = tracked ? nodes[property].get() : target[property];
1366
+ if (property === $NODE || property === "__proto__")
1367
+ return value;
1368
+ if (!tracked) {
1369
+ const desc = Object.getOwnPropertyDescriptor(target, property);
1370
+ if (CurrentReaction && (typeof value !== "function" || target.hasOwnProperty(property)) && !(desc && desc.get))
1371
+ value = getDataNode(nodes, property, value).get();
1372
+ }
1373
+ return isWrappable(value) ? wrap(value) : value;
1374
+ },
1375
+ has(target, property) {
1376
+ if (property === $RAW || property === $PROXY || property === $TRACK || property === $NODE || property === "__proto__")
1377
+ return true;
1378
+ this.get(target, property, target);
1379
+ return property in target;
1380
+ },
1381
+ set(target, property, value) {
1382
+ Writing && setProperty(target, property, unwrap(value));
1383
+ return true;
1384
+ },
1385
+ deleteProperty(target, property) {
1386
+ Writing && setProperty(target, property, void 0, true);
1387
+ return true;
1388
+ },
1389
+ ownKeys,
1390
+ getOwnPropertyDescriptor: proxyDescriptor
1391
+ };
1392
+ function setProperty(state, property, value, deleting = false) {
1393
+ if (!deleting && state[property] === value)
1394
+ return;
1395
+ const prev = state[property];
1396
+ const len = state.length;
1397
+ if (deleting)
1398
+ delete state[property];
1399
+ else
1400
+ state[property] = value;
1401
+ const nodes = getDataNodes(state);
1402
+ let node;
1403
+ if (node = getDataNode(nodes, property, prev))
1404
+ node.set(() => value);
1405
+ if (Array.isArray(state) && state.length !== len)
1406
+ (node = getDataNode(nodes, "length", len)) && node.set(state.length);
1407
+ (node = nodes._) && node.set();
1408
+ }
1409
+ function createStore(store) {
1410
+ const unwrappedStore = unwrap(store);
1411
+ const wrappedStore = wrap(unwrappedStore);
1412
+ const setStore = (fn) => {
1413
+ batch(() => {
1414
+ try {
1415
+ Writing = true;
1416
+ fn(wrappedStore);
1417
+ } finally {
1418
+ Writing = false;
1419
+ }
1420
+ });
1196
1421
  };
1197
- return _extends.apply(this, arguments);
1422
+ return [wrappedStore, setStore];
1198
1423
  }
1199
1424
 
1200
- function createRoute(routeConfig, options, parent, router) {
1425
+ function createRoute(routeConfig, options, originalIndex, parent, router) {
1201
1426
  const {
1202
1427
  id,
1203
1428
  routeId,
1204
1429
  path: routePath,
1205
1430
  fullPath
1206
1431
  } = routeConfig;
1207
-
1208
- const action = router.state.actions[id] || (() => {
1209
- router.state.actions[id] = {
1210
- pending: [],
1211
- submit: async (submission, actionOpts) => {
1212
- var _actionOpts$invalidat;
1213
-
1214
- if (!route) {
1215
- return;
1216
- }
1217
-
1218
- const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1219
- const actionState = {
1220
- submittedAt: Date.now(),
1221
- status: 'pending',
1222
- submission
1223
- };
1224
- action.current = actionState;
1225
- action.latest = actionState;
1226
- action.pending.push(actionState);
1227
- router.state = _extends({}, router.state, {
1228
- currentAction: actionState,
1229
- latestAction: actionState
1230
- });
1231
- router.notify();
1232
-
1233
- try {
1234
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1235
- actionState.data = res;
1236
-
1237
- if (invalidate) {
1238
- router.invalidateRoute({
1239
- to: '.',
1240
- fromCurrent: true
1241
- });
1242
- await router.reload();
1243
- }
1244
-
1245
- actionState.status = 'success';
1246
- return res;
1247
- } catch (err) {
1248
- console.error(err);
1249
- actionState.error = err;
1250
- actionState.status = 'error';
1251
- } finally {
1252
- action.pending = action.pending.filter(d => d !== actionState);
1253
- router.removeActionQueue.push({
1254
- action,
1255
- actionState
1256
- });
1257
- router.notify();
1258
- }
1259
- }
1260
- };
1261
- return router.state.actions[id];
1262
- })();
1263
-
1264
- const loader = router.state.loaders[id] || (() => {
1265
- router.state.loaders[id] = {
1266
- pending: [],
1267
- fetch: async loaderContext => {
1268
- if (!route) {
1269
- return;
1270
- }
1271
-
1272
- const loaderState = {
1273
- loadedAt: Date.now(),
1274
- loaderContext
1275
- };
1276
- loader.current = loaderState;
1277
- loader.latest = loaderState;
1278
- loader.pending.push(loaderState); // router.state = {
1279
- // ...router.state,
1280
- // currentAction: loaderState,
1281
- // latestAction: loaderState,
1282
- // }
1283
-
1284
- router.notify();
1285
-
1286
- try {
1287
- return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1288
- } finally {
1289
- loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1290
-
1291
- router.notify();
1292
- }
1293
- }
1294
- };
1295
- return router.state.loaders[id];
1296
- })();
1297
-
1298
1432
  let route = {
1433
+ routeInfo: undefined,
1299
1434
  routeId: id,
1300
1435
  routeRouteId: routeId,
1436
+ originalIndex,
1301
1437
  routePath,
1302
1438
  fullPath,
1303
1439
  options,
1304
1440
  router,
1305
1441
  childRoutes: undefined,
1306
1442
  parentRoute: parent,
1307
- action,
1308
- loader: loader,
1309
- buildLink: options => {
1310
- return router.buildLink(_extends({}, options, {
1311
- from: fullPath
1312
- }));
1313
- },
1314
- navigate: options => {
1315
- return router.navigate(_extends({}, options, {
1316
- from: fullPath
1317
- }));
1443
+ get action() {
1444
+ let action = router.store.actions[id] || (() => {
1445
+ router.setStore(s => {
1446
+ s.actions[id] = {
1447
+ submissions: [],
1448
+ submit: async (submission, actionOpts) => {
1449
+ if (!route) {
1450
+ return;
1451
+ }
1452
+ const invalidate = (actionOpts == null ? void 0 : actionOpts.invalidate) ?? true;
1453
+ const [actionStore, setActionStore] = createStore({
1454
+ submittedAt: Date.now(),
1455
+ status: 'pending',
1456
+ submission,
1457
+ isMulti: !!(actionOpts != null && actionOpts.multi)
1458
+ });
1459
+ router.setStore(s => {
1460
+ if (!(actionOpts != null && actionOpts.multi)) {
1461
+ s.actions[id].submissions = action.submissions.filter(d => d.isMulti);
1462
+ }
1463
+ s.actions[id].current = actionStore;
1464
+ s.actions[id].latest = actionStore;
1465
+ s.actions[id].submissions.push(actionStore);
1466
+ });
1467
+ try {
1468
+ const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1469
+ setActionStore(s => {
1470
+ s.data = res;
1471
+ });
1472
+ if (invalidate) {
1473
+ router.invalidateRoute({
1474
+ to: '.',
1475
+ fromCurrent: true
1476
+ });
1477
+ await router.reload();
1478
+ }
1479
+ setActionStore(s => {
1480
+ s.status = 'success';
1481
+ });
1482
+ return res;
1483
+ } catch (err) {
1484
+ console.error(err);
1485
+ setActionStore(s => {
1486
+ s.error = err;
1487
+ s.status = 'error';
1488
+ });
1489
+ }
1490
+ }
1491
+ };
1492
+ });
1493
+ return router.store.actions[id];
1494
+ })();
1495
+ return action;
1318
1496
  },
1319
- matchRoute: (matchLocation, opts) => {
1320
- return router.matchRoute(_extends({}, matchLocation, {
1321
- from: fullPath
1322
- }), opts);
1497
+ get loader() {
1498
+ let loader = router.store.loaders[id] || (() => {
1499
+ router.setStore(s => {
1500
+ s.loaders[id] = {
1501
+ pending: [],
1502
+ fetch: async loaderContext => {
1503
+ if (!route) {
1504
+ return;
1505
+ }
1506
+ const loaderState = {
1507
+ loadedAt: Date.now(),
1508
+ loaderContext
1509
+ };
1510
+ router.setStore(s => {
1511
+ s.loaders[id].current = loaderState;
1512
+ s.loaders[id].latest = loaderState;
1513
+ s.loaders[id].pending.push(loaderState);
1514
+ });
1515
+ try {
1516
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1517
+ } finally {
1518
+ router.setStore(s => {
1519
+ s.loaders[id].pending = s.loaders[id].pending.filter(d => d !== loaderState);
1520
+ });
1521
+ }
1522
+ }
1523
+ };
1524
+ });
1525
+ return router.store.loaders[id];
1526
+ })();
1527
+ return loader;
1323
1528
  }
1529
+
1530
+ // buildLink: (options) => {
1531
+ // return router.buildLink({
1532
+ // ...options,
1533
+ // from: fullPath,
1534
+ // } as any) as any
1535
+ // },
1536
+
1537
+ // navigate: (options) => {
1538
+ // return router.navigate({
1539
+ // ...options,
1540
+ // from: fullPath,
1541
+ // } as any) as any
1542
+ // },
1543
+
1544
+ // matchRoute: (matchLocation, opts) => {
1545
+ // return router.matchRoute(
1546
+ // {
1547
+ // ...matchLocation,
1548
+ // from: fullPath,
1549
+ // } as any,
1550
+ // opts,
1551
+ // ) as any
1552
+ // },
1324
1553
  };
1554
+
1325
1555
  router.options.createRoute == null ? void 0 : router.options.createRoute({
1326
1556
  router,
1327
1557
  route
1328
1558
  });
1329
1559
  return route;
1330
1560
  }
1331
- function cascadeLoaderData(matches) {
1332
- matches.forEach((match, index) => {
1333
- const parent = matches[index - 1];
1334
-
1335
- if (parent) {
1336
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1337
- }
1338
- });
1339
- }
1340
1561
 
1341
1562
  const rootRouteId = '__root__';
1342
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1563
+ const createRouteConfig = function (options, children, isRoot, parentId, parentPath) {
1343
1564
  if (options === void 0) {
1344
1565
  options = {};
1345
1566
  }
1346
-
1347
1567
  if (isRoot === void 0) {
1348
1568
  isRoot = true;
1349
1569
  }
1350
-
1351
1570
  if (isRoot) {
1352
1571
  options.path = rootRouteId;
1353
- } // Strip the root from parentIds
1354
-
1572
+ }
1355
1573
 
1574
+ // Strip the root from parentIds
1356
1575
  if (parentId === rootRouteId) {
1357
1576
  parentId = '';
1358
1577
  }
1578
+ let path = isRoot ? rootRouteId : options.path;
1359
1579
 
1360
- let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1361
-
1580
+ // If the path is anything other than an index path, trim it up
1362
1581
  if (path && path !== '/') {
1363
1582
  path = trimPath(path);
1364
1583
  }
1365
-
1366
1584
  const routeId = path || options.id;
1367
1585
  let id = joinPaths([parentId, routeId]);
1368
-
1369
1586
  if (path === rootRouteId) {
1370
1587
  path = '/';
1371
1588
  }
1372
-
1373
1589
  if (id !== rootRouteId) {
1374
1590
  id = joinPaths(['/', id]);
1375
1591
  }
1376
-
1377
1592
  const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1378
1593
  return {
1379
1594
  id: id,
@@ -1382,256 +1597,340 @@
1382
1597
  fullPath: fullPath,
1383
1598
  options: options,
1384
1599
  children,
1385
- createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1386
1600
  addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1387
- createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1601
+ createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath),
1602
+ generate: () => {
1603
+ invariant(false, `routeConfig.generate() is used by TanStack Router's file-based routing code generation and should not actually be called during runtime. `);
1604
+ }
1388
1605
  };
1389
1606
  };
1390
1607
 
1391
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1392
- function createRouteMatch(router, route, opts) {
1393
- const routeMatch = _extends({}, route, opts, {
1394
- router,
1608
+ /**
1609
+ * This function returns `a` if `b` is deeply equal.
1610
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
1611
+ * This can be used for structural sharing between JSON values for example.
1612
+ */
1613
+ function sharedClone(prev, next, touchAll) {
1614
+ const things = new Map();
1615
+ function recurse(prev, next) {
1616
+ if (prev === next) {
1617
+ return prev;
1618
+ }
1619
+ if (things.has(next)) {
1620
+ return things.get(next);
1621
+ }
1622
+ const prevIsArray = Array.isArray(prev);
1623
+ const nextIsArray = Array.isArray(next);
1624
+ const prevIsObj = isPlainObject(prev);
1625
+ const nextIsObj = isPlainObject(next);
1626
+ const isArray = prevIsArray && nextIsArray;
1627
+ const isObj = prevIsObj && nextIsObj;
1628
+ const isSameStructure = isArray || isObj;
1629
+
1630
+ // Both are arrays or objects
1631
+ if (isSameStructure) {
1632
+ const aSize = isArray ? prev.length : Object.keys(prev).length;
1633
+ const bItems = isArray ? next : Object.keys(next);
1634
+ const bSize = bItems.length;
1635
+ const copy = isArray ? [] : {};
1636
+ let equalItems = 0;
1637
+ for (let i = 0; i < bSize; i++) {
1638
+ const key = isArray ? i : bItems[i];
1639
+ if (copy[key] === prev[key]) {
1640
+ equalItems++;
1641
+ }
1642
+ }
1643
+ if (aSize === bSize && equalItems === aSize) {
1644
+ things.set(next, prev);
1645
+ return prev;
1646
+ }
1647
+ things.set(next, copy);
1648
+ for (let i = 0; i < bSize; i++) {
1649
+ const key = isArray ? i : bItems[i];
1650
+ if (typeof bItems[i] === 'function') {
1651
+ copy[key] = prev[key];
1652
+ } else {
1653
+ copy[key] = recurse(prev[key], next[key]);
1654
+ }
1655
+ if (copy[key] === prev[key]) {
1656
+ equalItems++;
1657
+ }
1658
+ }
1659
+ return copy;
1660
+ }
1661
+ if (nextIsArray) {
1662
+ const copy = [];
1663
+ things.set(next, copy);
1664
+ for (let i = 0; i < next.length; i++) {
1665
+ copy[i] = recurse(undefined, next[i]);
1666
+ }
1667
+ return copy;
1668
+ }
1669
+ if (nextIsObj) {
1670
+ const copy = {};
1671
+ things.set(next, copy);
1672
+ const nextKeys = Object.keys(next);
1673
+ for (let i = 0; i < nextKeys.length; i++) {
1674
+ const key = nextKeys[i];
1675
+ copy[key] = recurse(undefined, next[key]);
1676
+ }
1677
+ return copy;
1678
+ }
1679
+ return next;
1680
+ }
1681
+ return recurse(prev, next);
1682
+ }
1683
+
1684
+ // Copied from: https://github.com/jonschlinkert/is-plain-object
1685
+ function isPlainObject(o) {
1686
+ if (!hasObjectPrototype(o)) {
1687
+ return false;
1688
+ }
1689
+
1690
+ // If has modified constructor
1691
+ const ctor = o.constructor;
1692
+ if (typeof ctor === 'undefined') {
1693
+ return true;
1694
+ }
1695
+
1696
+ // If has modified prototype
1697
+ const prot = ctor.prototype;
1698
+ if (!hasObjectPrototype(prot)) {
1699
+ return false;
1700
+ }
1701
+
1702
+ // If constructor does not have an Object-specific method
1703
+ if (!prot.hasOwnProperty('isPrototypeOf')) {
1704
+ return false;
1705
+ }
1706
+
1707
+ // Most likely a plain Object
1708
+ return true;
1709
+ }
1710
+ function hasObjectPrototype(o) {
1711
+ return Object.prototype.toString.call(o) === '[object Object]';
1712
+ }
1713
+
1714
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1715
+ function createRouteMatch(router, route, opts) {
1716
+ let componentsPromise;
1717
+ let dataPromise;
1718
+ let latestId = '';
1719
+ let resolve = () => {};
1720
+ function setLoaderData(loaderData) {
1721
+ batch(() => {
1722
+ setStore(s => {
1723
+ s.routeLoaderData = sharedClone(s.routeLoaderData, loaderData);
1724
+ });
1725
+ updateLoaderData();
1726
+ });
1727
+ }
1728
+ function updateLoaderData() {
1729
+ setStore(s => {
1730
+ var _store$parentMatch;
1731
+ s.loaderData = sharedClone(s.loaderData, {
1732
+ ...((_store$parentMatch = store.parentMatch) == null ? void 0 : _store$parentMatch.store.loaderData),
1733
+ ...s.routeLoaderData
1734
+ });
1735
+ });
1736
+ }
1737
+ const [store, setStore] = createStore({
1395
1738
  routeSearch: {},
1396
1739
  search: {},
1397
- childMatches: [],
1398
1740
  status: 'idle',
1399
1741
  routeLoaderData: {},
1400
1742
  loaderData: {},
1401
- isPending: false,
1402
1743
  isFetching: false,
1403
- isInvalid: false,
1744
+ invalid: false,
1404
1745
  invalidAt: Infinity,
1405
- getIsInvalid: () => {
1746
+ get isInvalid() {
1406
1747
  const now = Date.now();
1407
- return routeMatch.isInvalid || routeMatch.invalidAt < now;
1408
- },
1748
+ return this.invalid || this.invalidAt < now;
1749
+ }
1750
+ });
1751
+ const routeMatch = {
1752
+ ...route,
1753
+ ...opts,
1754
+ store,
1755
+ // setStore,
1756
+ router,
1757
+ childMatches: [],
1409
1758
  __: {
1410
- abortController: new AbortController(),
1411
- latestId: '',
1412
- resolve: () => {},
1413
- notify: () => {
1414
- routeMatch.__.resolve();
1415
-
1416
- routeMatch.router.notify();
1417
- },
1418
- startPending: () => {
1419
- var _routeMatch$options$p, _routeMatch$options$p2;
1420
-
1421
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1422
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1423
-
1424
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1425
- return;
1426
- }
1427
-
1428
- routeMatch.__.pendingTimeout = setTimeout(() => {
1429
- routeMatch.isPending = true;
1430
-
1431
- routeMatch.__.resolve();
1432
-
1433
- if (typeof pendingMinMs !== 'undefined') {
1434
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1435
- }
1436
- }, pendingMs);
1437
- },
1438
- cancelPending: () => {
1439
- routeMatch.isPending = false;
1440
- clearTimeout(routeMatch.__.pendingTimeout);
1441
- clearTimeout(routeMatch.__.pendingMinTimeout);
1442
- delete routeMatch.__.pendingMinPromise;
1759
+ setParentMatch: parentMatch => {
1760
+ batch(() => {
1761
+ setStore(s => {
1762
+ s.parentMatch = parentMatch;
1763
+ });
1764
+ updateLoaderData();
1765
+ });
1443
1766
  },
1444
- // setParentMatch: (parentMatch?: RouteMatch) => {
1445
- // routeMatch.parentMatch = parentMatch
1446
- // },
1447
- // addChildMatch: (childMatch: RouteMatch) => {
1448
- // if (
1449
- // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1450
- // ) {
1451
- // return
1452
- // }
1453
- // routeMatch.childMatches.push(childMatch)
1454
- // },
1767
+ abortController: new AbortController(),
1455
1768
  validate: () => {
1456
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1457
-
1769
+ var _store$parentMatch2;
1458
1770
  // Validate the search params and stabilize them
1459
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1460
-
1771
+ const parentSearch = ((_store$parentMatch2 = store.parentMatch) == null ? void 0 : _store$parentMatch2.store.search) ?? router.store.currentLocation.search;
1461
1772
  try {
1462
- const prevSearch = routeMatch.routeSearch;
1773
+ const prevSearch = store.routeSearch;
1463
1774
  const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1464
- let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1465
-
1466
- if (prevSearch !== nextSearch) {
1467
- routeMatch.isInvalid = true;
1468
- }
1775
+ let nextSearch = sharedClone(prevSearch, (validator == null ? void 0 : validator(parentSearch)) ?? {});
1776
+ batch(() => {
1777
+ // Invalidate route matches when search param stability changes
1778
+ if (prevSearch !== nextSearch) {
1779
+ setStore(s => s.invalid = true);
1780
+ }
1469
1781
 
1470
- routeMatch.routeSearch = nextSearch;
1471
- routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1782
+ // TODO: Alright, do we need batch() here?
1783
+ setStore(s => {
1784
+ s.routeSearch = nextSearch;
1785
+ s.search = sharedClone(parentSearch, {
1786
+ ...parentSearch,
1787
+ ...nextSearch
1788
+ });
1789
+ });
1790
+ });
1791
+ componentTypes.map(async type => {
1792
+ const component = routeMatch.options[type];
1793
+ if (typeof routeMatch.__[type] !== 'function') {
1794
+ routeMatch.__[type] = component;
1795
+ }
1796
+ });
1472
1797
  } catch (err) {
1473
1798
  console.error(err);
1474
1799
  const error = new Error('Invalid search params found', {
1475
1800
  cause: err
1476
1801
  });
1477
1802
  error.code = 'INVALID_SEARCH_PARAMS';
1478
- routeMatch.status = 'error';
1479
- routeMatch.error = error; // Do not proceed with loading the route
1803
+ setStore(s => {
1804
+ s.status = 'error';
1805
+ s.error = error;
1806
+ });
1480
1807
 
1808
+ // Do not proceed with loading the route
1481
1809
  return;
1482
1810
  }
1483
1811
  }
1484
1812
  },
1485
1813
  cancel: () => {
1486
1814
  var _routeMatch$__$abortC;
1487
-
1488
1815
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1489
-
1490
- routeMatch.__.cancelPending();
1491
1816
  },
1492
1817
  invalidate: () => {
1493
- routeMatch.isInvalid = true;
1818
+ setStore(s => s.invalid = true);
1494
1819
  },
1495
1820
  hasLoaders: () => {
1496
- return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1821
+ return !!(route.options.loader || componentTypes.some(d => {
1822
+ var _route$options$d;
1823
+ return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
1824
+ }));
1497
1825
  },
1498
1826
  load: async loaderOpts => {
1499
1827
  const now = Date.now();
1500
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1828
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
1501
1829
 
1830
+ // If this is a preload, add it to the preload cache
1502
1831
  if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1503
1832
  // If the match is currently active, don't preload it
1504
- if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1833
+ if (router.store.currentMatches.find(d => d.matchId === routeMatch.matchId)) {
1505
1834
  return;
1506
1835
  }
1507
-
1508
- router.matchCache[routeMatch.matchId] = {
1836
+ router.store.matchCache[routeMatch.matchId] = {
1509
1837
  gc: now + loaderOpts.gcMaxAge,
1510
1838
  match: routeMatch
1511
1839
  };
1512
- } // If the match is invalid, errored or idle, trigger it to load
1513
-
1840
+ }
1514
1841
 
1515
- if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1842
+ // If the match is invalid, errored or idle, trigger it to load
1843
+ if (store.status === 'success' && store.isInvalid || store.status === 'error' || store.status === 'idle') {
1516
1844
  const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1517
- routeMatch.fetch({
1845
+ await routeMatch.fetch({
1518
1846
  maxAge
1519
1847
  });
1520
1848
  }
1521
1849
  },
1522
1850
  fetch: async opts => {
1523
- const id = '' + Date.now() + Math.random();
1524
- routeMatch.__.latestId = id; // If the match was in an error state, set it
1525
- // to a loading state again. Otherwise, keep it
1526
- // as loading or resolved
1527
-
1528
- if (routeMatch.status === 'idle') {
1529
- routeMatch.status = 'loading';
1530
- } // We started loading the route, so it's no longer invalid
1531
-
1851
+ const loadId = '' + Date.now() + Math.random();
1852
+ latestId = loadId;
1853
+ const checkLatest = async () => {
1854
+ if (loadId !== latestId) {
1855
+ // warning(true, 'Data loader is out of date!')
1856
+ return new Promise(() => {});
1857
+ }
1858
+ };
1859
+ batch(() => {
1860
+ // If the match was in an error state, set it
1861
+ // to a loading state again. Otherwise, keep it
1862
+ // as loading or resolved
1863
+ if (store.status === 'idle') {
1864
+ setStore(s => s.status = 'loading');
1865
+ }
1532
1866
 
1533
- routeMatch.isInvalid = false;
1534
- routeMatch.__.loadPromise = new Promise(async resolve => {
1867
+ // We started loading the route, so it's no longer invalid
1868
+ setStore(s => s.invalid = false);
1869
+ });
1870
+ routeMatch.__.loadPromise = new Promise(async r => {
1535
1871
  // We are now fetching, even if it's in the background of a
1536
1872
  // resolved state
1537
- routeMatch.isFetching = true;
1538
- routeMatch.__.resolve = resolve;
1539
-
1540
- const loaderPromise = (async () => {
1541
- // Load the elements and data in parallel
1542
- routeMatch.__.elementsPromise = (async () => {
1543
- // then run all element and data loaders in parallel
1544
- // For each element type, potentially load it asynchronously
1545
- await Promise.all(elementTypes.map(async type => {
1546
- const routeElement = routeMatch.options[type];
1547
-
1548
- if (routeMatch.__[type]) {
1549
- return;
1550
- }
1551
-
1552
- routeMatch.__[type] = await router.options.createElement(routeElement);
1553
- }));
1554
- })();
1555
-
1556
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1557
- try {
1558
- var _ref, _ref2, _opts$maxAge;
1559
-
1560
- if (routeMatch.options.loader) {
1561
- const data = await routeMatch.options.loader({
1562
- params: routeMatch.params,
1563
- search: routeMatch.routeSearch,
1564
- signal: routeMatch.__.abortController.signal
1565
- });
1566
-
1567
- if (id !== routeMatch.__.latestId) {
1568
- return routeMatch.__.loaderPromise;
1569
- }
1570
-
1571
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1572
- }
1573
-
1574
- routeMatch.error = undefined;
1575
- routeMatch.status = 'success';
1576
- routeMatch.updatedAt = Date.now();
1577
- 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);
1578
- } catch (err) {
1579
- if (id !== routeMatch.__.latestId) {
1580
- return routeMatch.__.loaderPromise;
1581
- }
1582
-
1583
- {
1584
- console.error(err);
1585
- }
1586
-
1587
- routeMatch.error = err;
1588
- routeMatch.status = 'error';
1589
- routeMatch.updatedAt = Date.now();
1873
+ setStore(s => s.isFetching = true);
1874
+ resolve = r;
1875
+ componentsPromise = (async () => {
1876
+ // then run all component and data loaders in parallel
1877
+ // For each component type, potentially load it asynchronously
1878
+
1879
+ await Promise.all(componentTypes.map(async type => {
1880
+ var _routeMatch$__$type;
1881
+ const component = routeMatch.options[type];
1882
+ if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
1883
+ routeMatch.__[type] = await router.options.loadComponent(component);
1590
1884
  }
1591
- });
1592
-
1885
+ }));
1886
+ })();
1887
+ dataPromise = Promise.resolve().then(async () => {
1593
1888
  try {
1594
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1595
-
1596
- if (id !== routeMatch.__.latestId) {
1597
- return routeMatch.__.loaderPromise;
1889
+ if (routeMatch.options.loader) {
1890
+ const data = await router.loadMatchData(routeMatch);
1891
+ await checkLatest();
1892
+ setLoaderData(data);
1598
1893
  }
1599
-
1600
- if (routeMatch.__.pendingMinPromise) {
1601
- await routeMatch.__.pendingMinPromise;
1602
- delete routeMatch.__.pendingMinPromise;
1603
- }
1604
- } finally {
1605
- if (id !== routeMatch.__.latestId) {
1606
- return routeMatch.__.loaderPromise;
1894
+ setStore(s => {
1895
+ s.error = undefined;
1896
+ s.status = 'success';
1897
+ s.updatedAt = Date.now();
1898
+ s.invalidAt = s.updatedAt + ((opts == null ? void 0 : opts.maxAge) ?? routeMatch.options.loaderMaxAge ?? router.options.defaultLoaderMaxAge ?? 0);
1899
+ });
1900
+ return store.routeLoaderData;
1901
+ } catch (err) {
1902
+ await checkLatest();
1903
+ {
1904
+ console.error(err);
1607
1905
  }
1608
-
1609
- routeMatch.__.cancelPending();
1610
-
1611
- routeMatch.isPending = false;
1612
- routeMatch.isFetching = false;
1613
-
1614
- routeMatch.__.notify();
1906
+ setStore(s => {
1907
+ s.error = err;
1908
+ s.status = 'error';
1909
+ s.updatedAt = Date.now();
1910
+ });
1911
+ throw err;
1615
1912
  }
1616
- })();
1617
-
1618
- routeMatch.__.loaderPromise = loaderPromise;
1619
- await loaderPromise;
1620
-
1621
- if (id !== routeMatch.__.latestId) {
1622
- return routeMatch.__.loaderPromise;
1913
+ });
1914
+ const after = async () => {
1915
+ await checkLatest();
1916
+ setStore(s => s.isFetching = false);
1917
+ delete routeMatch.__.loadPromise;
1918
+ resolve();
1919
+ };
1920
+ try {
1921
+ await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
1922
+ after();
1923
+ } catch {
1924
+ after();
1623
1925
  }
1624
-
1625
- delete routeMatch.__.loaderPromise;
1626
1926
  });
1627
- return await routeMatch.__.loadPromise;
1927
+ await routeMatch.__.loadPromise;
1928
+ await checkLatest();
1628
1929
  }
1629
- });
1630
-
1930
+ };
1631
1931
  if (!routeMatch.hasLoaders()) {
1632
- routeMatch.status = 'success';
1932
+ setStore(s => s.status = 'success');
1633
1933
  }
1634
-
1635
1934
  return routeMatch;
1636
1935
  }
1637
1936
 
@@ -1642,221 +1941,347 @@
1642
1941
  if (searchStr.substring(0, 1) === '?') {
1643
1942
  searchStr = searchStr.substring(1);
1644
1943
  }
1944
+ let query = decode(searchStr);
1645
1945
 
1646
- let query = decode(searchStr); // Try to parse any query params that might be json
1647
-
1946
+ // Try to parse any query params that might be json
1648
1947
  for (let key in query) {
1649
1948
  const value = query[key];
1650
-
1651
1949
  if (typeof value === 'string') {
1652
1950
  try {
1653
1951
  query[key] = parser(value);
1654
- } catch (err) {//
1952
+ } catch (err) {
1953
+ //
1655
1954
  }
1656
1955
  }
1657
1956
  }
1658
-
1659
1957
  return query;
1660
1958
  };
1661
1959
  }
1662
1960
  function stringifySearchWith(stringify) {
1663
1961
  return search => {
1664
- search = _extends({}, search);
1665
-
1962
+ search = {
1963
+ ...search
1964
+ };
1666
1965
  if (search) {
1667
1966
  Object.keys(search).forEach(key => {
1668
1967
  const val = search[key];
1669
-
1670
1968
  if (typeof val === 'undefined' || val === undefined) {
1671
1969
  delete search[key];
1672
1970
  } else if (val && typeof val === 'object' && val !== null) {
1673
1971
  try {
1674
1972
  search[key] = stringify(val);
1675
- } catch (err) {// silent
1973
+ } catch (err) {
1974
+ // silent
1676
1975
  }
1677
1976
  }
1678
1977
  });
1679
1978
  }
1680
-
1681
1979
  const searchStr = encode(search).toString();
1682
- return searchStr ? "?" + searchStr : '';
1980
+ return searchStr ? `?${searchStr}` : '';
1683
1981
  };
1684
1982
  }
1685
1983
 
1686
1984
  var _window$document;
1687
1985
  // Detect if we're in the DOM
1688
- const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
1986
+ const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement);
1689
1987
 
1988
+ // This is the default history object if none is defined
1690
1989
  const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
1691
-
1990
+ function getInitialRouterState() {
1991
+ return {
1992
+ status: 'idle',
1993
+ latestLocation: null,
1994
+ currentLocation: null,
1995
+ currentMatches: [],
1996
+ actions: {},
1997
+ loaders: {},
1998
+ lastUpdated: Date.now(),
1999
+ matchCache: {},
2000
+ get isFetching() {
2001
+ return this.status === 'loading' || this.currentMatches.some(d => d.store.isFetching);
2002
+ },
2003
+ get isPreloading() {
2004
+ return Object.values(this.matchCache).some(d => d.match.store.isFetching && !this.currentMatches.find(dd => dd.matchId === d.match.matchId));
2005
+ }
2006
+ };
2007
+ }
1692
2008
  function createRouter(userOptions) {
1693
- var _userOptions$stringif, _userOptions$parseSea;
1694
-
1695
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1696
-
1697
- const originalOptions = _extends({
2009
+ const originalOptions = {
1698
2010
  defaultLoaderGcMaxAge: 5 * 60 * 1000,
1699
2011
  defaultLoaderMaxAge: 0,
1700
2012
  defaultPreloadMaxAge: 2000,
1701
- defaultPreloadDelay: 50
1702
- }, userOptions, {
1703
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1704
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1705
- });
1706
-
1707
- let router = {
1708
- history,
2013
+ defaultPreloadDelay: 50,
2014
+ context: undefined,
2015
+ ...userOptions,
2016
+ stringifySearch: (userOptions == null ? void 0 : userOptions.stringifySearch) ?? defaultStringifySearch,
2017
+ parseSearch: (userOptions == null ? void 0 : userOptions.parseSearch) ?? defaultParseSearch
2018
+ };
2019
+ const [store, setStore] = createStore(getInitialRouterState());
2020
+ let navigationPromise;
2021
+ let startedLoadingAt = Date.now();
2022
+ let resolveNavigation = () => {};
2023
+ function onFocus() {
2024
+ router.load();
2025
+ }
2026
+ function buildRouteTree(rootRouteConfig) {
2027
+ const recurseRoutes = (routeConfigs, parent) => {
2028
+ return routeConfigs.map((routeConfig, i) => {
2029
+ const routeOptions = routeConfig.options;
2030
+ const route = createRoute(routeConfig, routeOptions, i, parent, router);
2031
+ const existingRoute = router.routesById[route.routeId];
2032
+ if (existingRoute) {
2033
+ {
2034
+ console.warn(`Duplicate routes found with id: ${String(route.routeId)}`, router.routesById, route);
2035
+ }
2036
+ throw new Error();
2037
+ }
2038
+ router.routesById[route.routeId] = route;
2039
+ const children = routeConfig.children;
2040
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2041
+ return route;
2042
+ });
2043
+ };
2044
+ const routes = recurseRoutes([rootRouteConfig]);
2045
+ return routes[0];
2046
+ }
2047
+ function parseLocation(location, previousLocation) {
2048
+ const parsedSearch = router.options.parseSearch(location.search);
2049
+ return {
2050
+ pathname: location.pathname,
2051
+ searchStr: location.search,
2052
+ search: sharedClone(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2053
+ hash: location.hash.split('#').reverse()[0] ?? '',
2054
+ href: `${location.pathname}${location.search}${location.hash}`,
2055
+ state: location.state,
2056
+ key: location.key
2057
+ };
2058
+ }
2059
+ function navigate(location) {
2060
+ const next = router.buildNext(location);
2061
+ return commitLocation(next, location.replace);
2062
+ }
2063
+ function buildLocation(dest) {
2064
+ var _last, _dest$__preSearchFilt, _dest$__preSearchFilt2, _dest$__postSearchFil;
2065
+ if (dest === void 0) {
2066
+ dest = {};
2067
+ }
2068
+ const fromPathname = dest.fromCurrent ? store.latestLocation.pathname : dest.from ?? store.latestLocation.pathname;
2069
+ let pathname = resolvePath(router.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
2070
+ const fromMatches = router.matchRoutes(store.latestLocation.pathname, {
2071
+ strictParseParams: true
2072
+ });
2073
+ const toMatches = router.matchRoutes(pathname);
2074
+ const prevParams = {
2075
+ ...((_last = last(fromMatches)) == null ? void 0 : _last.params)
2076
+ };
2077
+ let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2078
+ if (nextParams) {
2079
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2080
+ Object.assign({}, nextParams, fn(nextParams));
2081
+ });
2082
+ }
2083
+ pathname = interpolatePath(pathname, nextParams ?? {});
2084
+
2085
+ // Pre filters first
2086
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), store.latestLocation.search) : store.latestLocation.search;
2087
+
2088
+ // Then the link/navigate function
2089
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2090
+ : dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
2091
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2092
+ : {};
2093
+
2094
+ // Then post filters
2095
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2096
+ const search = sharedClone(store.latestLocation.search, postFilteredSearch);
2097
+ const searchStr = router.options.stringifySearch(search);
2098
+ let hash = dest.hash === true ? store.latestLocation.hash : functionalUpdate(dest.hash, store.latestLocation.hash);
2099
+ hash = hash ? `#${hash}` : '';
2100
+ return {
2101
+ pathname,
2102
+ search,
2103
+ searchStr,
2104
+ state: store.latestLocation.state,
2105
+ hash,
2106
+ href: `${pathname}${searchStr}${hash}`,
2107
+ key: dest.key
2108
+ };
2109
+ }
2110
+ function commitLocation(next, replace) {
2111
+ const id = '' + Date.now() + Math.random();
2112
+ let nextAction = 'replace';
2113
+ if (!replace) {
2114
+ nextAction = 'push';
2115
+ }
2116
+ const isSameUrl = parseLocation(router.history.location).href === next.href;
2117
+ if (isSameUrl && !next.key) {
2118
+ nextAction = 'replace';
2119
+ }
2120
+ router.history[nextAction]({
2121
+ pathname: next.pathname,
2122
+ hash: next.hash,
2123
+ search: next.searchStr
2124
+ }, {
2125
+ id,
2126
+ ...next.state
2127
+ });
2128
+ return navigationPromise = new Promise(resolve => {
2129
+ const previousNavigationResolve = resolveNavigation;
2130
+ resolveNavigation = () => {
2131
+ previousNavigationResolve();
2132
+ resolve();
2133
+ };
2134
+ });
2135
+ }
2136
+ const router = {
2137
+ types: undefined,
2138
+ // public api
2139
+ history: (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory(),
2140
+ store,
2141
+ setStore,
1709
2142
  options: originalOptions,
1710
- listeners: [],
1711
- removeActionQueue: [],
1712
- // Resolved after construction
1713
2143
  basepath: '',
1714
2144
  routeTree: undefined,
1715
2145
  routesById: {},
1716
- location: undefined,
1717
- allRouteInfo: undefined,
1718
- //
1719
- navigationPromise: Promise.resolve(),
1720
- resolveNavigation: () => {},
1721
- matchCache: {},
1722
- state: {
1723
- status: 'idle',
1724
- location: null,
1725
- matches: [],
1726
- actions: {},
1727
- loaders: {},
1728
- loaderData: {},
1729
- lastUpdated: Date.now(),
1730
- isFetching: false,
1731
- isPreloading: false
1732
- },
1733
- startedLoadingAt: Date.now(),
1734
- subscribe: listener => {
1735
- router.listeners.push(listener);
1736
- return () => {
1737
- router.listeners = router.listeners.filter(x => x !== listener);
1738
- };
2146
+ reset: () => {
2147
+ setStore(s => Object.assign(s, getInitialRouterState()));
1739
2148
  },
1740
2149
  getRoute: id => {
1741
2150
  return router.routesById[id];
1742
2151
  },
1743
- notify: () => {
1744
- router.state = _extends({}, router.state, {
1745
- isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1746
- isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
2152
+ dehydrate: () => {
2153
+ return {
2154
+ store: {
2155
+ ...pick(store, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
2156
+ currentMatches: store.currentMatches.map(match => ({
2157
+ matchId: match.matchId,
2158
+ store: pick(match.store, ['status', 'routeLoaderData', 'isInvalid', 'invalidAt'])
2159
+ }))
2160
+ },
2161
+ context: router.options.context
2162
+ };
2163
+ },
2164
+ hydrate: dehydratedRouter => {
2165
+ setStore(s => {
2166
+ // Update the context TODO: make this part of state?
2167
+ router.options.context = dehydratedRouter.context;
2168
+
2169
+ // Match the routes
2170
+ const currentMatches = router.matchRoutes(dehydratedRouter.store.latestLocation.pathname, {
2171
+ strictParseParams: true
2172
+ });
2173
+ currentMatches.forEach((match, index) => {
2174
+ const dehydratedMatch = dehydratedRouter.store.currentMatches[index];
2175
+ invariant(dehydratedMatch && dehydratedMatch.matchId === match.matchId, 'Oh no! There was a hydration mismatch when attempting to restore the state of the router! 😬');
2176
+ Object.assign(match, dehydratedMatch);
2177
+ });
2178
+ currentMatches.forEach(match => match.__.validate());
2179
+ Object.assign(s, {
2180
+ ...dehydratedRouter.store,
2181
+ currentMatches
2182
+ });
1747
2183
  });
1748
- cascadeLoaderData(router.state.matches);
1749
- router.listeners.forEach(listener => listener(router));
1750
2184
  },
1751
2185
  mount: () => {
1752
- const next = router.__.buildLocation({
1753
- to: '.',
1754
- search: true,
1755
- hash: true
1756
- }); // If the current location isn't updated, trigger a navigation
1757
- // to the current location. Otherwise, load the current location.
1758
-
1759
-
1760
- if (next.href !== router.location.href) {
1761
- router.__.commitLocation(next, true);
1762
- } else {
1763
- router.loadLocation();
1764
- }
1765
-
1766
- const unsub = history.listen(event => {
1767
- router.loadLocation(router.__.parseLocation(event.location, router.location));
1768
- }); // addEventListener does not exist in React Native, but window does
1769
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2186
+ // Mount only does anything on the client
2187
+ if (!isServer) {
2188
+ // If the router matches are empty, load the matches
2189
+ if (!store.currentMatches.length) {
2190
+ router.load();
2191
+ }
2192
+ const unsub = router.history.listen(event => {
2193
+ router.load(parseLocation(event.location, store.latestLocation));
2194
+ });
1770
2195
 
1771
- if (!isServer && window.addEventListener) {
1772
- // Listen to visibillitychange and focus
1773
- window.addEventListener('visibilitychange', router.onFocus, false);
1774
- window.addEventListener('focus', router.onFocus, false);
2196
+ // addEventListener does not exist in React Native, but window does
2197
+ // In the future, we might need to invert control here for more adapters
2198
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2199
+ if (window.addEventListener) {
2200
+ // Listen to visibilitychange and focus
2201
+ window.addEventListener('visibilitychange', onFocus, false);
2202
+ window.addEventListener('focus', onFocus, false);
2203
+ }
2204
+ return () => {
2205
+ unsub();
2206
+ if (window.removeEventListener) {
2207
+ // Be sure to unsubscribe if a new handler is set
2208
+ window.removeEventListener('visibilitychange', onFocus);
2209
+ window.removeEventListener('focus', onFocus);
2210
+ }
2211
+ };
1775
2212
  }
1776
-
1777
- return () => {
1778
- unsub(); // Be sure to unsubscribe if a new handler is set
1779
-
1780
- window.removeEventListener('visibilitychange', router.onFocus);
1781
- window.removeEventListener('focus', router.onFocus);
1782
- };
1783
- },
1784
- onFocus: () => {
1785
- router.loadLocation();
2213
+ return () => {};
1786
2214
  },
1787
2215
  update: opts => {
2216
+ const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
2217
+ if (!store.latestLocation || newHistory) {
2218
+ if (opts != null && opts.history) {
2219
+ router.history = opts.history;
2220
+ }
2221
+ setStore(s => {
2222
+ s.latestLocation = parseLocation(router.history.location);
2223
+ s.currentLocation = s.latestLocation;
2224
+ });
2225
+ }
1788
2226
  Object.assign(router.options, opts);
1789
2227
  const {
1790
2228
  basepath,
1791
2229
  routeConfig
1792
2230
  } = router.options;
1793
- router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1794
-
2231
+ router.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
1795
2232
  if (routeConfig) {
1796
2233
  router.routesById = {};
1797
- router.routeTree = router.__.buildRouteTree(routeConfig);
2234
+ router.routeTree = buildRouteTree(routeConfig);
1798
2235
  }
1799
-
1800
2236
  return router;
1801
2237
  },
1802
2238
  cancelMatches: () => {
1803
- var _router$state$pending, _router$state$pending2;
1804
- [...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 => {
2239
+ [...store.currentMatches, ...(store.pendingMatches || [])].forEach(match => {
1805
2240
  match.cancel();
1806
2241
  });
1807
2242
  },
1808
- loadLocation: async next => {
1809
- const id = Math.random();
1810
- router.startedLoadingAt = id;
1811
-
1812
- if (next) {
1813
- // Ingest the new location
1814
- router.location = next;
1815
- } // Clear out old actions
1816
-
1817
-
1818
- router.removeActionQueue.forEach(_ref => {
1819
- let {
1820
- action,
1821
- actionState
1822
- } = _ref;
1823
-
1824
- if (router.state.currentAction === actionState) {
1825
- router.state.currentAction = undefined;
2243
+ load: async next => {
2244
+ let now = Date.now();
2245
+ const startedAt = now;
2246
+ startedLoadingAt = startedAt;
2247
+
2248
+ // Cancel any pending matches
2249
+ router.cancelMatches();
2250
+ let matches;
2251
+ batch(() => {
2252
+ if (next) {
2253
+ // Ingest the new location
2254
+ setStore(s => {
2255
+ s.latestLocation = next;
2256
+ });
1826
2257
  }
1827
2258
 
1828
- if (action.current === actionState) {
1829
- action.current = undefined;
1830
- }
1831
- });
1832
- router.removeActionQueue = []; // Cancel any pending matches
1833
-
1834
- router.cancelMatches(); // Match the routes
1835
-
1836
- const matches = router.matchRoutes(location.pathname, {
1837
- strictParseParams: true
1838
- });
1839
- router.state = _extends({}, router.state, {
1840
- pending: {
1841
- matches: matches,
1842
- location: router.location
1843
- },
1844
- status: 'loading'
1845
- });
1846
- router.notify(); // Load the matches
1847
-
1848
- await router.loadMatches(matches, {
1849
- withPending: true
2259
+ // Match the routes
2260
+ matches = router.matchRoutes(store.latestLocation.pathname, {
2261
+ strictParseParams: true
2262
+ });
2263
+ console.log('set loading', matches);
2264
+ setStore(s => {
2265
+ s.status = 'loading';
2266
+ s.pendingMatches = matches;
2267
+ s.pendingLocation = store.latestLocation;
2268
+ });
1850
2269
  });
1851
2270
 
1852
- if (router.startedLoadingAt !== id) {
1853
- // Ignore side-effects of match loading
1854
- return router.navigationPromise;
2271
+ // Load the matches
2272
+ try {
2273
+ await router.loadMatches(matches);
2274
+ } catch (err) {
2275
+ console.log(err);
2276
+ invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
1855
2277
  }
1856
-
1857
- const previousMatches = router.state.matches;
2278
+ if (startedLoadingAt !== startedAt) {
2279
+ // Ignore side-effects of outdated side-effects
2280
+ return navigationPromise;
2281
+ }
2282
+ const previousMatches = store.currentMatches;
1858
2283
  const exiting = [],
1859
- staying = [];
2284
+ staying = [];
1860
2285
  previousMatches.forEach(d => {
1861
2286
  if (matches.find(dd => dd.matchId === d.matchId)) {
1862
2287
  staying.push(d);
@@ -1864,24 +2289,24 @@
1864
2289
  exiting.push(d);
1865
2290
  }
1866
2291
  });
1867
- const now = Date.now();
2292
+ const entering = matches.filter(d => {
2293
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
2294
+ });
2295
+ now = Date.now();
1868
2296
  exiting.forEach(d => {
1869
- var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1870
-
1871
2297
  d.__.onExit == null ? void 0 : d.__.onExit({
1872
2298
  params: d.params,
1873
- search: d.routeSearch
1874
- }); // Clear idle error states when match leaves
2299
+ search: d.store.routeSearch
2300
+ });
1875
2301
 
1876
- if (d.status === 'error' && !d.isFetching) {
1877
- d.status = 'idle';
1878
- d.error = undefined;
2302
+ // Clear idle error states when match leaves
2303
+ if (d.store.status === 'error' && !d.store.isFetching) {
2304
+ d.store.status = 'idle';
2305
+ d.store.error = undefined;
1879
2306
  }
1880
-
1881
- 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);
1882
-
2307
+ const gc = Math.max(d.options.loaderGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0, d.options.loaderMaxAge ?? router.options.defaultLoaderMaxAge ?? 0);
1883
2308
  if (gc > 0) {
1884
- router.matchCache[d.matchId] = {
2309
+ store.matchCache[d.matchId] = {
1885
2310
  gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1886
2311
  match: d
1887
2312
  };
@@ -1890,62 +2315,65 @@
1890
2315
  staying.forEach(d => {
1891
2316
  d.options.onTransition == null ? void 0 : d.options.onTransition({
1892
2317
  params: d.params,
1893
- search: d.routeSearch
2318
+ search: d.store.routeSearch
1894
2319
  });
1895
2320
  });
1896
- const entering = matches.filter(d => {
1897
- return !previousMatches.find(dd => dd.matchId === d.matchId);
1898
- });
1899
2321
  entering.forEach(d => {
1900
- d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
2322
+ d.__.onExit = d.options.onLoaded == null ? void 0 : d.options.onLoaded({
1901
2323
  params: d.params,
1902
- search: d.search
2324
+ search: d.store.search
1903
2325
  });
1904
- delete router.matchCache[d.matchId];
2326
+ delete store.matchCache[d.matchId];
1905
2327
  });
1906
-
1907
- if (matches.some(d => d.status === 'loading')) {
1908
- router.notify();
1909
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
1910
- }
1911
-
1912
- if (router.startedLoadingAt !== id) {
2328
+ if (startedLoadingAt !== startedAt) {
1913
2329
  // Ignore side-effects of match loading
1914
2330
  return;
1915
2331
  }
1916
-
1917
- router.state = _extends({}, router.state, {
1918
- location: router.location,
1919
- matches,
1920
- pending: undefined,
1921
- status: 'idle'
2332
+ matches.forEach(match => {
2333
+ // Clear actions
2334
+ if (match.action) {
2335
+ // TODO: Check reactivity here
2336
+ match.action.current = undefined;
2337
+ match.action.submissions = [];
2338
+ }
1922
2339
  });
1923
- router.notify();
1924
- router.resolveNavigation();
2340
+ setStore(s => {
2341
+ console.log('set', matches);
2342
+ Object.assign(s, {
2343
+ status: 'idle',
2344
+ currentLocation: store.latestLocation,
2345
+ currentMatches: matches,
2346
+ pendingLocation: undefined,
2347
+ pendingMatches: undefined
2348
+ });
2349
+ });
2350
+ resolveNavigation();
1925
2351
  },
1926
2352
  cleanMatchCache: () => {
1927
2353
  const now = Date.now();
1928
- Object.keys(router.matchCache).forEach(matchId => {
1929
- const entry = router.matchCache[matchId]; // Don't remove loading matches
2354
+ setStore(s => {
2355
+ Object.keys(s.matchCache).forEach(matchId => {
2356
+ const entry = s.matchCache[matchId];
1930
2357
 
1931
- if (entry.match.status === 'loading') {
1932
- return;
1933
- } // Do not remove successful matches that are still valid
1934
-
1935
-
1936
- if (entry.gc > 0 && entry.gc > now) {
1937
- return;
1938
- } // Everything else gets removed
2358
+ // Don't remove loading matches
2359
+ if (entry.match.store.status === 'loading') {
2360
+ return;
2361
+ }
1939
2362
 
2363
+ // Do not remove successful matches that are still valid
2364
+ if (entry.gc > 0 && entry.gc > now) {
2365
+ return;
2366
+ }
1940
2367
 
1941
- delete router.matchCache[matchId];
2368
+ // Everything else gets removed
2369
+ delete s.matchCache[matchId];
2370
+ });
1942
2371
  });
1943
2372
  },
1944
- loadRoute: async function loadRoute(navigateOpts) {
2373
+ loadRoute: async function (navigateOpts) {
1945
2374
  if (navigateOpts === void 0) {
1946
- navigateOpts = router.location;
2375
+ navigateOpts = store.latestLocation;
1947
2376
  }
1948
-
1949
2377
  const next = router.buildNext(navigateOpts);
1950
2378
  const matches = router.matchRoutes(next.pathname, {
1951
2379
  strictParseParams: true
@@ -1953,143 +2381,176 @@
1953
2381
  await router.loadMatches(matches);
1954
2382
  return matches;
1955
2383
  },
1956
- preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1957
- var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
1958
-
2384
+ preloadRoute: async function (navigateOpts, loaderOpts) {
1959
2385
  if (navigateOpts === void 0) {
1960
- navigateOpts = router.location;
2386
+ navigateOpts = store.latestLocation;
1961
2387
  }
1962
-
1963
2388
  const next = router.buildNext(navigateOpts);
1964
2389
  const matches = router.matchRoutes(next.pathname, {
1965
2390
  strictParseParams: true
1966
2391
  });
1967
2392
  await router.loadMatches(matches, {
1968
2393
  preload: true,
1969
- maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
1970
- gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
2394
+ maxAge: loaderOpts.maxAge ?? router.options.defaultPreloadMaxAge ?? router.options.defaultLoaderMaxAge ?? 0,
2395
+ gcMaxAge: loaderOpts.gcMaxAge ?? router.options.defaultPreloadGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0
1971
2396
  });
1972
2397
  return matches;
1973
2398
  },
1974
2399
  matchRoutes: (pathname, opts) => {
1975
- var _router$state$pending3, _router$state$pending4;
1976
-
1977
2400
  router.cleanMatchCache();
1978
2401
  const matches = [];
1979
-
1980
2402
  if (!router.routeTree) {
1981
2403
  return matches;
1982
2404
  }
1983
-
1984
- 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 : [])];
1985
-
2405
+ const existingMatches = [...store.currentMatches, ...(store.pendingMatches ?? [])];
1986
2406
  const recurse = async routes => {
1987
- var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
1988
-
2407
+ var _foundRoute$childRout;
1989
2408
  const parentMatch = last(matches);
1990
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1991
- const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
2409
+ let params = (parentMatch == null ? void 0 : parentMatch.params) ?? {};
2410
+ const filteredRoutes = (router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) ?? routes;
1992
2411
  let foundRoutes = [];
1993
-
1994
2412
  const findMatchInRoutes = (parentRoutes, routes) => {
1995
2413
  routes.some(route => {
1996
- var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
1997
-
2414
+ var _route$childRoutes, _route$childRoutes2;
1998
2415
  if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
1999
2416
  return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
2000
2417
  }
2001
-
2002
2418
  const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
2003
- const matchParams = matchPathname(pathname, {
2419
+ const matchParams = matchPathname(router.basepath, pathname, {
2004
2420
  to: route.fullPath,
2005
2421
  fuzzy,
2006
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2422
+ caseSensitive: route.options.caseSensitive ?? router.options.caseSensitive
2007
2423
  });
2008
-
2009
2424
  if (matchParams) {
2010
2425
  let parsedParams;
2011
-
2012
2426
  try {
2013
- var _route$options$parseP;
2014
-
2015
- parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
2427
+ parsedParams = (route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) ?? matchParams;
2016
2428
  } catch (err) {
2017
2429
  if (opts != null && opts.strictParseParams) {
2018
2430
  throw err;
2019
2431
  }
2020
2432
  }
2021
-
2022
- params = _extends({}, params, parsedParams);
2433
+ params = {
2434
+ ...params,
2435
+ ...parsedParams
2436
+ };
2023
2437
  }
2024
-
2025
2438
  if (!!matchParams) {
2026
2439
  foundRoutes = [...parentRoutes, route];
2027
2440
  }
2028
-
2029
2441
  return !!foundRoutes.length;
2030
2442
  });
2031
2443
  return !!foundRoutes.length;
2032
2444
  };
2033
-
2034
2445
  findMatchInRoutes([], filteredRoutes);
2035
-
2036
2446
  if (!foundRoutes.length) {
2037
2447
  return;
2038
2448
  }
2039
-
2040
2449
  foundRoutes.forEach(foundRoute => {
2041
- var _router$matchCache$ma;
2042
-
2450
+ var _store$matchCache$mat;
2043
2451
  const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2044
2452
  const matchId = interpolatePath(foundRoute.routeId, params, true);
2045
- const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2453
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_store$matchCache$mat = store.matchCache[matchId]) == null ? void 0 : _store$matchCache$mat.match) || createRouteMatch(router, foundRoute, {
2454
+ parentMatch,
2046
2455
  matchId,
2047
2456
  params,
2048
- pathname: joinPaths([pathname, interpolatedPath])
2457
+ pathname: joinPaths([router.basepath, interpolatedPath])
2049
2458
  });
2050
2459
  matches.push(match);
2051
2460
  });
2052
2461
  const foundRoute = last(foundRoutes);
2053
-
2054
2462
  if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2055
2463
  recurse(foundRoute.childRoutes);
2056
2464
  }
2057
2465
  };
2058
-
2059
2466
  recurse([router.routeTree]);
2060
- cascadeLoaderData(matches);
2467
+ linkMatches(matches);
2061
2468
  return matches;
2062
2469
  },
2063
2470
  loadMatches: async (resolvedMatches, loaderOpts) => {
2064
- const matchPromises = resolvedMatches.map(async match => {
2471
+ resolvedMatches.forEach(async match => {
2065
2472
  // Validate the match (loads search params etc)
2066
2473
  match.__.validate();
2474
+ });
2067
2475
 
2476
+ // Check each match middleware to see if the route can be accessed
2477
+ await Promise.all(resolvedMatches.map(async match => {
2478
+ try {
2479
+ await (match.options.beforeLoad == null ? void 0 : match.options.beforeLoad({
2480
+ router: router,
2481
+ match
2482
+ }));
2483
+ } catch (err) {
2484
+ if (!(loaderOpts != null && loaderOpts.preload)) {
2485
+ match.options.onLoadError == null ? void 0 : match.options.onLoadError(err);
2486
+ }
2487
+ throw err;
2488
+ }
2489
+ }));
2490
+ const matchPromises = resolvedMatches.map(async match => {
2491
+ var _search$__data;
2492
+ const search = match.store.search;
2493
+ if ((_search$__data = search.__data) != null && _search$__data.matchId && search.__data.matchId !== match.matchId) {
2494
+ return;
2495
+ }
2068
2496
  match.load(loaderOpts);
2069
-
2070
- if (match.status === 'loading') {
2071
- // If requested, start the pending timers
2072
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2073
- // This might be completion, error, or a pending state
2074
-
2497
+ if (match.store.status !== 'success' && match.__.loadPromise) {
2498
+ // Wait for the first sign of activity from the match
2075
2499
  await match.__.loadPromise;
2076
2500
  }
2077
2501
  });
2078
- router.notify();
2079
2502
  await Promise.all(matchPromises);
2080
2503
  },
2081
- invalidateRoute: opts => {
2082
- var _router$state$pending5, _router$state$pending6;
2504
+ loadMatchData: async routeMatch => {
2505
+ if (isServer || !router.options.useServerData) {
2506
+ return (await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
2507
+ // parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
2508
+ params: routeMatch.params,
2509
+ search: routeMatch.store.routeSearch,
2510
+ signal: routeMatch.__.abortController.signal
2511
+ }))) || {};
2512
+ } else {
2513
+ const next = router.buildNext({
2514
+ to: '.',
2515
+ search: d => ({
2516
+ ...(d ?? {}),
2517
+ __data: {
2518
+ matchId: routeMatch.matchId
2519
+ }
2520
+ })
2521
+ });
2522
+
2523
+ // Refresh:
2524
+ // '/dashboard'
2525
+ // '/dashboard/invoices/'
2526
+ // '/dashboard/invoices/123'
2527
+
2528
+ // New:
2529
+ // '/dashboard/invoices/456'
2530
+
2531
+ // TODO: batch requests when possible
2083
2532
 
2533
+ const res = await fetch(next.href, {
2534
+ method: 'GET'
2535
+ // signal: routeMatch.__.abortController.signal,
2536
+ });
2537
+
2538
+ if (res.ok) {
2539
+ return res.json();
2540
+ }
2541
+ throw new Error('Failed to fetch match data');
2542
+ }
2543
+ },
2544
+ invalidateRoute: opts => {
2084
2545
  const next = router.buildNext(opts);
2085
2546
  const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2086
- [...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 => {
2547
+ [...store.currentMatches, ...(store.pendingMatches ?? [])].forEach(match => {
2087
2548
  if (unloadedMatchIds.includes(match.matchId)) {
2088
2549
  match.invalidate();
2089
2550
  }
2090
2551
  });
2091
2552
  },
2092
- reload: () => router.__.navigate({
2553
+ reload: () => navigate({
2093
2554
  fromCurrent: true,
2094
2555
  replace: true,
2095
2556
  search: true
@@ -2098,31 +2559,28 @@
2098
2559
  return resolvePath(router.basepath, from, cleanPath(path));
2099
2560
  },
2100
2561
  matchRoute: (location, opts) => {
2101
- var _location$from;
2102
-
2103
2562
  // const location = router.buildNext(opts)
2104
- location = _extends({}, location, {
2105
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2106
- });
2107
- const next = router.buildNext(location);
2108
2563
 
2564
+ location = {
2565
+ ...location,
2566
+ to: location.to ? router.resolvePath(location.from ?? '', location.to) : undefined
2567
+ };
2568
+ const next = router.buildNext(location);
2109
2569
  if (opts != null && opts.pending) {
2110
- var _router$state$pending7;
2111
-
2112
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2570
+ if (!store.pendingLocation) {
2113
2571
  return false;
2114
2572
  }
2115
-
2116
- return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2573
+ return !!matchPathname(router.basepath, store.pendingLocation.pathname, {
2574
+ ...opts,
2117
2575
  to: next.pathname
2118
- }));
2576
+ });
2119
2577
  }
2120
-
2121
- return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2578
+ return matchPathname(router.basepath, store.currentLocation.pathname, {
2579
+ ...opts,
2122
2580
  to: next.pathname
2123
- }));
2581
+ });
2124
2582
  },
2125
- navigate: async _ref8 => {
2583
+ navigate: async _ref => {
2126
2584
  let {
2127
2585
  from,
2128
2586
  to = '.',
@@ -2130,22 +2588,21 @@
2130
2588
  hash,
2131
2589
  replace,
2132
2590
  params
2133
- } = _ref8;
2591
+ } = _ref;
2134
2592
  // If this link simply reloads the current route,
2135
2593
  // make sure it has a new key so it will trigger a data refresh
2594
+
2136
2595
  // If this `to` is a valid external URL, return
2137
2596
  // null for LinkUtils
2138
2597
  const toString = String(to);
2139
2598
  const fromString = String(from);
2140
2599
  let isExternal;
2141
-
2142
2600
  try {
2143
- new URL("" + toString);
2601
+ new URL(`${toString}`);
2144
2602
  isExternal = true;
2145
2603
  } catch (e) {}
2146
-
2147
2604
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2148
- return router.__.navigate({
2605
+ return navigate({
2149
2606
  from: fromString,
2150
2607
  to: toString,
2151
2608
  search,
@@ -2154,9 +2611,7 @@
2154
2611
  params
2155
2612
  });
2156
2613
  },
2157
- buildLink: _ref9 => {
2158
- var _preload, _ref10;
2159
-
2614
+ buildLink: _ref2 => {
2160
2615
  let {
2161
2616
  from,
2162
2617
  to = '.',
@@ -2171,20 +2626,20 @@
2171
2626
  preloadGcMaxAge: userPreloadGcMaxAge,
2172
2627
  preloadDelay: userPreloadDelay,
2173
2628
  disabled
2174
- } = _ref9;
2175
-
2629
+ } = _ref2;
2176
2630
  // If this link simply reloads the current route,
2177
2631
  // make sure it has a new key so it will trigger a data refresh
2632
+
2178
2633
  // If this `to` is a valid external URL, return
2179
2634
  // null for LinkUtils
2635
+
2180
2636
  try {
2181
- new URL("" + to);
2637
+ new URL(`${to}`);
2182
2638
  return {
2183
2639
  type: 'external',
2184
2640
  href: to
2185
2641
  };
2186
2642
  } catch (e) {}
2187
-
2188
2643
  const nextOpts = {
2189
2644
  from,
2190
2645
  to,
@@ -2194,70 +2649,72 @@
2194
2649
  replace
2195
2650
  };
2196
2651
  const next = router.buildNext(nextOpts);
2197
- preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2198
- const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2652
+ preload = preload ?? router.options.defaultPreload;
2653
+ const preloadDelay = userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0;
2199
2654
 
2200
- const pathIsEqual = router.state.location.pathname === next.pathname;
2201
- const currentPathSplit = router.state.location.pathname.split('/');
2655
+ // Compare path/hash for matches
2656
+ const pathIsEqual = store.currentLocation.pathname === next.pathname;
2657
+ const currentPathSplit = store.currentLocation.pathname.split('/');
2202
2658
  const nextPathSplit = next.pathname.split('/');
2203
2659
  const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2204
- const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2205
-
2660
+ const hashIsEqual = store.currentLocation.hash === next.hash;
2661
+ // Combine the matches based on user options
2206
2662
  const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2207
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2663
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true;
2208
2664
 
2209
- const isActive = pathTest && hashTest; // The click handler
2665
+ // The final "active" test
2666
+ const isActive = pathTest && hashTest;
2210
2667
 
2668
+ // The click handler
2211
2669
  const handleClick = e => {
2212
2670
  if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2213
2671
  e.preventDefault();
2214
-
2215
2672
  if (pathIsEqual && !search && !hash) {
2216
2673
  router.invalidateRoute(nextOpts);
2217
- } // All is well? Navigate!)
2218
-
2674
+ }
2219
2675
 
2220
- router.__.navigate(nextOpts);
2676
+ // All is well? Navigate!
2677
+ navigate(nextOpts);
2221
2678
  }
2222
- }; // The click handler
2223
-
2679
+ };
2224
2680
 
2681
+ // The click handler
2225
2682
  const handleFocus = e => {
2226
2683
  if (preload) {
2227
2684
  router.preloadRoute(nextOpts, {
2228
2685
  maxAge: userPreloadMaxAge,
2229
2686
  gcMaxAge: userPreloadGcMaxAge
2687
+ }).catch(err => {
2688
+ console.log(err);
2689
+ console.warn('Error preloading route! ☝️');
2230
2690
  });
2231
2691
  }
2232
2692
  };
2233
-
2234
2693
  const handleEnter = e => {
2235
2694
  const target = e.target || {};
2236
-
2237
2695
  if (preload) {
2238
2696
  if (target.preloadTimeout) {
2239
2697
  return;
2240
2698
  }
2241
-
2242
2699
  target.preloadTimeout = setTimeout(() => {
2243
2700
  target.preloadTimeout = null;
2244
2701
  router.preloadRoute(nextOpts, {
2245
2702
  maxAge: userPreloadMaxAge,
2246
2703
  gcMaxAge: userPreloadGcMaxAge
2704
+ }).catch(err => {
2705
+ console.log(err);
2706
+ console.warn('Error preloading route! ☝️');
2247
2707
  });
2248
2708
  }, preloadDelay);
2249
2709
  }
2250
2710
  };
2251
-
2252
2711
  const handleLeave = e => {
2253
2712
  const target = e.target || {};
2254
-
2255
2713
  if (target.preloadTimeout) {
2256
2714
  clearTimeout(target.preloadTimeout);
2257
2715
  target.preloadTimeout = null;
2258
2716
  }
2259
2717
  };
2260
-
2261
2718
  return {
2262
2719
  type: 'internal',
2263
2720
  next,
@@ -2270,184 +2727,37 @@
2270
2727
  };
2271
2728
  },
2272
2729
  buildNext: opts => {
2273
- const next = router.__.buildLocation(opts);
2274
-
2730
+ const next = buildLocation(opts);
2275
2731
  const matches = router.matchRoutes(next.pathname);
2276
-
2277
- const __preSearchFilters = matches.map(match => {
2278
- var _match$options$preSea;
2279
-
2280
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2281
- }).flat().filter(Boolean);
2282
-
2283
- const __postSearchFilters = matches.map(match => {
2284
- var _match$options$postSe;
2285
-
2286
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2287
- }).flat().filter(Boolean);
2288
-
2289
- return router.__.buildLocation(_extends({}, opts, {
2732
+ const __preSearchFilters = matches.map(match => match.options.preSearchFilters ?? []).flat().filter(Boolean);
2733
+ const __postSearchFilters = matches.map(match => match.options.postSearchFilters ?? []).flat().filter(Boolean);
2734
+ return buildLocation({
2735
+ ...opts,
2290
2736
  __preSearchFilters,
2291
2737
  __postSearchFilters
2292
- }));
2293
- },
2294
- __: {
2295
- buildRouteTree: rootRouteConfig => {
2296
- const recurseRoutes = (routeConfigs, parent) => {
2297
- return routeConfigs.map(routeConfig => {
2298
- const routeOptions = routeConfig.options;
2299
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
2300
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2301
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2302
- // }
2303
-
2304
- const existingRoute = router.routesById[route.routeId];
2305
-
2306
- if (existingRoute) {
2307
- {
2308
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2309
- }
2310
-
2311
- throw new Error();
2312
- }
2313
- router.routesById[route.routeId] = route;
2314
- const children = routeConfig.children;
2315
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2316
- return route;
2317
- });
2318
- };
2319
-
2320
- const routes = recurseRoutes([rootRouteConfig]);
2321
- return routes[0];
2322
- },
2323
- parseLocation: (location, previousLocation) => {
2324
- var _location$hash$split$;
2325
-
2326
- const parsedSearch = router.options.parseSearch(location.search);
2327
- return {
2328
- pathname: location.pathname,
2329
- searchStr: location.search,
2330
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2331
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2332
- href: "" + location.pathname + location.search + location.hash,
2333
- state: location.state,
2334
- key: location.key
2335
- };
2336
- },
2337
- navigate: location => {
2338
- const next = router.buildNext(location);
2339
- return router.__.commitLocation(next, location.replace);
2340
- },
2341
- buildLocation: function buildLocation(dest) {
2342
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2343
-
2344
- if (dest === void 0) {
2345
- dest = {};
2346
- }
2347
-
2348
- // const resolvedFrom: Location = {
2349
- // ...router.location,
2350
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2351
-
2352
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2353
-
2354
- const fromMatches = router.matchRoutes(router.location.pathname, {
2355
- strictParseParams: true
2356
- });
2357
- const toMatches = router.matchRoutes(pathname);
2358
-
2359
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2360
-
2361
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2362
-
2363
- if (nextParams) {
2364
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2365
- Object.assign({}, nextParams, fn(nextParams));
2366
- });
2367
- }
2368
-
2369
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2370
-
2371
- 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
2372
-
2373
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2374
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2375
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2376
- : {}; // Then post filters
2377
-
2378
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2379
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2380
- const searchStr = router.options.stringifySearch(search);
2381
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2382
- hash = hash ? "#" + hash : '';
2383
- return {
2384
- pathname,
2385
- search,
2386
- searchStr,
2387
- state: router.location.state,
2388
- hash,
2389
- href: "" + pathname + searchStr + hash,
2390
- key: dest.key
2391
- };
2392
- },
2393
- commitLocation: (next, replace) => {
2394
- const id = '' + Date.now() + Math.random();
2395
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2396
- let nextAction = 'replace';
2397
-
2398
- if (!replace) {
2399
- nextAction = 'push';
2400
- }
2401
-
2402
- const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2403
-
2404
- if (isSameUrl && !next.key) {
2405
- nextAction = 'replace';
2406
- }
2407
-
2408
- if (nextAction === 'replace') {
2409
- history.replace({
2410
- pathname: next.pathname,
2411
- hash: next.hash,
2412
- search: next.searchStr
2413
- }, {
2414
- id
2415
- });
2416
- } else {
2417
- history.push({
2418
- pathname: next.pathname,
2419
- hash: next.hash,
2420
- search: next.searchStr
2421
- }, {
2422
- id
2423
- });
2424
- }
2425
-
2426
- router.navigationPromise = new Promise(resolve => {
2427
- const previousNavigationResolve = router.resolveNavigation;
2428
-
2429
- router.resolveNavigation = () => {
2430
- previousNavigationResolve();
2431
- resolve();
2432
- };
2433
- });
2434
- return router.navigationPromise;
2435
- }
2738
+ });
2436
2739
  }
2437
2740
  };
2438
- router.location = router.__.parseLocation(history.location);
2439
- router.state.location = router.location;
2440
- router.update(userOptions); // Allow frameworks to hook into the router creation
2741
+ router.update(userOptions);
2441
2742
 
2743
+ // Allow frameworks to hook into the router creation
2442
2744
  router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2443
2745
  return router;
2444
2746
  }
2445
-
2446
2747
  function isCtrlEvent(e) {
2447
2748
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2448
2749
  }
2750
+ function linkMatches(matches) {
2751
+ matches.forEach((match, index) => {
2752
+ const parent = matches[index - 1];
2753
+ if (parent) {
2754
+ match.__.setParentMatch(parent);
2755
+ } else {
2756
+ match.__.setParentMatch(undefined);
2757
+ }
2758
+ });
2759
+ }
2449
2760
 
2450
- exports.cascadeLoaderData = cascadeLoaderData;
2451
2761
  exports.cleanPath = cleanPath;
2452
2762
  exports.createBrowserHistory = createBrowserHistory;
2453
2763
  exports.createHashHistory = createHashHistory;
@@ -2469,9 +2779,10 @@
2469
2779
  exports.matchPathname = matchPathname;
2470
2780
  exports.parsePathname = parsePathname;
2471
2781
  exports.parseSearchWith = parseSearchWith;
2472
- exports.replaceEqualDeep = replaceEqualDeep;
2782
+ exports.pick = pick;
2473
2783
  exports.resolvePath = resolvePath;
2474
2784
  exports.rootRouteId = rootRouteId;
2785
+ exports.sharedClone = sharedClone;
2475
2786
  exports.stringifySearchWith = stringifySearchWith;
2476
2787
  exports.trimPath = trimPath;
2477
2788
  exports.trimPathLeft = trimPathLeft;