@tanstack/router-core 0.0.1-beta.35 → 0.0.1-beta.39

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 (38) hide show
  1. package/build/cjs/index.js +2 -1
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/path.js +5 -7
  4. package/build/cjs/path.js.map +1 -1
  5. package/build/cjs/route.js +112 -96
  6. package/build/cjs/route.js.map +1 -1
  7. package/build/cjs/routeConfig.js +2 -2
  8. package/build/cjs/routeConfig.js.map +1 -1
  9. package/build/cjs/routeMatch.js +107 -65
  10. package/build/cjs/routeMatch.js.map +1 -1
  11. package/build/cjs/router.js +352 -372
  12. package/build/cjs/router.js.map +1 -1
  13. package/build/cjs/searchParams.js +4 -3
  14. package/build/cjs/searchParams.js.map +1 -1
  15. package/build/cjs/sharedClone.js +122 -0
  16. package/build/cjs/sharedClone.js.map +1 -0
  17. package/build/cjs/utils.js +1 -59
  18. package/build/cjs/utils.js.map +1 -1
  19. package/build/esm/index.js +686 -614
  20. package/build/esm/index.js.map +1 -1
  21. package/build/stats-html.html +1 -1
  22. package/build/stats-react.json +183 -158
  23. package/build/types/index.d.ts +61 -78
  24. package/build/umd/index.development.js +1032 -617
  25. package/build/umd/index.development.js.map +1 -1
  26. package/build/umd/index.production.js +1 -1
  27. package/build/umd/index.production.js.map +1 -1
  28. package/package.json +2 -1
  29. package/src/index.ts +1 -0
  30. package/src/link.ts +20 -12
  31. package/src/route.ts +160 -140
  32. package/src/routeConfig.ts +7 -2
  33. package/src/routeMatch.ts +146 -99
  34. package/src/router.ts +462 -523
  35. package/src/sharedClone.ts +118 -0
  36. package/src/utils.ts +0 -65
  37. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -31
  38. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
@@ -14,8 +14,8 @@
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
21
  for (var key in source) {
@@ -26,7 +26,7 @@
26
26
  }
27
27
  return target;
28
28
  };
29
- return _extends$1.apply(this, arguments);
29
+ return _extends.apply(this, arguments);
30
30
  }
31
31
 
32
32
  /**
@@ -170,7 +170,7 @@
170
170
 
171
171
  if (index == null) {
172
172
  index = 0;
173
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
173
+ globalHistory.replaceState(_extends({}, globalHistory.state, {
174
174
  idx: index
175
175
  }), '');
176
176
  }
@@ -185,7 +185,7 @@
185
185
  state = null;
186
186
  }
187
187
 
188
- return readOnly(_extends$1({
188
+ return readOnly(_extends({
189
189
  pathname: location.pathname,
190
190
  hash: '',
191
191
  search: ''
@@ -419,7 +419,7 @@
419
419
 
420
420
  if (index == null) {
421
421
  index = 0;
422
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
422
+ globalHistory.replaceState(_extends({}, globalHistory.state, {
423
423
  idx: index
424
424
  }), '');
425
425
  }
@@ -446,7 +446,7 @@
446
446
  state = null;
447
447
  }
448
448
 
449
- return readOnly(_extends$1({
449
+ return readOnly(_extends({
450
450
  pathname: location.pathname,
451
451
  hash: '',
452
452
  search: ''
@@ -598,7 +598,7 @@
598
598
  initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
599
599
  initialIndex = _options3.initialIndex;
600
600
  var entries = initialEntries.map(function (entry) {
601
- var location = readOnly(_extends$1({
601
+ var location = readOnly(_extends({
602
602
  pathname: '/',
603
603
  search: '',
604
604
  hash: '',
@@ -623,7 +623,7 @@
623
623
  state = null;
624
624
  }
625
625
 
626
- return readOnly(_extends$1({
626
+ return readOnly(_extends({
627
627
  pathname: location.pathname,
628
628
  search: '',
629
629
  hash: ''
@@ -830,63 +830,6 @@
830
830
  throw new Error(value);
831
831
  }
832
832
 
833
- /**
834
- * This function returns `a` if `b` is deeply equal.
835
- * If not, it will replace any deeply equal children of `b` with those of `a`.
836
- * This can be used for structural sharing between JSON values for example.
837
- */
838
- function replaceEqualDeep(prev, next) {
839
- if (prev === next) {
840
- return prev;
841
- }
842
- const array = Array.isArray(prev) && Array.isArray(next);
843
- if (array || isPlainObject(prev) && isPlainObject(next)) {
844
- const aSize = array ? prev.length : Object.keys(prev).length;
845
- const bItems = array ? next : Object.keys(next);
846
- const bSize = bItems.length;
847
- const copy = array ? [] : {};
848
- let equalItems = 0;
849
- for (let i = 0; i < bSize; i++) {
850
- const key = array ? i : bItems[i];
851
- copy[key] = replaceEqualDeep(prev[key], next[key]);
852
- if (copy[key] === prev[key]) {
853
- equalItems++;
854
- }
855
- }
856
- return aSize === bSize && equalItems === aSize ? prev : copy;
857
- }
858
- return next;
859
- }
860
-
861
- // Copied from: https://github.com/jonschlinkert/is-plain-object
862
- function isPlainObject(o) {
863
- if (!hasObjectPrototype(o)) {
864
- return false;
865
- }
866
-
867
- // If has modified constructor
868
- const ctor = o.constructor;
869
- if (typeof ctor === 'undefined') {
870
- return true;
871
- }
872
-
873
- // If has modified prototype
874
- const prot = ctor.prototype;
875
- if (!hasObjectPrototype(prot)) {
876
- return false;
877
- }
878
-
879
- // If constructor does not have an Object-specific method
880
- if (!prot.hasOwnProperty('isPrototypeOf')) {
881
- return false;
882
- }
883
-
884
- // Most likely a plain Object
885
- return true;
886
- }
887
- function hasObjectPrototype(o) {
888
- return Object.prototype.toString.call(o) === '[object Object]';
889
- }
890
833
  function last(arr) {
891
834
  return arr[arr.length - 1];
892
835
  }
@@ -895,7 +838,7 @@
895
838
  if (typeof console !== 'undefined') console.warn(message);
896
839
  try {
897
840
  throw new Error(message);
898
- } catch (_unused) {}
841
+ } catch {}
899
842
  }
900
843
  return true;
901
844
  }
@@ -932,8 +875,8 @@
932
875
  return trimPathRight(trimPathLeft(path));
933
876
  }
