@tanstack/react-router 0.0.1-beta.260 → 0.0.1-beta.262

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,7 +10,7 @@ import { AnyRouteMatch, RouteMatch } from './Matches';
10
10
  import { ParsedLocation } from './location';
11
11
  import { LocationState } from './location';
12
12
  import { SearchSerializer, SearchParser } from './searchParams';
13
- import { BuildLinkFn, BuildLocationFn, CommitLocationOptions, InjectedHtmlEntry, MatchRouteFn, NavigateFn } from './RouterProvider';
13
+ import { BuildLocationFn, CommitLocationOptions, InjectedHtmlEntry, MatchRouteFn, NavigateFn } from './RouterProvider';
14
14
  declare global {
15
15
  interface Window {
16
16
  __TSR_DEHYDRATED__?: HydrationCtx;
@@ -167,7 +167,6 @@ export declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated
167
167
  invalidate?: boolean;
168
168
  }) => Promise<void>;
169
169
  preloadRoute: (navigateOpts?: BuildNextOptions) => Promise<RouteMatch<AnyRoute, any>[]>;
170
- buildLink: BuildLinkFn<TRouteTree>;
171
170
  matchRoute: MatchRouteFn<TRouteTree>;
172
171
  injectHtml: (html: string | (() => Promise<string> | string)) => Promise<void>;
173
172
  dehydrateData: <T>(key: any, getData: T | (() => T | Promise<T>)) => () => T | undefined;
@@ -1643,17 +1643,15 @@
1643
1643
  return _extends.apply(this, arguments);
1644
1644
  }
1645
1645
 
1646
+ const preloadWarning = 'Error preloading route! ☝️';
1646
1647
  function useLinkProps(options) {
1647
- const {
1648
- buildLink
1649
- } = useRouter();
1648
+ const router = useRouter();
1650
1649
  const matchPathname = useMatch({
1651
1650
  strict: false,
1652
1651
  select: s => s.pathname
1653
1652
  });
1654
1653
  const {
1655
1654
  // custom props
1656
- type,
1657
1655
  children,
1658
1656
  target,
1659
1657
  activeProps = () => ({
@@ -1668,8 +1666,8 @@
1668
1666
  to,
1669
1667
  state,
1670
1668
  mask,
1671
- preload,
1672
- preloadDelay,
1669
+ preload: userPreload,
1670
+ preloadDelay: userPreloadDelay,
1673
1671
  replace,
1674
1672
  startTransition,
1675
1673
  resetScroll,
@@ -1683,27 +1681,100 @@
1683
1681
  onTouchStart,
1684
1682
  ...rest
1685
1683
  } = options;
1686
- const linkInfo = buildLink({
1684
+
1685
+ // If this link simply reloads the current route,
1686
+ // make sure it has a new key so it will trigger a data refresh
1687
+
1688
+ // If this `to` is a valid external URL, return
1689
+ // null for LinkUtils
1690
+
1691
+ const dest = {
1687
1692
  from: options.to ? matchPathname : undefined,
1688
1693
  ...options
1689
- });
1690
- if (linkInfo.type === 'external') {
1691
- const {
1692
- href
1693
- } = linkInfo;
1694
+ };
1695
+ let type = 'internal';
1696
+ try {
1697
+ new URL(`${to}`);
1698
+ type = 'external';
1699
+ } catch {}
1700
+ if (type === 'external') {
1694
1701
  return {
1695
- href
1702
+ href: to
1696
1703
  };
1697
1704
  }
1698
- const {
1699
- handleClick,
1700
- handleFocus,
1701
- handleEnter,
1702
- handleLeave,
1703
- handleTouchStart,
1704
- isActive,
1705
- next
1706
- } = linkInfo;
1705
+ const next = router.buildLocation(dest);
1706
+ const preload = userPreload ?? router.options.defaultPreload;
1707
+ const preloadDelay = userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0;
1708
+ const isActive = useRouterState({
1709
+ select: s => {
1710
+ // Compare path/hash for matches
1711
+ const currentPathSplit = s.location.pathname.split('/');
1712
+ const nextPathSplit = next.pathname.split('/');
1713
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
1714
+ // Combine the matches based on user router.options
1715
+ const pathTest = activeOptions?.exact ? s.location.pathname === next.pathname : pathIsFuzzyEqual;
1716
+ const hashTest = activeOptions?.includeHash ? s.location.hash === next.hash : true;
1717
+ const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(s.location.search, next.search, true) : true;
1718
+
1719
+ // The final "active" test
1720
+ return pathTest && hashTest && searchTest;
1721
+ }
1722
+ });
1723
+
1724
+ // The click handler
1725
+ const handleClick = e => {
1726
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1727
+ e.preventDefault();
1728
+
1729
+ // All is well? Navigate!
1730
+ router.commitLocation({
1731
+ ...next,
1732
+ replace,
1733
+ resetScroll,
1734
+ startTransition
1735
+ });
1736
+ }
1737
+ };
1738
+
1739
+ // The click handler
1740
+ const handleFocus = e => {
1741
+ if (preload) {
1742
+ router.preloadRoute(dest).catch(err => {
1743
+ console.warn(err);
1744
+ console.warn(preloadWarning);
1745
+ });
1746
+ }
1747
+ };
1748
+ const handleTouchStart = e => {
1749
+ if (preload) {
1750
+ router.preloadRoute(dest).catch(err => {
1751
+ console.warn(err);
1752
+ console.warn(preloadWarning);
1753
+ });
1754
+ }
1755
+ };
1756
+ const handleEnter = e => {
1757
+ const target = e.target || {};
1758
+ if (preload) {
1759
+ if (target.preloadTimeout) {
1760
+ return;
1761
+ }
1762
+ target.preloadTimeout = setTimeout(() => {
1763
+ target.preloadTimeout = null;
1764
+ router.preloadRoute(dest).catch(err => {
1765
+ console.warn(err);
1766
+ console.warn(preloadWarning);
1767
+ });
1768
+ }, preloadDelay);
1769
+ }
1770
+ };
1771
+ const handleLeave = e => {
1772
+ const target = e.target || {};
1773
+ if (target.preloadTimeout) {
1774
+ clearTimeout(target.preloadTimeout);
1775
+ target.preloadTimeout = null;
1776
+ }
1777
+ };
1707
1778
  const composeHandlers = handlers => e => {
1708
1779
  if (e.persist) e.persist();
1709
1780
  handlers.filter(Boolean).forEach(handler => {
@@ -1751,6 +1822,9 @@
1751
1822
  }) : props.children
1752
1823
  }));
1753
1824
  });
