@tanstack/react-router 1.5.3 → 1.5.5

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.
Files changed (61) hide show
  1. package/build/cjs/Matches.js +15 -14
  2. package/build/cjs/Matches.js.map +1 -1
  3. package/build/cjs/RouterProvider.js +6 -27
  4. package/build/cjs/RouterProvider.js.map +1 -1
  5. package/build/cjs/awaited.js +2 -2
  6. package/build/cjs/awaited.js.map +1 -1
  7. package/build/cjs/index.js +11 -7
  8. package/build/cjs/index.js.map +1 -1
  9. package/build/cjs/link.js +4 -3
  10. package/build/cjs/link.js.map +1 -1
  11. package/build/cjs/router.js.map +1 -1
  12. package/build/cjs/routerContext.js +42 -0
  13. package/build/cjs/routerContext.js.map +1 -0
  14. package/build/cjs/scroll-restoration.js +3 -3
  15. package/build/cjs/scroll-restoration.js.map +1 -1
  16. package/build/cjs/useBlocker.js +2 -2
  17. package/build/cjs/useBlocker.js.map +1 -1
  18. package/build/cjs/useNavigate.js +3 -3
  19. package/build/cjs/useNavigate.js.map +1 -1
  20. package/build/cjs/useParams.js +2 -2
  21. package/build/cjs/useParams.js.map +1 -1
  22. package/build/cjs/useRouteContext.js +23 -0
  23. package/build/cjs/useRouteContext.js.map +1 -0
  24. package/build/cjs/useRouter.js +44 -0
  25. package/build/cjs/useRouter.js.map +1 -0
  26. package/build/cjs/useRouterState.js +24 -0
  27. package/build/cjs/useRouterState.js.map +1 -0
  28. package/build/cjs/utils.js +0 -8
  29. package/build/cjs/utils.js.map +1 -1
  30. package/build/esm/index.js +192 -188
  31. package/build/esm/index.js.map +1 -1
  32. package/build/stats-html.html +1 -1
  33. package/build/stats-react.json +582 -431
  34. package/build/types/RouterProvider.d.ts +2 -13
  35. package/build/types/index.d.ts +4 -1
  36. package/build/types/router.d.ts +6 -5
  37. package/build/types/routerContext.d.ts +3 -0
  38. package/build/types/useRouteContext.d.ts +7 -0
  39. package/build/types/useRouter.d.ts +5 -0
  40. package/build/types/useRouterState.d.ts +6 -0
  41. package/build/types/utils.d.ts +0 -6
  42. package/build/umd/index.development.js +367 -363
  43. package/build/umd/index.development.js.map +1 -1
  44. package/build/umd/index.production.js +1 -1
  45. package/build/umd/index.production.js.map +1 -1
  46. package/package.json +2 -2
  47. package/src/Matches.tsx +2 -1
  48. package/src/RouterProvider.tsx +8 -60
  49. package/src/awaited.tsx +1 -1
  50. package/src/index.tsx +4 -2
  51. package/src/link.tsx +8 -7
  52. package/src/router.ts +18 -5
  53. package/src/routerContext.tsx +11 -0
  54. package/src/scroll-restoration.tsx +1 -1
  55. package/src/useBlocker.tsx +1 -1
  56. package/src/useNavigate.tsx +1 -1
  57. package/src/useParams.tsx +1 -1
  58. package/src/useRouteContext.ts +24 -0
  59. package/src/useRouter.tsx +20 -0
  60. package/src/useRouterState.tsx +17 -0
  61. package/src/utils.ts +0 -24
@@ -18,6 +18,69 @@ import * as React from 'react';
18
18
  import { useStore } from '@tanstack/react-store';
19
19
  import { Store } from '@tanstack/store';
20
20
 