934
877
  function resolvePath(basepath, base, to) {
935
- base = base.replace(new RegExp("^" + basepath), '/');
936
- to = to.replace(new RegExp("^" + basepath), '/');
878
+ base = base.replace(new RegExp(`^${basepath}`), '/');
879
+ to = to.replace(new RegExp(`^${basepath}`), '/');
937
880
  let baseSegments = parsePathname(base);
938
881
  const toSegments = parsePathname(to);
939
882
  toSegments.forEach((toSegment, index) => {
@@ -1014,8 +957,7 @@
1014
957
  return '';
1015
958
  }
1016
959
  if (segment.type === 'param') {
1017
- var _segment$value$substr;
1018
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
960
+ return params[segment.value.substring(1)] ?? '';
1019
961
  }
1020
962
  return segment.value;
1021
963
  }));
@@ -1027,16 +969,15 @@
1027
969
  if (matchLocation.to && !pathParams) {
1028
970
  return;
1029
971
  }
1030
- return pathParams != null ? pathParams : {};
972
+ return pathParams ?? {};
1031
973
  }
1032
974
  function matchByPath(basepath, from, matchLocation) {
1033
- var _matchLocation$to;
1034
975
  if (!from.startsWith(basepath)) {
1035
976
  return undefined;
1036
977
  }
1037
978
  from = basepath != '/' ? from.substring(basepath.length) : from;
1038
979
  const baseSegments = parsePathname(from);
1039
- const to = "" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*');
980
+ const to = `${matchLocation.to ?? '*'}`;
1040
981
  const routeSegments = parsePathname(to);
1041
982
  const params = {};
1042
983
  let isMatch = (() => {
@@ -1137,135 +1078,480 @@
1137
1078
  return out;
1138
1079
  }
1139
1080
 
1140
- function _extends() {
1141
- _extends = Object.assign ? Object.assign.bind() : function (target) {
1142
- for (var i = 1; i < arguments.length; i++) {
1143
- var source = arguments[i];
1144
- for (var key in source) {
1145
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1146
- 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);
1147
1154
  }
1148
1155
  }
1149
1156
  }
1150
- return target;
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;
1212
+ }
1213
+ }
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
+ }
1252
+
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
+ });
1151
1421
  };
1152
- return _extends.apply(this, arguments);
1422
+ return [wrappedStore, setStore];
1153
1423
  }
1154
1424
 