1825
+ function isCtrlEvent(e) {
1826
+ return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
1827
+ }
1754
1828
 
1755
1829
  // @ts-nocheck
1756
1830
 
@@ -1880,7 +1954,6 @@
1880
1954
  //
1881
1955
 
1882
1956
  const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1883
- const preloadWarning = 'Error preloading route! ☝️';
1884
1957
  class Router {
1885
1958
  // Option-independent properties
1886
1959
  tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
@@ -2425,13 +2498,13 @@
2425
2498
  pendingMatches: s.pendingMatches?.map(d => d.id === match.id ? match : d)
2426
2499
  }));
2427
2500
  };
2428
- const abortController = new AbortController();
2429
2501
 
2430
2502
  // Check each match middleware to see if the route can be accessed
2431
2503
  try {
2432
2504
  for (let [index, match] of matches.entries()) {
2433
2505
  const parentMatch = matches[index - 1];
2434
2506
  const route = this.looseRoutesById[match.routeId];
2507
+ const abortController = new AbortController();
2435
2508
  const handleErrorAndRedirect = (err, code) => {
2436
2509
  err.routerCode = code;
2437
2510
  firstBadMatchIndex = firstBadMatchIndex ?? index;
@@ -2451,7 +2524,7 @@
2451
2524
  error: err,
2452
2525
  status: 'error',
2453
2526
  updatedAt: Date.now(),
2454
- abortController
2527
+ abortController: new AbortController()
2455
2528
  };
2456
2529
  };
2457
2530
  try {
@@ -2464,7 +2537,7 @@
2464
2537
  const parentContext = parentMatch?.context ?? this.options.context ?? {};
2465
2538
  const beforeLoadContext = (await route.options.beforeLoad?.({
2466
2539
  search: match.search,
2467
- abortController: match.abortController,
2540
+ abortController,
2468
2541
  params: match.params,
2469
2542
  preload: !!preload,
2470
2543
  context: parentContext,
@@ -2486,7 +2559,8 @@
2486
2559
  };
2487
2560
  matches[index] = match = {
2488
2561
  ...match,
2489
- context: replaceEqualDeep(match.context, context)
2562
+ context: replaceEqualDeep(match.context, context),
2563
+ abortController
2490
2564
  };
2491
2565
  } catch (err) {
2492
2566
  handleErrorAndRedirect(err, 'BEFORE_LOAD');
@@ -2757,114 +2831,6 @@
2757
2831
  });
2758
2832
  return matches;
2759
2833
  };
2760
- buildLink = dest => {
2761
- // If this link simply reloads the current route,
2762
- // make sure it has a new key so it will trigger a data refresh
2763
-
2764
- // If this `to` is a valid external URL, return
2765
- // null for LinkUtils
2766
-
2767
- const {
2768
- to,
2769
- preload: userPreload,
2770
- preloadDelay: userPreloadDelay,
2771
- activeOptions,
2772
- disabled,
2773
- target,
2774
- replace,
2775
- resetScroll,
2776
- startTransition
2777
- } = dest;
2778
- try {
2779
- new URL(`${to}`);
2780
- return {
2781
- type: 'external',
2782
- href: to
2783
- };
2784
- } catch (e) {}
2785
- const nextOpts = dest;
2786
- const next = this.buildLocation(nextOpts);
2787
- const preload = userPreload ?? this.options.defaultPreload;
2788
- const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
2789
-
2790
- // Compare path/hash for matches
2791
- const currentPathSplit = this.latestLocation.pathname.split('/');
2792
- const nextPathSplit = next.pathname.split('/');
2793
- const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2794
- // Combine the matches based on user this.options
2795
- const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
2796
- const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
2797
- const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
2798
-
2799
- // The final "active" test
2800
- const isActive = pathTest && hashTest && searchTest;
2801
-
2802
- // The click handler
2803
- const handleClick = e => {
2804
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2805
- e.preventDefault();
2806
-
2807
- // All is well? Navigate!
2808
- this.commitLocation({
2809
- ...next,
2810
- replace,
2811
- resetScroll,
2812
- startTransition
2813
- });
2814
- }
2815
- };
2816
-
2817
- // The click handler
2818
- const handleFocus = e => {
2819
- if (preload) {
2820
- this.preloadRoute(nextOpts).catch(err => {
2821
- console.warn(err);
2822
- console.warn(preloadWarning);
2823
- });
2824
- }
2825
- };
2826
- const handleTouchStart = e => {
2827
- if (preload) {
2828
- this.preloadRoute(nextOpts).catch(err => {
2829
- console.warn(err);
2830
- console.warn(preloadWarning);
2831
- });
2832
- }
2833
- };
2834
- const handleEnter = e => {
2835
- const target = e.target || {};
2836
- if (preload) {
2837
- if (target.preloadTimeout) {
2838
- return;
2839
- }
2840
- target.preloadTimeout = setTimeout(() => {
2841
- target.preloadTimeout = null;
2842
- this.preloadRoute(nextOpts).catch(err => {
2843
- console.warn(err);
2844
- console.warn(preloadWarning);
2845
- });
2846
- }, preloadDelay);
2847
- }
2848
- };
2849
- const handleLeave = e => {
2850
- const target = e.target || {};
2851
- if (target.preloadTimeout) {
2852
- clearTimeout(target.preloadTimeout);
2853
- target.preloadTimeout = null;
2854
- }
2855
- };
2856
- return {
2857
- type: 'internal',
2858
- next,
2859
- handleFocus,
2860
- handleClick,
2861
- handleEnter,
2862
- handleLeave,
2863
- handleTouchStart,
2864
- isActive,
2865
- disabled
2866
- };
2867
- };
2868
2834
  matchRoute = (location, opts) => {
2869
2835
  location = {
2870
2836
  ...location,
@@ -2970,9 +2936,6 @@
2970
2936
  return imported[key || 'default'](...args);
2971
2937
  };
2972
2938
  }
2973
- function isCtrlEvent(e) {
2974
- return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2975
- }
2976
2939
  class SearchParamError extends Error {}
2977
2940
  class PathParamError extends Error {}
2978
2941
  function getInitialRouterState(location) {