@tanstack/react-router 0.0.1-beta.12 → 0.0.1-beta.14

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.
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import * as React from 'react';
12
12
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
13
+ export { lazyWithPreload as lazy } from 'react-lazy-with-preload/lib/index';
13
14
 
14
15
  function _extends$2() {
15
16
  _extends$2 = Object.assign ? Object.assign.bind() : function (target) {
@@ -1427,7 +1428,7 @@ const createRouteConfig = function createRouteConfig(options, children, isRoot,
1427
1428
  };
1428
1429
  };
1429
1430
 
1430
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1431
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1431
1432
  function createRouteMatch(router, route, opts) {
1432
1433
  const routeMatch = _extends({}, route, opts, {
1433
1434
  router,
@@ -1437,7 +1438,6 @@ function createRouteMatch(router, route, opts) {
1437
1438
  status: 'idle',
1438
1439
  routeLoaderData: {},
1439
1440
  loaderData: {},
1440
- isPending: false,
1441
1441
  isFetching: false,
1442
1442
  isInvalid: false,
1443
1443
  invalidAt: Infinity,
@@ -1455,32 +1455,6 @@ function createRouteMatch(router, route, opts) {
1455
1455
 
1456
1456
  routeMatch.router.notify();
1457
1457
  },
1458
- startPending: () => {
1459
- var _routeMatch$options$p, _routeMatch$options$p2;
1460
-
1461
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1462
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1463
-
1464
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1465
- return;
1466
- }
1467
-
1468
- routeMatch.__.pendingTimeout = setTimeout(() => {
1469
- routeMatch.isPending = true;
1470
-
1471
- routeMatch.__.resolve();
1472
-
1473
- if (typeof pendingMinMs !== 'undefined') {
1474
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1475
- }
1476
- }, pendingMs);
1477
- },
1478
- cancelPending: () => {
1479
- routeMatch.isPending = false;
1480
- clearTimeout(routeMatch.__.pendingTimeout);
1481
- clearTimeout(routeMatch.__.pendingMinTimeout);
1482
- delete routeMatch.__.pendingMinPromise;
1483
- },
1484
1458
  validate: () => {
1485
1459
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1486
1460
 
@@ -1500,11 +1474,11 @@ function createRouteMatch(router, route, opts) {
1500
1474
 
1501
1475
  routeMatch.routeSearch = nextSearch;
1502
1476
  routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1503
- elementTypes.map(async type => {
1504
- const routeElement = routeMatch.options[type];
1477
+ componentTypes.map(async type => {
1478
+ const component = routeMatch.options[type];
1505
1479
 
1506
1480
  if (typeof routeMatch.__[type] !== 'function') {
1507
- routeMatch.__[type] = routeElement;
1481
+ routeMatch.__[type] = component;
1508
1482
  }
1509
1483
  });
1510
1484
  } catch (err) {
@@ -1524,14 +1498,16 @@ function createRouteMatch(router, route, opts) {
1524
1498
  var _routeMatch$__$abortC;
1525
1499
 
1526
1500
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1527
-
1528
- routeMatch.__.cancelPending();
1529
1501
  },
1530
1502
  invalidate: () => {
1531
1503
  routeMatch.isInvalid = true;
1532
1504
  },
1533
1505
  hasLoaders: () => {
1534
- return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1506
+ return !!(route.options.loader || componentTypes.some(d => {
1507
+ var _route$options$d;
1508
+
1509
+ return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
1510
+ }));
1535
1511
  },
1536
1512
  load: async loaderOpts => {
1537
1513
  const now = Date.now();
@@ -1575,91 +1551,79 @@ function createRouteMatch(router, route, opts) {
1575
1551
  routeMatch.isFetching = true;
1576
1552
  routeMatch.__.resolve = resolve;
1577
1553
 
1578
- routeMatch.__.loaderDataPromise = (async () => {
1579
- // Load the elements and data in parallel
1580
- routeMatch.__.elementsPromise = (async () => {
1581
- // then run all element and data loaders in parallel
1582
- // For each element type, potentially load it asynchronously
1583
- await Promise.all(elementTypes.map(async type => {
1584
- const routeElement = routeMatch.options[type];
1554
+ routeMatch.__.componentsPromise = (async () => {
1555
+ // then run all component and data loaders in parallel
1556
+ // For each component type, potentially load it asynchronously
1557
+ await Promise.all(componentTypes.map(async type => {
1558
+ var _routeMatch$__$type;
1585
1559
 
1586
- if (typeof routeMatch.__[type] === 'function') {
1587
- routeMatch.__[type] = await router.options.createElement(routeElement);
1588
- }
1589
- }));
1590
- })();
1591
-
1592
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1593
- try {
1594
- var _ref, _ref2, _opts$maxAge;
1595
-
1596
- if (routeMatch.options.loader) {
1597
- const data = await routeMatch.options.loader({
1598
- params: routeMatch.params,
1599
- search: routeMatch.routeSearch,
1600
- signal: routeMatch.__.abortController.signal
1601
- });
1602
-
1603
- if (id !== routeMatch.__.latestId) {
1604
- return routeMatch.__.loadPromise;
1605
- }
1560
+ const component = routeMatch.options[type];
1606
1561
 
1607
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1608
- }
1562
+ if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
1563
+ routeMatch.__[type] = await router.options.loadComponent(component);
1564
+ }
1565
+ }));
1566
+ })();
1567
+
1568
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1569
+ try {
1570
+ var _ref, _ref2, _opts$maxAge;
1571
+
1572
+ if (routeMatch.options.loader) {
1573
+ const data = await routeMatch.options.loader({
1574
+ params: routeMatch.params,
1575
+ search: routeMatch.routeSearch,
1576
+ signal: routeMatch.__.abortController.signal
1577
+ });
1609
1578
 
1610
- routeMatch.error = undefined;
1611
- routeMatch.status = 'success';
1612
- routeMatch.updatedAt = Date.now();
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);
1614
- } catch (err) {
1615
1579
  if (id !== routeMatch.__.latestId) {
1616
1580
  return routeMatch.__.loadPromise;
1617
1581
  }
1618
1582
 
1619
- if (process.env.NODE_ENV !== 'production') {
1620
- console.error(err);
1621
- }
1622
-
1623
- routeMatch.error = err;
1624
- routeMatch.status = 'error';
1625
- routeMatch.updatedAt = Date.now();
1583
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1626
1584
  }
1627
- });
1628
-
1629
- try {
1630
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1631
1585
 
1586
+ routeMatch.error = undefined;
1587
+ routeMatch.status = 'success';
1588
+ routeMatch.updatedAt = Date.now();
1589
+ 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);
1590
+ } catch (err) {
1632
1591
  if (id !== routeMatch.__.latestId) {
1633
1592
  return routeMatch.__.loadPromise;
1634
1593
  }
1635
1594
 
1636
- if (routeMatch.__.pendingMinPromise) {
1637
- await routeMatch.__.pendingMinPromise;
1638
- delete routeMatch.__.pendingMinPromise;
1639
- }
1640
- } finally {
1641
- if (id !== routeMatch.__.latestId) {
1642
- return routeMatch.__.loadPromise;
1595
+ if (process.env.NODE_ENV !== 'production') {
1596
+ console.error(err);
1643
1597
  }
1644
1598
 
1645
- routeMatch.__.cancelPending();
1599
+ routeMatch.error = err;
1600
+ routeMatch.status = 'error';
1601
+ routeMatch.updatedAt = Date.now();
1602
+ }
1603
+ });
1646
1604
 
1647
- routeMatch.isPending = false;
1648
- routeMatch.isFetching = false;
1605
+ try {
1606
+ await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise]);
1649
1607
 
1650
- routeMatch.__.notify();
1608
+ if (id !== routeMatch.__.latestId) {
1609
+ return routeMatch.__.loadPromise;
1610
+ }
1611
+ } finally {
1612
+ if (id !== routeMatch.__.latestId) {
1613
+ return routeMatch.__.loadPromise;
1651
1614
  }
1652
- })();
1653
1615
 
1654
- await routeMatch.__.loaderDataPromise;
1616
+ routeMatch.isFetching = false;
1655
1617
 
1656
- if (id !== routeMatch.__.latestId) {
1657
- return routeMatch.__.loadPromise;
1618
+ routeMatch.__.notify();
1658
1619
  }
1659
-
1660
- delete routeMatch.__.loaderDataPromise;
1661
1620
  });
1662
1621
  await routeMatch.__.loadPromise;
1622
+
1623
+ if (id !== routeMatch.__.latestId) {
1624
+ return routeMatch.__.loadPromise;
1625
+ }
1626
+
1663
1627
  delete routeMatch.__.loadPromise;
1664
1628
  }
1665
1629
  });