1155
- function createRoute(routeConfig, options, parent, router) {
1425
+ function createRoute(routeConfig, options, originalIndex, parent, router) {
1156
1426
  const {
1157
1427
  id,
1158
1428
  routeId,
1159
1429
  path: routePath,
1160
1430
  fullPath
1161
1431
  } = routeConfig;
1162
- const action = router.state.actions[id] || (() => {
1163
- router.state.actions[id] = {
1164
- submissions: [],
1165
- submit: async (submission, actionOpts) => {
1166
- var _actionOpts$invalidat;
1167
- if (!route) {
1168
- return;
1169
- }
1170
- const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1171
- if (!(actionOpts != null && actionOpts.multi)) {
1172
- action.submissions = action.submissions.filter(d => d.isMulti);
1173
- }
1174
- const actionState = {
1175
- submittedAt: Date.now(),
1176
- status: 'pending',
1177
- submission,
1178
- isMulti: !!(actionOpts != null && actionOpts.multi)
1179
- };
1180
- action.current = actionState;
1181
- action.latest = actionState;
1182
- action.submissions.push(actionState);
1183
- router.notify();
1184
- try {
1185
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1186
- actionState.data = res;
1187
- if (invalidate) {
1188
- router.invalidateRoute({
1189
- to: '.',
1190
- fromCurrent: true
1191
- });
1192
- await router.reload();
1193
- }
1194
- actionState.status = 'success';
1195
- return res;
1196
- } catch (err) {
1197
- console.log('tanner');
1198
- console.error(err);
1199
- actionState.error = err;
1200
- actionState.status = 'error';
1201
- } finally {
1202
- router.notify();
1203
- }
1204
- }
1205
- };
1206
- return router.state.actions[id];
1207
- })();
1208
- const loader = router.state.loaders[id] || (() => {
1209
- router.state.loaders[id] = {
1210
- pending: [],
1211
- fetch: async loaderContext => {
1212
- if (!route) {
1213
- return;
1214
- }
1215
- const loaderState = {
1216
- loadedAt: Date.now(),
1217
- loaderContext
1218
- };
1219
- loader.current = loaderState;
1220
- loader.latest = loaderState;
1221
- loader.pending.push(loaderState);
1222
-
1223
- // router.state = {
1224
- // ...router.state,
1225
- // currentAction: loaderState,
1226
- // latestAction: loaderState,
1227
- // }
1228
-
1229
- router.notify();
1230
- try {
1231
- return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1232
- } finally {
1233
- loader.pending = loader.pending.filter(d => d !== loaderState);
1234
- // router.removeActionQueue.push({ loader, loaderState })
1235
- router.notify();
1236
- }
1237
- }
1238
- };
1239
- return router.state.loaders[id];
1240
- })();
1241
1432
  let route = {
1242
1433
  routeInfo: undefined,
1243
1434
  routeId: id,
1244
1435
  routeRouteId: routeId,
1436
+ originalIndex,
1245
1437
  routePath,
1246
1438
  fullPath,
1247
1439
  options,
1248
1440
  router,
1249
1441
  childRoutes: undefined,
1250
1442
  parentRoute: parent,
1251
- action,
1252
- loader: loader,
1253
- buildLink: options => {
1254
- return router.buildLink(_extends({}, options, {
1255
- from: fullPath
1256
- }));
1257
- },
1258
- navigate: options => {
1259
- return router.navigate(_extends({}, options, {
1260
- from: fullPath
1261
- }));
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;
1262
1496
  },
1263
- matchRoute: (matchLocation, opts) => {
1264
- return router.matchRoute(_extends({}, matchLocation, {
1265
- from: fullPath
1266
- }), 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;
1267
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
+ // },
1268
1553
  };
1554
+
1269
1555
  router.options.createRoute == null ? void 0 : router.options.createRoute({
1270
1556
  router,
1271
1557
  route
@@ -1274,7 +1560,7 @@
1274
1560
  }
1275
1561
 
1276
1562
  const rootRouteId = '__root__';
1277
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1563
+ const createRouteConfig = function (options, children, isRoot, parentId, parentPath) {
1278
1564
  if (options === void 0) {
1279
1565
  options = {};
1280
1566
  }
@@ -1314,53 +1600,194 @@
1314
1600
  addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1315
1601
  createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath),
1316
1602
  generate: () => {
1317
- invariant(false, "routeConfig.generate() is used by TanStack Router's file-based routing code generation and should not actually be called during runtime. ");
1603
+ invariant(false, `routeConfig.generate() is used by TanStack Router's file-based routing code generation and should not actually be called during runtime. `);
1318
1604
  }
1319
1605
  };
1320
1606
  };
1321
1607
 
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
+
1322
1714
  const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1323
1715
  function createRouteMatch(router, route, opts) {
1324
- const routeMatch = _extends({}, route, opts, {
1325
- router,
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({
1326
1738
  routeSearch: {},
1327
1739
  search: {},
1328
- childMatches: [],
1329
1740
  status: 'idle',
1330
1741
  routeLoaderData: {},
1331
1742
  loaderData: {},
1332
1743
  isFetching: false,
1333
- isInvalid: false,
1744
+ invalid: false,
1334
1745
  invalidAt: Infinity,
1335
- // pendingActions: [],
1336
- getIsInvalid: () => {
1746
+ get isInvalid() {
1337
1747
  const now = Date.now();
1338
- return routeMatch.isInvalid || routeMatch.invalidAt < now;
1339
- },
1748
+ return this.invalid || this.invalidAt < now;
1749
+ }
1750
+ });
1751
+ const routeMatch = {
1752
+ ...route,
1753
+ ...opts,
1754
+ store,
1755
+ // setStore,
1756
+ router,
1757
+ childMatches: [],
1340
1758
  __: {
1341
- abortController: new AbortController(),
1342
- latestId: '',
1343
- resolve: () => {},
1344
- notify: () => {
1345
- routeMatch.__.resolve();
1346
- routeMatch.router.notify();
1759
+ setParentMatch: parentMatch => {
1760
+ batch(() => {
1761
+ setStore(s => {
1762
+ s.parentMatch = parentMatch;
1763
+ });
1764
+ updateLoaderData();
1765
+ });
1347
1766
  },
1767
+ abortController: new AbortController(),
1348
1768
  validate: () => {
1349
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1769
+ var _store$parentMatch2;
1350
1770
  // Validate the search params and stabilize them
1351
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.__location.search;
1771
+ const parentSearch = ((_store$parentMatch2 = store.parentMatch) == null ? void 0 : _store$parentMatch2.store.search) ?? router.store.currentLocation.search;
1352
1772
  try {
1353
- var _validator;
1354
- const prevSearch = routeMatch.routeSearch;
1773
+ const prevSearch = store.routeSearch;
1355
1774
  const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1356
- let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {});
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
+ }
1357
1781
 
1358
- // Invalidate route matches when search param stability changes
1359
- if (prevSearch !== nextSearch) {
1360
- routeMatch.isInvalid = true;
1361
- }
1362
- routeMatch.routeSearch = nextSearch;
1363
- 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
+ });
1364
1791
  componentTypes.map(async type => {
1365
1792
  const component = routeMatch.options[type];
1366
1793
  if (typeof routeMatch.__[type] !== 'function') {
@@ -1373,8 +1800,11 @@
1373
1800
  cause: err
1374
1801
  });
1375
1802
  error.code = 'INVALID_SEARCH_PARAMS';
1376
- routeMatch.status = 'error';
1377
- routeMatch.error = error;
1803
+ setStore(s => {
1804
+ s.status = 'error';
1805
+ s.error = error;
1806
+ });
1807
+
1378
1808
  // Do not proceed with loading the route
1379
1809
  return;
1380
1810
  }
@@ -1385,7 +1815,7 @@
1385
1815
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1386
1816
  },
1387
1817
  invalidate: () => {
1388
- routeMatch.isInvalid = true;
1818
+ setStore(s => s.invalid = true);
1389
1819
  },
1390
1820
  hasLoaders: () => {
1391
1821
  return !!(route.options.loader || componentTypes.some(d => {
@@ -1400,17 +1830,17 @@
1400
1830
  // If this is a preload, add it to the preload cache
1401
1831
  if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1402
1832
  // If the match is currently active, don't preload it
1403
- if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1833
+ if (router.store.currentMatches.find(d => d.matchId === routeMatch.matchId)) {
1404
1834
  return;
1405
1835
  }
1406
- router.matchCache[routeMatch.matchId] = {
1836
+ router.store.matchCache[routeMatch.matchId] = {
1407
1837
  gc: now + loaderOpts.gcMaxAge,
1408
1838
  match: routeMatch
1409
1839
  };
1410
1840
  }
1411
1841
 
1412
1842
  // If the match is invalid, errored or idle, trigger it to load
1413
- if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1843
+ if (store.status === 'success' && store.isInvalid || store.status === 'error' || store.status === 'idle') {
1414
1844
  const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1415
1845
  await routeMatch.fetch({
1416
1846
  maxAge
@@ -1419,29 +1849,30 @@
1419
1849
  },
1420
1850
  fetch: async opts => {
1421
1851
  const loadId = '' + Date.now() + Math.random();
1422
- routeMatch.__.latestId = loadId;
1852
+ latestId = loadId;
1423
1853
  const checkLatest = async () => {
1424
- if (loadId !== routeMatch.__.latestId) {
1854
+ if (loadId !== latestId) {
1425
1855
  // warning(true, 'Data loader is out of date!')
1426
1856
  return new Promise(() => {});
1427
1857
  }
1428
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
+ }
1429
1866
 
1430
- // If the match was in an error state, set it
1431
- // to a loading state again. Otherwise, keep it
1432
- // as loading or resolved
1433
- if (routeMatch.status === 'idle') {
1434
- routeMatch.status = 'loading';
1435
- }
1436
-
1437
- // We started loading the route, so it's no longer invalid
1438
- routeMatch.isInvalid = false;
1439
- 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 => {
1440
1871
  // We are now fetching, even if it's in the background of a
1441
1872
  // resolved state
1442
- routeMatch.isFetching = true;
1443
- routeMatch.__.resolve = resolve;
1444
- routeMatch.__.componentsPromise = (async () => {
1873
+ setStore(s => s.isFetching = true);
1874
+ resolve = r;
1875
+ componentsPromise = (async () => {
1445
1876
  // then run all component and data loaders in parallel
1446
1877
  // For each component type, potentially load it asynchronously
1447
1878
 
@@ -1453,49 +1884,52 @@
1453
1884
  }
1454
1885
  }));
1455
1886
  })();
1456
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1887
+ dataPromise = Promise.resolve().then(async () => {
1457
1888
  try {
1458
- var _ref, _ref2, _opts$maxAge;
1459
1889
  if (routeMatch.options.loader) {
1460
1890
  const data = await router.loadMatchData(routeMatch);
1461
1891
  await checkLatest();
1462
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1892
+ setLoaderData(data);
1463
1893
  }
1464
- routeMatch.error = undefined;
1465
- routeMatch.status = 'success';
1466
- routeMatch.updatedAt = Date.now();
1467
- 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);
1468
- return routeMatch.routeLoaderData;
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;
1469
1901
  } catch (err) {
1470
1902
  await checkLatest();
1471
1903
  {
1472
1904
  console.error(err);
1473
1905
  }
1474
- routeMatch.error = err;
1475
- routeMatch.status = 'error';
1476
- routeMatch.updatedAt = Date.now();
1906
+ setStore(s => {
1907
+ s.error = err;
1908
+ s.status = 'error';
1909
+ s.updatedAt = Date.now();
1910
+ });
1477
1911
  throw err;
1478
1912
  }
1479
1913
  });
1480
1914
  const after = async () => {
1481
1915
  await checkLatest();
1482
- routeMatch.isFetching = false;
1916
+ setStore(s => s.isFetching = false);
1483
1917
  delete routeMatch.__.loadPromise;
1484
- routeMatch.__.notify();
1918
+ resolve();
1485
1919
  };
1486
1920
  try {
1487
- await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise.catch(() => {})]);
1921
+ await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
1488
1922
  after();
1489
- } catch (_unused) {
1923
+ } catch {
1490
1924
  after();
1491
1925
  }
1492
1926
  });
1493
1927
  await routeMatch.__.loadPromise;
1494
1928
  await checkLatest();
1495
1929
  }
1496
- });
1930
+ };
1497
1931
  if (!routeMatch.hasLoaders()) {
1498
- routeMatch.status = 'success';
1932
+ setStore(s => s.status = 'success');
1499
1933
  }
1500
1934
  return routeMatch;
1501
1935
  }
@@ -1525,7 +1959,9 @@
1525
1959
  }
1526
1960
  function stringifySearchWith(stringify) {
1527
1961
  return search => {
1528
- search = _extends({}, search);
1962
+ search = {
1963
+ ...search
1964
+ };
1529
1965
  if (search) {
1530
1966
  Object.keys(search).forEach(key => {
1531
1967
  const val = search[key];
@@ -1541,7 +1977,7 @@
1541
1977
  });
1542
1978
  }
1543
1979
  const searchStr = encode(search).toString();
1544
- return searchStr ? "?" + searchStr : '';
1980
+ return searchStr ? `?${searchStr}` : '';
1545
1981
  };
1546
1982
  }
1547
1983
 
@@ -1554,216 +1990,296 @@
1554
1990
  function getInitialRouterState() {
1555
1991
  return {
1556
1992
  status: 'idle',
1557
- location: null,
1558
- matches: [],
1993
+ latestLocation: null,
1994
+ currentLocation: null,
1995
+ currentMatches: [],
1559
1996
  actions: {},
1560
1997
  loaders: {},
1561
1998
  lastUpdated: Date.now(),
1562
- isFetching: false,
1563
- isPreloading: false
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
+ }
1564
2006
  };
1565
2007
  }
1566
2008
  function createRouter(userOptions) {
1567
- var _userOptions$stringif, _userOptions$parseSea;
1568
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1569
- const originalOptions = _extends({
2009
+ const originalOptions = {
1570
2010
  defaultLoaderGcMaxAge: 5 * 60 * 1000,
1571
2011
  defaultLoaderMaxAge: 0,
1572
2012
  defaultPreloadMaxAge: 2000,
1573
2013
  defaultPreloadDelay: 50,
1574
- context: undefined
1575
- }, userOptions, {
1576
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1577
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1578
- });
1579
- let router = {
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 = {
1580
2137
  types: undefined,
1581
2138
  // public api
1582
- history,
2139
+ history: (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory(),
2140
+ store,
2141
+ setStore,
1583
2142
  options: originalOptions,
1584
- listeners: [],
1585
- // Resolved after construction
1586
2143
  basepath: '',
1587
2144
  routeTree: undefined,
1588
2145
  routesById: {},
1589
- __location: undefined,
1590
- //
1591
- resolveNavigation: () => {},
1592
- matchCache: {},
1593
- state: getInitialRouterState(),
1594
2146
  reset: () => {
1595
- router.state = getInitialRouterState();
1596
- router.notify();
1597
- },
1598
- startedLoadingAt: Date.now(),
1599
- subscribe: listener => {
1600
- router.listeners.push(listener);
1601
- return () => {
1602
- router.listeners = router.listeners.filter(x => x !== listener);
1603
- };
2147
+ setStore(s => Object.assign(s, getInitialRouterState()));
1604
2148
  },
1605
2149
  getRoute: id => {
1606
2150
  return router.routesById[id];
1607
2151
  },
1608
- notify: () => {
1609
- const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
1610
- const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
1611
- if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1612
- router.state = _extends({}, router.state, {
1613
- isFetching,
1614
- isPreloading
1615
- });
1616
- }
1617
- cascadeLoaderData(router.state.matches);
1618
- router.listeners.forEach(listener => listener(router));
1619
- },
1620
2152
  dehydrate: () => {
1621
2153
  return {
1622
- location: router.__location,
1623
- state: _extends({}, pick(router.state, ['status', 'location', 'lastUpdated', 'location']), {
1624
- matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
1625
- }),
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
+ },
1626
2161
  context: router.options.context
1627
2162
  };
1628
2163
  },
1629
- hydrate: dehydratedState => {
1630
- // Update the location
1631
- router.__location = dehydratedState.location;
1632
-
1633
- // Update the context
1634
- router.options.context = dehydratedState.context;
2164
+ hydrate: dehydratedRouter => {
2165
+ setStore(s => {
2166
+ // Update the context TODO: make this part of state?
2167
+ router.options.context = dehydratedRouter.context;
1635
2168
 
1636
- // Match the routes
1637
- const matches = router.matchRoutes(router.__location.pathname, {
1638
- strictParseParams: true
1639
- });
1640
- matches.forEach((match, index) => {
1641
- const dehydratedMatch = dehydratedState.state.matches[index];
1642
- invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1643
- Object.assign(match, dehydratedMatch);
1644
- });
1645
- matches.forEach(match => match.__.validate());
1646
- router.state = _extends({}, router.state, dehydratedState, {
1647
- matches
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
+ });
1648
2183
  });
1649
2184
  },
1650
2185
  mount: () => {
1651
- router.__.buildLocation({
1652
- to: '.',
1653
- search: true,
1654
- hash: true
1655
- });
1656
-
1657
- // If the current location isn't updated, trigger a navigation
1658
- // to the current location. Otherwise, load the current location.
1659
- // if (next.href !== router.__location.href) {
1660
- // router.__.commitLocation(next, true)
1661
- // }
1662
-
1663
- if (!router.state.matches.length) {
1664
- router.load();
1665
- }
1666
- const unsub = router.history.listen(event => {
1667
- router.load(router.__.parseLocation(event.location, router.__location));
1668
- });
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
+ });
1669
2195
 
1670
- // addEventListener does not exist in React Native, but window does
1671
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1672
- if (!isServer && window.addEventListener) {
1673
- // Listen to visibillitychange and focus
1674
- window.addEventListener('visibilitychange', router.onFocus, false);
1675
- window.addEventListener('focus', router.onFocus, false);
1676
- }
1677
- return () => {
1678
- unsub();
1679
- if (!isServer && window.removeEventListener) {
1680
- // Be sure to unsubscribe if a new handler is set
1681
- window.removeEventListener('visibilitychange', router.onFocus);
1682
- window.removeEventListener('focus', router.onFocus);
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);
1683
2203
  }
1684
- };
1685
- },
1686
- onFocus: () => {
1687
- router.load();
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
+ };
2212
+ }
2213
+ return () => {};
1688
2214
  },
