@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.
@@ -11,7 +11,7 @@
11
11
  (function (global, factory) {
12
12
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('use-sync-external-store/shim')) :
13
13
  typeof define === 'function' && define.amd ? define(['exports', 'react', 'use-sync-external-store/shim'], factory) :
14
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactLocation = {}, global.React, global.shim));
14
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactRouter = {}, global.React, global.shim));
15
15
  })(this, (function (exports, React, shim) { 'use strict';
16
16
 
17
17
  function _interopNamespace(e) {
@@ -991,6 +991,12 @@
991
991
 
992
992
  return updater;
993
993
  }
994
+ function pick(parent, keys) {
995
+ return keys.reduce((obj, key) => {
996
+ obj[key] = parent[key];
997
+ return obj;
998
+ }, {});
999
+ }
994
1000
 
995
1001
  function joinPaths(paths) {
996
1002
  return cleanPath(paths.filter(Boolean).join('/'));
@@ -1217,6 +1223,7 @@
1217
1223
  var str = decodeURIComponent(mix);
1218
1224
  if (str === 'false') return false;
1219
1225
  if (str === 'true') return true;
1226
+ if (str.charAt(0) === '0') return str;
1220
1227
  return +str * 0 === 0 ? +str : str;
1221
1228
  }
1222
1229
 
@@ -1267,7 +1274,7 @@
1267
1274
 
1268
1275
  const action = router.state.actions[id] || (() => {
1269
1276
  router.state.actions[id] = {
1270
- pending: [],
1277
+ submissions: [],
1271
1278
  submit: async (submission, actionOpts) => {
1272
1279
  var _actionOpts$invalidat;
1273
1280
 
@@ -1276,18 +1283,20 @@
1276
1283
  }
1277
1284
 
1278
1285
  const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1286
+
1287
+ if (!(actionOpts != null && actionOpts.multi)) {
1288
+ action.submissions = action.submissions.filter(d => d.isMulti);
1289
+ }
1290
+
1279
1291
  const actionState = {
1280
1292
  submittedAt: Date.now(),
1281
1293
  status: 'pending',
1282
- submission
1294
+ submission,
1295
+ isMulti: !!(actionOpts != null && actionOpts.multi)
1283
1296
  };
1284
1297
  action.current = actionState;
1285
1298
  action.latest = actionState;
1286
- action.pending.push(actionState);
1287
- router.state = _extends({}, router.state, {
1288
- currentAction: actionState,
1289
- latestAction: actionState
1290
- });
1299
+ action.submissions.push(actionState);
1291
1300
  router.notify();
1292
1301
 
1293
1302
  try {
@@ -1309,11 +1318,6 @@
1309
1318
  actionState.error = err;
1310
1319
  actionState.status = 'error';
1311
1320
  } finally {
1312
- action.pending = action.pending.filter(d => d !== actionState);
1313
- router.removeActionQueue.push({
1314
- action,
1315
- actionState
1316
- });
1317
1321
  router.notify();
1318
1322
  }
1319
1323
  }
@@ -1321,6 +1325,40 @@
1321
1325
  return router.state.actions[id];
1322
1326
  })();
1323
1327
 
1328
+ const loader = router.state.loaders[id] || (() => {
1329
+ router.state.loaders[id] = {
1330
+ pending: [],
1331
+ fetch: async loaderContext => {
1332
+ if (!route) {
1333
+ return;
1334
+ }
1335
+
1336
+ const loaderState = {
1337
+ loadedAt: Date.now(),
1338
+ loaderContext
1339
+ };
1340
+ loader.current = loaderState;
1341
+ loader.latest = loaderState;
1342
+ loader.pending.push(loaderState); // router.state = {
1343
+ // ...router.state,
1344
+ // currentAction: loaderState,
1345
+ // latestAction: loaderState,
1346
+ // }
1347
+
1348
+ router.notify();
1349
+
1350
+ try {
1351
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1352
+ } finally {
1353
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1354
+
1355
+ router.notify();
1356
+ }
1357
+ }
1358
+ };
1359
+ return router.state.loaders[id];
1360
+ })();
1361
+
1324
1362
  let route = {
1325
1363
  routeId: id,
1326
1364
  routeRouteId: routeId,
@@ -1331,6 +1369,7 @@
1331
1369
  childRoutes: undefined,
1332
1370
  parentRoute: parent,
1333
1371
  action,
1372
+ loader: loader,
1334
1373
  buildLink: options => {
1335
1374
  return router.buildLink(_extends({}, options, {
1336
1375
  from: fullPath
@@ -1353,15 +1392,6 @@
1353
1392
  });
1354
1393
  return route;
1355
1394
  }
1356
- function cascadeLoaderData(matches) {
1357
- matches.forEach((match, index) => {
1358
- const parent = matches[index - 1];
1359
-
1360
- if (parent) {
1361
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1362
- }
1363
- });
1364
- }
1365
1395
 
1366
1396
  const rootRouteId = '__root__';
1367
1397
  const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
@@ -1427,6 +1457,7 @@
1427
1457
  isFetching: false,
1428
1458
  isInvalid: false,
1429
1459
  invalidAt: Infinity,
1460
+ // pendingActions: [],
1430
1461
  getIsInvalid: () => {
1431
1462
  const now = Date.now();
1432
1463
  return routeMatch.isInvalid || routeMatch.invalidAt < now;
@@ -1466,17 +1497,6 @@
1466
1497
  clearTimeout(routeMatch.__.pendingMinTimeout);
1467
1498
  delete routeMatch.__.pendingMinPromise;
1468
1499
  },
1469
- // setParentMatch: (parentMatch?: RouteMatch) => {
1470
- // routeMatch.parentMatch = parentMatch
1471
- // },
1472
- // addChildMatch: (childMatch: RouteMatch) => {
1473
- // if (
1474
- // routeMatch.childMatches.find((d) => d.matchId === childMatch.matchId)
1475
- // ) {
1476
- // return
1477
- // }
1478
- // routeMatch.childMatches.push(childMatch)
1479
- // },
1480
1500
  validate: () => {
1481
1501
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1482
1502
 
@@ -1484,9 +1504,11 @@
1484
1504
  const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1485
1505
 
1486
1506
  try {
1507
+ var _validator;
1508
+
1487
1509
  const prevSearch = routeMatch.routeSearch;
1488
1510
  const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1489
- let nextSearch = replaceEqualDeep(prevSearch, validator == null ? void 0 : validator(parentSearch)); // Invalidate route matches when search param stability changes
1511
+ let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {}); // Invalidate route matches when search param stability changes
1490
1512
 
1491
1513
  if (prevSearch !== nextSearch) {
1492
1514
  routeMatch.isInvalid = true;
@@ -1494,6 +1516,13 @@
1494
1516
 
1495
1517
  routeMatch.routeSearch = nextSearch;
1496
1518
  routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1519
+ elementTypes.map(async type => {
1520
+ const routeElement = routeMatch.options[type];
1521
+
1522
+ if (typeof routeMatch.__[type] !== 'function') {
1523
+ routeMatch.__[type] = routeElement;
1524
+ }
1525
+ });
1497
1526
  } catch (err) {
1498
1527
  console.error(err);
1499
1528
  const error = new Error('Invalid search params found', {
@@ -1518,9 +1547,33 @@
1518
1547
  routeMatch.isInvalid = true;
1519
1548
  },
1520
1549
  hasLoaders: () => {
1521
- return !!(route.options.loader || route.options.import || elementTypes.some(d => typeof route.options[d] === 'function'));
1550
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1551
+ },
1552
+ load: async loaderOpts => {
1553
+ const now = Date.now();
1554
+ 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
1555
+
1556
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1557
+ // If the match is currently active, don't preload it
1558
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1559
+ return;
1560
+ }
1561
+
1562
+ router.matchCache[routeMatch.matchId] = {
1563
+ gc: now + loaderOpts.gcMaxAge,
1564
+ match: routeMatch
1565
+ };
1566
+ } // If the match is invalid, errored or idle, trigger it to load
1567
+
1568
+
1569
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1570
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1571
+ await routeMatch.fetch({
1572
+ maxAge
1573
+ });
1574
+ }
1522
1575
  },
1523
- load: async opts => {
1576
+ fetch: async opts => {
1524
1577
  const id = '' + Date.now() + Math.random();
1525
1578
  routeMatch.__.latestId = id; // If the match was in an error state, set it
1526
1579
  // to a loading state again. Otherwise, keep it
@@ -1538,37 +1591,16 @@
1538
1591
  routeMatch.isFetching = true;
1539
1592
  routeMatch.__.resolve = resolve;
1540
1593
 
1541
- const loaderPromise = (async () => {
1542
- const importer = routeMatch.options.import; // First, run any importers
1543
-
1544
- if (importer) {
1545
- routeMatch.__.importPromise = importer({
1546
- params: routeMatch.params // search: routeMatch.search,
1547
-
1548
- }).then(imported => {
1549
- routeMatch.__ = _extends({}, routeMatch.__, imported);
1550
- });
1551
- } // Wait for the importer to finish before
1552
- // attempting to load elements and data
1553
-
1554
-
1555
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1556
-
1594
+ routeMatch.__.loaderDataPromise = (async () => {
1595
+ // Load the elements and data in parallel
1557
1596
  routeMatch.__.elementsPromise = (async () => {
1558
1597
  // then run all element and data loaders in parallel
1559
1598
  // For each element type, potentially load it asynchronously
1560
1599
  await Promise.all(elementTypes.map(async type => {
1561
1600
  const routeElement = routeMatch.options[type];
1562
1601
 
1563
- if (routeMatch.__[type]) {
1564
- return;
1565
- }
1566
-
1567
- if (typeof routeElement === 'function') {
1568
- const res = await routeElement(routeMatch);
1569
- routeMatch.__[type] = res;
1570
- } else {
1571
- routeMatch.__[type] = routeMatch.options[type];
1602
+ if (typeof routeMatch.__[type] === 'function') {
1603
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1572
1604
  }
1573
1605
  }));
1574
1606
  })();
@@ -1585,7 +1617,7 @@
1585
1617
  });
1586
1618
 
1587
1619
  if (id !== routeMatch.__.latestId) {
1588
- return routeMatch.__.loaderPromise;
1620
+ return routeMatch.__.loadPromise;
1589
1621
  }
1590
1622
 
1591
1623
  routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
@@ -1597,7 +1629,7 @@
1597
1629
  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);
1598
1630
  } catch (err) {
1599
1631
  if (id !== routeMatch.__.latestId) {
1600
- return routeMatch.__.loaderPromise;
1632
+ return routeMatch.__.loadPromise;
1601
1633
  }
1602
1634
 
1603
1635
  {
@@ -1614,7 +1646,7 @@
1614
1646
  await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1615
1647
 
1616
1648
  if (id !== routeMatch.__.latestId) {
1617
- return routeMatch.__.loaderPromise;
1649
+ return routeMatch.__.loadPromise;
1618
1650
  }
1619
1651
 
1620
1652
  if (routeMatch.__.pendingMinPromise) {
@@ -1623,7 +1655,7 @@
1623
1655
  }
1624
1656
  } finally {
1625
1657
  if (id !== routeMatch.__.latestId) {
1626
- return routeMatch.__.loaderPromise;
1658
+ return routeMatch.__.loadPromise;
1627
1659
  }
1628
1660
 
1629
1661
  routeMatch.__.cancelPending();
@@ -1635,16 +1667,16 @@
1635
1667
  }
1636
1668
  })();
1637
1669
 
1638
- routeMatch.__.loaderPromise = loaderPromise;
1639
- await loaderPromise;
1670
+ await routeMatch.__.loaderDataPromise;
1640
1671
 
1641
1672
  if (id !== routeMatch.__.latestId) {
1642
- return routeMatch.__.loaderPromise;
1673
+ return routeMatch.__.loadPromise;
1643
1674
  }
1644
1675
 
1645
- delete routeMatch.__.loaderPromise;
1676
+ delete routeMatch.__.loaderDataPromise;
1646
1677
  });
1647
- return await routeMatch.__.loadPromise;
1678
+ await routeMatch.__.loadPromise;
1679
+ delete routeMatch.__.loadPromise;
1648
1680
  }
1649
1681
  });
1650
1682
 
@@ -1705,9 +1737,22 @@
1705
1737
 
1706
1738
  var _window$document;
1707
1739
  // Detect if we're in the DOM
1708
- const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
1740
+ const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
1709
1741
 
1710
- const createDefaultHistory = () => !isServer ? createBrowserHistory() : createMemoryHistory();
1742
+ const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
1743
+
1744
+ function getInitialRouterState() {
1745
+ return {
1746
+ status: 'idle',
1747
+ location: null,
1748
+ matches: [],
1749
+ actions: {},
1750
+ loaders: {},
1751
+ lastUpdated: Date.now(),
1752
+ isFetching: false,
1753
+ isPreloading: false
1754
+ };
1755
+ }
1711
1756
 
1712
1757
  function createRouter(userOptions) {
1713
1758
  var _userOptions$stringif, _userOptions$parseSea;
@@ -1725,9 +1770,9 @@
1725
1770
  });
1726
1771
 
1727
1772
  let router = {
1773
+ history,
1728
1774
  options: originalOptions,
1729
1775
  listeners: [],
1730
- removeActionQueue: [],
1731
1776
  // Resolved after construction
1732
1777
  basepath: '',
1733
1778
  routeTree: undefined,
@@ -1738,15 +1783,10 @@
1738
1783
  navigationPromise: Promise.resolve(),
1739
1784
  resolveNavigation: () => {},
1740
1785
  matchCache: {},
1741
- state: {
1742
- status: 'idle',
1743
- location: null,
1744
- matches: [],
1745
- actions: {},
1746
- loaderData: {},
1747
- lastUpdated: Date.now(),
1748
- isFetching: false,
1749
- isPreloading: false
1786
+ state: getInitialRouterState(),
1787
+ reset: () => {
1788
+ router.state = getInitialRouterState();
1789
+ router.notify();
1750
1790
  },
1751
1791
  startedLoadingAt: Date.now(),
1752
1792
  subscribe: listener => {
@@ -1764,24 +1804,44 @@
1764
1804
  isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1765
1805
  });
1766
1806
  cascadeLoaderData(router.state.matches);
1767
- router.listeners.forEach(listener => listener());
1807
+ router.listeners.forEach(listener => listener(router));
1808
+ },
1809
+ dehydrateState: () => {
1810
+ return _extends({}, pick(router.state, ['status', 'location', 'lastUpdated']), {
1811
+ matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
1812
+ });
1813
+ },
1814
+ hydrateState: dehydratedState => {
1815
+ // Match the routes
1816
+ const matches = router.matchRoutes(router.location.pathname, {
1817
+ strictParseParams: true
1818
+ });
1819
+ matches.forEach((match, index) => {
1820
+ const dehydratedMatch = dehydratedState.matches[index];
1821
+ invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1822
+ Object.assign(match, dehydratedMatch);
1823
+ });
1824
+ router.loadMatches(matches);
1825
+ router.state = _extends({}, router.state, dehydratedState, {
1826
+ matches
1827
+ });
1768
1828
  },
1769
1829
  mount: () => {
1770
- const next = router.buildLocation({
1830
+ const next = router.__.buildLocation({
1771
1831
  to: '.',
1772
1832
  search: true,
1773
1833
  hash: true
1774
1834
  }); // If the current location isn't updated, trigger a navigation
1775
1835
  // to the current location. Otherwise, load the current location.
1776
1836
 
1837
+
1777
1838
  if (next.href !== router.location.href) {
1778
- router.commitLocation(next, true);
1779
- } else {
1780
- router.loadLocation();
1781
- }
1839
+ router.__.commitLocation(next, true);
1840
+ } // router.load()
1841
+
1782
1842
 
1783
- const unsub = history.listen(event => {
1784
- router.loadLocation(router.parseLocation(event.location, router.location));
1843
+ const unsub = router.history.listen(event => {
1844
+ router.load(router.__.parseLocation(event.location, router.location));
1785
1845
  }); // addEventListener does not exist in React Native, but window does
1786
1846
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1787
1847
 
@@ -1792,16 +1852,30 @@
1792
1852
  }
1793
1853
 
1794
1854
  return () => {
1795
- unsub(); // Be sure to unsubscribe if a new handler is set
1855
+ unsub();
1796
1856
 
1797
- window.removeEventListener('visibilitychange', router.onFocus);
1798
- window.removeEventListener('focus', router.onFocus);
1857
+ if (!isServer && window.removeEventListener) {
1858
+ // Be sure to unsubscribe if a new handler is set
1859
+ window.removeEventListener('visibilitychange', router.onFocus);
1860
+ window.removeEventListener('focus', router.onFocus);
1861
+ }
1799
1862
  };
1800
1863
  },
1801
1864
  onFocus: () => {
1802
- router.loadLocation();
1865
+ router.load();
1803
1866
  },
1804
1867
  update: opts => {
1868
+ const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
1869
+
1870
+ if (!router.location || newHistory) {
1871
+ if (opts != null && opts.history) {
1872
+ router.history = opts.history;
1873
+ }
1874
+
1875
+ router.location = router.__.parseLocation(router.history.location);
1876
+ router.state.location = router.location;
1877
+ }
1878
+
1805
1879
  Object.assign(router.options, opts);
1806
1880
  const {
1807
1881
  basepath,
@@ -1811,204 +1885,30 @@
1811
1885
 
1812
1886
  if (routeConfig) {
1813
1887
  router.routesById = {};
1814
- router.routeTree = router.buildRouteTree(routeConfig);
1888
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1815
1889
  }
1816
1890
 
1817
1891
  return router;
1818
1892
  },
1819
- buildRouteTree: rootRouteConfig => {
1820
- const recurseRoutes = (routeConfigs, parent) => {
1821
- return routeConfigs.map(routeConfig => {
1822
- const routeOptions = routeConfig.options;
1823
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1824
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1825
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1826
- // }
1827
-
1828
- const existingRoute = router.routesById[route.routeId];
1829
-
1830
- if (existingRoute) {
1831
- {
1832
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1833
- }
1834
-
1835
- throw new Error();
1836
- }
1837
- router.routesById[route.routeId] = route;
1838
- const children = routeConfig.children;
1839
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1840
- return route;
1841
- });
1842
- };
1843
-
1844
- const routes = recurseRoutes([rootRouteConfig]);
1845
- return routes[0];
1846
- },
1847
- parseLocation: (location, previousLocation) => {
1848
- var _location$hash$split$;
1849
-
1850
- const parsedSearch = router.options.parseSearch(location.search);
1851
- return {
1852
- pathname: location.pathname,
1853
- searchStr: location.search,
1854
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1855
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1856
- href: "" + location.pathname + location.search + location.hash,
1857
- state: location.state,
1858
- key: location.key
1859
- };
1860
- },
1861
- buildLocation: function buildLocation(dest) {
1862
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
1863
-
1864
- if (dest === void 0) {
1865
- dest = {};
1866
- }
1867
-
1868
- // const resolvedFrom: Location = {
1869
- // ...router.location,
1870
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
1871
-
1872
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
1873
-
1874
- const fromMatches = router.matchRoutes(router.location.pathname, {
1875
- strictParseParams: true
1876
- });
1877
- const toMatches = router.matchRoutes(pathname);
1878
-
1879
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
1880
-
1881
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1882
-
1883
- if (nextParams) {
1884
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1885
- Object.assign({}, nextParams, fn(nextParams));
1886
- });
1887
- }
1888
-
1889
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1890
-
1891
- 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
1892
-
1893
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1894
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1895
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1896
- : {}; // Then post filters
1897
-
1898
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1899
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1900
- const searchStr = router.options.stringifySearch(search);
1901
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1902
- hash = hash ? "#" + hash : '';
1903
- return {
1904
- pathname,
1905
- search,
1906
- searchStr,
1907
- state: router.location.state,
1908
- hash,
1909
- href: "" + pathname + searchStr + hash,
1910
- key: dest.key
1911
- };
1912
- },
1913
- commitLocation: (next, replace) => {
1914
- const id = '' + Date.now() + Math.random();
1915
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1916
- let nextAction = 'replace';
1917
-
1918
- if (!replace) {
1919
- nextAction = 'push';
1920
- }
1921
-
1922
- const isSameUrl = router.parseLocation(history.location).href === next.href;
1923
-
1924
- if (isSameUrl && !next.key) {
1925
- nextAction = 'replace';
1926
- }
1927
-
1928
- if (nextAction === 'replace') {
1929
- history.replace({
1930
- pathname: next.pathname,
1931
- hash: next.hash,
1932
- search: next.searchStr
1933
- }, {
1934
- id
1935
- });
1936
- } else {
1937
- history.push({
1938
- pathname: next.pathname,
1939
- hash: next.hash,
1940
- search: next.searchStr
1941
- }, {
1942
- id
1943
- });
1944
- }
1945
-
1946
- router.navigationPromise = new Promise(resolve => {
1947
- const previousNavigationResolve = router.resolveNavigation;
1948
-
1949
- router.resolveNavigation = () => {
1950
- previousNavigationResolve();
1951
- resolve();
1952
- };
1953
- });
1954
- return router.navigationPromise;
1955
- },
1956
- buildNext: opts => {
1957
- const next = router.buildLocation(opts);
1958
- const matches = router.matchRoutes(next.pathname);
1959
-
1960
- const __preSearchFilters = matches.map(match => {
1961
- var _match$options$preSea;
1962
-
1963
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1964
- }).flat().filter(Boolean);
1965
-
1966
- const __postSearchFilters = matches.map(match => {
1967
- var _match$options$postSe;
1968
-
1969
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1970
- }).flat().filter(Boolean);
1971
-
1972
- return router.buildLocation(_extends({}, opts, {
1973
- __preSearchFilters,
1974
- __postSearchFilters
1975
- }));
1976
- },
1977
1893
  cancelMatches: () => {
1978
1894
  var _router$state$pending, _router$state$pending2;
1979
1895
  [...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 => {
1980
1896
  match.cancel();
1981
1897
  });
1982
1898
  },
1983
- loadLocation: async next => {
1899
+ load: async next => {
1984
1900
  const id = Math.random();
1985
1901
  router.startedLoadingAt = id;
1986
1902
 
1987
1903
  if (next) {
1988
1904
  // Ingest the new location
1989
1905
  router.location = next;
1990
- } // Clear out old actions
1991
-
1992
-
1993
- router.removeActionQueue.forEach(_ref => {
1994
- let {
1995
- action,
1996
- actionState
1997
- } = _ref;
1998
-
1999
- if (router.state.currentAction === actionState) {
2000
- router.state.currentAction = undefined;
2001
- }
1906
+ } // Cancel any pending matches
2002
1907
 
2003
- if (action.current === actionState) {
2004
- action.current = undefined;
2005
- }
2006
- });
2007
- router.removeActionQueue = []; // Cancel any pending matches
2008
1908
 
2009
1909
  router.cancelMatches(); // Match the routes
2010
1910
 
2011
- const matches = router.matchRoutes(location.pathname, {
1911
+ const matches = router.matchRoutes(router.location.pathname, {
2012
1912
  strictParseParams: true
2013
1913
  });
2014
1914
  router.state = _extends({}, router.state, {
@@ -2041,19 +1941,24 @@
2041
1941
  });
2042
1942
  const now = Date.now();
2043
1943
  exiting.forEach(d => {
2044
- var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
1944
+ var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
2045
1945
 
2046
1946
  d.__.onExit == null ? void 0 : d.__.onExit({
2047
1947
  params: d.params,
2048
1948
  search: d.routeSearch
2049
- }); // Clear idle error states when match leaves
1949
+ }); // // Clear actions
1950
+ // if (d.action) {
1951
+ // d.action.current = undefined
1952
+ // d.action.submissions = []
1953
+ // }
1954
+ // Clear idle error states when match leaves
2050
1955
 
2051
1956
  if (d.status === 'error' && !d.isFetching) {
2052
1957
  d.status = 'idle';
2053
1958
  d.error = undefined;
2054
1959
  }
2055
1960
 
2056
- 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);
1961
+ 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);
2057
1962
 
2058
1963
  if (gc > 0) {
2059
1964
  router.matchCache[d.matchId] = {
@@ -2076,18 +1981,21 @@
2076
1981
  params: d.params,
2077
1982
  search: d.search
2078
1983
  });
2079
- });
2080
-
2081
- if (matches.some(d => d.status === 'loading')) {
2082
- router.notify();
2083
- await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
2084
- }
1984
+ delete router.matchCache[d.matchId];
1985
+ }); // router.notify()
2085
1986
 
