@tanstack/router-core 0.0.1-beta.36 → 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.
@@ -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,134 +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.error(err);
1198
- actionState.error = err;
1199
- actionState.status = 'error';
1200
- } finally {
1201
- router.notify();
1202
- }
1203
- }
1204
- };
1205
- return router.state.actions[id];
1206
- })();
1207
- const loader = router.state.loaders[id] || (() => {
1208
- router.state.loaders[id] = {
1209
- pending: [],
1210
- fetch: async loaderContext => {
1211
- if (!route) {
1212
- return;
1213
- }
1214
- const loaderState = {
1215
- loadedAt: Date.now(),
1216
- loaderContext
1217
- };
1218
- loader.current = loaderState;
1219
- loader.latest = loaderState;
1220
- loader.pending.push(loaderState);
1221
-
1222
- // router.state = {
1223
- // ...router.state,
1224
- // currentAction: loaderState,
1225
- // latestAction: loaderState,
1226
- // }
1227
-
1228
- router.notify();
1229
- try {
1230
- return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1231
- } finally {
1232
- loader.pending = loader.pending.filter(d => d !== loaderState);
1233
- // router.removeActionQueue.push({ loader, loaderState })
1234
- router.notify();
1235
- }
1236
- }
1237
- };
1238
- return router.state.loaders[id];
1239
- })();
1240
1432
  let route = {
1241
1433
  routeInfo: undefined,
1242
1434
  routeId: id,
1243
1435
  routeRouteId: routeId,
1436
+ originalIndex,
1244
1437
  routePath,
1245
1438
  fullPath,
1246
1439
  options,
1247
1440
  router,
1248
1441
  childRoutes: undefined,
1249
1442
  parentRoute: parent,
1250
- action,
1251
- loader: loader,
1252
- buildLink: options => {
1253
- return router.buildLink(_extends({}, options, {
1254
- from: fullPath
1255
- }));
1256
- },
1257
- navigate: options => {
1258
- return router.navigate(_extends({}, options, {
1259
- from: fullPath
1260
- }));
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;
1261
1496
  },
1262
- matchRoute: (matchLocation, opts) => {
1263
- return router.matchRoute(_extends({}, matchLocation, {
1264
- from: fullPath
1265
- }), 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;
1266
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
+ // },
1267
1553
  };
1554
+
1268
1555
  router.options.createRoute == null ? void 0 : router.options.createRoute({
1269
1556
  router,
1270
1557
  route
@@ -1273,7 +1560,7 @@
1273
1560
  }
1274
1561
 
1275
1562
  const rootRouteId = '__root__';
1276
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1563
+ const createRouteConfig = function (options, children, isRoot, parentId, parentPath) {
1277
1564
  if (options === void 0) {
1278
1565
  options = {};
1279
1566
  }
@@ -1313,53 +1600,194 @@
1313
1600
  addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1314
1601
  createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath),
1315
1602
  generate: () => {
1316
- 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. `);
1317
1604
  }
1318
1605
  };
1319
1606
  };
1320
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
+
1321
1714
  const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1322
1715
  function createRouteMatch(router, route, opts) {
1323
- const routeMatch = _extends({}, route, opts, {
1324
- 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({
1325
1738
  routeSearch: {},
1326
1739
  search: {},
1327
- childMatches: [],
1328
1740
  status: 'idle',
1329
1741
  routeLoaderData: {},
1330
1742
  loaderData: {},
1331
1743
  isFetching: false,
1332
- isInvalid: false,
1744
+ invalid: false,
1333
1745
  invalidAt: Infinity,
1334
- // pendingActions: [],
1335
- getIsInvalid: () => {
1746
+ get isInvalid() {
1336
1747
  const now = Date.now();
1337
- return routeMatch.isInvalid || routeMatch.invalidAt < now;
1338
- },
1748
+ return this.invalid || this.invalidAt < now;
1749
+ }
1750
+ });
1751
+ const routeMatch = {
1752
+ ...route,
1753
+ ...opts,
1754
+ store,
1755
+ // setStore,
1756
+ router,
1757
+ childMatches: [],
1339
1758
  __: {
1340
- abortController: new AbortController(),
1341
- latestId: '',
1342
- resolve: () => {},
1343
- notify: () => {
1344
- routeMatch.__.resolve();
1345
- routeMatch.router.notify();
1759
+ setParentMatch: parentMatch => {
1760
+ batch(() => {
1761
+ setStore(s => {
1762
+ s.parentMatch = parentMatch;
1763
+ });
1764
+ updateLoaderData();
1765
+ });
1346
1766
  },
1767
+ abortController: new AbortController(),
1347
1768
  validate: () => {
1348
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1769
+ var _store$parentMatch2;
1349
1770
  // Validate the search params and stabilize them
1350
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.state.currentLocation.search;
1771
+ const parentSearch = ((_store$parentMatch2 = store.parentMatch) == null ? void 0 : _store$parentMatch2.store.search) ?? router.store.currentLocation.search;
1351
1772
  try {
1352
- var _validator;
1353
- const prevSearch = routeMatch.routeSearch;
1773
+ const prevSearch = store.routeSearch;
1354
1774
  const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1355
- 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
+ }
1356
1781
 
1357
- // Invalidate route matches when search param stability changes
1358
- if (prevSearch !== nextSearch) {
1359
- routeMatch.isInvalid = true;
1360
- }
1361
- routeMatch.routeSearch = nextSearch;
1362
- 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
+ });
1363
1791
  componentTypes.map(async type => {
1364
1792
  const component = routeMatch.options[type];
1365
1793
  if (typeof routeMatch.__[type] !== 'function') {
@@ -1372,8 +1800,11 @@
1372
1800
  cause: err
1373
1801
  });
1374
1802
  error.code = 'INVALID_SEARCH_PARAMS';
1375
- routeMatch.status = 'error';
1376
- routeMatch.error = error;
1803
+ setStore(s => {
1804
+ s.status = 'error';
1805
+ s.error = error;
1806
+ });
1807
+
1377
1808
  // Do not proceed with loading the route
1378
1809
  return;
1379
1810
  }
@@ -1384,7 +1815,7 @@
1384
1815
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1385
1816
  },
1386
1817
  invalidate: () => {
1387
- routeMatch.isInvalid = true;
1818
+ setStore(s => s.invalid = true);
1388
1819
  },
1389
1820
  hasLoaders: () => {
1390
1821
  return !!(route.options.loader || componentTypes.some(d => {
@@ -1399,17 +1830,17 @@
1399
1830
  // If this is a preload, add it to the preload cache
1400
1831
  if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1401
1832
  // If the match is currently active, don't preload it
1402
- if (router.state.currentMatches.find(d => d.matchId === routeMatch.matchId)) {
1833
+ if (router.store.currentMatches.find(d => d.matchId === routeMatch.matchId)) {
1403
1834
  return;
1404
1835
  }
1405
- router.matchCache[routeMatch.matchId] = {
1836
+ router.store.matchCache[routeMatch.matchId] = {
1406
1837
  gc: now + loaderOpts.gcMaxAge,
1407
1838
  match: routeMatch
1408
1839
  };
1409
1840
  }
1410
1841
 
1411
1842
  // If the match is invalid, errored or idle, trigger it to load
1412
- 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') {
1413
1844
  const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1414
1845
  await routeMatch.fetch({
1415
1846
  maxAge
@@ -1418,29 +1849,30 @@
1418
1849
  },
1419
1850
  fetch: async opts => {
1420
1851
  const loadId = '' + Date.now() + Math.random();
1421
- routeMatch.__.latestId = loadId;
1852
+ latestId = loadId;
1422
1853
  const checkLatest = async () => {
1423
- if (loadId !== routeMatch.__.latestId) {
1854
+ if (loadId !== latestId) {
1424
1855
  // warning(true, 'Data loader is out of date!')
1425
1856
  return new Promise(() => {});
1426
1857
  }
1427
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
+ }
1428
1866
 
1429
- // If the match was in an error state, set it
1430
- // to a loading state again. Otherwise, keep it
1431
- // as loading or resolved
1432
- if (routeMatch.status === 'idle') {
1433
- routeMatch.status = 'loading';
1434
- }
1435
-
1436
- // We started loading the route, so it's no longer invalid
1437
- routeMatch.isInvalid = false;
1438
- 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 => {
1439
1871
  // We are now fetching, even if it's in the background of a
1440
1872
  // resolved state
1441
- routeMatch.isFetching = true;
1442
- routeMatch.__.resolve = resolve;
1443
- routeMatch.__.componentsPromise = (async () => {
1873
+ setStore(s => s.isFetching = true);
1874
+ resolve = r;
1875
+ componentsPromise = (async () => {
1444
1876
  // then run all component and data loaders in parallel
1445
1877
  // For each component type, potentially load it asynchronously
1446
1878
 
@@ -1452,49 +1884,52 @@
1452
1884
  }
1453
1885
  }));
1454
1886
  })();
1455
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1887
+ dataPromise = Promise.resolve().then(async () => {
1456
1888
  try {
1457
- var _ref, _ref2, _opts$maxAge;
1458
1889
  if (routeMatch.options.loader) {
1459
1890
  const data = await router.loadMatchData(routeMatch);
1460
1891
  await checkLatest();
1461
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1892
+ setLoaderData(data);
1462
1893
  }
1463
- routeMatch.error = undefined;
1464
- routeMatch.status = 'success';
1465
- routeMatch.updatedAt = Date.now();
1466
- 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);
1467
- 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;
1468
1901
  } catch (err) {
1469
1902
  await checkLatest();
1470
1903
  {
1471
1904
  console.error(err);
1472
1905
  }
1473
- routeMatch.error = err;
1474
- routeMatch.status = 'error';
1475
- routeMatch.updatedAt = Date.now();
1906
+ setStore(s => {
1907
+ s.error = err;
1908
+ s.status = 'error';
1909
+ s.updatedAt = Date.now();
1910
+ });
1476
1911
  throw err;
1477
1912
  }
1478
1913
  });
1479
1914
  const after = async () => {
1480
1915
  await checkLatest();
1481
- routeMatch.isFetching = false;
1916
+ setStore(s => s.isFetching = false);
1482
1917
  delete routeMatch.__.loadPromise;
1483
- routeMatch.__.notify();
1918
+ resolve();
1484
1919
  };
1485
1920
  try {
1486
- await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise.catch(() => {})]);
1921
+ await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
1487
1922
  after();
1488
- } catch (_unused) {
1923
+ } catch {
1489
1924
  after();
1490
1925
  }
1491
1926
  });
1492
1927
  await routeMatch.__.loadPromise;
1493
1928
  await checkLatest();
1494
1929
  }
1495
- });
1930
+ };
1496
1931
  if (!routeMatch.hasLoaders()) {
1497
- routeMatch.status = 'success';
1932
+ setStore(s => s.status = 'success');
1498
1933
  }
1499
1934
  return routeMatch;
1500
1935
  }
@@ -1524,7 +1959,9 @@
1524
1959
  }
1525
1960
  function stringifySearchWith(stringify) {
1526
1961
  return search => {
1527
- search = _extends({}, search);
1962
+ search = {
1963
+ ...search
1964
+ };
1528
1965
  if (search) {
1529
1966
  Object.keys(search).forEach(key => {
1530
1967
  const val = search[key];
@@ -1540,7 +1977,7 @@
1540
1977
  });
1541
1978
  }
1542
1979
  const searchStr = encode(search).toString();
1543
- return searchStr ? "?" + searchStr : '';
1980
+ return searchStr ? `?${searchStr}` : '';
1544
1981
  };
1545
1982
  }
1546
1983
 
@@ -1559,177 +1996,277 @@
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
- //
1590
- resolveNavigation: () => {},
1591
- matchCache: {},
1592
- state: getInitialRouterState(),
1593
2146
  reset: () => {
1594
- router.state = getInitialRouterState();
1595
- router.notify();
1596
- },
1597
- startedLoadingAt: Date.now(),
1598
- subscribe: listener => {
1599
- router.listeners.push(listener);
1600
- return () => {
1601
- router.listeners = router.listeners.filter(x => x !== listener);
1602
- };
2147
+ setStore(s => Object.assign(s, getInitialRouterState()));
1603
2148
  },
1604
2149
  getRoute: id => {
1605
2150
  return router.routesById[id];
1606
2151
  },
1607
- notify: () => {
1608
- const isFetching = router.state.status === 'loading' || router.state.currentMatches.some(d => d.isFetching);
1609
- const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.currentMatches.find(dd => dd.matchId === d.match.matchId));
1610
- if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1611
- router.state = _extends({}, router.state, {
1612
- isFetching,
1613
- isPreloading
1614
- });
1615
- }
1616
- cascadeLoaderData(router.state.currentMatches);
1617
- router.listeners.forEach(listener => listener(router));
1618
- },
1619
2152
  dehydrate: () => {
1620
2153
  return {
1621
- state: _extends({}, pick(router.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']), {
1622
- currentMatches: router.state.currentMatches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
1623
- }),
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
+ },
1624
2161
  context: router.options.context
1625
2162
  };
1626
2163
  },
1627
- hydrate: dehydratedState => {
1628
- // Update the location
1629
- router.state.latestLocation = dehydratedState.state.latestLocation;
1630
- router.state.currentLocation = dehydratedState.state.currentLocation;
2164
+ hydrate: dehydratedRouter => {
2165
+ setStore(s => {
2166
+ // Update the context TODO: make this part of state?
2167
+ router.options.context = dehydratedRouter.context;
1631
2168
 
1632
- // Update the context
1633
- router.options.context = dehydratedState.context;
1634
-
1635
- // Match the routes
1636
- const currentMatches = router.matchRoutes(router.state.latestLocation.pathname, {
1637
- strictParseParams: true
1638
- });
1639
- currentMatches.forEach((match, index) => {
1640
- const dehydratedMatch = dehydratedState.state.currentMatches[index];
1641
- invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1642
- Object.assign(match, dehydratedMatch);
1643
- });
1644
- currentMatches.forEach(match => match.__.validate());
1645
- router.state = _extends({}, router.state, dehydratedState, {
1646
- currentMatches
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
+ });
1647
2183
  });
1648
2184
  },
1649
2185
  mount: () => {
1650
- if (!router.state.currentMatches.length) {
1651
- router.load();
1652
- }
1653
- const unsub = router.history.listen(event => {
1654
- router.load(router.__.parseLocation(event.location, router.state.latestLocation));
1655
- });
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
+ });
1656
2195
 
1657
- // addEventListener does not exist in React Native, but window does
1658
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1659
- if (!isServer && window.addEventListener) {
1660
- // Listen to visibillitychange and focus
1661
- window.addEventListener('visibilitychange', router.onFocus, false);
1662
- window.addEventListener('focus', router.onFocus, false);
1663
- }
1664
- return () => {
1665
- unsub();
1666
- if (!isServer && window.removeEventListener) {
1667
- // Be sure to unsubscribe if a new handler is set
1668
- window.removeEventListener('visibilitychange', router.onFocus);
1669
- 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);
1670
2203
  }
1671
- };
1672
- },
1673
- onFocus: () => {
1674
- 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 () => {};
1675
2214
  },
1676
2215
  update: opts => {
1677
- var _trimPath;
1678
2216
  const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
1679
- if (!router.state.latestLocation || newHistory) {
2217
+ if (!store.latestLocation || newHistory) {
1680
2218
  if (opts != null && opts.history) {
1681
2219
  router.history = opts.history;
1682
2220
  }
1683
- router.state.latestLocation = router.__.parseLocation(router.history.location);
1684
- router.state.currentLocation = router.state.latestLocation;
2221
+ setStore(s => {
2222
+ s.latestLocation = parseLocation(router.history.location);
2223
+ s.currentLocation = s.latestLocation;
2224
+ });
1685
2225
  }
1686
2226
  Object.assign(router.options, opts);
1687
2227
  const {
1688
2228
  basepath,
1689
2229
  routeConfig
1690
2230
  } = router.options;
1691
- router.basepath = "/" + ((_trimPath = trimPath(basepath != null ? basepath : '')) != null ? _trimPath : '');
2231
+ router.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
1692
2232
  if (routeConfig) {
1693
2233
  router.routesById = {};
1694
- router.routeTree = router.__.buildRouteTree(routeConfig);
2234
+ router.routeTree = buildRouteTree(routeConfig);
1695
2235
  }
1696
2236
  return router;
1697
2237
  },
1698
2238
  cancelMatches: () => {
1699
- var _router$state$pending;
1700
- [...router.state.currentMatches, ...((_router$state$pending = router.state.pendingMatches) != null ? _router$state$pending : [])].forEach(match => {
2239
+ [...store.currentMatches, ...(store.pendingMatches || [])].forEach(match => {
1701
2240
  match.cancel();
1702
2241
  });
1703
2242
  },
1704
2243
  load: async next => {
1705
- const id = Math.random();
1706
- router.startedLoadingAt = id;
1707
- if (next) {
1708
- // Ingest the new location
1709
- router.state.latestLocation = next;
1710
- }
2244
+ let now = Date.now();
2245
+ const startedAt = now;
2246
+ startedLoadingAt = startedAt;
1711
2247
 
1712
2248
  // Cancel any pending matches
1713
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
+ }
1714
2258
 
1715
- // Match the routes
1716
- const matches = router.matchRoutes(router.state.latestLocation.pathname, {
1717
- strictParseParams: true
1718
- });
1719
- if (typeof document !== 'undefined') {
1720
- router.state = _extends({}, router.state, {
1721
- status: 'loading',
1722
- pendingMatches: matches,
1723
- pendingLocation: router.state.latestLocation
2259
+ // Match the routes
2260
+ matches = router.matchRoutes(store.latestLocation.pathname, {
2261
+ strictParseParams: true
1724
2262
  });
1725
- } else {
1726
- router.state = _extends({}, router.state, {
1727
- status: 'loading',
1728
- currentMatches: matches,
1729
- currentLocation: router.state.latestLocation
2263
+ console.log('set loading', matches);
2264
+ setStore(s => {
2265
+ s.status = 'loading';
2266
+ s.pendingMatches = matches;
2267
+ s.pendingLocation = store.latestLocation;
1730
2268
  });
1731
- }
1732
- router.notify();
2269
+ });
1733
2270
 
1734
2271
  // Load the matches
1735
2272
  try {
@@ -1738,11 +2275,11 @@
1738
2275
  console.log(err);
1739
2276
  invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
1740
2277
  }
1741
- if (router.startedLoadingAt !== id) {
1742
- // Ignore side-effects of match loading
1743
- return router.navigationPromise;
2278
+ if (startedLoadingAt !== startedAt) {
2279
+ // Ignore side-effects of outdated side-effects
2280
+ return navigationPromise;
1744
2281
  }
1745
- const previousMatches = router.state.currentMatches;
2282
+ const previousMatches = store.currentMatches;
1746
2283
  const exiting = [],
1747
2284
  staying = [];
1748
2285
  previousMatches.forEach(d => {
@@ -1755,22 +2292,21 @@
1755
2292
  const entering = matches.filter(d => {
1756
2293
  return !previousMatches.find(dd => dd.matchId === d.matchId);
1757
2294
  });
1758
- const now = Date.now();
2295
+ now = Date.now();
1759
2296
  exiting.forEach(d => {
1760
- var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
1761
2297
  d.__.onExit == null ? void 0 : d.__.onExit({
1762
2298
  params: d.params,
1763
- search: d.routeSearch
2299
+ search: d.store.routeSearch
1764
2300
  });
1765
2301
 
1766
2302
  // Clear idle error states when match leaves
1767
- if (d.status === 'error' && !d.isFetching) {
1768
- d.status = 'idle';
1769
- d.error = undefined;
2303
+ if (d.store.status === 'error' && !d.store.isFetching) {
2304
+ d.store.status = 'idle';
2305
+ d.store.error = undefined;
1770
2306
  }
1771
- 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);
1772
2308
  if (gc > 0) {
1773
- router.matchCache[d.matchId] = {
2309
+ store.matchCache[d.matchId] = {
1774
2310
  gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1775
2311
  match: d
1776
2312
  };
@@ -1779,59 +2315,64 @@
1779
2315
  staying.forEach(d => {
1780
2316
  d.options.onTransition == null ? void 0 : d.options.onTransition({
1781
2317
  params: d.params,
1782
- search: d.routeSearch
2318
+ search: d.store.routeSearch
1783
2319
  });
1784
2320
  });
1785
2321
  entering.forEach(d => {
1786
2322
  d.__.onExit = d.options.onLoaded == null ? void 0 : d.options.onLoaded({
1787
2323
  params: d.params,
1788
- search: d.search
2324
+ search: d.store.search
1789
2325
  });
1790
- delete router.matchCache[d.matchId];
2326
+ delete store.matchCache[d.matchId];
1791
2327
  });
1792
- if (router.startedLoadingAt !== id) {
2328
+ if (startedLoadingAt !== startedAt) {
1793
2329
  // Ignore side-effects of match loading
1794
2330
  return;
1795
2331
  }
1796
2332
  matches.forEach(match => {
1797
2333
  // Clear actions
1798
2334
  if (match.action) {
2335
+ // TODO: Check reactivity here
1799
2336
  match.action.current = undefined;
1800
2337
  match.action.submissions = [];
1801
2338
  }
1802
2339
  });
1803
- router.state = _extends({}, router.state, {
1804
- status: 'idle',
1805
- currentLocation: router.state.latestLocation,
1806
- currentMatches: matches,
1807
- pendingLocation: undefined,
1808
- pendingMatches: undefined
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
+ });
1809
2349
  });
1810
- router.notify();
1811
- router.resolveNavigation();
2350
+ resolveNavigation();
1812
2351
  },
1813
2352
  cleanMatchCache: () => {
1814
2353
  const now = Date.now();
1815
- Object.keys(router.matchCache).forEach(matchId => {
1816
- const entry = router.matchCache[matchId];
2354
+ setStore(s => {
2355
+ Object.keys(s.matchCache).forEach(matchId => {
2356
+ const entry = s.matchCache[matchId];
1817
2357
 
1818
- // Don't remove loading matches
1819
- if (entry.match.status === 'loading') {
1820
- return;
1821
- }
2358
+ // Don't remove loading matches
2359
+ if (entry.match.store.status === 'loading') {
2360
+ return;
2361
+ }
1822
2362
 
1823
- // Do not remove successful matches that are still valid
1824
- if (entry.gc > 0 && entry.gc > now) {
1825
- return;
1826
- }
2363
+ // Do not remove successful matches that are still valid
2364
+ if (entry.gc > 0 && entry.gc > now) {
2365
+ return;
2366
+ }
1827
2367
 
1828
- // Everything else gets removed
1829
- delete router.matchCache[matchId];
2368
+ // Everything else gets removed
2369
+ delete s.matchCache[matchId];
2370
+ });
1830
2371
  });
1831
2372
  },
1832
- loadRoute: async function loadRoute(navigateOpts) {
2373
+ loadRoute: async function (navigateOpts) {
1833
2374
  if (navigateOpts === void 0) {
1834
- navigateOpts = router.state.latestLocation;
2375
+ navigateOpts = store.latestLocation;
1835
2376
  }
1836
2377
  const next = router.buildNext(navigateOpts);
1837
2378
  const matches = router.matchRoutes(next.pathname, {
@@ -1840,10 +2381,9 @@
1840
2381
  await router.loadMatches(matches);
1841
2382
  return matches;
1842
2383
  },
1843
- preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1844
- var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
2384
+ preloadRoute: async function (navigateOpts, loaderOpts) {
1845
2385
  if (navigateOpts === void 0) {
1846
- navigateOpts = router.state.latestLocation;
2386
+ navigateOpts = store.latestLocation;
1847
2387
  }
1848
2388
  const next = router.buildNext(navigateOpts);
1849
2389
  const matches = router.matchRoutes(next.pathname, {
@@ -1851,28 +2391,27 @@
1851
2391
  });
1852
2392
  await router.loadMatches(matches, {
1853
2393
  preload: true,
1854
- maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
1855
- 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
1856
2396
  });
1857
2397
  return matches;
1858
2398
  },
1859
2399
  matchRoutes: (pathname, opts) => {
1860
- var _router$state$pending2;
1861
2400
  router.cleanMatchCache();
1862
2401
  const matches = [];
1863
2402
  if (!router.routeTree) {
1864
2403
  return matches;
1865
2404
  }
1866
- const existingMatches = [...router.state.currentMatches, ...((_router$state$pending2 = router.state.pendingMatches) != null ? _router$state$pending2 : [])];
2405
+ const existingMatches = [...store.currentMatches, ...(store.pendingMatches ?? [])];
1867
2406
  const recurse = async routes => {
1868
- var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
2407
+ var _foundRoute$childRout;
1869
2408
  const parentMatch = last(matches);
1870
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
1871
- 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;
1872
2411
  let foundRoutes = [];
1873
2412
  const findMatchInRoutes = (parentRoutes, routes) => {
1874
2413
  routes.some(route => {
1875
- var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
2414
+ var _route$childRoutes, _route$childRoutes2;
1876
2415
  if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
1877
2416
  return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
1878
2417
  }
@@ -1880,28 +2419,21 @@
1880
2419
  const matchParams = matchPathname(router.basepath, pathname, {
1881
2420
  to: route.fullPath,
1882
2421
  fuzzy,
1883
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2422
+ caseSensitive: route.options.caseSensitive ?? router.options.caseSensitive
1884
2423
  });
1885
-
1886
- // console.log(
1887
- // router.basepath,
1888
- // route.fullPath,
1889
- // fuzzy,
1890
- // pathname,
1891
- // matchParams,
1892
- // )
1893
-
1894
2424
  if (matchParams) {
1895
2425
  let parsedParams;
1896
2426
  try {
1897
- var _route$options$parseP;
1898
- 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;
1899
2428
  } catch (err) {
1900
2429
  if (opts != null && opts.strictParseParams) {
1901
2430
  throw err;
1902
2431
  }
1903
2432
  }
1904
- params = _extends({}, params, parsedParams);
2433
+ params = {
2434
+ ...params,
2435
+ ...parsedParams
2436
+ };
1905
2437
  }
1906
2438
  if (!!matchParams) {
1907
2439
  foundRoutes = [...parentRoutes, route];
@@ -1915,10 +2447,10 @@
1915
2447
  return;
1916
2448
  }
1917
2449
  foundRoutes.forEach(foundRoute => {
1918
- var _router$matchCache$ma;
2450
+ var _store$matchCache$mat;
1919
2451
  const interpolatedPath = interpolatePath(foundRoute.routePath, params);
1920
2452
  const matchId = interpolatePath(foundRoute.routeId, params, true);
1921
- 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, {
1922
2454
  parentMatch,
1923
2455
  matchId,
1924
2456
  params,
@@ -1932,7 +2464,7 @@
1932
2464
  }
1933
2465
  };
1934
2466
  recurse([router.routeTree]);
1935
- cascadeLoaderData(matches);
2467
+ linkMatches(matches);
1936
2468
  return matches;
1937
2469
  },
1938
2470
  loadMatches: async (resolvedMatches, loaderOpts) => {
@@ -1957,32 +2489,31 @@
1957
2489
  }));
1958
2490
  const matchPromises = resolvedMatches.map(async match => {
1959
2491
  var _search$__data;
1960
- const search = match.search;
2492
+ const search = match.store.search;
1961
2493
  if ((_search$__data = search.__data) != null && _search$__data.matchId && search.__data.matchId !== match.matchId) {
1962
2494
  return;
1963
2495
  }
1964
2496
  match.load(loaderOpts);
1965
- if (match.status !== 'success' && match.__.loadPromise) {
2497
+ if (match.store.status !== 'success' && match.__.loadPromise) {
1966
2498
  // Wait for the first sign of activity from the match
1967
2499
  await match.__.loadPromise;
1968
2500
  }
1969
2501
  });
1970
- router.notify();
1971
2502
  await Promise.all(matchPromises);
1972
2503
  },
1973
2504
  loadMatchData: async routeMatch => {
1974
2505
  if (isServer || !router.options.useServerData) {
1975
- var _await$routeMatch$opt;
1976
- 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({
1977
2507
  // parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
1978
2508
  params: routeMatch.params,
1979
- search: routeMatch.routeSearch,
2509
+ search: routeMatch.store.routeSearch,
1980
2510
  signal: routeMatch.__.abortController.signal
1981
- }))) != null ? _await$routeMatch$opt : {};
2511
+ }))) || {};
1982
2512
  } else {
1983
2513
  const next = router.buildNext({
1984
2514
  to: '.',
1985
- search: d => _extends({}, d != null ? d : {}, {
2515
+ search: d => ({
2516
+ ...(d ?? {}),
1986
2517
  __data: {
1987
2518
  matchId: routeMatch.matchId
1988
2519
  }
@@ -2011,16 +2542,15 @@
2011
2542
  }
2012
2543
  },
2013
2544
  invalidateRoute: opts => {
2014
- var _router$state$pending3;
2015
2545
  const next = router.buildNext(opts);
2016
2546
  const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2017
- [...router.state.currentMatches, ...((_router$state$pending3 = router.state.pendingMatches) != null ? _router$state$pending3 : [])].forEach(match => {
2547
+ [...store.currentMatches, ...(store.pendingMatches ?? [])].forEach(match => {
2018
2548
  if (unloadedMatchIds.includes(match.matchId)) {
2019
2549
  match.invalidate();
2020
2550
  }
2021
2551
  });
2022
2552
  },
2023
- reload: () => router.__.navigate({
2553
+ reload: () => navigate({
2024
2554
  fromCurrent: true,
2025
2555
  replace: true,
2026
2556
  search: true
@@ -2029,26 +2559,28 @@
2029
2559
  return resolvePath(router.basepath, from, cleanPath(path));
2030
2560
  },
2031
2561
  matchRoute: (location, opts) => {
2032
- var _location$from;
2033
2562
  // const location = router.buildNext(opts)
2034
2563
 
2035
- location = _extends({}, location, {
2036
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
2037
- });
2564
+ location = {
2565
+ ...location,
2566
+ to: location.to ? router.resolvePath(location.from ?? '', location.to) : undefined
2567
+ };
2038
2568
  const next = router.buildNext(location);
2039
2569
  if (opts != null && opts.pending) {
2040
- if (!router.state.pendingLocation) {
2570
+ if (!store.pendingLocation) {
2041
2571
  return false;
2042
2572
  }
2043
- return !!matchPathname(router.basepath, router.state.pendingLocation.pathname, _extends({}, opts, {
2573
+ return !!matchPathname(router.basepath, store.pendingLocation.pathname, {
2574
+ ...opts,
2044
2575
  to: next.pathname
2045
- }));
2576
+ });
2046
2577
  }
2047
- return !!matchPathname(router.basepath, router.state.currentLocation.pathname, _extends({}, opts, {
2578
+ return matchPathname(router.basepath, store.currentLocation.pathname, {
2579
+ ...opts,
2048
2580
  to: next.pathname
2049
- }));
2581
+ });
2050
2582
  },
2051
- navigate: async _ref7 => {
2583
+ navigate: async _ref => {
2052
2584
  let {
2053
2585
  from,
2054
2586
  to = '.',
@@ -2056,7 +2588,7 @@
2056
2588
  hash,
2057
2589
  replace,
2058
2590
  params
2059
- } = _ref7;
2591
+ } = _ref;
2060
2592
  // If this link simply reloads the current route,
2061
2593
  // make sure it has a new key so it will trigger a data refresh
2062
2594
 
@@ -2066,11 +2598,11 @@
2066
2598
  const fromString = String(from);
2067
2599
  let isExternal;
2068
2600
  try {
2069
- new URL("" + toString);
2601
+ new URL(`${toString}`);
2070
2602
  isExternal = true;
2071
2603
  } catch (e) {}
2072
2604
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2073
- return router.__.navigate({
2605
+ return navigate({
2074
2606
  from: fromString,
2075
2607
  to: toString,
2076
2608
  search,
@@ -2079,8 +2611,7 @@
2079
2611
  params
2080
2612
  });
2081
2613
  },
2082
- buildLink: _ref8 => {
2083
- var _preload, _ref9;
2614
+ buildLink: _ref2 => {
2084
2615
  let {
2085
2616
  from,
2086
2617
  to = '.',
@@ -2095,7 +2626,7 @@
2095
2626
  preloadGcMaxAge: userPreloadGcMaxAge,
2096
2627
  preloadDelay: userPreloadDelay,
2097
2628
  disabled
2098
- } = _ref8;
2629
+ } = _ref2;
2099
2630
  // If this link simply reloads the current route,
2100
2631
  // make sure it has a new key so it will trigger a data refresh
2101
2632
 
@@ -2103,7 +2634,7 @@
2103
2634
  // null for LinkUtils
2104
2635
 
2105
2636
  try {
2106
- new URL("" + to);
2637
+ new URL(`${to}`);
2107
2638
  return {
2108
2639
  type: 'external',
2109
2640
  href: to
@@ -2118,15 +2649,15 @@
2118
2649
  replace
2119
2650
  };
2120
2651
  const next = router.buildNext(nextOpts);
2121
- preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2122
- 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;
2123
2654
 
2124
2655
  // Compare path/hash for matches
2125
- const pathIsEqual = router.state.currentLocation.pathname === next.pathname;
2126
- const currentPathSplit = router.state.currentLocation.pathname.split('/');
2656
+ const pathIsEqual = store.currentLocation.pathname === next.pathname;
2657
+ const currentPathSplit = store.currentLocation.pathname.split('/');
2127
2658
  const nextPathSplit = next.pathname.split('/');
2128
2659
  const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2129
- const hashIsEqual = router.state.currentLocation.hash === next.hash;
2660
+ const hashIsEqual = store.currentLocation.hash === next.hash;
2130
2661
  // Combine the matches based on user options
2131
2662
  const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2132
2663
  const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true;
@@ -2142,8 +2673,8 @@
2142
2673
  router.invalidateRoute(nextOpts);
2143
2674
  }
2144
2675
 
2145
- // All is well? Navigate!)
2146
- router.__.navigate(nextOpts);
2676
+ // All is well? Navigate!
2677
+ navigate(nextOpts);
2147
2678
  }
2148
2679
  };
2149
2680
 
@@ -2196,143 +2727,15 @@
2196
2727
  };
2197
2728
  },
2198
2729
  buildNext: opts => {
2199
- const next = router.__.buildLocation(opts);
2730
+ const next = buildLocation(opts);
2200
2731
  const matches = router.matchRoutes(next.pathname);
2201
- const __preSearchFilters = matches.map(match => {
2202
- var _match$options$preSea;
2203
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2204
- }).flat().filter(Boolean);
2205
- const __postSearchFilters = matches.map(match => {
2206
- var _match$options$postSe;
2207
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2208
- }).flat().filter(Boolean);
2209
- 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,
2210
2736
  __preSearchFilters,
2211
2737
  __postSearchFilters
2212
- }));
2213
- },
2214
- __: {
2215
- buildRouteTree: rootRouteConfig => {
2216
- const recurseRoutes = (routeConfigs, parent) => {
2217
- return routeConfigs.map(routeConfig => {
2218
- const routeOptions = routeConfig.options;
2219
- const route = createRoute(routeConfig, routeOptions, parent, router);
2220
- const existingRoute = router.routesById[route.routeId];
2221
- if (existingRoute) {
2222
- {
2223
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2224
- }
2225
- throw new Error();
2226
- }
2227
- router.routesById[route.routeId] = route;
2228
- const children = routeConfig.children;
2229
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2230
- return route;
2231
- });
2232
- };
2233
- const routes = recurseRoutes([rootRouteConfig]);
2234
- return routes[0];
2235
- },
2236
- parseLocation: (location, previousLocation) => {
2237
- var _location$hash$split$;
2238
- const parsedSearch = router.options.parseSearch(location.search);
2239
- return {
2240
- pathname: location.pathname,
2241
- searchStr: location.search,
2242
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2243
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2244
- href: "" + location.pathname + location.search + location.hash,
2245
- state: location.state,
2246
- key: location.key
2247
- };
2248
- },
2249
- navigate: location => {
2250
- const next = router.buildNext(location);
2251
- return router.__.commitLocation(next, location.replace);
2252
- },
2253
- buildLocation: function buildLocation(dest) {
2254
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2255
- if (dest === void 0) {
2256
- dest = {};
2257
- }
2258
- const fromPathname = dest.fromCurrent ? router.state.latestLocation.pathname : (_dest$from = dest.from) != null ? _dest$from : router.state.latestLocation.pathname;
2259
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2260
- const fromMatches = router.matchRoutes(router.state.latestLocation.pathname, {
2261
- strictParseParams: true
2262
- });
2263
- const toMatches = router.matchRoutes(pathname);
2264
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2265
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2266
- if (nextParams) {
2267
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2268
- Object.assign({}, nextParams, fn(nextParams));
2269
- });
2270
- }
2271
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {});
2272
-
2273
- // Pre filters first
2274
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.state.latestLocation.search) : router.state.latestLocation.search;
2275
-
2276
- // Then the link/navigate function
2277
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2278
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2279
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2280
- : {};
2281
-
2282
- // Then post filters
2283
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2284
- const search = replaceEqualDeep(router.state.latestLocation.search, postFilteredSearch);
2285
- const searchStr = router.options.stringifySearch(search);
2286
- let hash = dest.hash === true ? router.state.latestLocation.hash : functionalUpdate(dest.hash, router.state.latestLocation.hash);
2287
- hash = hash ? "#" + hash : '';
2288
- return {
2289
- pathname,
2290
- search,
2291
- searchStr,
2292
- state: router.state.latestLocation.state,
2293
- hash,
2294
- href: "" + pathname + searchStr + hash,
2295
- key: dest.key
2296
- };
2297
- },
2298
- commitLocation: (next, replace) => {
2299
- const id = '' + Date.now() + Math.random();
2300
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2301
- let nextAction = 'replace';
2302
- if (!replace) {
2303
- nextAction = 'push';
2304
- }
2305
- const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2306
- if (isSameUrl && !next.key) {
2307
- nextAction = 'replace';
2308
- }
2309
- if (nextAction === 'replace') {
2310
- history.replace({
2311
- pathname: next.pathname,
2312
- hash: next.hash,
2313
- search: next.searchStr
2314
- }, _extends({
2315
- id
2316
- }, next.state));
2317
- } else {
2318
- history.push({
2319
- pathname: next.pathname,
2320
- hash: next.hash,
2321
- search: next.searchStr
2322
- }, {
2323
- id
2324
- });
2325
- }
2326
- router.navigationPromise = new Promise(resolve => {
2327
- const previousNavigationResolve = router.resolveNavigation;
2328
- router.resolveNavigation = () => {
2329
- previousNavigationResolve();
2330
- resolve();
2331
- delete router.navigationPromise;
2332
- };
2333
- });
2334
- return router.navigationPromise;
2335
- }
2738
+ });
2336
2739
  }
2337
2740
  };
2338
2741
  router.update(userOptions);
@@ -2344,11 +2747,13 @@
2344
2747
  function isCtrlEvent(e) {
2345
2748
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2346
2749
  }
2347
- function cascadeLoaderData(matches) {
2750
+ function linkMatches(matches) {
2348
2751
  matches.forEach((match, index) => {
2349
2752
  const parent = matches[index - 1];
2350
2753
  if (parent) {
2351
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
2754
+ match.__.setParentMatch(parent);
2755
+ } else {
2756
+ match.__.setParentMatch(undefined);
2352
2757
  }
2353
2758
  });
2354
2759
  }
@@ -2375,9 +2780,9 @@
2375
2780
  exports.parsePathname = parsePathname;
2376
2781
  exports.parseSearchWith = parseSearchWith;
2377
2782
  exports.pick = pick;
2378
- exports.replaceEqualDeep = replaceEqualDeep;
2379
2783
  exports.resolvePath = resolvePath;
2380
2784
  exports.rootRouteId = rootRouteId;
2785
+ exports.sharedClone = sharedClone;
2381
2786
  exports.stringifySearchWith = stringifySearchWith;
2382
2787
  exports.trimPath = trimPath;
2383
2788
  exports.trimPathLeft = trimPathLeft;