@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.
@@ -9,10 +9,10 @@
9
9
  * @license MIT
10
10
  */
11
11
  (function (global, factory) {
12
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('use-sync-external-store/shim')) :
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.ReactRouter = {}, global.React, global.shim));
15
- })(this, (function (exports, React, shim) { 'use strict';
12
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('use-sync-external-store/shim'), require('react-lazy-with-preload/lib/index')) :
13
+ typeof define === 'function' && define.amd ? define(['exports', 'react', 'use-sync-external-store/shim', 'react-lazy-with-preload/lib/index'], factory) :
14
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactRouter = {}, global.React, global.shim, global.index));
15
+ })(this, (function (exports, React, shim, index) { 'use strict';
16
16
 
17
17
  function _interopNamespace(e) {
18
18
  if (e && e.__esModule) return e;
@@ -1443,7 +1443,7 @@
1443
1443
  };
1444
1444
  };
1445
1445
 
1446
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1446
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1447
1447
  function createRouteMatch(router, route, opts) {
1448
1448
  const routeMatch = _extends({}, route, opts, {
1449
1449
  router,
@@ -1453,7 +1453,6 @@
1453
1453
  status: 'idle',
1454
1454
  routeLoaderData: {},
1455
1455
  loaderData: {},
1456
- isPending: false,
1457
1456
  isFetching: false,
1458
1457
  isInvalid: false,
1459
1458
  invalidAt: Infinity,
@@ -1471,32 +1470,6 @@
1471
1470
 
1472
1471
  routeMatch.router.notify();
1473
1472
  },
1474
- startPending: () => {
1475
- var _routeMatch$options$p, _routeMatch$options$p2;
1476
-
1477
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1478
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1479
-
1480
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1481
- return;
1482
- }
1483
-
1484
- routeMatch.__.pendingTimeout = setTimeout(() => {
1485
- routeMatch.isPending = true;
1486
-
1487
- routeMatch.__.resolve();
1488
-
1489
- if (typeof pendingMinMs !== 'undefined') {
1490
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1491
- }
1492
- }, pendingMs);
1493
- },
1494
- cancelPending: () => {
1495
- routeMatch.isPending = false;
1496
- clearTimeout(routeMatch.__.pendingTimeout);
1497
- clearTimeout(routeMatch.__.pendingMinTimeout);
1498
- delete routeMatch.__.pendingMinPromise;
1499
- },
1500
1473
  validate: () => {
1501
1474
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1502
1475
 
@@ -1516,11 +1489,11 @@
1516
1489
 
1517
1490
  routeMatch.routeSearch = nextSearch;
1518
1491
  routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1519
- elementTypes.map(async type => {
1520
- const routeElement = routeMatch.options[type];
1492
+ componentTypes.map(async type => {
1493
+ const component = routeMatch.options[type];
1521
1494
 
1522
1495
  if (typeof routeMatch.__[type] !== 'function') {
1523
- routeMatch.__[type] = routeElement;
1496
+ routeMatch.__[type] = component;
1524
1497
  }
1525
1498
  });
1526
1499
  } catch (err) {
@@ -1540,14 +1513,16 @@
1540
1513
  var _routeMatch$__$abortC;
1541
1514
 
1542
1515
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1543
-
1544
- routeMatch.__.cancelPending();
1545
1516
  },
1546
1517
  invalidate: () => {
1547
1518
  routeMatch.isInvalid = true;
1548
1519
  },
1549
1520
  hasLoaders: () => {
1550
- return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1521
+ return !!(route.options.loader || componentTypes.some(d => {
1522
+ var _route$options$d;
1523
+
1524
+ return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
1525
+ }));
1551
1526
  },
1552
1527
  load: async loaderOpts => {
1553
1528
  const now = Date.now();
@@ -1591,91 +1566,79 @@
1591
1566
  routeMatch.isFetching = true;
1592
1567
  routeMatch.__.resolve = resolve;
1593
1568
 
1594
- routeMatch.__.loaderDataPromise = (async () => {
1595
- // Load the elements and data in parallel
1596
- routeMatch.__.elementsPromise = (async () => {
1597
- // then run all element and data loaders in parallel
1598
- // For each element type, potentially load it asynchronously
1599
- await Promise.all(elementTypes.map(async type => {
1600
- const routeElement = routeMatch.options[type];
1569
+ routeMatch.__.componentsPromise = (async () => {
1570
+ // then run all component and data loaders in parallel
1571
+ // For each component type, potentially load it asynchronously
1572
+ await Promise.all(componentTypes.map(async type => {
1573
+ var _routeMatch$__$type;
1601
1574
 
1602
- if (typeof routeMatch.__[type] === 'function') {
1603
- routeMatch.__[type] = await router.options.createElement(routeElement);
1604
- }
1605
- }));
1606
- })();
1607
-
1608
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1609
- try {
1610
- var _ref, _ref2, _opts$maxAge;
1611
-
1612
- if (routeMatch.options.loader) {
1613
- const data = await routeMatch.options.loader({
1614
- params: routeMatch.params,
1615
- search: routeMatch.routeSearch,
1616
- signal: routeMatch.__.abortController.signal
1617
- });
1618
-
1619
- if (id !== routeMatch.__.latestId) {
1620
- return routeMatch.__.loadPromise;
1621
- }
1575
+ const component = routeMatch.options[type];
1622
1576
 
1623
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1624
- }
1577
+ if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
1578
+ routeMatch.__[type] = await router.options.loadComponent(component);
1579
+ }
1580
+ }));
1581
+ })();
1582
+
1583
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1584
+ try {
1585
+ var _ref, _ref2, _opts$maxAge;
1586
+
1587
+ if (routeMatch.options.loader) {
1588
+ const data = await routeMatch.options.loader({
1589
+ params: routeMatch.params,
1590
+ search: routeMatch.routeSearch,
1591
+ signal: routeMatch.__.abortController.signal
1592
+ });
1625
1593
 
1626
- routeMatch.error = undefined;
1627
- routeMatch.status = 'success';
1628
- routeMatch.updatedAt = Date.now();
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);
1630
- } catch (err) {
1631
1594
  if (id !== routeMatch.__.latestId) {
1632
1595
  return routeMatch.__.loadPromise;
1633
1596
  }
1634
1597
 
1635
- {
1636
- console.error(err);
1637
- }
1638
-
1639
- routeMatch.error = err;
1640
- routeMatch.status = 'error';
1641
- routeMatch.updatedAt = Date.now();
1598
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1642
1599
  }
1643
- });
1644
-
1645
- try {
1646
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1647
1600
 
1601
+ routeMatch.error = undefined;
1602
+ routeMatch.status = 'success';
1603
+ routeMatch.updatedAt = Date.now();
1604
+ 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);
1605
+ } catch (err) {
1648
1606
  if (id !== routeMatch.__.latestId) {
1649
1607
  return routeMatch.__.loadPromise;
1650
1608
  }
1651
1609
 
1652
- if (routeMatch.__.pendingMinPromise) {
1653
- await routeMatch.__.pendingMinPromise;
1654
- delete routeMatch.__.pendingMinPromise;
1655
- }
1656
- } finally {
1657
- if (id !== routeMatch.__.latestId) {
1658
- return routeMatch.__.loadPromise;
1610
+ {
1611
+ console.error(err);
1659
1612
  }
1660
1613
 
1661
- routeMatch.__.cancelPending();
1614
+ routeMatch.error = err;
1615
+ routeMatch.status = 'error';
1616
+ routeMatch.updatedAt = Date.now();
1617
+ }
1618
+ });
1662
1619
 
1663
- routeMatch.isPending = false;
1664
- routeMatch.isFetching = false;
1620
+ try {
1621
+ await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise]);
1665
1622
 
1666
- routeMatch.__.notify();
1623
+ if (id !== routeMatch.__.latestId) {
1624
+ return routeMatch.__.loadPromise;
1625
+ }
1626
+ } finally {
1627
+ if (id !== routeMatch.__.latestId) {
1628
+ return routeMatch.__.loadPromise;
1667
1629
  }
1668
- })();
1669
1630
 
1670
- await routeMatch.__.loaderDataPromise;
1631
+ routeMatch.isFetching = false;
1671
1632
 
1672
- if (id !== routeMatch.__.latestId) {
1673
- return routeMatch.__.loadPromise;
1633
+ routeMatch.__.notify();
1674
1634
  }
1675
-
1676
- delete routeMatch.__.loaderDataPromise;
1677
1635
  });