21
+ let routerContext = /*#__PURE__*/React.createContext(null);
22
+ if (typeof document !== 'undefined') {
23
+ if (window.__TSR_ROUTER_CONTEXT__) {
24
+ routerContext = window.__TSR_ROUTER_CONTEXT__;
25
+ } else {
26
+ window.__TSR_ROUTER_CONTEXT__ = routerContext;
27
+ }
28
+ }
29
+
30
+ function useRouter(opts) {
31
+ const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || routerContext : routerContext;
32
+ const value = React.useContext(resolvedContext);
33
+ warning(!((opts?.warn ?? true) && !value), 'useRouter must be used inside a <RouterProvider> component!');
34
+ return value;
35
+ }
36
+
37
+ function defer(_promise) {
38
+ const promise = _promise;
39
+ if (!promise.__deferredState) {
40
+ promise.__deferredState = {
41
+ uid: Math.random().toString(36).slice(2),
42
+ status: 'pending'
43
+ };
44
+ const state = promise.__deferredState;
45
+ promise.then(data => {
46
+ state.status = 'success';
47
+ state.data = data;
48
+ }).catch(error => {
49
+ state.status = 'error';
50
+ state.error = error;
51
+ });
52
+ }
53
+ return promise;
54
+ }
55
+ function isDehydratedDeferred(obj) {
56
+ return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
57
+ }
58
+
59
+ function useAwaited({
60
+ promise
61
+ }) {
62
+ const router = useRouter();
63
+ let state = promise.__deferredState;
64
+ const key = `__TSR__DEFERRED__${state.uid}`;
65
+ if (isDehydratedDeferred(promise)) {
66
+ state = router.hydrateData(key);
67
+ promise = Promise.resolve(state.data);
68
+ promise.__deferredState = state;
69
+ }
70
+ if (state.status === 'pending') {
71
+ throw promise;
72
+ }
73
+ if (state.status === 'error') {
74
+ throw state.error;
75
+ }
76
+ router.dehydrateData(key, state);
77
+ return [state.data];
78
+ }
79
+ function Await(props) {
80
+ const awaited = useAwaited(props);
81
+ return props.children(...awaited);
82
+ }
83
+
21
84
  function CatchBoundary(props) {
22
85
  const errorComponent = props.errorComponent ?? ErrorComponent;
23
86
  return /*#__PURE__*/React.createElement(CatchBoundaryImpl, {
@@ -109,6 +172,13 @@ function ErrorComponent({
109
172
  }, error.message ? /*#__PURE__*/React.createElement("code", null, error.message) : null)) : null);
110
173
  }
111
174
 
175
+ function useRouterState(opts) {
176
+ const contextRouter = useRouter({
177
+ warn: opts?.router === undefined
178
+ });
179
+ return useStore((opts?.router || contextRouter).__store, opts?.select);
180
+ }
181
+
112
182
  // from https://stackoverflow.com/a/76458160
113
183
 
114
184
  // export type Expand<T> = T
@@ -301,12 +371,6 @@ function shallow(objA, objB) {
301
371
  }
302
372
  return true;
303
373
  }
304
- function useRouteContext(opts) {
305
- return useMatch({
306
- ...opts,
307
- select: match => opts?.select ? opts.select(match.context) : match.context
308
- });
309
- }
310
374
  const useLayoutEffect$1 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
311
375
  function escapeJSON(jsonString) {
312
376
  return jsonString.replace(/\\/g, '\\\\') // Escape backslashes
@@ -501,188 +565,6 @@ function useLoaderData(opts) {
501
565
  });
502
566
  }
503
567
 