@@ -1783,10 +1747,16 @@ function createRouter(userOptions) {
1783
1747
  return router.routesById[id];
1784
1748
  },
1785
1749
  notify: () => {
1786
- router.state = _extends({}, router.state, {
1787
- isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1788
- isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1789
- });
1750
+ const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
1751
+ const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
1752
+
1753
+ if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1754
+ router.state = _extends({}, router.state, {
1755
+ isFetching,
1756
+ isPreloading
1757
+ });
1758
+ }
1759
+
1790
1760
  cascadeLoaderData(router.state.matches);
1791
1761
  router.listeners.forEach(listener => listener(router));
1792
1762
  },
@@ -1805,7 +1775,7 @@ function createRouter(userOptions) {
1805
1775
  invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1806
1776
  Object.assign(match, dehydratedMatch);
1807
1777
  });
1808
- router.loadMatches(matches);
1778
+ matches.forEach(match => match.__.validate());
1809
1779
  router.state = _extends({}, router.state, dehydratedState, {
1810
1780
  matches
1811
1781
  });
@@ -1821,8 +1791,11 @@ function createRouter(userOptions) {
1821
1791
 
1822
1792
  if (next.href !== router.location.href) {
1823
1793
  router.__.commitLocation(next, true);
1824
- } // router.load()
1794
+ }
1825
1795
 