1678
1636
  await routeMatch.__.loadPromise;
1637
+
1638
+ if (id !== routeMatch.__.latestId) {
1639
+ return routeMatch.__.loadPromise;
1640
+ }
1641
+
1679
1642
  delete routeMatch.__.loadPromise;
1680
1643
  }
1681
1644
  });
@@ -1799,10 +1762,16 @@
1799
1762
  return router.routesById[id];
1800
1763
  },
1801
1764
  notify: () => {
1802
- router.state = _extends({}, router.state, {
1803
- isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1804
- isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1805
- });
1765
+ const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
1766
+ const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
1767
+
1768
+ if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1769
+ router.state = _extends({}, router.state, {
1770
+ isFetching,
1771
+ isPreloading
1772
+ });
1773
+ }
1774
+
1806
1775
  cascadeLoaderData(router.state.matches);
1807
1776
  router.listeners.forEach(listener => listener(router));
1808
1777
  },
@@ -1821,7 +1790,7 @@
1821
1790
  invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1822
1791
  Object.assign(match, dehydratedMatch);
1823
1792
  });
1824
- router.loadMatches(matches);
1793
+ matches.forEach(match => match.__.validate());
1825
1794
  router.state = _extends({}, router.state, dehydratedState, {
1826
1795
  matches
1827
1796
  });