2086
1987
  if (router.startedLoadingAt !== id) {
2087
1988
  // Ignore side-effects of match loading
2088
1989
  return;
2089
1990
  }
2090
1991
 
1992
+ matches.forEach(match => {
1993
+ // Clear actions
1994
+ if (match.action) {
1995
+ match.action.current = undefined;
1996
+ match.action.submissions = [];
1997
+ }
1998
+ });
2091
1999
  router.state = _extends({}, router.state, {
2092
2000
  location: router.location,
2093
2001
  matches,
@@ -2128,7 +2036,7 @@
2128
2036
  return matches;
2129
2037
  },
2130
2038
  preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
2131
- var _ref4, _ref5, _loaderOpts$maxAge, _ref6, _ref7, _loaderOpts$gcMaxAge;
2039
+ var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
2132
2040
 
2133
2041
  if (navigateOpts === void 0) {
2134
2042
  navigateOpts = router.location;
@@ -2140,8 +2048,8 @@
2140
2048
  });
2141
2049
  await router.loadMatches(matches, {
2142
2050
  preload: true,
2143
- maxAge: (_ref4 = (_ref5 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref5 : router.options.defaultLoaderMaxAge) != null ? _ref4 : 0,
2144
- gcMaxAge: (_ref6 = (_ref7 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0
2051
+ maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
2052
+ gcMaxAge: (_ref5 = (_ref6 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref6 : router.options.defaultLoaderGcMaxAge) != null ? _ref5 : 0
2145
2053
  });
2146
2054
  return matches;
2147
2055
  },
@@ -2235,38 +2143,20 @@
2235
2143
  return matches;
2236
2144
  },
2237
2145
  loadMatches: async (resolvedMatches, loaderOpts) => {
2238
- const now = Date.now();
2239
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2240
2146
  const matchPromises = resolvedMatches.map(async match => {
2241
2147
  // Validate the match (loads search params etc)
2242
- match.__.validate(); // If this is a preload, add it to the preload cache
2148
+ match.__.validate();
2243
2149
 
2244
-
2245
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2246
- // If the match is currently active, don't preload it
2247
- if (router.state.matches.find(d => d.matchId === match.matchId)) {
2248
- return;
2249
- }
2250
-
2251
- router.matchCache[match.matchId] = {
2252
- gc: now + loaderOpts.gcMaxAge,
2253
- match
2254
- };
2255
- } // If the match is invalid, errored or idle, trigger it to load
2256
-
2257
-
2258
- if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2259
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2260
- match.load({
2261
- maxAge
2262
- });
2263
- }
2150
+ match.load(loaderOpts);
2264
2151
 
2265
2152
  if (match.status === 'loading') {
2266
2153
  // If requested, start the pending timers
2267
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
2268
- // This might be completion, error, or a pending state
2154
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending();
2155
+ }
2269
2156
 
2157
+ if (match.__.loadPromise) {
2158
+ // Wait for the first sign of activity from the match
2159
+ // This might be completion, error, or a pending state
2270
2160
  await match.__.loadPromise;
2271
2161
  }
2272
2162
  });
@@ -2284,7 +2174,7 @@
2284
2174
  }
