@tanstack/react-router 0.0.1-alpha.9 → 0.0.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -975,6 +975,12 @@ function functionalUpdate(updater, previous) {
975
975
 
976
976
  return updater;
977
977
  }
978
+ function pick(parent, keys) {
979
+ return keys.reduce((obj, key) => {
980
+ obj[key] = parent[key];
981
+ return obj;
982
+ }, {});
983
+ }
978
984
 
979
985
  function joinPaths(paths) {
980
986
  return cleanPath(paths.filter(Boolean).join('/'));
@@ -1201,6 +1207,7 @@ function toValue(mix) {
1201
1207
  var str = decodeURIComponent(mix);
1202
1208
  if (str === 'false') return false;
1203
1209
  if (str === 'true') return true;
1210
+ if (str.charAt(0) === '0') return str;
1204
1211
  return +str * 0 === 0 ? +str : str;
1205
1212
  }
1206
1213
 
@@ -1251,7 +1258,7 @@ function createRoute(routeConfig, options, parent, router) {
1251
1258
 
1252
1259
  const action = router.state.actions[id] || (() => {
1253
1260
  router.state.actions[id] = {
1254
- pending: [],
1261
+ submissions: [],
1255
1262
  submit: async (submission, actionOpts) => {
1256
1263
  var _actionOpts$invalidat;
1257
1264
 
@@ -1260,18 +1267,20 @@ function createRoute(routeConfig, options, parent, router) {
1260
1267
  }
1261
1268
 
1262
1269
  const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1270
+
1271
+ if (!(actionOpts != null && actionOpts.multi)) {
1272
+ action.submissions = action.submissions.filter(d => d.isMulti);
1273
+ }
1274
+
1263
1275
  const actionState = {
1264
1276
  submittedAt: Date.now(),
1265
1277
  status: 'pending',
1266
- submission
1278
+ submission,
1279
+ isMulti: !!(actionOpts != null && actionOpts.multi)
1267
1280
  };
1268
1281
  action.current = actionState;
1269
1282
  action.latest = actionState;
1270
- action.pending.push(actionState);
1271
- router.state = _extends({}, router.state, {
1272
- currentAction: actionState,
1273
- latestAction: actionState
1274
- });
1283
+ action.submissions.push(actionState);
1275
1284
  router.notify();
1276
1285
 
1277
1286
  try {
@@ -1293,11 +1302,6 @@ function createRoute(routeConfig, options, parent, router) {
1293
1302
  actionState.error = err;
1294
1303
  actionState.status = 'error';
1295
1304
  } finally {
1296
- action.pending = action.pending.filter(d => d !== actionState);
1297
- router.removeActionQueue.push({
1298
- action,
1299
- actionState
1300
- });
1301
1305
  router.notify();
1302
1306
  }
1303
1307
  }
@@ -1305,6 +1309,40 @@ function createRoute(routeConfig, options, parent, router) {
1305
1309
  return router.state.actions[id];
1306
1310
  })();
1307
1311
 
1312
+ const loader = router.state.loaders[id] || (() => {
1313
+ router.state.loaders[id] = {
1314
+ pending: [],
1315
+ fetch: async loaderContext => {
1316
+ if (!route) {
1317
+ return;
1318
+ }
1319
+
1320
+ const loaderState = {
1321
+ loadedAt: Date.now(),
1322
+ loaderContext
1323
+ };
1324
+ loader.current = loaderState;
1325
+ loader.latest = loaderState;
1326
+ loader.pending.push(loaderState); // router.state = {
1327
+ // ...router.state,
1328
+ // currentAction: loaderState,
1329
+ // latestAction: loaderState,
1330
+ // }
1331
+
1332
+ router.notify();
1333
+
1334
+ try {
1335
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1336
+ } finally {
1337
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1338
+
1339
+ router.notify();
1340
+ }
1341
+ }
1342
+ };
1343
+ return router.state.loaders[id];
1344
+ })();
1345
+
1308
1346
  let route = {
1309
1347
  routeId: id,
1310
1348
  routeRouteId: routeId,
@@ -1315,6 +1353,7 @@ function createRoute(routeConfig, options, parent, router) {
1315
1353
  childRoutes: undefined,
1316
1354
  parentRoute: parent,
1317
1355
  action,
1356
+ loader: loader,
1318
1357
  buildLink: options => {
1319
1358
  return router.buildLink(_extends({}, options, {
1320
1359
  from: fullPath
@@ -1337,15 +1376,6 @@ function createRoute(routeConfig, options, parent, router) {
1337
1376
  });
1338
1377
  return route;
1339
1378
  }
1340
- function cascadeLoaderData(matches) {
1341
- matches.forEach((match, index) => {
1342
- const parent = matches[index - 1];
1343
-
1344
- if (parent) {
1345
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1346
- }
1347
- });
1348
- }
1349
1379
 
1350
1380
  const rootRouteId = '__root__';
1351
1381
  const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
@@ -1411,6 +1441,7 @@ function createRouteMatch(router, route, opts) {
1411
1441
  isFetching: false,
1412
1442
  isInvalid: false,
1413
1443
  invalidAt: Infinity,
1444
+ // pendingActions: [],
1414
1445
  getIsInvalid: () => {
1415
1446
  const now = Date.now();
1416
1447
  return routeMatch.isInvalid || routeMatch.invalidAt < now;
@@ -1450,17 +1481,6 @@ function createRouteMatch(router, route, opts) {
1450
1481
  clearTimeout(routeMatch.__.pendingMinTimeout);
1451
1482
  delete routeMatch.__.pendingMinPromise;
1452
1483
  },
1453
- // setParentMatch: (parentMatch?: RouteMatch) => {
1454
- // routeMatch.parentMatch = parentMatch
1455
- // },
1456
- // addChildMatch: (childMatch: RouteMatch) => {
1457
- // if (
1458
- // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1459
- // ) {
1460
- // return
1461
- // }
1462
- // routeMatch.childMatches.push(childMatch)
1463
- // },
1464
1484
  validate: () => {
1465
1485
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1466
1486
 
@@ -1468,9 +1488,11 @@ function createRouteMatch(router, route, opts) {
1468
1488
  const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1469
1489
 
1470
1490
  try {
1491
+ var _validator;
1492
+
1471
1493
  const prevSearch = routeMatch.routeSearch;
1472
1494
  const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1473
- let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1495
+ let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {}); // Invalidate route matches when search param stability changes
1474
1496
 
1475
1497
  if (prevSearch !== nextSearch) {
1476
1498
  routeMatch.isInvalid = true;
@@ -1478,6 +1500,13 @@ function createRouteMatch(router, route, opts) {
1478
1500
 
1479
1501
  routeMatch.routeSearch = nextSearch;
1480
1502
  routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1503
+ elementTypes.map(async type => {
1504
+ const routeElement = routeMatch.options[type];
1505
+
1506
+ if (typeof routeMatch.__[type] !== 'function') {
1507
+ routeMatch.__[type] = routeElement;
1508
+ }
1509
+ });
1481
1510
  } catch (err) {
1482
1511
  console.error(err);
1483
1512
  const error = new Error('Invalid search params found', {
@@ -1502,9 +1531,33 @@ function createRouteMatch(router, route, opts) {
1502
1531
  routeMatch.isInvalid = true;
1503
1532
  },
1504
1533
  hasLoaders: () => {
1505
- return !!(route.options.loader || route.options.import || elementTypes.some(d => typeof route.options[d] === 'function'));
1534
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1535
+ },
1536
+ load: async loaderOpts => {
1537
+ const now = Date.now();
1538
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1539
+
1540
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1541
+ // If the match is currently active, don't preload it
1542
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1543
+ return;
1544
+ }
1545
+
1546
+ router.matchCache[routeMatch.matchId] = {
1547
+ gc: now + loaderOpts.gcMaxAge,
1548
+ match: routeMatch
1549
+ };
1550
+ } // If the match is invalid, errored or idle, trigger it to load
1551
+
1552
+
1553
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1554
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1555
+ await routeMatch.fetch({
1556
+ maxAge
1557
+ });
1558
+ }
1506
1559
  },
1507
- load: async opts => {
1560
+ fetch: async opts => {
1508
1561
  const id = '' + Date.now() + Math.random();
1509
1562
  routeMatch.__.latestId = id; // If the match was in an error state, set it
1510
1563
  // to a loading state again. Otherwise, keep it
@@ -1522,37 +1575,16 @@ function createRouteMatch(router, route, opts) {
1522
1575
  routeMatch.isFetching = true;
1523
1576
  routeMatch.__.resolve = resolve;
1524
1577
 
1525
- const loaderPromise = (async () => {
1526
- const importer = routeMatch.options.import; // First, run any importers
1527
-
1528
- if (importer) {
1529
- routeMatch.__.importPromise = importer({
1530
- params: routeMatch.params // search: routeMatch.search,
1531
-
1532
- }).then(imported => {
1533
- routeMatch.__ = _extends({}, routeMatch.__, imported);
1534
- });
1535
- } // Wait for the importer to finish before
1536
- // attempting to load elements and data
1537
-
1538
-
1539
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1540
-
1578
+ routeMatch.__.loaderDataPromise = (async () => {
1579
+ // Load the elements and data in parallel
1541
1580
  routeMatch.__.elementsPromise = (async () => {
1542
1581
  // then run all element and data loaders in parallel
1543
1582
  // For each element type, potentially load it asynchronously
1544
1583
  await Promise.all(elementTypes.map(async type => {
1545
1584
  const routeElement = routeMatch.options[type];
1546
1585
 
1547
- if (routeMatch.__[type]) {
1548
- return;
1549
- }
1550
-
1551
- if (typeof routeElement === 'function') {
1552
- const res = await routeElement(routeMatch);
1553
- routeMatch.__[type] = res;
1554
- } else {
1555
- routeMatch.__[type] = routeMatch.options[type];
1586
+ if (typeof routeMatch.__[type] === 'function') {
1587
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1556
1588
  }
1557
1589
  }));
1558
1590
  })();
@@ -1569,7 +1601,7 @@ function createRouteMatch(router, route, opts) {
1569
1601
  });
1570
1602
 
1571
1603
  if (id !== routeMatch.__.latestId) {
1572
- return routeMatch.__.loaderPromise;
1604
+ return routeMatch.__.loadPromise;
1573
1605
  }
1574
1606
 
1575
1607
  routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
@@ -1581,7 +1613,7 @@ function createRouteMatch(router, route, opts) {
1581
1613
  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);
1582
1614
  } catch (err) {
1583
1615
  if (id !== routeMatch.__.latestId) {
1584
- return routeMatch.__.loaderPromise;
1616
+ return routeMatch.__.loadPromise;
1585
1617
  }
1586
1618
 
1587
1619
  if (process.env.NODE_ENV !== 'production') {
@@ -1598,7 +1630,7 @@ function createRouteMatch(router, route, opts) {
1598
1630
  await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1599
1631
 
1600
1632
  if (id !== routeMatch.__.latestId) {
1601
- return routeMatch.__.loaderPromise;
1633
+ return routeMatch.__.loadPromise;
1602
1634
  }
1603
1635
 
1604
1636
  if (routeMatch.__.pendingMinPromise) {
@@ -1607,7 +1639,7 @@ function createRouteMatch(router, route, opts) {
1607
1639
  }
1608
1640
  } finally {
1609
1641
  if (id !== routeMatch.__.latestId) {
1610
- return routeMatch.__.loaderPromise;
1642
+ return routeMatch.__.loadPromise;
1611
1643
  }
1612
1644
 
1613
1645
  routeMatch.__.cancelPending();
@@ -1619,16 +1651,16 @@ function createRouteMatch(router, route, opts) {
1619
1651
  }
1620
1652
  })();
1621
1653
 
1622
- routeMatch.__.loaderPromise = loaderPromise;
1623
- await loaderPromise;
1654
+ await routeMatch.__.loaderDataPromise;
1624
1655
 
1625
1656
  if (id !== routeMatch.__.latestId) {
1626
- return routeMatch.__.loaderPromise;
1657
+ return routeMatch.__.loadPromise;
1627
1658
  }
1628
1659
 
1629
- delete routeMatch.__.loaderPromise;
1660
+ delete routeMatch.__.loaderDataPromise;
1630
1661
  });
1631
- return await routeMatch.__.loadPromise;
1662
+ await routeMatch.__.loadPromise;
1663
+ delete routeMatch.__.loadPromise;
1632
1664
  }
1633
1665
  });
1634
1666
 
@@ -1689,9 +1721,22 @@ function stringifySearchWith(stringify) {
1689
1721
 
1690
1722
  var _window$document;
1691
1723
  // Detect if we're in the DOM
1692
- const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1724
+ const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
1693
1725
 
1694
- const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1726
+ const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
1727
+
1728
+ function getInitialRouterState() {
1729
+ return {
1730
+ status: 'idle',
1731
+ location: null,
1732
+ matches: [],
1733
+ actions: {},
1734
+ loaders: {},
1735
+ lastUpdated: Date.now(),
1736
+ isFetching: false,
1737
+ isPreloading: false
1738
+ };
1739
+ }
1695
1740
 
1696
1741
  function createRouter(userOptions) {
1697
1742
  var _userOptions$stringif, _userOptions$parseSea;
@@ -1709,9 +1754,9 @@ function createRouter(userOptions) {
1709
1754
  });
1710
1755
 
1711
1756
  let router = {
1757
+ history,
1712
1758
  options: originalOptions,
1713
1759
  listeners: [],
1714
- removeActionQueue: [],
1715
1760
  // Resolved after construction
1716
1761
  basepath: '',
1717
1762
  routeTree: undefined,
@@ -1722,15 +1767,10 @@ function createRouter(userOptions) {
1722
1767
  navigationPromise: Promise.resolve(),
1723
1768
  resolveNavigation: () => {},
1724
1769
  matchCache: {},
1725
- state: {
1726
- status: 'idle',
1727
- location: null,
1728
- matches: [],
1729
- actions: {},
1730
- loaderData: {},
1731
- lastUpdated: Date.now(),
1732
- isFetching: false,
1733
- isPreloading: false
1770
+ state: getInitialRouterState(),
1771
+ reset: () => {
1772
+ router.state = getInitialRouterState();
1773
+ router.notify();
1734
1774
  },
1735
1775
  startedLoadingAt: Date.now(),
1736
1776
  subscribe: listener => {
@@ -1748,24 +1788,44 @@ function createRouter(userOptions) {
1748
1788
  isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1749
1789
  });
1750
1790
  cascadeLoaderData(router.state.matches);
1751
- router.listeners.forEach(listener => listener());
1791
+ router.listeners.forEach(listener => listener(router));
1792
+ },
1793
+ dehydrateState: () => {
1794
+ return _extends({}, pick(router.state, ['status', 'location', 'lastUpdated']), {
1795
+ matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
1796
+ });
1797
+ },
1798
+ hydrateState: dehydratedState => {
1799
+ // Match the routes
1800
+ const matches = router.matchRoutes(router.location.pathname, {
1801
+ strictParseParams: true
1802
+ });
1803
+ matches.forEach((match, index) => {
1804
+ const dehydratedMatch = dehydratedState.matches[index];
1805
+ invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1806
+ Object.assign(match, dehydratedMatch);
1807
+ });
1808
+ router.loadMatches(matches);
1809
+ router.state = _extends({}, router.state, dehydratedState, {
1810
+ matches
1811
+ });
1752
1812
  },
1753
1813
  mount: () => {
1754
- const next = router.buildLocation({
1814
+ const next = router.__.buildLocation({
1755
1815
  to: '.',
1756
1816
  search: true,
1757
1817
  hash: true
1758
1818
  }); // If the current location isn't updated, trigger a navigation
1759
1819
  // to the current location. Otherwise, load the current location.
1760
1820
 
1821
+
1761
1822
  if (next.href !== router.location.href) {
1762
- router.commitLocation(next, true);
1763
- } else {
1764
- router.loadLocation();
1765
- }
1823
+ router.__.commitLocation(next, true);
1824
+ } // router.load()
1825
+
1766
1826
 
1767
- const unsub = history.listen(event => {
1768
- router.loadLocation(router.parseLocation(event.location, router.location));
1827
+ const unsub = router.history.listen(event => {
1828
+ router.load(router.__.parseLocation(event.location, router.location));
1769
1829
  }); // addEventListener does not exist in React Native, but window does
1770
1830
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1771
1831
 
@@ -1776,16 +1836,30 @@ function createRouter(userOptions) {
1776
1836
  }
1777
1837
 
1778
1838
  return () => {
1779
- unsub(); // Be sure to unsubscribe if a new handler is set
1839
+ unsub();
1780
1840
 
1781
- window.removeEventListener('visibilitychange', router.onFocus);
1782
- window.removeEventListener('focus', router.onFocus);
1841
+ if (!isServer && window.removeEventListener) {
1842
+ // Be sure to unsubscribe if a new handler is set
1843
+ window.removeEventListener('visibilitychange', router.onFocus);
1844
+ window.removeEventListener('focus', router.onFocus);
1845
+ }
1783
1846
  };
1784
1847
  },
1785
1848
  onFocus: () => {
1786
- router.loadLocation();
1849
+ router.load();
1787
1850
  },
1788
1851
  update: opts => {
1852
+ const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
1853
+
1854
+ if (!router.location || newHistory) {
1855
+ if (opts != null && opts.history) {
1856
+ router.history = opts.history;
1857
+ }
1858
+
1859
+ router.location = router.__.parseLocation(router.history.location);
1860
+ router.state.location = router.location;
1861
+ }
1862
+
1789
1863
  Object.assign(router.options, opts);
1790
1864
  const {
1791
1865
  basepath,
@@ -1795,204 +1869,30 @@ function createRouter(userOptions) {
1795
1869
 
1796
1870
  if (routeConfig) {
1797
1871
  router.routesById = {};
1798
- router.routeTree = router.buildRouteTree(routeConfig);
1872
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1799
1873
  }
1800
1874
 
1801
1875
  return router;
1802
1876
  },
1803
- buildRouteTree: rootRouteConfig => {
1804
- const recurseRoutes = (routeConfigs, parent) => {
1805
- return routeConfigs.map(routeConfig => {
1806
- const routeOptions = routeConfig.options;
1807
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1808
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1809
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1810
- // }
1811
-
1812
- const existingRoute = router.routesById[route.routeId];
1813
-
1814
- if (existingRoute) {
1815
- if (process.env.NODE_ENV !== 'production') {
1816
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1817
- }
1818
-
1819
- throw new Error();
1820
- }
1821
- router.routesById[route.routeId] = route;
1822
- const children = routeConfig.children;
1823
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1824
- return route;
1825
- });
1826
- };
1827
-
1828
- const routes = recurseRoutes([rootRouteConfig]);
1829
- return routes[0];
1830
- },
1831
- parseLocation: (location, previousLocation) => {
1832
- var _location$hash$split$;
1833
-
1834
- const parsedSearch = router.options.parseSearch(location.search);
1835
- return {
1836
- pathname: location.pathname,
1837
- searchStr: location.search,
1838
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1839
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1840
- href: "" + location.pathname + location.search + location.hash,
1841
- state: location.state,
1842
- key: location.key
1843
- };
1844
- },
1845
- buildLocation: function buildLocation(dest) {
1846
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
1847
-
1848
- if (dest === void 0) {
1849
- dest = {};
1850
- }
1851
-
1852
- // const resolvedFrom: Location = {
1853
- // ...router.location,
1854
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
1855
-
1856
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
1857
-
1858
- const fromMatches = router.matchRoutes(router.location.pathname, {
1859
- strictParseParams: true
1860
- });
1861
- const toMatches = router.matchRoutes(pathname);
1862
-
1863
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
1864
-
1865
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1866
-
1867
- if (nextParams) {
1868
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1869
- Object.assign({}, nextParams, fn(nextParams));
1870
- });
1871
- }
1872
-
1873
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1874
-
1875
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
1876
-
1877
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1878
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1879
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1880
- : {}; // Then post filters
1881
-
1882
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1883
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1884
- const searchStr = router.options.stringifySearch(search);
1885
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1886
- hash = hash ? "#" + hash : '';
1887
- return {
1888
- pathname,
1889
- search,
1890
- searchStr,
1891
- state: router.location.state,
1892
- hash,
1893
- href: "" + pathname + searchStr + hash,
1894
- key: dest.key
1895
- };
1896
- },
1897
- commitLocation: (next, replace) => {
1898
- const id = '' + Date.now() + Math.random();
1899
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1900
- let nextAction = 'replace';
1901
-
1902
- if (!replace) {
1903
- nextAction = 'push';
1904
- }
1905
-
1906
- const isSameUrl = router.parseLocation(history.location).href === next.href;
1907
-
1908
- if (isSameUrl && !next.key) {
1909
- nextAction = 'replace';
1910
- }
1911
-
1912
- if (nextAction === 'replace') {
1913
- history.replace({
1914
- pathname: next.pathname,
1915
- hash: next.hash,
1916
- search: next.searchStr
1917
- }, {
1918
- id
1919
- });
1920
- } else {
1921
- history.push({
1922
- pathname: next.pathname,
1923
- hash: next.hash,
1924
- search: next.searchStr
1925
- }, {
1926
- id
1927
- });
1928
- }
1929
-
1930
- router.navigationPromise = new Promise(resolve => {
1931
- const previousNavigationResolve = router.resolveNavigation;
1932
-
1933
- router.resolveNavigation = () => {
1934
- previousNavigationResolve();
1935
- resolve();
1936
- };
1937
- });
1938
- return router.navigationPromise;
1939
- },
1940
- buildNext: opts => {
1941
- const next = router.buildLocation(opts);
1942
- const matches = router.matchRoutes(next.pathname);
1943
-
1944
- const __preSearchFilters = matches.map(match => {
1945
- var _match$options$preSea;
1946
-
1947
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1948
- }).flat().filter(Boolean);
1949
-
1950
- const __postSearchFilters = matches.map(match => {
1951
- var _match$options$postSe;
1952
-
1953
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1954
- }).flat().filter(Boolean);
1955
-
1956
- return router.buildLocation(_extends({}, opts, {
1957
- __preSearchFilters,
1958
- __postSearchFilters
1959
- }));
1960
- },
1961
1877
  cancelMatches: () => {
1962
1878
  var _router$state$pending, _router$state$pending2;
1963
1879
  [...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 => {
1964
1880
  match.cancel();
1965
1881
  });
1966
1882
  },
1967
- loadLocation: async next => {
1883
+ load: async next => {
1968
1884
  const id = Math.random();
1969
1885
  router.startedLoadingAt = id;
1970
1886
 
1971
1887
  if (next) {
1972
1888
  // Ingest the new location
1973
1889
  router.location = next;
1974
- } // Clear out old actions
1975
-
1976
-
1977
- router.removeActionQueue.forEach(_ref => {
1978
- let {
1979
- action,
1980
- actionState
1981
- } = _ref;
1982
-
1983
- if (router.state.currentAction === actionState) {
1984
- router.state.currentAction = undefined;
1985
- }
1890
+ } // Cancel any pending matches
1986
1891
 
1987
- if (action.current === actionState) {
1988
- action.current = undefined;
1989
- }
1990
- });
1991
- router.removeActionQueue = []; // Cancel any pending matches
1992
1892
 
1993
1893
  router.cancelMatches(); // Match the routes
1994
1894
 
1995
- const matches = router.matchRoutes(location.pathname, {
1895
+ const matches = router.matchRoutes(router.location.pathname, {
1996
1896
  strictParseParams: true
1997
1897
  });
1998
1898
  router.state = _extends({}, router.state, {
@@ -2025,19 +1925,24 @@ function createRouter(userOptions) {
2025
1925
  });
2026
1926
  const now = Date.now();
2027
1927
  exiting.forEach(d => {
2028
- var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1928
+ var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
2029
1929
 
2030
1930
  d.__.onExit == null ? void 0 : d.__.onExit({
2031
1931
  params: d.params,
2032
1932
  search: d.routeSearch
2033
- }); // Clear idle error states when match leaves
1933
+ }); // // Clear actions
1934
+ // if (d.action) {
1935
+ // d.action.current = undefined
1936
+ // d.action.submissions = []
1937
+ // }
1938
+ // Clear idle error states when match leaves
2034
1939
 
2035
1940
  if (d.status === 'error' && !d.isFetching) {
2036
1941
  d.status = 'idle';
2037
1942
  d.error = undefined;
2038
1943
  }
2039
1944
 
2040
- const gc = Math.max((_ref2 = (_d$options$loaderGcMa = d.options.loaderGcMaxAge) != null ? _d$options$loaderGcMa : router.options.defaultLoaderGcMaxAge) != null ? _ref2 : 0, (_ref3 = (_d$options$loaderMaxA = d.options.loaderMaxAge) != null ? _d$options$loaderMaxA : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0);
1945
+ 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);
2041
1946
 
2042
1947
  if (gc > 0) {
2043
1948
  router.matchCache[d.matchId] = {
@@ -2060,18 +1965,21 @@ function createRouter(userOptions) {
2060
1965
  params: d.params,
2061
1966
  search: d.search
2062
1967
  });
2063
- });
2064
-
2065
- if (matches.some(d => d.status === 'loading')) {
2066
- router.notify();
2067
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
2068
- }
1968
+ delete router.matchCache[d.matchId];
1969
+ }); // router.notify()
2069
1970
 
2070
1971
  if (router.startedLoadingAt !== id) {
2071
1972
  // Ignore side-effects of match loading
2072
1973
  return;
2073
1974
  }
2074
1975
 
1976
+ matches.forEach(match => {
1977
+ // Clear actions
1978
+ if (match.action) {
1979
+ match.action.current = undefined;
1980
+ match.action.submissions = [];
1981
+ }
1982
+ });
2075
1983
  router.state = _extends({}, router.state, {
2076
1984
  location: router.location,
2077
1985
  matches,
@@ -2112,7 +2020,7 @@ function createRouter(userOptions) {
2112
2020
  return matches;
2113
2021
  },
2114
2022
  preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
2115
- var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
2023
+ var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
2116
2024
 
2117
2025
  if (navigateOpts === void 0) {
2118
2026
  navigateOpts = router.location;
@@ -2124,8 +2032,8 @@ function createRouter(userOptions) {
2124
2032
  });
2125
2033
  await router.loadMatches(matches, {
2126
2034
  preload: true,
2127
- maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
2128
- gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
2035
+ maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
2036
+ gcMaxAge: (_ref5 = (_ref6 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref6 : router.options.defaultLoaderGcMaxAge) != null ? _ref5 : 0
2129
2037
  });
2130
2038
  return matches;
2131
2039
  },
@@ -2219,38 +2127,20 @@ function createRouter(userOptions) {
2219
2127
  return matches;
2220
2128
  },
2221
2129
  loadMatches: async (resolvedMatches, loaderOpts) => {
2222
- const now = Date.now();
2223
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2224
2130
  const matchPromises = resolvedMatches.map(async match => {
2225
2131
  // Validate the match (loads search params etc)
2226
- match.__.validate(); // If this is a preload, add it to the preload cache
2132
+ match.__.validate();
2227
2133
 
2228
-
2229
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2230
- // If the match is currently active, don't preload it
2231
- if (router.state.matches.find(d => d.matchId === match.matchId)) {
2232
- return;
2233
- }
2234
-
2235
- router.matchCache[match.matchId] = {
2236
- gc: now + loaderOpts.gcMaxAge,
2237
- match
2238
- };
2239
- } // If the match is invalid, errored or idle, trigger it to load
2240
-
2241
-
2242
- if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2243
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2244
- match.load({
2245
- maxAge
2246
- });
2247
- }
2134
+ match.load(loaderOpts);
2248
2135
 
2249
2136
  if (match.status === 'loading') {
2250
2137
  // If requested, start the pending timers
2251
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2252
- // This might be completion, error, or a pending state
2138
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending();
2139
+ }
2253
2140
 
2141
+ if (match.__.loadPromise) {
2142
+ // Wait for the first sign of activity from the match
2143
+ // This might be completion, error, or a pending state
2254
2144
  await match.__.loadPromise;
2255
2145
  }
2256
2146
  });
@@ -2268,7 +2158,7 @@ function createRouter(userOptions) {
2268
2158
  }
2269
2159
  });
2270
2160
  },
2271
- reload: () => router._navigate({
2161
+ reload: () => router.__.navigate({
2272
2162
  fromCurrent: true,
2273
2163
  replace: true,
2274
2164
  search: true
@@ -2301,11 +2191,7 @@ function createRouter(userOptions) {
2301
2191
  to: next.pathname
2302
2192
  }));
2303
2193
  },
2304
- _navigate: location => {
2305
- const next = router.buildNext(location);
2306
- return router.commitLocation(next, location.replace);
2307
- },
2308
- navigate: async _ref8 => {
2194
+ navigate: async _ref7 => {
2309
2195
  let {
2310
2196
  from,
2311
2197
  to = '.',
@@ -2313,7 +2199,7 @@ function createRouter(userOptions) {
2313
2199
  hash,
2314
2200
  replace,
2315
2201
  params
2316
- } = _ref8;
2202
+ } = _ref7;
2317
2203
  // If this link simply reloads the current route,
2318
2204
  // make sure it has a new key so it will trigger a data refresh
2319
2205
  // If this `to` is a valid external URL, return
@@ -2328,7 +2214,7 @@ function createRouter(userOptions) {
2328
2214
  } catch (e) {}
2329
2215
 
2330
2216
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2331
- return router._navigate({
2217
+ return router.__.navigate({
2332
2218
  from: fromString,
2333
2219
  to: toString,
2334
2220
  search,
@@ -2337,8 +2223,8 @@ function createRouter(userOptions) {
2337
2223
  params
2338
2224
  });
2339
2225
  },
2340
- buildLink: _ref9 => {
2341
- var _preload, _ref10;
2226
+ buildLink: _ref8 => {
2227
+ var _preload, _ref9;
2342
2228
 
2343
2229
  let {
2344
2230
  from,
@@ -2354,7 +2240,7 @@ function createRouter(userOptions) {
2354
2240
  preloadGcMaxAge: userPreloadGcMaxAge,
2355
2241
  preloadDelay: userPreloadDelay,
2356
2242
  disabled
2357
- } = _ref9;
2243
+ } = _ref8;
2358
2244
 
2359
2245
  // If this link simply reloads the current route,
2360
2246
  // make sure it has a new key so it will trigger a data refresh
@@ -2378,7 +2264,7 @@ function createRouter(userOptions) {
2378
2264
  };
2379
2265
  const next = router.buildNext(nextOpts);
2380
2266
  preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2381
- const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2267
+ const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0; // Compare path/hash for matches
2382
2268
 
2383
2269
  const pathIsEqual = router.state.location.pathname === next.pathname;
2384
2270
  const currentPathSplit = router.state.location.pathname.split('/');
@@ -2400,7 +2286,7 @@ function createRouter(userOptions) {
2400
2286
  } // All is well? Navigate!)
2401
2287
 
2402
2288
 
2403
- router._navigate(nextOpts);
2289
+ router.__.navigate(nextOpts);
2404
2290
  }
2405
2291
  }; // The click handler
2406
2292
 
@@ -2451,10 +2337,169 @@ function createRouter(userOptions) {
2451
2337
  isActive,
2452
2338
  disabled
2453
2339
  };
2340
+ },
2341
+ buildNext: opts => {
2342
+ const next = router.__.buildLocation(opts);
2343
+
2344
+ const matches = router.matchRoutes(next.pathname);
2345
+
2346
+ const __preSearchFilters = matches.map(match => {
2347
+ var _match$options$preSea;
2348
+
2349
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2350
+ }).flat().filter(Boolean);
2351
+
2352
+ const __postSearchFilters = matches.map(match => {
2353
+ var _match$options$postSe;
2354
+
2355
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2356
+ }).flat().filter(Boolean);
2357
+
2358
+ return router.__.buildLocation(_extends({}, opts, {
2359
+ __preSearchFilters,
2360
+ __postSearchFilters
2361
+ }));
2362
+ },
2363
+ __: {
2364
+ buildRouteTree: rootRouteConfig => {
2365
+ const recurseRoutes = (routeConfigs, parent) => {
2366
+ return routeConfigs.map(routeConfig => {
2367
+ const routeOptions = routeConfig.options;
2368
+ const route = createRoute(routeConfig, routeOptions, parent, router);
2369
+ const existingRoute = router.routesById[route.routeId];
2370
+
2371
+ if (existingRoute) {
2372
+ if (process.env.NODE_ENV !== 'production') {
2373
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2374
+ }
2375
+
2376
+ throw new Error();
2377
+ }
2378
+ router.routesById[route.routeId] = route;
2379
+ const children = routeConfig.children;
2380
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2381
+ return route;
2382
+ });
2383
+ };
2384
+
2385
+ const routes = recurseRoutes([rootRouteConfig]);
2386
+ return routes[0];
2387
+ },
2388
+ parseLocation: (location, previousLocation) => {
2389
+ var _location$hash$split$;
2390
+
2391
+ const parsedSearch = router.options.parseSearch(location.search);
2392
+ return {
2393
+ pathname: location.pathname,
2394
+ searchStr: location.search,
2395
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2396
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2397
+ href: "" + location.pathname + location.search + location.hash,
2398
+ state: location.state,
2399
+ key: location.key
2400
+ };
2401
+ },
2402
+ navigate: location => {
2403
+ const next = router.buildNext(location);
2404
+ return router.__.commitLocation(next, location.replace);
2405
+ },
2406
+ buildLocation: function buildLocation(dest) {
2407
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2408
+
2409
+ if (dest === void 0) {
2410
+ dest = {};
2411
+ }
2412
+
2413
+ // const resolvedFrom: Location = {
2414
+ // ...router.location,
2415
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2416
+
2417
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2418
+
2419
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2420
+ strictParseParams: true
2421
+ });
2422
+ const toMatches = router.matchRoutes(pathname);
2423
+
2424
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2425
+
2426
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2427
+
2428
+ if (nextParams) {
2429
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2430
+ Object.assign({}, nextParams, fn(nextParams));
2431
+ });
2432
+ }
2433
+
2434
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2435
+
2436
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
2437
+
2438
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2439
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2440
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2441
+ : {}; // Then post filters
2442
+
2443
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2444
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2445
+ const searchStr = router.options.stringifySearch(search);
2446
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2447
+ hash = hash ? "#" + hash : '';
2448
+ return {
2449
+ pathname,
2450
+ search,
2451
+ searchStr,
2452
+ state: router.location.state,
2453
+ hash,
2454
+ href: "" + pathname + searchStr + hash,
2455
+ key: dest.key
2456
+ };
2457
+ },
2458
+ commitLocation: (next, replace) => {
2459
+ const id = '' + Date.now() + Math.random();
2460
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2461
+ let nextAction = 'replace';
2462
+
2463
+ if (!replace) {
2464
+ nextAction = 'push';
2465
+ }
2466
+
2467
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2468
+
2469
+ if (isSameUrl && !next.key) {
2470
+ nextAction = 'replace';
2471
+ }
2472
+
2473
+ if (nextAction === 'replace') {
2474
+ history.replace({
2475
+ pathname: next.pathname,
2476
+ hash: next.hash,
2477
+ search: next.searchStr
2478
+ }, {
2479
+ id
2480
+ });
2481
+ } else {
2482
+ history.push({
2483
+ pathname: next.pathname,
2484
+ hash: next.hash,
2485
+ search: next.searchStr
2486
+ }, {
2487
+ id
2488
+ });
2489
+ }
2490
+
2491
+ router.navigationPromise = new Promise(resolve => {
2492
+ const previousNavigationResolve = router.resolveNavigation;
2493
+
2494
+ router.resolveNavigation = () => {
2495
+ previousNavigationResolve();
2496
+ resolve();
2497
+ };
2498
+ });
2499
+ return router.navigationPromise;
2500
+ }
2454
2501
  }
2455
2502
  };
2456
- router.location = router.parseLocation(history.location);
2457
- router.state.location = router.location;
2458
2503
  router.update(userOptions); // Allow frameworks to hook into the router creation
2459
2504
 
2460
2505
  router.options.createRouter == null ? void 0 : router.options.createRouter(router);
@@ -2465,6 +2510,16 @@ function isCtrlEvent(e) {
2465
2510
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2466
2511
  }
2467
2512
 
2513
+ function cascadeLoaderData(matches) {
2514
+ matches.forEach((match, index) => {
2515
+ const parent = matches[index - 1];
2516
+
2517
+ if (parent) {
2518
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
2519
+ }
2520
+ });
2521
+ }
2522
+
2468
2523
  const _excluded = ["type", "children", "target", "activeProps", "inactiveProps", "activeOptions", "disabled", "hash", "search", "params", "to", "preload", "preloadDelay", "preloadMaxAge", "replace", "style", "className", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onTouchStart", "onTouchEnd"],
2469
2524
  _excluded2 = ["pending", "caseSensitive", "children"],
2470
2525
  _excluded3 = ["children", "router"];
@@ -2479,12 +2534,23 @@ function MatchesProvider(props) {
2479
2534
  }
2480
2535
 
2481
2536
  const useRouterSubscription = router => {
2482
- useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state);
2537
+ useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state, () => router.state);
2483
2538
  };
2484
2539
 
2485
2540
  function createReactRouter(opts) {
2486
2541
  const makeRouteExt = (route, router) => {
2487
2542
  return {
2543
+ useRoute: function useRoute(subRouteId) {
2544
+ if (subRouteId === void 0) {
2545
+ subRouteId = '.';
2546
+ }
2547
+
2548
+ const resolvedRouteId = router.resolvePath(route.routeId, subRouteId);
2549
+ const resolvedRoute = router.getRoute(resolvedRouteId);
2550
+ useRouterSubscription(router);
2551
+ invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
2552
+ return resolvedRoute;
2553
+ },
2488
2554
  linkProps: options => {
2489
2555
  var _functionalUpdate, _functionalUpdate2;
2490
2556
 
@@ -2592,24 +2658,17 @@ function createReactRouter(opts) {
2592
2658
  useRouterSubscription(router);
2593
2659
  return router.state;
2594
2660
  },
2595
- useRoute: routeId => {
2596
- const route = router.getRoute(routeId);
2597
- useRouterSubscription(router);
2598
- invariant(route, "Could not find a route for route \"" + routeId + "\"! Did you forget to add it to your route config?");
2599
- return route;
2600
- },
2601
- useMatch: routeId => {
2661
+ useMatch: (routeId, opts) => {
2662
+ var _useMatches, _opts$strict;
2663
+
2602
2664
  useRouterSubscription(router);
2603
2665
  invariant(routeId !== rootRouteId, "\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2604
-
2605
- const runtimeMatch = _useMatch();
2606
-
2666
+ const runtimeMatch = (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2607
2667
  const match = router.state.matches.find(d => d.routeId === routeId);
2608
- invariant(match, "Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2609
- invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2610
2668
 
2611
- if (!match) {
2612
- invariant('Match not found!');
2669
+ if ((_opts$strict = opts == null ? void 0 : opts.strict) != null ? _opts$strict : true) {
2670
+ invariant(match, "Could not find an active match for \"" + routeId + "\"!");
2671
+ invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch('" + (match == null ? void 0 : match.routeId) + "') is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useMatch(" + (match == null ? void 0 : match.routeId) + ", { strict: false })' or 'useRoute(" + (match == null ? void 0 : match.routeId) + ")' instead?");
2613
2672
  }
2614
2673
 
2615
2674
  return match;
@@ -2625,6 +2684,19 @@ function createReactRouter(opts) {
2625
2684
  } = _ref;
2626
2685
  const routeExt = makeRouteExt(route, router);
2627
2686
  Object.assign(route, routeExt);
2687
+ },
2688
+ createElement: async element => {
2689
+ if (typeof element === 'function') {
2690
+ const res = await element(); // Support direct import() calls
2691
+
2692
+ if (typeof res === 'object' && res.default) {
2693
+ return /*#__PURE__*/React.createElement(res.default);
2694
+ } else {
2695
+ return res;
2696
+ }
2697
+ }
2698
+
2699
+ return element;
2628
2700
  }
2629
2701
  }));
2630
2702
  return coreRouter;
@@ -2639,7 +2711,9 @@ function RouterProvider(_ref2) {
2639
2711
  router.update(rest);
2640
2712
  useRouterSubscription(router);
2641
2713
  useLayoutEffect(() => {
2642
- return router.mount();
2714
+ const unsub = router.mount();
2715
+ router.load();
2716
+ return unsub;
2643
2717
  }, [router]);
2644
2718
  return /*#__PURE__*/React.createElement(routerContext.Provider, {
2645
2719
  value: {
@@ -2659,61 +2733,49 @@ function useRouter() {
2659
2733
 
2660
2734
  function useMatches() {
2661
2735
  return React.useContext(matchesContext);
2662
- } // function useParentMatches(): RouteMatch[] {
2663
- // const router = useRouter()
2664
- // const match = useMatch()
2665
- // const matches = router.state.matches
2666
- // return matches.slice(
2667
- // 0,
2668
- // matches.findIndex((d) => d.matchId === match.matchId) - 1,
2669
- // )
2670
- // }
2671
-
2672
-
2673
- function _useMatch() {
2674
- var _useMatches;
2675
-
2676
- return (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2677
2736
  }
2678
2737
 
2679
2738
  function Outlet() {
2680
- var _childMatch$options$c;
2739
+ var _match$options$catchE;
2681
2740
 
2682
2741
  const router = useRouter();
2683
- const [, ...matches] = useMatches();
2684
- const childMatch = matches[0];
2685
- if (!childMatch) return null;
2742
+ const matches = useMatches().slice(1);
2743
+ const match = matches[0];
2744
+
2745
+ if (!match) {
2746
+ return null;
2747
+ }
2686
2748
 
2687
2749
  const element = (() => {
2688
- var _childMatch$__$errorE, _ref4;
2750
+ var _match$__$errorElemen, _ref4, _ref5;
2689
2751
 
2690
- if (!childMatch) {
2752
+ if (!match) {
2691
2753
  return null;
2692
2754
  }
2693
2755
 
2694
- const errorElement = (_childMatch$__$errorE = childMatch.__.errorElement) != null ? _childMatch$__$errorE : router.options.defaultErrorElement;
2756
+ const errorElement = (_match$__$errorElemen = match.__.errorElement) != null ? _match$__$errorElemen : router.options.defaultErrorElement;
2695
2757
 
2696
- if (childMatch.status === 'error') {
2758
+ if (match.status === 'error') {
2697
2759
  if (errorElement) {
2698
2760
  return errorElement;
2699
2761
  }
2700
2762
 
2701
- if (childMatch.options.useErrorBoundary || router.options.useErrorBoundary) {
2702
- throw childMatch.error;
2763
+ if (match.options.useErrorBoundary || router.options.useErrorBoundary) {
2764
+ throw match.error;
2703
2765
  }
2704
2766
 
2705
2767
  return /*#__PURE__*/React.createElement(DefaultErrorBoundary, {
2706
- error: childMatch.error
2768
+ error: match.error
2707
2769
  });
2708
2770
  }
2709
2771
 
2710
- if (childMatch.status === 'loading' || childMatch.status === 'idle') {
2711
- if (childMatch.isPending) {
2712
- var _childMatch$__$pendin;
2772
+ if (match.status === 'loading' || match.status === 'idle') {
2773
+ if (match.isPending) {
2774
+ var _match$__$pendingElem;
2713
2775
 
2714
- const pendingElement = (_childMatch$__$pendin = childMatch.__.pendingElement) != null ? _childMatch$__$pendin : router.options.defaultPendingElement;
2776
+ const pendingElement = (_match$__$pendingElem = match.__.pendingElement) != null ? _match$__$pendingElem : router.options.defaultPendingElement;
2715
2777
 
2716
- if (childMatch.options.pendingMs || pendingElement) {
2778
+ if (match.options.pendingMs || pendingElement) {
2717
2779
  var _ref3;
2718
2780
 
2719
2781
  return (_ref3 = pendingElement) != null ? _ref3 : null;
@@ -2723,13 +2785,12 @@ function Outlet() {
2723
2785
  return null;
2724
2786
  }
2725
2787
 
2726
- return (_ref4 = childMatch.__.element) != null ? _ref4 : router.options.defaultElement;
2788
+ return (_ref4 = (_ref5 = match.__.element) != null ? _ref5 : router.options.defaultElement) != null ? _ref4 : /*#__PURE__*/React.createElement(Outlet, null);
2727
2789
  })();
2728
2790
 
2729
- const catchElement = (_childMatch$options$c = childMatch == null ? void 0 : childMatch.options.catchElement) != null ? _childMatch$options$c : router.options.defaultCatchElement;
2791
+ const catchElement = (_match$options$catchE = match == null ? void 0 : match.options.catchElement) != null ? _match$options$catchE : router.options.defaultCatchElement;
2730
2792
  return /*#__PURE__*/React.createElement(MatchesProvider, {
2731
- value: matches,
2732
- key: childMatch.matchId
2793
+ value: matches
2733
2794
  }, /*#__PURE__*/React.createElement(CatchBoundary, {
2734
2795
  catchElement: catchElement
2735
2796
  }, element));
@@ -2741,13 +2802,6 @@ class CatchBoundary extends React.Component {
2741
2802
  this.state = {
2742
2803
  error: false
2743
2804
  };
2744
-
2745
- this.reset = () => {
2746
- this.setState({
2747
- error: false,
2748
- info: false
2749
- });
2750
- };
2751
2805
  }
2752
2806
 
2753
2807
  componentDidCatch(error, info) {
@@ -2772,10 +2826,10 @@ class CatchBoundary extends React.Component {
2772
2826
 
2773
2827
  }
2774
2828
 
2775
- function DefaultErrorBoundary(_ref5) {
2829
+ function DefaultErrorBoundary(_ref6) {
2776
2830
  let {
2777
2831
  error
2778
- } = _ref5;
2832
+ } = _ref6;
2779
2833
  return /*#__PURE__*/React.createElement("div", {
2780
2834
  style: {
2781
2835
  padding: '.5rem',
@@ -2797,19 +2851,32 @@ function DefaultErrorBoundary(_ref5) {
2797
2851
  padding: '.5rem',
2798
2852
  color: 'red'
2799
2853
  }
2800
- }, error.message) : null)), /*#__PURE__*/React.createElement("div", {
2801
- style: {
2802
- height: '1rem'
2803
- }
2804
- }), /*#__PURE__*/React.createElement("div", {
2805
- style: {
2806
- fontSize: '.8em',
2807
- borderLeft: '3px solid rgba(127, 127, 127, 1)',
2808
- paddingLeft: '.5rem',
2809
- opacity: 0.5
2810
- }
2811
- }, "If you are the owner of this website, it's highly recommended that you configure your own custom Catch/Error boundaries for the router. You can optionally configure a boundary for each route."));
2812
- } // TODO: Add prompt
2854
+ }, error.message) : null)));
2855
+ }
2856
+ function usePrompt(message, when) {
2857
+ const router = useRouter();
2858
+ React.useEffect(() => {
2859
+ if (!when) return;
2860
+ let unblock = router.history.block(transition => {
2861
+ if (window.confirm(message)) {
2862
+ unblock();
2863
+ transition.retry();
2864
+ } else {
2865
+ router.location.pathname = window.location.pathname;
2866
+ }
2867
+ });
2868
+ return unblock;
2869
+ }, [when, location, message]);
2870
+ }
2871
+ function Prompt(_ref7) {
2872
+ let {
2873
+ message,
2874
+ when,
2875
+ children
2876
+ } = _ref7;
2877
+ usePrompt(message, when != null ? when : true);
2878
+ return children != null ? children : null;
2879
+ }
2813
2880
 
2814
- export { DefaultErrorBoundary, MatchesProvider, Outlet, RouterProvider, cascadeLoaderData, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, invariant, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning };
2881
+ export { DefaultErrorBoundary, MatchesProvider, Outlet, Prompt, RouterProvider, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, invariant, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, usePrompt, warning };
2815
2882
  //# sourceMappingURL=index.js.map