@@ -1837,8 +1806,11 @@
1837
1806
 
1838
1807
  if (next.href !== router.location.href) {
1839
1808
  router.__.commitLocation(next, true);
1840
- } // router.load()
1809
+ }
1841
1810
 
1811
+ if (!router.state.matches.length) {
1812
+ router.load();
1813
+ }
1842
1814
 
1843
1815
  const unsub = router.history.listen(event => {
1844
1816
  router.load(router.__.parseLocation(event.location, router.location));
@@ -1911,18 +1883,26 @@
1911
1883
  const matches = router.matchRoutes(router.location.pathname, {
1912
1884
  strictParseParams: true
1913
1885
  });
1914
- router.state = _extends({}, router.state, {
1915
- pending: {
1886
+
1887
+ if (typeof document !== 'undefined') {
1888
+ router.state = _extends({}, router.state, {
1889
+ pending: {
1890
+ matches: matches,
1891
+ location: router.location
1892
+ },
1893
+ status: 'loading'
1894
+ });
1895
+ } else {
1896
+ router.state = _extends({}, router.state, {
1916
1897
  matches: matches,
1917
- location: router.location
1918
- },
1919
- status: 'loading'
1920
- });
1898
+ location: router.location,
1899
+ status: 'loading'
1900
+ });
1901
+ }
1902
+
1921
1903
  router.notify(); // Load the matches
1922
1904
 
1923
- await router.loadMatches(matches, {
1924
- withPending: true
1925
- });
1905
+ await router.loadMatches(matches);
1926
1906
 
1927
1907
  if (router.startedLoadingAt !== id) {
1928
1908
  // Ignore side-effects of match loading
@@ -2144,14 +2124,8 @@
2144
2124
 
2145
2125
  match.load(loaderOpts);
2146
2126
 
2147
- if (match.status === 'loading') {
2148
- // If requested, start the pending timers
2149
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending();
2150
- }
2151
-
2152
2127
  if (match.__.loadPromise) {
2153
2128
  // Wait for the first sign of activity from the match
2154
- // This might be completion, error, or a pending state
2155
2129
  await match.__.loadPromise;
2156
2130
  }
2157
2131
  });
@@ -2537,9 +2511,6 @@
2537
2511
  //
2538
2512
  const matchesContext = /*#__PURE__*/React__namespace.createContext(null);
2539
2513
  const routerContext = /*#__PURE__*/React__namespace.createContext(null); // Detect if we're in the DOM
2540
-
2541
- const isDOM = Boolean(typeof window !== 'undefined' && window.document && window.document.createElement);
2542
- const useLayoutEffect = isDOM ? React__namespace.useLayoutEffect : React__namespace.useEffect;
2543
2514
  function MatchesProvider(props) {
2544
2515
  return /*#__PURE__*/React__namespace.createElement(matchesContext.Provider, props);
2545
2516
  }
@@ -2603,6 +2574,12 @@
2603
2574
  next
2604
2575
  } = linkInfo;