2285
2175
  });
2286
2176
  },
2287
- reload: () => router._navigate({
2177
+ reload: () => router.__.navigate({
2288
2178
  fromCurrent: true,
2289
2179
  replace: true,
2290
2180
  search: true
@@ -2317,11 +2207,7 @@
2317
2207
  to: next.pathname
2318
2208
  }));
2319
2209
  },
2320
- _navigate: location => {
2321
- const next = router.buildNext(location);
2322
- return router.commitLocation(next, location.replace);
2323
- },
2324
- navigate: async _ref8 => {
2210
+ navigate: async _ref7 => {
2325
2211
  let {
2326
2212
  from,
2327
2213
  to = '.',
@@ -2329,7 +2215,7 @@
2329
2215
  hash,
2330
2216
  replace,
2331
2217
  params
2332
- } = _ref8;
2218
+ } = _ref7;
2333
2219
  // If this link simply reloads the current route,
2334
2220
  // make sure it has a new key so it will trigger a data refresh
2335
2221
  // If this `to` is a valid external URL, return
@@ -2344,7 +2230,7 @@
2344
2230
  } catch (e) {}
2345
2231
 
2346
2232
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2347
- return router._navigate({
2233
+ return router.__.navigate({
2348
2234
  from: fromString,
2349
2235
  to: toString,
2350
2236
  search,
@@ -2353,8 +2239,8 @@
2353
2239
  params
2354
2240
  });
2355
2241
  },
2356
- buildLink: _ref9 => {
2357
- var _preload, _ref10;
2242
+ buildLink: _ref8 => {
2243
+ var _preload, _ref9;
2358
2244
 
2359
2245
  let {
2360
2246
  from,
@@ -2370,7 +2256,7 @@
2370
2256
  preloadGcMaxAge: userPreloadGcMaxAge,
2371
2257
  preloadDelay: userPreloadDelay,
2372
2258
  disabled
2373
- } = _ref9;
2259
+ } = _ref8;
2374
2260
 
2375
2261
  // If this link simply reloads the current route,
2376
2262
  // make sure it has a new key so it will trigger a data refresh
@@ -2394,7 +2280,7 @@
2394
2280
  };
2395
2281
  const next = router.buildNext(nextOpts);
2396
2282
  preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2397
- const preloadDelay = (_ref10 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref10 : 0; // Compare path/hash for matches
2283
+ const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0; // Compare path/hash for matches
2398
2284
 
2399
2285
  const pathIsEqual = router.state.location.pathname === next.pathname;
2400
2286
  const currentPathSplit = router.state.location.pathname.split('/');
@@ -2416,7 +2302,7 @@
2416
2302
  } // All is well? Navigate!)
2417
2303
 
2418
2304
 
2419
- router._navigate(nextOpts);
2305
+ router.__.navigate(nextOpts);
2420
2306
  }