1689
2215
  update: opts => {
1690
- var _trimPath;
1691
2216
  const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
1692
- if (!router.__location || newHistory) {
2217
+ if (!store.latestLocation || newHistory) {
1693
2218
  if (opts != null && opts.history) {
1694
2219
  router.history = opts.history;
1695
2220
  }
1696
- router.__location = router.__.parseLocation(router.history.location);
1697
- router.state.location = router.__location;
2221
+ setStore(s => {
2222
+ s.latestLocation = parseLocation(router.history.location);
2223
+ s.currentLocation = s.latestLocation;
2224
+ });
1698
2225
  }
1699
2226
  Object.assign(router.options, opts);
1700
2227
  const {
1701
2228
  basepath,
1702
2229
  routeConfig
1703
2230
  } = router.options;
1704
- router.basepath = "/" + ((_trimPath = trimPath(basepath != null ? basepath : '')) != null ? _trimPath : '');
2231
+ router.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
1705
2232
  if (routeConfig) {
1706
2233
  router.routesById = {};
1707
- router.routeTree = router.__.buildRouteTree(routeConfig);
2234
+ router.routeTree = buildRouteTree(routeConfig);
1708
2235
  }
1709
2236
  return router;
1710
2237
  },
1711
2238
  cancelMatches: () => {
1712
- var _router$state$pending, _router$state$pending2;
1713
- [...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 => {
1714
2240
  match.cancel();
1715
2241
  });
1716
2242
  },
1717
2243
  load: async next => {
1718
- const id = Math.random();
1719
- router.startedLoadingAt = id;
1720
- if (next) {
1721
- // Ingest the new location
1722
- router.__location = next;
1723
- }
2244
+ let now = Date.now();
2245
+ const startedAt = now;
2246
+ startedLoadingAt = startedAt;
1724
2247
 
1725
2248
  // Cancel any pending matches
1726
2249
  router.cancelMatches();
2250
+ let matches;
2251
+ batch(() => {
2252
+ if (next) {
2253
+ // Ingest the new location
2254
+ setStore(s => {
2255
+ s.latestLocation = next;
2256
+ });
2257
+ }
1727
2258
 
1728
- // Match the routes
1729
- const matches = router.matchRoutes(router.__location.pathname, {
1730
- strictParseParams: true
1731
- });
1732
- if (typeof document !== 'undefined') {
1733
- router.state = _extends({}, router.state, {
1734
- pending: {
1735
- matches: matches,
1736
- location: router.__location
1737
- },
1738
- status: 'loading'
2259
+ // Match the routes
2260
+ matches = router.matchRoutes(store.latestLocation.pathname, {
2261
+ strictParseParams: true
1739
2262
  });
1740
- } else {
1741
- router.state = _extends({}, router.state, {
1742
- matches: matches,
1743
- location: router.__location,
1744
- status: 'loading'
2263
+ console.log('set loading', matches);
2264
+ setStore(s => {
2265
+ s.status = 'loading';
2266
+ s.pendingMatches = matches;
2267
+ s.pendingLocation = store.latestLocation;
1745
2268
  });
1746
- }
2269
+ });
1747
2270
 
1748
- // Check if each match middleware to see if the route can be accessed
2271
+ // Load the matches
1749
2272
  try {
1750
- await Promise.all(matches.map(match => match.options.beforeLoad == null ? void 0 : match.options.beforeLoad({
1751
- router: router,
1752
- match
1753
- })));
2273
+ await router.loadMatches(matches);
1754
2274
  } catch (err) {
1755
- console.info(err);
1756
- invariant(false, "A route's beforeLoad middleware failed! \uD83D\uDC46");
2275
+ console.log(err);
2276
+ invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
1757
2277
  }
1758
- router.notify();
1759
-
1760
- // Load the matches
1761
- await router.loadMatches(matches);
1762
- if (router.startedLoadingAt !== id) {
1763
- // Ignore side-effects of match loading
1764
- return router.navigationPromise;
2278
+ if (startedLoadingAt !== startedAt) {
2279
+ // Ignore side-effects of outdated side-effects
2280
+ return navigationPromise;
1765
2281
  }
1766
- const previousMatches = router.state.matches;
2282
+ const previousMatches = store.currentMatches;
1767
2283
  const exiting = [],
1768
2284
  staying = [];
1769
2285
  previousMatches.forEach(d => {
@@ -1776,22 +2292,21 @@
1776
2292
  const entering = matches.filter(d => {
1777
2293
  return !previousMatches.find(dd => dd.matchId === d.matchId);
1778
2294
  });
1779
- const now = Date.now();
2295
+ now = Date.now();
1780
2296
  exiting.forEach(d => {
1781
- var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
1782
2297
  d.__.onExit == null ? void 0 : d.__.onExit({
1783
2298
  params: d.params,
1784
- search: d.routeSearch
2299
+ search: d.store.routeSearch
1785
2300
  });
1786
2301
 
1787
2302
  // Clear idle error states when match leaves
1788
- if (d.status === 'error' && !d.isFetching) {
1789
- d.status = 'idle';
1790
- d.error = undefined;
2303
+ if (d.store.status === 'error' && !d.store.isFetching) {
2304
+ d.store.status = 'idle';
2305
+ d.store.error = undefined;
1791
2306
  }
1792
- const gc = Math.max((_ref = (_d$options$loaderGcMa = d.options.loaderGcMaxAge) != null ? _d$options$loaderGcMa : router.options.defaultLoaderGcMaxAge) != null ? _ref : 0, (_ref2 = (_d$options$loaderMaxA = d.options.loaderMaxAge) != null ? _d$options$loaderMaxA : router.options.defaultLoaderMaxAge) != null ? _ref2 : 0);
2307
+ const gc = Math.max(d.options.loaderGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0, d.options.loaderMaxAge ?? router.options.defaultLoaderMaxAge ?? 0);
1793
2308
  if (gc > 0) {
1794
- router.matchCache[d.matchId] = {
2309
+ store.matchCache[d.matchId] = {
1795
2310
  gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1796
2311
  match: d
1797
2312
  };
@@ -1800,58 +2315,64 @@
1800
2315
  staying.forEach(d => {
1801
2316
  d.options.onTransition == null ? void 0 : d.options.onTransition({
1802
2317
  params: d.params,
1803
- search: d.routeSearch
2318
+ search: d.store.routeSearch
1804
2319
  });
1805
2320
  });
1806
2321
  entering.forEach(d => {
1807
2322
  d.__.onExit = d.options.onLoaded == null ? void 0 : d.options.onLoaded({
1808
2323
  params: d.params,
1809
- search: d.search
2324
+ search: d.store.search
1810
2325
  });
1811
- delete router.matchCache[d.matchId];
2326
+ delete store.matchCache[d.matchId];
1812
2327
  });
1813
- if (router.startedLoadingAt !== id) {
2328
+ if (startedLoadingAt !== startedAt) {
1814
2329
  // Ignore side-effects of match loading
1815
2330
  return;
1816
2331
  }
1817
2332
  matches.forEach(match => {
1818
2333
  // Clear actions
1819
2334
  if (match.action) {
2335
+ // TODO: Check reactivity here
1820
2336
  match.action.current = undefined;
1821
2337
  match.action.submissions = [];
1822
2338
  }
1823
2339
  });
1824
- router.state = _extends({}, router.state, {
1825
- location: router.__location,
1826
- matches,
1827
- pending: undefined,
1828
- status: 'idle'
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
+ });
1829
2349
  });
1830
- router.notify();
1831
- router.resolveNavigation();
2350
+ resolveNavigation();
1832
2351
  },
1833
2352
  cleanMatchCache: () => {
1834
2353
  const now = Date.now();
1835
- Object.keys(router.matchCache).forEach(matchId => {
1836
- const entry = router.matchCache[matchId];
2354
+ setStore(s => {
2355
+ Object.keys(s.matchCache).forEach(matchId => {
2356
+ const entry = s.matchCache[matchId];
1837
2357
 
1838
- // Don't remove loading matches
1839
- if (entry.match.status === 'loading') {
1840
- return;
1841
- }
2358
+ // Don't remove loading matches
2359
+ if (entry.match.store.status === 'loading') {
2360
+ return;
2361
+ }
1842
2362
 
1843
- // Do not remove successful matches that are still valid
1844
- if (entry.gc > 0 && entry.gc > now) {
1845
- return;
1846
- }
2363
+ // Do not remove successful matches that are still valid
2364
+ if (entry.gc > 0 && entry.gc > now) {
2365
+ return;
2366
+ }
1847
2367
 
1848
- // Everything else gets removed
1849
- delete router.matchCache[matchId];
2368
+ // Everything else gets removed
2369
+ delete s.matchCache[matchId];
2370
+ });
1850
2371
  });
1851
2372
  },
1852
- loadRoute: async function loadRoute(navigateOpts) {
2373
+ loadRoute: async function (navigateOpts) {
1853
2374
  if (navigateOpts === void 0) {
1854
- navigateOpts = router.__location;
2375
+ navigateOpts = store.latestLocation;
1855
2376
  }
1856
2377
  const next = router.buildNext(navigateOpts);
1857
2378
  const matches = router.matchRoutes(next.pathname, {
@@ -1860,10 +2381,9 @@
1860
2381
  await router.loadMatches(matches);
1861
2382
  return matches;
1862
2383
  },
1863
- preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1864
- var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
2384
+ preloadRoute: async function (navigateOpts, loaderOpts) {
1865
2385
  if (navigateOpts === void 0) {
1866
- navigateOpts = router.__location;
2386
+ navigateOpts = store.latestLocation;
1867
2387
  }
1868
2388
  const next = router.buildNext(navigateOpts);
1869
2389
  const matches = router.matchRoutes(next.pathname, {
@@ -1871,28 +2391,27 @@
1871
2391
  });
1872
2392
  await router.loadMatches(matches, {
1873
2393
  preload: true,
1874
- maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
1875
- gcMaxAge: (_ref5 = (_ref6 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref6 : router.options.defaultLoaderGcMaxAge) != null ? _ref5 : 0
2394
+ maxAge: loaderOpts.maxAge ?? router.options.defaultPreloadMaxAge ?? router.options.defaultLoaderMaxAge ?? 0,
2395
+ gcMaxAge: loaderOpts.gcMaxAge ?? router.options.defaultPreloadGcMaxAge ?? router.options.defaultLoaderGcMaxAge ?? 0
1876
2396
  });
1877
2397
  return matches;
1878
2398
  },
1879
2399
  matchRoutes: (pathname, opts) => {
1880
- var _router$state$pending3, _router$state$pending4;
1881
2400
  router.cleanMatchCache();
1882
2401
  const matches = [];
1883
2402
  if (!router.routeTree) {
1884
2403
  return matches;
1885
2404
  }
1886
- 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 : [])];
2405
+ const existingMatches = [...store.currentMatches, ...(store.pendingMatches ?? [])];
1887
2406
  const recurse = async routes => {
1888
- var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
2407
+ var _foundRoute$childRout;
1889
2408
  const parentMatch = last(matches);
1890
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1891
- 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;
1892
2411
  let foundRoutes = [];
1893
2412
  const findMatchInRoutes = (parentRoutes, routes) => {
1894
2413
  routes.some(route => {
1895
- var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
2414
+ var _route$childRoutes, _route$childRoutes2;
1896
2415
  if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
1897
2416
  return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
1898
2417
  }
@@ -1900,20 +2419,21 @@
1900
2419
  const matchParams = matchPathname(router.basepath, pathname, {
1901
2420
  to: route.fullPath,
1902
2421
  fuzzy,
1903
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2422
+ caseSensitive: route.options.caseSensitive ?? router.options.caseSensitive
1904
2423
  });
1905
- console.log(router.basepath, route.fullPath, fuzzy, pathname, matchParams);
1906
2424
  if (matchParams) {
1907
2425
  let parsedParams;
1908
2426
  try {
1909
- var _route$options$parseP;
1910
- 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;
1911
2428
  } catch (err) {
1912
2429
  if (opts != null && opts.strictParseParams) {
1913
2430
  throw err;
1914
2431
  }
1915
2432
  }
1916
- params = _extends({}, params, parsedParams);
2433
+ params = {
2434
+ ...params,
2435
+ ...parsedParams
2436
+ };
1917
2437
  }
1918
2438
  if (!!matchParams) {
1919
2439
  foundRoutes = [...parentRoutes, route];
@@ -1927,10 +2447,10 @@
1927
2447
  return;
1928
2448
  }
1929
2449
  foundRoutes.forEach(foundRoute => {
1930
- var _router$matchCache$ma;
2450
+ var _store$matchCache$mat;
1931
2451
  const interpolatedPath = interpolatePath(foundRoute.routePath, params);
1932
2452
  const matchId = interpolatePath(foundRoute.routeId, params, true);
1933
- 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, {
1934
2454
  parentMatch,
1935
2455
  matchId,
1936
2456
  params,
@@ -1944,40 +2464,56 @@
1944
2464
  }
1945
2465
  };
1946
2466
  recurse([router.routeTree]);
1947
- cascadeLoaderData(matches);
2467
+ linkMatches(matches);
1948
2468
  return matches;
1949
2469
  },
1950
2470
  loadMatches: async (resolvedMatches, loaderOpts) => {
1951
- const matchPromises = resolvedMatches.map(async match => {
1952
- var _search$__data;
2471
+ resolvedMatches.forEach(async match => {
1953
2472
  // Validate the match (loads search params etc)
1954
2473
  match.__.validate();
1955
- const search = match.search;
2474
+ });
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;
1956
2493
  if ((_search$__data = search.__data) != null && _search$__data.matchId && search.__data.matchId !== match.matchId) {
1957
2494
  return;
1958
2495
  }
1959
2496
  match.load(loaderOpts);
1960
- if (match.status !== 'success' && match.__.loadPromise) {
2497
+ if (match.store.status !== 'success' && match.__.loadPromise) {
1961
2498
  // Wait for the first sign of activity from the match
1962
2499
  await match.__.loadPromise;
1963
2500
  }
1964
2501
  });
1965
- router.notify();
1966
2502
  await Promise.all(matchPromises);
1967
2503
  },
1968
2504
  loadMatchData: async routeMatch => {
1969
2505
  if (isServer || !router.options.useServerData) {
1970
- var _await$routeMatch$opt;
1971
- return (_await$routeMatch$opt = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
2506
+ return (await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
1972
2507
  // parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
1973
2508
  params: routeMatch.params,
1974
- search: routeMatch.routeSearch,
2509
+ search: routeMatch.store.routeSearch,
1975
2510
  signal: routeMatch.__.abortController.signal
1976
- }))) != null ? _await$routeMatch$opt : {};
2511
+ }))) || {};
1977
2512
  } else {
1978
2513
  const next = router.buildNext({
1979
2514
  to: '.',
1980
- search: d => _extends({}, d != null ? d : {}, {
2515
+ search: d => ({
2516
+ ...(d ?? {}),
1981
2517
  __data: {
1982
2518
  matchId: routeMatch.matchId
1983
2519
  }
@@ -2006,16 +2542,15 @@
2006
2542
  }
2007
2543
  },
2008
2544
  invalidateRoute: opts => {
2009
- var _router$state$pending5, _router$state$pending6;
2010
2545
  const next = router.buildNext(opts);
2011
2546
  const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2012
- [...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 => {
2013
2548
  if (unloadedMatchIds.includes(match.matchId)) {
2014
2549
  match.invalidate();
2015
2550
  }
2016
2551
  });
2017
2552
  },
2018
- reload: () => router.__.navigate({
2553
+ reload: () => navigate({
2019
2554
  fromCurrent: true,
2020
2555
  replace: true,
2021
2556
  search: true
@@ -2024,27 +2559,28 @@
2024
2559
  return resolvePath(router.basepath, from, cleanPath(path));
2025
2560
  },
2026
2561
  matchRoute: (location, opts) => {
2027
- var _location$from;
2028
2562
  // const location = router.buildNext(opts)
2029
2563
 
2030
- location = _extends({}, location, {
2031
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2032
- });
2564
+ location = {
2565
+ ...location,
2566
+ to: location.to ? router.resolvePath(location.from ?? '', location.to) : undefined
2567
+ };
2033
2568
  const next = router.buildNext(location);
2034
2569
  if (opts != null && opts.pending) {
2035
- var _router$state$pending7;
2036
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2570
+ if (!store.pendingLocation) {
2037
2571
  return false;
2038
2572
  }
2039
- return !!matchPathname(router.basepath, router.state.pending.location.pathname, _extends({}, opts, {
2573
+ return !!matchPathname(router.basepath, store.pendingLocation.pathname, {
2574
+ ...opts,
2040
2575
  to: next.pathname
2041
- }));
2576
+ });
2042
2577
  }
2043
- return !!matchPathname(router.basepath, router.state.location.pathname, _extends({}, opts, {
2578
+ return matchPathname(router.basepath, store.currentLocation.pathname, {
2579
+ ...opts,
2044
2580
  to: next.pathname
2045
- }));
2581
+ });
2046
2582
  },
2047
- navigate: async _ref7 => {
2583
+ navigate: async _ref => {
2048
2584
  let {
2049
2585
  from,
2050
2586
  to = '.',
@@ -2052,7 +2588,7 @@
2052
2588
  hash,
2053
2589
  replace,
2054
2590
  params
2055
- } = _ref7;
2591
+ } = _ref;
2056
2592
  // If this link simply reloads the current route,
2057
2593
  // make sure it has a new key so it will trigger a data refresh
2058
2594
 
@@ -2062,11 +2598,11 @@
2062
2598
  const fromString = String(from);
2063
2599
  let isExternal;
2064
2600
  try {
2065
- new URL("" + toString);
2601
+ new URL(`${toString}`);
2066
2602
  isExternal = true;
2067
2603
  } catch (e) {}
2068
2604
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2069
- return router.__.navigate({
2605
+ return navigate({
2070
2606
  from: fromString,
2071
2607
  to: toString,
2072
2608
  search,
@@ -2075,8 +2611,7 @@
2075
2611
  params
2076
2612
  });
2077
2613
  },
2078
- buildLink: _ref8 => {
2079
- var _preload, _ref9;
2614
+ buildLink: _ref2 => {
2080
2615
  let {
2081
2616
  from,
2082
2617
  to = '.',
@@ -2091,7 +2626,7 @@
2091
2626
  preloadGcMaxAge: userPreloadGcMaxAge,
2092
2627
  preloadDelay: userPreloadDelay,
2093
2628
  disabled
2094
- } = _ref8;
2629
+ } = _ref2;
2095
2630
  // If this link simply reloads the current route,
2096
2631
  // make sure it has a new key so it will trigger a data refresh
2097
2632
 
@@ -2099,7 +2634,7 @@
2099
2634
  // null for LinkUtils
2100
2635
 
2101
2636
  try {
2102
- new URL("" + to);
2637
+ new URL(`${to}`);
2103
2638
  return {
2104
2639
  type: 'external',
2105
2640
  href: to
@@ -2114,15 +2649,15 @@
2114
2649
  replace
2115
2650
  };
2116
2651
  const next = router.buildNext(nextOpts);
2117
- preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2118
- const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0;
2652
+ preload = preload ?? router.options.defaultPreload;
2653
+ const preloadDelay = userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0;
2119
2654
 
2120
2655
  // Compare path/hash for matches
2121
- const pathIsEqual = router.state.location.pathname === next.pathname;
2122
- const currentPathSplit = router.state.location.pathname.split('/');
2656
+ const pathIsEqual = store.currentLocation.pathname === next.pathname;
2657
+ const currentPathSplit = store.currentLocation.pathname.split('/');
2123
2658
  const nextPathSplit = next.pathname.split('/');
2124
2659
  const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2125
- const hashIsEqual = router.state.location.hash === next.hash;
2660
+ const hashIsEqual = store.currentLocation.hash === next.hash;
2126
2661
  // Combine the matches based on user options
2127
2662
  const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2128
2663
  const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true;
@@ -2138,8 +2673,8 @@
2138
2673
  router.invalidateRoute(nextOpts);
2139
2674
  }
2140
2675
 
2141
- // All is well? Navigate!)
2142
- router.__.navigate(nextOpts);
2676
+ // All is well? Navigate!
2677
+ navigate(nextOpts);
2143
2678
  }
2144
2679
  };
2145
2680
 
@@ -2149,6 +2684,9 @@
2149
2684
  router.preloadRoute(nextOpts, {
2150
2685
  maxAge: userPreloadMaxAge,
2151
2686
  gcMaxAge: userPreloadGcMaxAge
2687
+ }).catch(err => {
2688
+ console.log(err);
2689
+ console.warn('Error preloading route! ☝️');
2152
2690
  });
2153
2691
  }
2154
2692
  };
@@ -2163,6 +2701,9 @@
2163
2701
  router.preloadRoute(nextOpts, {
2164
2702
  maxAge: userPreloadMaxAge,
2165
2703
  gcMaxAge: userPreloadGcMaxAge
2704
+ }).catch(err => {
2705
+ console.log(err);
2706
+ console.warn('Error preloading route! ☝️');
2166
2707
  });
2167
2708
  }, preloadDelay);
2168
2709
  }
@@ -2186,143 +2727,15 @@
2186
2727
  };
2187
2728
  },
2188
2729
  buildNext: opts => {
2189
- const next = router.__.buildLocation(opts);
2730
+ const next = buildLocation(opts);
2190
2731
  const matches = router.matchRoutes(next.pathname);
2191
- const __preSearchFilters = matches.map(match => {
2192
- var _match$options$preSea;
2193
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2194
- }).flat().filter(Boolean);
2195
- const __postSearchFilters = matches.map(match => {
2196
- var _match$options$postSe;
2197
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2198
- }).flat().filter(Boolean);
2199
- 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,
2200
2736
  __preSearchFilters,
2201
2737
  __postSearchFilters
2202
- }));
2203
- },
2204
- __: {
2205
- buildRouteTree: rootRouteConfig => {
2206
- const recurseRoutes = (routeConfigs, parent) => {
2207
- return routeConfigs.map(routeConfig => {
2208
- const routeOptions = routeConfig.options;
2209
- const route = createRoute(routeConfig, routeOptions, parent, router);
2210
- const existingRoute = router.routesById[route.routeId];
2211
- if (existingRoute) {
2212
- {
2213
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2214
- }
2215
- throw new Error();
2216
- }
2217
- router.routesById[route.routeId] = route;
2218
- const children = routeConfig.children;
2219
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2220
- return route;
2221
- });
2222
- };
2223
- const routes = recurseRoutes([rootRouteConfig]);
2224
- return routes[0];
2225
- },
2226
- parseLocation: (location, previousLocation) => {
2227
- var _location$hash$split$;
2228
- const parsedSearch = router.options.parseSearch(location.search);
2229
- return {
2230
- pathname: location.pathname,
2231
- searchStr: location.search,
2232
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2233
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2234
- href: "" + location.pathname + location.search + location.hash,
2235
- state: location.state,
2236
- key: location.key
2237
- };
2238
- },
2239
- navigate: location => {
2240
- const next = router.buildNext(location);
2241
- return router.__.commitLocation(next, location.replace);
2242
- },
2243
- buildLocation: function buildLocation(dest) {
2244
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2245
- if (dest === void 0) {
2246
- dest = {};
2247
- }
2248
- const fromPathname = dest.fromCurrent ? router.__location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.__location.pathname;
2249
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2250
- const fromMatches = router.matchRoutes(router.__location.pathname, {
2251
- strictParseParams: true
2252
- });
2253
- const toMatches = router.matchRoutes(pathname);
2254
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2255
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2256
- if (nextParams) {
2257
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2258
- Object.assign({}, nextParams, fn(nextParams));
2259
- });
2260
- }
2261
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {});
2262
-
2263
- // Pre filters first
2264
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.__location.search) : router.__location.search;
2265
-
2266
- // Then the link/navigate function
2267
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2268
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2269
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2270
- : {};
2271
-
2272
- // Then post filters
2273
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2274
- const search = replaceEqualDeep(router.__location.search, postFilteredSearch);
2275
- const searchStr = router.options.stringifySearch(search);
2276
- let hash = dest.hash === true ? router.__location.hash : functionalUpdate(dest.hash, router.__location.hash);
2277
- hash = hash ? "#" + hash : '';
2278
- return {
2279
- pathname,
2280
- search,
2281
- searchStr,
2282
- state: router.__location.state,
2283
- hash,
2284
- href: "" + pathname + searchStr + hash,
2285
- key: dest.key
2286
- };
2287
- },
2288
- commitLocation: (next, replace) => {
2289
- const id = '' + Date.now() + Math.random();
2290
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2291
- let nextAction = 'replace';
2292
- if (!replace) {
2293
- nextAction = 'push';
2294
- }
2295
- const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2296
- if (isSameUrl && !next.key) {
2297
- nextAction = 'replace';
2298
- }
2299
- if (nextAction === 'replace') {
2300
- history.replace({
2301
- pathname: next.pathname,
2302
- hash: next.hash,
2303
- search: next.searchStr
2304
- }, _extends({
2305
- id
2306
- }, next.state));
2307
- } else {
2308
- history.push({
2309
- pathname: next.pathname,
2310
- hash: next.hash,
2311
- search: next.searchStr
2312
- }, {
2313
- id
2314
- });
2315
- }
2316
- router.navigationPromise = new Promise(resolve => {
2317
- const previousNavigationResolve = router.resolveNavigation;
2318
- router.resolveNavigation = () => {
2319
- previousNavigationResolve();
2320
- resolve();
2321
- delete router.navigationPromise;
2322
- };
2323
- });
2324
- return router.navigationPromise;
2325
- }
2738
+ });
2326
2739
  }
2327
2740
  };
2328
2741
  router.update(userOptions);
@@ -2334,11 +2747,13 @@
2334
2747
  function isCtrlEvent(e) {
2335
2748
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2336
2749
  }
2337
- function cascadeLoaderData(matches) {
2750
+ function linkMatches(matches) {
2338
2751
  matches.forEach((match, index) => {
2339
2752
  const parent = matches[index - 1];
2340
2753
  if (parent) {
2341
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
2754
+ match.__.setParentMatch(parent);
2755
+ } else {
2756
+ match.__.setParentMatch(undefined);
2342
2757
  }
2343
2758
  });
2344
2759
  }
@@ -2365,9 +2780,9 @@
2365
2780
  exports.parsePathname = parsePathname;
2366
2781
  exports.parseSearchWith = parseSearchWith;
2367
2782
  exports.pick = pick;
2368
- exports.replaceEqualDeep = replaceEqualDeep;
2369
2783
  exports.resolvePath = resolvePath;
2370
2784
  exports.rootRouteId = rootRouteId;
2785
+ exports.sharedClone = sharedClone;
2371
2786
  exports.stringifySearchWith = stringifySearchWith;
2372
2787
  exports.trimPath = trimPath;
2373
2788
  exports.trimPathLeft = trimPathLeft;