2605
2576
 
2577
+ const reactHandleClick = e => {
2578
+ React__namespace.startTransition(() => {
2579
+ handleClick(e);
2580
+ });
2581
+ };
2582
+
2606
2583
  const composeHandlers = handlers => e => {
2607
2584
  e.persist();
2608
2585
  handlers.forEach(handler => {
@@ -2616,7 +2593,7 @@
2616
2593
  const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
2617
2594
  return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2618
2595
  href: disabled ? undefined : next.href,
2619
- onClick: composeHandlers([handleClick, onClick]),
2596
+ onClick: composeHandlers([reactHandleClick, onClick]),
2620
2597
  onFocus: composeHandlers([handleFocus, onFocus]),
2621
2598
  onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2622
2599
  onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
@@ -2696,18 +2673,12 @@
2696
2673
  const routeExt = makeRouteExt(route, router);
2697
2674
  Object.assign(route, routeExt);
2698
2675
  },
2699
- createElement: async element => {
2700
- if (typeof element === 'function') {
2701
- const res = await element(); // Support direct import() calls
2702
-
2703
- if (typeof res === 'object' && res.default) {
2704
- return /*#__PURE__*/React__namespace.createElement(res.default);
2705
- } else {
2706
- return res;
2707
- }
2676
+ loadComponent: async component => {
2677
+ if (component.preload && typeof document !== 'undefined') {
2678
+ component.preload(); // return await component.preload()
2708
2679
  }
2709
2680
 
2710
- return element;
2681
+ return component;
2711
2682
  }
2712
2683
  }));
2713
2684
  return coreRouter;
@@ -2721,10 +2692,8 @@
2721
2692
 
2722
2693
  router.update(rest);
2723
2694
  useRouterSubscription(router);
2724
- useLayoutEffect(() => {
2725
- const unsub = router.mount();
2726
- router.load();
2727
- return unsub;
2695
+ React__namespace.useEffect(() => {
2696
+ return router.mount();
2728
2697
  }, [router]);
2729
2698
  return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
2730
2699
  value: {
@@ -2744,64 +2713,43 @@
2744
2713
  return React__namespace.useContext(matchesContext);
2745
2714
  }
2746
2715
  function Outlet() {
2747
- var _match$options$catchE;
2716
+ var _ref3, _match$__$pendingComp, _match$__$errorCompon;
2748
2717
 
2749
2718
  const router = useRouter();
2750
2719
  const matches = useMatches().slice(1);
2751
2720
  const match = matches[0];
2721
+ const defaultPending = React__namespace.useCallback(() => null, []);
2752
2722
 
2753
2723
  if (!match) {
2754
2724
  return null;
2755
2725
  }
2756
2726
 
2757
- const element = (() => {
2758
- var _match$__$errorElemen, _ref4, _ref5;
2759
-
2760
- if (!match) {
2761
- return null;
2762
- }
2763
-
2764
- const errorElement = (_match$__$errorElemen = match.__.errorElement) != null ? _match$__$errorElemen : router.options.defaultErrorElement;
2765
-
2727
+ const PendingComponent = (_ref3 = (_match$__$pendingComp = match.__.pendingComponent) != null ? _match$__$pendingComp : router.options.defaultPendingComponent) != null ? _ref3 : defaultPending;
2728
+ const errorComponent = (_match$__$errorCompon = match.__.errorComponent) != null ? _match$__$errorCompon : router.options.defaultErrorComponent;
2729
+ return /*#__PURE__*/React__namespace.createElement(MatchesProvider, {
2730
+ value: matches
2731
+ }, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
2732
+ fallback: /*#__PURE__*/React__namespace.createElement(PendingComponent, null)
2733
+ }, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
2734
+ errorComponent: errorComponent
2735
+ }, (() => {
2766
2736
  if (match.status === 'error') {
2767
- if (errorElement) {
2768
- return errorElement;
2769
- }
2770
-
2771
- if (match.options.useErrorBoundary || router.options.useErrorBoundary) {
2772
- throw match.error;
2773
- }
2774
-
2775
- return /*#__PURE__*/React__namespace.createElement(DefaultErrorBoundary, {
2776
- error: match.error
2777
- });
2737
+ throw match.error;
2778
2738
  }
2779
2739
 
2780
- if (match.status === 'loading' || match.status === 'idle') {
2781
- if (match.isPending) {
2782
- var _match$__$pendingElem;
2783
-
2784
- const pendingElement = (_match$__$pendingElem = match.__.pendingElement) != null ? _match$__$pendingElem : router.options.defaultPendingElement;
2785
-
2786
- if (match.options.pendingMs || pendingElement) {
2787
- var _ref3;
2788
-
2789
- return (_ref3 = pendingElement) != null ? _ref3 : null;
2790
- }
2791
- }
2740
+ if (match.status === 'success') {
2741
+ var _ref4, _ref5;
2792
2742
 
2793
- return null;
2743
+ return /*#__PURE__*/React__namespace.createElement((_ref4 = (_ref5 = match.__.component) != null ? _ref5 : router.options.defaultComponent) != null ? _ref4 : Outlet);
2794
2744
  }
2795
2745
 
2796
- return (_ref4 = (_ref5 = match.__.element) != null ? _ref5 : router.options.defaultElement) != null ? _ref4 : /*#__PURE__*/React__namespace.createElement(Outlet, null);
2797
- })();
2746
+ if (match.__.loadPromise) {
2747
+ console.log(match.matchId, 'suspend');
2748
+ throw match.__.loadPromise;
2749
+ }
2798
2750
 
2799
- const catchElement = (_match$options$catchE = match == null ? void 0 : match.options.catchElement) != null ? _match$options$catchE : router.options.defaultCatchElement;
2800
- return /*#__PURE__*/React__namespace.createElement(MatchesProvider, {
2801
- value: matches
2802
- }, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
2803
- catchElement: catchElement
2804
- }, element));
2751
+ invariant(false, 'This should never happen!');
2752
+ })())));
2805
2753
  }