504
- const useTransition = React.useTransition || (() => [false, cb => {
505
- cb();
506
- }]);
507
- let routerContext = /*#__PURE__*/React.createContext(null);
508
- if (typeof document !== 'undefined') {
509
- if (window.__TSR_ROUTER_CONTEXT__) {
510
- routerContext = window.__TSR_ROUTER_CONTEXT__;
511
- } else {
512
- window.__TSR_ROUTER_CONTEXT__ = routerContext;
513
- }
514
- }
515
- function RouterProvider({
516
- router,
517
- ...rest
518
- }) {
519
- // Allow the router to update options on the router instance
520
- router.update({
521
- ...router.options,
522
- ...rest,
523
- context: {
524
- ...router.options.context,
525
- ...rest?.context
526
- }
527
- });
528
- const matches = router.options.InnerWrap ? /*#__PURE__*/React.createElement(router.options.InnerWrap, null, /*#__PURE__*/React.createElement(Matches, null)) : /*#__PURE__*/React.createElement(Matches, null);
529
- const provider = /*#__PURE__*/React.createElement(routerContext.Provider, {
530
- value: router
531
- }, matches, /*#__PURE__*/React.createElement(Transitioner, null));
532
- if (router.options.Wrap) {
533
- return /*#__PURE__*/React.createElement(router.options.Wrap, null, provider);
534
- }
535
- return provider;
536
- }
537
- function Transitioner() {
538
- const mountLoadCount = React.useRef(0);
539
- const router = useRouter();
540
- const routerState = useRouterState({
541
- select: s => pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning'])
542
- });
543
- const [isTransitioning, startReactTransition] = useTransition();
544
- router.startReactTransition = startReactTransition;
545
- React.useEffect(() => {
546
- if (isTransitioning) {
547
- router.__store.setState(s => ({
548
- ...s,
549
- isTransitioning
550
- }));
551
- }
552
- }, [isTransitioning]);
553
- const tryLoad = () => {
554
- const apply = cb => {
555
- if (!routerState.isTransitioning) {
556
- startReactTransition(() => cb());
557
- } else {
558
- cb();
559
- }
560
- };
561
- apply(() => {
562
- try {
563
- router.load();
564
- } catch (err) {
565
- console.error(err);
566
- }
567
- });
568
- };
569
- useLayoutEffect$1(() => {
570
- const unsub = router.history.subscribe(() => {
571
- router.latestLocation = router.parseLocation(router.latestLocation);
572
- if (routerState.location !== router.latestLocation) {
573
- tryLoad();
574
- }
575
- });
576
- const nextLocation = router.buildLocation({
577
- search: true,
578
- params: true,
579
- hash: true,
580
- state: true
581
- });
582
- if (routerState.location.href !== nextLocation.href) {
583
- router.commitLocation({
584
- ...nextLocation,
585
- replace: true
586
- });
587
- }
588
- return () => {
589
- unsub();
590
- };
591
- }, [router.history]);
592
- useLayoutEffect$1(() => {
593
- if (React.useTransition ? routerState.isTransitioning && !isTransitioning : !routerState.isLoading && routerState.resolvedLocation !== routerState.location) {
594
- router.emit({
595
- type: 'onResolved',
596
- fromLocation: routerState.resolvedLocation,
597
- toLocation: routerState.location,
598
- pathChanged: routerState.location.href !== routerState.resolvedLocation?.href
599
- });
600
- if (document.querySelector) {
601
- if (routerState.location.hash !== '') {
602
- const el = document.getElementById(routerState.location.hash);
603
- if (el) {
604
- el.scrollIntoView();
605
- }
606
- }
607
- }
608
- router.__store.setState(s => ({
609
- ...s,
610
- isTransitioning: false,
611
- resolvedLocation: s.location
612
- }));
613
- }
614
- }, [routerState.isTransitioning, isTransitioning, routerState.isLoading, routerState.resolvedLocation, routerState.location]);
615
- useLayoutEffect$1(() => {
616
- if (!window.__TSR_DEHYDRATED__ && !mountLoadCount.current) {
617
- mountLoadCount.current++;
618
- tryLoad();
619
- }
620
- }, []);
621
- return null;
622
- }
623
- function getRouteMatch(state, id) {
624
- return [...state.cachedMatches, ...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
625
- }
626
- function useRouterState(opts) {
627
- const contextRouter = useRouter({
628
- warn: opts?.router === undefined
629
- });
630
- return useStore((opts?.router || contextRouter).__store, opts?.select);
631
- }
632
- function useRouter(opts) {
633
- const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || routerContext : routerContext;
634
- const value = React.useContext(resolvedContext);
635
- warning(!((opts?.warn ?? true) && !value), 'useRouter must be used inside a <RouterProvider> component!');
636
- return value;
637
- }
638
-
639
- function defer(_promise) {
640
- const promise = _promise;
641
- if (!promise.__deferredState) {
642
- promise.__deferredState = {
643
- uid: Math.random().toString(36).slice(2),
644
- status: 'pending'
645
- };
646
- const state = promise.__deferredState;
647
- promise.then(data => {
648
- state.status = 'success';
649
- state.data = data;
650
- }).catch(error => {
651
- state.status = 'error';
652
- state.error = error;
653
- });
654
- }
655
- return promise;
656
- }
657
- function isDehydratedDeferred(obj) {
658
- return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
659
- }
660
-
661
- function useAwaited({
662
- promise
663
- }) {
664
- const router = useRouter();
665
- let state = promise.__deferredState;
666
- const key = `__TSR__DEFERRED__${state.uid}`;
667
- if (isDehydratedDeferred(promise)) {
668
- state = router.hydrateData(key);
669
- promise = Promise.resolve(state.data);
670
- promise.__deferredState = state;
671
- }
672
- if (state.status === 'pending') {
673
- throw promise;
674
- }
675
- if (state.status === 'error') {
676
- throw state.error;
677
- }
678
- router.dehydrateData(key, state);
679
- return [state.data];
680
- }
681
- function Await(props) {
682
- const awaited = useAwaited(props);
683
- return props.children(...awaited);
684
- }
685
-
686
568
  function joinPaths(paths) {
687
569
  return cleanPath(paths.filter(Boolean).join('/'));
688
570
  }
@@ -1512,6 +1394,121 @@ function stringifySearchWith(stringify, parser) {
1512
1394
  };
1513
1395
  }