1796
+ if (!router.state.matches.length) {
1797
+ router.load();
1798
+ }
1826
1799
 
1827
1800
  const unsub = router.history.listen(event => {
1828
1801
  router.load(router.__.parseLocation(event.location, router.location));
@@ -1895,18 +1868,26 @@ function createRouter(userOptions) {
1895
1868
  const matches = router.matchRoutes(router.location.pathname, {
1896
1869
  strictParseParams: true
1897
1870
  });
1898
- router.state = _extends({}, router.state, {
1899
- pending: {
1871
+
1872
+ if (typeof document !== 'undefined') {
1873
+ router.state = _extends({}, router.state, {
1874
+ pending: {
1875
+ matches: matches,
1876
+ location: router.location
1877
+ },
1878
+ status: 'loading'
1879
+ });
1880
+ } else {
1881
+ router.state = _extends({}, router.state, {
1900
1882
  matches: matches,
1901
- location: router.location
1902
- },
1903
- status: 'loading'
1904
- });
1883
+ location: router.location,
1884
+ status: 'loading'
1885
+ });
1886
+ }
1887
+
1905
1888
  router.notify(); // Load the matches
1906
1889
 
1907
- await router.loadMatches(matches, {
1908
- withPending: true
1909
- });
1890
+ await router.loadMatches(matches);
1910
1891
 
1911
1892
  if (router.startedLoadingAt !== id) {
1912
1893
  // Ignore side-effects of match loading
@@ -2128,14 +2109,8 @@ function createRouter(userOptions) {
2128
2109
 
2129
2110
  match.load(loaderOpts);
2130
2111
 
2131
- if (match.status === 'loading') {
2132
- // If requested, start the pending timers
2133
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending();
2134
- }
2135
-
2136
2112
  if (match.__.loadPromise) {
2137
2113
  // Wait for the first sign of activity from the match
2138
- // This might be completion, error, or a pending state
2139
2114
  await match.__.loadPromise;
2140
2115
  }
2141
2116
  });
@@ -2521,9 +2496,6 @@ const _excluded = ["type", "children", "target", "activeProps", "inactiveProps",
2521
2496
  //
2522
2497
  const matchesContext = /*#__PURE__*/React.createContext(null);
2523
2498
  const routerContext = /*#__PURE__*/React.createContext(null); // Detect if we're in the DOM
2524
-
2525
- const isDOM = Boolean(typeof window !== 'undefined' && window.document && window.document.createElement);
2526
- const useLayoutEffect = isDOM ? React.useLayoutEffect : React.useEffect;
2527
2499
  function MatchesProvider(props) {
2528
2500
  return /*#__PURE__*/React.createElement(matchesContext.Provider, props);
2529
2501
  }
@@ -2587,6 +2559,12 @@ function createReactRouter(opts) {
2587
2559
  next
2588
2560
  } = linkInfo;
2589
2561
 
2562
+ const reactHandleClick = e => {
2563
+ React.startTransition(() => {
2564
+ handleClick(e);
2565
+ });
2566
+ };
2567
+
2590
2568
  const composeHandlers = handlers => e => {
2591
2569
  e.persist();
2592
2570
  handlers.forEach(handler => {
@@ -2600,7 +2578,7 @@ function createReactRouter(opts) {
2600
2578
  const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
2601
2579
  return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2602
2580
  href: disabled ? undefined : next.href,
2603
- onClick: composeHandlers([handleClick, onClick]),
2581
+ onClick: composeHandlers([reactHandleClick, onClick]),
2604
2582
  onFocus: composeHandlers([handleFocus, onFocus]),
2605
2583
  onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2606
2584
  onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
@@ -2680,18 +2658,12 @@ function createReactRouter(opts) {
2680
2658
  const routeExt = makeRouteExt(route, router);
2681
2659
  Object.assign(route, routeExt);
2682
2660
  },
2683
- createElement: async element => {
2684
- if (typeof element === 'function') {
2685
- const res = await element(); // Support direct import() calls
2686
-
2687
- if (typeof res === 'object' && res.default) {
2688
- return /*#__PURE__*/React.createElement(res.default);
2689
- } else {
2690
- return res;
2691
- }
2661
+ loadComponent: async component => {
2662
+ if (component.preload && typeof document !== 'undefined') {
2663
+ component.preload(); // return await component.preload()
2692
2664
  }
2693
2665
 
2694
- return element;
2666
+ return component;
2695
2667
  }
2696
2668
  }));
2697
2669
  return coreRouter;
@@ -2705,10 +2677,8 @@ function RouterProvider(_ref2) {
2705
2677
 
2706
2678
  router.update(rest);
2707
2679
  useRouterSubscription(router);
2708
- useLayoutEffect(() => {
2709
- const unsub = router.mount();
2710
- router.load();
2711
- return unsub;
2680
+ React.useEffect(() => {
2681
+ return router.mount();
2712
2682
  }, [router]);
2713
2683
  return /*#__PURE__*/React.createElement(routerContext.Provider, {
2714
2684
  value: {
@@ -2728,64 +2698,43 @@ function useMatches() {
2728
2698
  return React.useContext(matchesContext);
2729
2699
  }
2730
2700
  function Outlet() {
2731
- var _match$options$catchE;
2701
+ var _ref3, _match$__$pendingComp, _match$__$errorCompon;
2732
2702
 
2733
2703
  const router = useRouter();
2734
2704
  const matches = useMatches().slice(1);
2735
2705
  const match = matches[0];
2706
+ const defaultPending = React.useCallback(() => null, []);
2736
2707
 
2737
2708
  if (!match) {
2738
2709
  return null;
2739
2710
  }
2740
2711
 
2741
- const element = (() => {
2742
- var _match$__$errorElemen, _ref4, _ref5;
2743
-
2744
- if (!match) {
2745
- return null;
2746
- }
2747
-
2748
- const errorElement = (_match$__$errorElemen = match.__.errorElement) != null ? _match$__$errorElemen : router.options.defaultErrorElement;
2749
-
2712
+ const PendingComponent = (_ref3 = (_match$__$pendingComp = match.__.pendingComponent) != null ? _match$__$pendingComp : router.options.defaultPendingComponent) != null ? _ref3 : defaultPending;
2713
+ const errorComponent = (_match$__$errorCompon = match.__.errorComponent) != null ? _match$__$errorCompon : router.options.defaultErrorComponent;
2714
+ return /*#__PURE__*/React.createElement(MatchesProvider, {
2715
+ value: matches
2716
+ }, /*#__PURE__*/React.createElement(React.Suspense, {
2717
+ fallback: /*#__PURE__*/React.createElement(PendingComponent, null)
2718
+ }, /*#__PURE__*/React.createElement(CatchBoundary, {
2719
+ errorComponent: errorComponent
2720
+ }, (() => {
2750
2721
  if (match.status === 'error') {
2751
- if (errorElement) {
2752
- return errorElement;
2753
- }
2754
-
2755
- if (match.options.useErrorBoundary || router.options.useErrorBoundary) {
2756
- throw match.error;
2757
- }
2758
-
2759
- return /*#__PURE__*/React.createElement(DefaultErrorBoundary, {
2760
- error: match.error
2761
- });
2722
+ throw match.error;
2762
2723
  }
2763
2724
 
2764
- if (match.status === 'loading' || match.status === 'idle') {
2765
- if (match.isPending) {
2766
- var _match$__$pendingElem;
2767
-
2768
- const pendingElement = (_match$__$pendingElem = match.__.pendingElement) != null ? _match$__$pendingElem : router.options.defaultPendingElement;
2769
-
2770
- if (match.options.pendingMs || pendingElement) {
2771
- var _ref3;
2772
-
2773
- return (_ref3 = pendingElement) != null ? _ref3 : null;
2774
- }
2775
- }
2725
+ if (match.status === 'success') {
2726
+ var _ref4, _ref5;
2776
2727
 
2777
- return null;
2728
+ return /*#__PURE__*/React.createElement((_ref4 = (_ref5 = match.__.component) != null ? _ref5 : router.options.defaultComponent) != null ? _ref4 : Outlet);
2778
2729
  }
2779
2730
 
2780
- return (_ref4 = (_ref5 = match.__.element) != null ? _ref5 : router.options.defaultElement) != null ? _ref4 : /*#__PURE__*/React.createElement(Outlet, null);
2781
- })();
2731
+ if (match.__.loadPromise) {
2732
+ console.log(match.matchId, 'suspend');
2733
+ throw match.__.loadPromise;
2734
+ }
2782
2735
 
2783
- const catchElement = (_match$options$catchE = match == null ? void 0 : match.options.catchElement) != null ? _match$options$catchE : router.options.defaultCatchElement;
2784
- return /*#__PURE__*/React.createElement(MatchesProvider, {
2785
- value: matches
2786
- }, /*#__PURE__*/React.createElement(CatchBoundary, {
2787
- catchElement: catchElement
2788
- }, element));
2736
+ invariant(false, 'This should never happen!');
2737
+ })())));
2789
2738
  }
2790
2739
 
2791
2740
  class CatchBoundary extends React.Component {
@@ -2805,12 +2754,12 @@ class CatchBoundary extends React.Component {
2805
2754
  }
2806
2755
 
2807
2756
  render() {
2808
- var _this$props$catchElem;
2757
+ var _this$props$errorComp;
2809
2758
 
2810
- const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultErrorBoundary;
2759
+ const errorComponent = (_this$props$errorComp = this.props.errorComponent) != null ? _this$props$errorComp : DefaultErrorBoundary;
2811
2760
 
2812
2761
  if (this.state.error) {
2813
- return typeof catchElement === 'function' ? catchElement(this.state) : catchElement;
2762
+ return /*#__PURE__*/React.createElement(errorComponent, this.state);
2814
2763
  }
2815
2764
 
2816
2765
  return this.props.children;