2806
2754
 
2807
2755
  class CatchBoundary extends React__namespace.Component {
@@ -2821,12 +2769,12 @@
2821
2769
  }
2822
2770
 
2823
2771
  render() {
2824
- var _this$props$catchElem;
2772
+ var _this$props$errorComp;
2825
2773
 
2826
- const catchElement = (_this$props$catchElem = this.props.catchElement) != null ? _this$props$catchElem : DefaultErrorBoundary;
2774
+ const errorComponent = (_this$props$errorComp = this.props.errorComponent) != null ? _this$props$errorComp : DefaultErrorBoundary;
2827
2775
 
2828
2776
  if (this.state.error) {
2829
- return typeof catchElement === 'function' ? catchElement(this.state) : catchElement;
2777
+ return /*#__PURE__*/React__namespace.createElement(errorComponent, this.state);
2830
2778
  }
2831
2779
 
2832
2780
  return this.props.children;
@@ -2886,6 +2834,10 @@
2886
2834
  return children != null ? children : null;
2887
2835
  }
2888
2836
 
2837
+ Object.defineProperty(exports, 'lazy', {
2838
+ enumerable: true,
2839
+ get: function () { return index.lazyWithPreload; }
2840
+ });
2889
2841
  exports.DefaultErrorBoundary = DefaultErrorBoundary;
2890
2842
  exports.MatchesProvider = MatchesProvider;
2891
2843
  exports.Outlet = Outlet;