2421
2307
  }; // The click handler
2422
2308
 
@@ -2467,10 +2353,169 @@
2467
2353
  isActive,
2468
2354
  disabled
2469
2355
  };
2356
+ },
2357
+ buildNext: opts => {
2358
+ const next = router.__.buildLocation(opts);
2359
+
2360
+ const matches = router.matchRoutes(next.pathname);
2361
+
2362
+ const __preSearchFilters = matches.map(match => {
2363
+ var _match$options$preSea;
2364
+
2365
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2366
+ }).flat().filter(Boolean);
2367
+
2368
+ const __postSearchFilters = matches.map(match => {
2369
+ var _match$options$postSe;
2370
+
2371
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2372
+ }).flat().filter(Boolean);
2373
+
2374
+ return router.__.buildLocation(_extends({}, opts, {
2375
+ __preSearchFilters,
2376
+ __postSearchFilters
2377
+ }));
2378
+ },
2379
+ __: {
2380
+ buildRouteTree: rootRouteConfig => {
2381
+ const recurseRoutes = (routeConfigs, parent) => {
2382
+ return routeConfigs.map(routeConfig => {
2383
+ const routeOptions = routeConfig.options;
2384
+ const route = createRoute(routeConfig, routeOptions, parent, router);
2385
+ const existingRoute = router.routesById[route.routeId];
2386
+
2387
+ if (existingRoute) {
2388
+ {
2389
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2390
+ }
2391
+
2392
+ throw new Error();
2393
+ }
2394
+ router.routesById[route.routeId] = route;
2395
+ const children = routeConfig.children;
2396
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2397
+ return route;
2398
+ });
2399
+ };
2400
+
2401
+ const routes = recurseRoutes([rootRouteConfig]);
2402
+ return routes[0];
2403
+ },
2404
+ parseLocation: (location, previousLocation) => {
2405
+ var _location$hash$split$;
2406
+
2407
+ const parsedSearch = router.options.parseSearch(location.search);
2408
+ return {
2409
+ pathname: location.pathname,
2410
+ searchStr: location.search,
2411
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2412
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2413
+ href: "" + location.pathname + location.search + location.hash,
2414
+ state: location.state,
2415
+ key: location.key
2416
+ };
2417
+ },
2418
+ navigate: location => {
2419
+ const next = router.buildNext(location);
2420
+ return router.__.commitLocation(next, location.replace);
2421
+ },
2422
+ buildLocation: function buildLocation(dest) {
2423
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2424
+
2425
+ if (dest === void 0) {
2426
+ dest = {};
2427
+ }
2428
+
2429
+ // const resolvedFrom: Location = {
2430
+ // ...router.location,
2431
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2432
+
2433
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2434
+
2435
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2436
+ strictParseParams: true
2437
+ });
2438
+ const toMatches = router.matchRoutes(pathname);
2439
+
2440
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2441
+
2442
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2443
+
2444
+ if (nextParams) {
2445
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2446
+ Object.assign({}, nextParams, fn(nextParams));
2447
+ });
2448
+ }
2449
+
2450
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2451
+
2452
+ 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
2453
+
2454
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2455
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2456
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2457
+ : {}; // Then post filters
2458
+
2459
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2460
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2461
+ const searchStr = router.options.stringifySearch(search);
2462
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2463
+ hash = hash ? "#" + hash : '';
2464
+ return {
2465
+ pathname,
2466
+ search,
2467
+ searchStr,
2468
+ state: router.location.state,
2469
+ hash,
2470
+ href: "" + pathname + searchStr + hash,
2471
+ key: dest.key
2472
+ };
2473
+ },
2474
+ commitLocation: (next, replace) => {
2475
+ const id = '' + Date.now() + Math.random();
2476
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2477
+ let nextAction = 'replace';
2478
+
2479
+ if (!replace) {
2480
+ nextAction = 'push';
2481
+ }
2482
+
2483
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2484
+
2485
+ if (isSameUrl && !next.key) {
2486
+ nextAction = 'replace';
2487
+ }
2488
+
2489
+ if (nextAction === 'replace') {
2490
+ history.replace({
2491
+ pathname: next.pathname,
2492
+ hash: next.hash,
2493
+ search: next.searchStr
2494
+ }, {
2495
+ id
2496
+ });
2497
+ } else {
2498
+ history.push({
2499
+ pathname: next.pathname,
2500
+ hash: next.hash,
2501
+ search: next.searchStr
2502
+ }, {
2503
+ id
2504
+ });
2505
+ }
2506
+
2507
+ router.navigationPromise = new Promise(resolve => {
2508
+ const previousNavigationResolve = router.resolveNavigation;
2509
+
2510
+ router.resolveNavigation = () => {
2511
+ previousNavigationResolve();
2512
+ resolve();
2513
+ };
2514
+ });
2515
+ return router.navigationPromise;
2516
+ }
2470
2517
  }