1514
1396
 
1397
+ const useTransition = React.useTransition || (() => [false, cb => {
1398
+ cb();
1399
+ }]);
1400
+ function RouterProvider({
1401
+ router,
1402
+ ...rest
1403
+ }) {
1404
+ // Allow the router to update options on the router instance
1405
+ router.update({
1406
+ ...router.options,
1407
+ ...rest,
1408
+ context: {
1409
+ ...router.options.context,
1410
+ ...rest?.context
1411
+ }
1412
+ });
1413
+ const matches = router.options.InnerWrap ? /*#__PURE__*/React.createElement(router.options.InnerWrap, null, /*#__PURE__*/React.createElement(Matches, null)) : /*#__PURE__*/React.createElement(Matches, null);
1414
+ const provider = /*#__PURE__*/React.createElement(routerContext.Provider, {
1415
+ value: router
1416
+ }, matches, /*#__PURE__*/React.createElement(Transitioner, null));
1417
+ if (router.options.Wrap) {
1418
+ return /*#__PURE__*/React.createElement(router.options.Wrap, null, provider);
1419
+ }
1420
+ return provider;
1421
+ }
1422
+ function Transitioner() {
1423
+ const mountLoadCount = React.useRef(0);
1424
+ const router = useRouter();
1425
+ const routerState = useRouterState({
1426
+ select: s => pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning'])
1427
+ });
1428
+ const [isTransitioning, startReactTransition] = useTransition();
1429
+ router.startReactTransition = startReactTransition;
1430
+ React.useEffect(() => {
1431
+ if (isTransitioning) {
1432
+ router.__store.setState(s => ({
1433
+ ...s,
1434
+ isTransitioning
1435
+ }));
1436
+ }
1437
+ }, [isTransitioning]);
1438
+ const tryLoad = () => {
1439
+ const apply = cb => {
1440
+ if (!routerState.isTransitioning) {
1441
+ startReactTransition(() => cb());
1442
+ } else {
1443
+ cb();
1444
+ }
1445
+ };
1446
+ apply(() => {
1447
+ try {
1448
+ router.load();
1449
+ } catch (err) {
1450
+ console.error(err);
1451
+ }
1452
+ });
1453
+ };
1454
+ useLayoutEffect$1(() => {
1455
+ const unsub = router.history.subscribe(() => {
1456
+ router.latestLocation = router.parseLocation(router.latestLocation);
1457
+ if (routerState.location !== router.latestLocation) {
1458
+ tryLoad();
1459
+ }
1460
+ });
1461
+ const nextLocation = router.buildLocation({
1462
+ search: true,
1463
+ params: true,
1464
+ hash: true,
1465
+ state: true
1466
+ });
1467
+ if (routerState.location.href !== nextLocation.href) {
1468
+ router.commitLocation({
1469
+ ...nextLocation,
1470
+ replace: true
1471
+ });
1472
+ }
1473
+ return () => {
1474
+ unsub();
1475
+ };
1476
+ }, [router.history]);
1477
+ useLayoutEffect$1(() => {
1478
+ if (React.useTransition ? routerState.isTransitioning && !isTransitioning : !routerState.isLoading && routerState.resolvedLocation !== routerState.location) {
1479
+ router.emit({
1480
+ type: 'onResolved',
1481
+ fromLocation: routerState.resolvedLocation,
1482
+ toLocation: routerState.location,
1483
+ pathChanged: routerState.location.href !== routerState.resolvedLocation?.href
1484
+ });
1485
+ if (document.querySelector) {
1486
+ if (routerState.location.hash !== '') {
1487
+ const el = document.getElementById(routerState.location.hash);
1488
+ if (el) {
1489
+ el.scrollIntoView();
1490
+ }
1491
+ }
1492
+ }
1493
+ router.__store.setState(s => ({
1494
+ ...s,
1495
+ isTransitioning: false,
1496
+ resolvedLocation: s.location
1497
+ }));
1498
+ }
1499
+ }, [routerState.isTransitioning, isTransitioning, routerState.isLoading, routerState.resolvedLocation, routerState.location]);
1500
+ useLayoutEffect$1(() => {
1501
+ if (!window.__TSR_DEHYDRATED__ && !mountLoadCount.current) {
1502
+ mountLoadCount.current++;
1503
+ tryLoad();
1504
+ }
1505
+ }, []);
1506
+ return null;
1507
+ }
1508
+ function getRouteMatch(state, id) {
1509
+ return [...state.cachedMatches, ...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
1510
+ }
1511
+
1515
1512
  // import warning from 'tiny-warning'
1516
1513
 
1517
1514
  //
@@ -2807,5 +2804,12 @@ function Navigate(props) {
2807
2804
  return null;
2808
2805
  }
2809
2806
 
2807
+ function useRouteContext(opts) {
2808
+ return useMatch({
2809
+ ...opts,
2810
+ select: match => opts?.select ? opts.select(match.context) : match.context
2811
+ });
2812
+ }
2813
+
2810
2814
  export { Await, Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, FileRouteLoader, Link, Match, MatchRoute, Matches, Navigate, NotFoundRoute, Outlet, PathParamError, RootRoute, Route, RouteApi, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, deepEqual, defaultParseSearch, defaultStringifySearch, defer, encode, escapeJSON, functionalUpdate, getInitialRouterState, getRenderedMatches, getRouteMatch, interpolatePath, isDehydratedDeferred, isPlainArray, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchContext, matchPathname, parsePathname, parseSearchWith, pick, redirect, removeBasepath, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, useAwaited, useBlocker, useElementScrollRestoration, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useLoaderDeps, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useParentMatches, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
2811
2815
  //# sourceMappingURL=index.js.map