2471
2518
  };
2472
- router.location = router.parseLocation(history.location);
2473
- router.state.location = router.location;
2474
2519
  router.update(userOptions); // Allow frameworks to hook into the router creation
2475
2520
 
2476
2521
  router.options.createRouter == null ? void 0 : router.options.createRouter(router);
@@ -2481,6 +2526,16 @@
2481
2526
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2482
2527
  }
2483
2528
 
2529
+ function cascadeLoaderData(matches) {
2530
+ matches.forEach((match, index) => {
2531
+ const parent = matches[index - 1];
2532
+
2533
+ if (parent) {
2534
+ match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
2535
+ }
2536
+ });
2537
+ }
2538
+
2484
2539
  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"],
2485
2540
  _excluded2 = ["pending", "caseSensitive", "children"],
2486
2541
  _excluded3 = ["children", "router"];
@@ -2495,12 +2550,23 @@
2495
2550
  }
2496
2551
 
2497
2552
  const useRouterSubscription = router => {
2498
- shim.useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state);
2553
+ shim.useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state, () => router.state);
2499
2554
  };
2500
2555
 
2501
2556
  function createReactRouter(opts) {
2502
2557
  const makeRouteExt = (route, router) => {
2503
2558
  return {
2559
+ useRoute: function useRoute(subRouteId) {
2560
+ if (subRouteId === void 0) {
2561
+ subRouteId = '.';
2562
+ }
2563
+
2564
+ const resolvedRouteId = router.resolvePath(route.routeId, subRouteId);
2565
+ const resolvedRoute = router.getRoute(resolvedRouteId);
2566
+ useRouterSubscription(router);
2567
+ invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
2568
+ return resolvedRoute;
2569
+ },
2504
2570
  linkProps: options => {
2505
2571
  var _functionalUpdate, _functionalUpdate2;
2506
2572
 
@@ -2608,24 +2674,17 @@
2608
2674
  useRouterSubscription(router);
2609
2675
  return router.state;
2610
2676
  },
2611
- useRoute: routeId => {
2612
- const route = router.getRoute(routeId);
2613
- useRouterSubscription(router);
2614
- invariant(route, "Could not find a route for route \"" + routeId + "\"! Did you forget to add it to your route config?");
2615
- return route;
2616
- },
2617
- useMatch: routeId => {
2677
+ useMatch: (routeId, opts) => {
2678
+ var _useMatches, _opts$strict;
2679
+
2618
2680
  useRouterSubscription(router);
2619
2681
  invariant(routeId !== rootRouteId, "\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2620
-
2621
- const runtimeMatch = _useMatch();
2622
-
2682
+ const runtimeMatch = (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2623
2683
  const match = router.state.matches.find(d => d.routeId === routeId);
2624
- invariant(match, "Could not find a match for route \"" + routeId + "\" being rendered in this component!");
2625
- 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?");
2626
2684
 
2627
- if (!match) {
2628
- invariant('Match not found!');
2685
+ if ((_opts$strict = opts == null ? void 0 : opts.strict) != null ? _opts$strict : true) {
2686
+ invariant(match, "Could not find an active match for \"" + routeId + "\"!");
2687
+ 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?");
2629
2688
  }
2630
2689
 
2631
2690
  return match;
@@ -2641,6 +2700,19 @@
2641
2700
  } = _ref;
2642
2701
  const routeExt = makeRouteExt(route, router);
2643
2702
  Object.assign(route, routeExt);
2703
+ },
2704
+ createElement: async element => {
2705
+ if (typeof element === 'function') {
2706
+ const res = await element(); // Support direct import() calls
2707
+
2708
+ if (typeof res === 'object' && res.default) {
2709
+ return /*#__PURE__*/React__namespace.createElement(res.default);
2710
+ } else {
2711
+ return res;
2712
+ }
2713
+ }
2714
+
2715
+ return element;
2644
2716
  }
2645
2717
  }));
2646
2718
  return coreRouter;
@@ -2655,7 +2727,9 @@
2655
2727
  router.update(rest);
2656
2728
  useRouterSubscription(router);
2657
2729
  useLayoutEffect(() => {
2658
- return router.mount();
2730
+ const unsub = router.mount();
2731
+ router.load();
2732
+ return unsub;
2659
2733
  }, [router]);
2660
2734
  return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
2661
2735
  value: {
@@ -2675,61 +2749,49 @@
2675
2749
 
2676
2750
  function useMatches() {
2677
2751
  return React__namespace.useContext(matchesContext);
2678
- } // function useParentMatches(): RouteMatch[] {
2679
- // const router = useRouter()
2680
- // const match = useMatch()
2681
- // const matches = router.state.matches
2682
- // return matches.slice(
2683
- // 0,
2684
- // matches.findIndex((d) => d.matchId === match.matchId) - 1,
2685
- // )
2686
- // }
2687
-
2688
-
2689
- function _useMatch() {
2690
- var _useMatches;
2691
-
2692
- return (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2693
2752
  }
2694
2753
 
2695
2754
  function Outlet() {
2696
- var _childMatch$options$c;
2755
+ var _match$options$catchE;
2697
2756
 
2698
2757
  const router = useRouter();
2699
- const [, ...matches] = useMatches();
2700
- const childMatch = matches[0];
2701
- if (!childMatch) return null;
2758
+ const matches = useMatches().slice(1);
2759
+ const match = matches[0];
2760
+
2761
+ if (!match) {
2762
+ return null;
2763
+ }
2702
2764
 
2703
2765
  const element = (() => {
2704
- var _childMatch$__$errorE, _ref4;
2766
+ var _match$__$errorElemen, _ref4, _ref5;
2705
2767
 
2706
- if (!childMatch) {
2768
+ if (!match) {
2707
2769
  return null;
2708
2770
  }
2709
2771
 
2710
- const errorElement = (_childMatch$__$errorE = childMatch.__.errorElement) != null ? _childMatch$__$errorE : router.options.defaultErrorElement;
2772
+ const errorElement = (_match$__$errorElemen = match.__.errorElement) != null ? _match$__$errorElemen : router.options.defaultErrorElement;
2711
2773
 
2712
- if (childMatch.status === 'error') {
2774
+ if (match.status === 'error') {
2713
2775
  if (errorElement) {
2714
2776
  return errorElement;
2715
2777
  }
2716
2778
 
2717
- if (childMatch.options.useErrorBoundary || router.options.useErrorBoundary) {
2718
- throw childMatch.error;
2779
+ if (match.options.useErrorBoundary || router.options.useErrorBoundary) {
2780
+ throw match.error;
2719
2781
  }
2720
2782
 
2721
2783
  return /*#__PURE__*/React__namespace.createElement(DefaultErrorBoundary, {
2722
- error: childMatch.error
2784
+ error: match.error
2723
2785
  });
2724
2786
  }
2725
2787
 
2726
- if (childMatch.status === 'loading' || childMatch.status === 'idle') {
2727
- if (childMatch.isPending) {
2728
- var _childMatch$__$pendin;
2788
+ if (match.status === 'loading' || match.status === 'idle') {
2789
+ if (match.isPending) {
2790
+ var _match$__$pendingElem;
2729
2791
 
2730
- const pendingElement = (_childMatch$__$pendin = childMatch.__.pendingElement) != null ? _childMatch$__$pendin : router.options.defaultPendingElement;
2792
+ const pendingElement = (_match$__$pendingElem = match.__.pendingElement) != null ? _match$__$pendingElem : router.options.defaultPendingElement;
2731
2793
 
2732
- if (childMatch.options.pendingMs || pendingElement) {
2794
+ if (match.options.pendingMs || pendingElement) {
2733
2795
  var _ref3;
2734
2796
 
2735
2797
  return (_ref3 = pendingElement) != null ? _ref3 : null;
@@ -2739,13 +2801,12 @@
2739
2801
  return null;
2740
2802
  }
2741
2803
 
2742
- return (_ref4 = childMatch.__.element) != null ? _ref4 : router.options.defaultElement;
2804
+ return (_ref4 = (_ref5 = match.__.element) != null ? _ref5 : router.options.defaultElement) != null ? _ref4 : /*#__PURE__*/React__namespace.createElement(Outlet, null);
2743
2805
  })();
2744
2806
 
2745
- const catchElement = (_childMatch$options$c = childMatch == null ? void 0 : childMatch.options.catchElement) != null ? _childMatch$options$c : router.options.defaultCatchElement;
2807
+ const catchElement = (_match$options$catchE = match == null ? void 0 : match.options.catchElement) != null ? _match$options$catchE : router.options.defaultCatchElement;
2746
2808
  return /*#__PURE__*/React__namespace.createElement(MatchesProvider, {
2747
- value: matches,
2748
- key: childMatch.matchId
2809
+ value: matches
2749
2810
  }, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
2750
2811
  catchElement: catchElement
2751
2812
  }, element));
@@ -2757,13 +2818,6 @@
2757
2818
  this.state = {
2758
2819
  error: false
2759
2820
  };
2760
-
2761
- this.reset = () => {
2762
- this.setState({
2763
- error: false,
2764
- info: false
2765
- });
2766
- };
2767
2821
  }
2768
2822
 
2769
2823
  componentDidCatch(error, info) {
@@ -2788,10 +2842,10 @@
2788
2842
 
2789
2843
  }
2790
2844
 
2791
- function DefaultErrorBoundary(_ref5) {
2845
+ function DefaultErrorBoundary(_ref6) {
2792
2846
  let {
2793
2847
  error
2794
- } = _ref5;
2848
+ } = _ref6;
2795
2849
  return /*#__PURE__*/React__namespace.createElement("div", {
2796
2850
  style: {
2797
2851
  padding: '.5rem',
@@ -2813,25 +2867,38 @@
2813
2867
  padding: '.5rem',
2814
2868
  color: 'red'
2815
2869
  }
2816
- }, error.message) : null)), /*#__PURE__*/React__namespace.createElement("div", {
2817
- style: {
2818
- height: '1rem'
2819
- }
2820
- }), /*#__PURE__*/React__namespace.createElement("div", {
2821
- style: {
2822
- fontSize: '.8em',
2823
- borderLeft: '3px solid rgba(127, 127, 127, 1)',
2824
- paddingLeft: '.5rem',
2825
- opacity: 0.5
2826
- }
2827
- }, "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."));
2828
- } // TODO: Add prompt
2870
+ }, error.message) : null)));
2871
+ }
2872
+ function usePrompt(message, when) {
2873
+ const router = useRouter();
2874
+ React__namespace.useEffect(() => {
2875
+ if (!when) return;
2876
+ let unblock = router.history.block(transition => {
2877
+ if (window.confirm(message)) {
2878
+ unblock();
2879
+ transition.retry();
2880
+ } else {
2881
+ router.location.pathname = window.location.pathname;
2882
+ }
2883
+ });
2884
+ return unblock;
2885
+ }, [when, location, message]);
2886
+ }
2887
+ function Prompt(_ref7) {
2888
+ let {
2889
+ message,
2890
+ when,
2891
+ children
2892
+ } = _ref7;
2893
+ usePrompt(message, when != null ? when : true);
2894
+ return children != null ? children : null;
2895
+ }
2829
2896
 
2830
2897
  exports.DefaultErrorBoundary = DefaultErrorBoundary;
2831
2898
  exports.MatchesProvider = MatchesProvider;
2832
2899
  exports.Outlet = Outlet;
2900
+ exports.Prompt = Prompt;
2833
2901
  exports.RouterProvider = RouterProvider;
2834
- exports.cascadeLoaderData = cascadeLoaderData;
2835
2902
  exports.cleanPath = cleanPath;
2836
2903
  exports.createBrowserHistory = createBrowserHistory;
2837
2904
  exports.createHashHistory = createHashHistory;
@@ -2854,6 +2921,7 @@
2854
2921
  exports.matchPathname = matchPathname;
2855
2922
  exports.parsePathname = parsePathname;
2856
2923
  exports.parseSearchWith = parseSearchWith;
2924
+ exports.pick = pick;
2857
2925
  exports.replaceEqualDeep = replaceEqualDeep;
2858
2926
  exports.resolvePath = resolvePath;
2859
2927
  exports.rootRouteId = rootRouteId;
@@ -2861,6 +2929,7 @@
2861
2929
  exports.trimPath = trimPath;
2862
2930
  exports.trimPathLeft = trimPathLeft;
2863
2931
  exports.trimPathRight = trimPathRight;
2932
+ exports.usePrompt = usePrompt;
2864
2933
  exports.warning = warning;
2865
2934
 
2866
2935
  Object.defineProperty(exports, '__esModule', { value: true });