@tanstack/router-devtools 0.0.1-beta.142 → 0.0.1-beta.143

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/router-devtools",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.142",
4
+ "version": "0.0.1-beta.143",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router/",
package/src/devtools.tsx CHANGED
@@ -412,17 +412,22 @@ export function TanStackRouterDevtools({
412
412
  function RouteComp({
413
413
  route,
414
414
  isRoot,
415
- matches,
415
+ router,
416
416
  activeRouteId,
417
+ activeMatchId,
417
418
  setActiveRouteId,
419
+ setActiveMatchId,
418
420
  }: {
419
421
  route: AnyRootRoute | AnyRoute
420
422
  isRoot?: boolean
421
- matches: RouteMatch[]
423
+ router: AnyRouter
422
424
  activeRouteId: string | undefined
425
+ activeMatchId: string | undefined
423
426
  setActiveRouteId: (id: string) => void
427
+ setActiveMatchId: (id: string) => void
424
428
  }) {
425
- const match = matches.find((d) => d.routeId === route.id)
429
+ const matches = Object.values(router.state.matchesById)
430
+ const match = router.state.matches.find((d) => d.routeId === route.id)
426
431
 
427
432
  return (
428
433
  <div>
@@ -430,8 +435,10 @@ function RouteComp({
430
435
  role="button"
431
436
  aria-label={`Open match details for ${route.id}`}
432
437
  onClick={() => {
433
- if (match)
438
+ if (match) {
434
439
  setActiveRouteId(activeRouteId === route.id ? '' : route.id)
440
+ setActiveMatchId(match.id)
441
+ }
435
442
  }}
436
443
  style={{
437
444
  display: 'flex',
@@ -454,7 +461,7 @@ function RouteComp({
454
461
  fontWeight: 'bold',
455
462
  borderRadius: '100%',
456
463
  transition: 'all .2s ease-out',
457
- background: getRouteStatusColor(matches, route, theme),
464
+ background: getRouteStatusColor(matches, route, theme, router),
458
465
  opacity: match ? 1 : 0.3,
459
466
  }}
460
467
  />
@@ -467,6 +474,7 @@ function RouteComp({
467
474
  padding: '.25rem .5rem .25rem 0',
468
475
  paddingLeft: isRoot ? '.5rem' : 0,
469
476
  opacity: match ? 1 : 0.7,
477
+ fontSize: '0.7rem',
470
478
  }}
471
479
  >
472
480
  <span>{route.path || trimPath(route.id)} </span>
@@ -488,9 +496,11 @@ function RouteComp({
488
496
  <RouteComp
489
497
  key={r.id}
490
498
  route={r}
491
- matches={matches}
499
+ router={router}
492
500
  activeRouteId={activeRouteId}
501
+ activeMatchId={activeMatchId}
493
502
  setActiveRouteId={setActiveRouteId}
503
+ setActiveMatchId={setActiveMatchId}
494
504
  />
495
505
  ))}
496
506
  </div>
@@ -530,16 +540,37 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
530
540
  'tanstackRouterDevtoolsActiveRouteId',
531
541
  '',
532
542
  )
533
-
534
- const allMatches: RouteMatch[] = React.useMemo(
535
- () => [...Object.values(router.state.matches)],
536
- [router.state.matches],
543
+ const [activeMatchId, setActiveMatchId] = useLocalStorage(
544
+ 'tanstackRouterDevtoolsActiveMatchId',
545
+ '',
537
546
  )
538
547
 
539
- const activeMatch = allMatches?.find((d) => d.routeId === activeRouteId)
548
+ const activeMatch = React.useMemo(
549
+ () =>
550
+ router.state.matchesById[activeRouteId as any] ||
551
+ router.state.matchesById[activeMatchId as any],
552
+ [activeRouteId, activeMatchId],
553
+ )
540
554
 
541
555
  const hasSearch = Object.keys(router.state.location.search || {}).length
542
556
 
557
+ const preloadMatches = Object.values(router.state.matchesById).filter(
558
+ (match) => {
559
+ return (
560
+ !router.state.matchIds.includes(match.id) &&
561
+ !router.state.pendingMatchIds.includes(match.id)
562
+ )
563
+ },
564
+ )
565
+
566
+ React.useEffect(() => {
567
+ const interval = setInterval(() => {
568
+ router.cleanMatches()
569
+ }, 1000)
570
+
571
+ return () => clearInterval(interval)
572
+ }, [router])
573
+
543
574
  return (
544
575
  <ThemeProvider theme={theme}>
545
576
  <Panel ref={ref} className="TanStackRouterDevtoolsPanel" {...panelProps}>
@@ -675,71 +706,152 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
675
706
  >
676
707
  <div
677
708
  style={{
678
- padding: '.5em',
679
- background: theme.backgroundAlt,
680
- position: 'sticky',
681
- top: 0,
682
- zIndex: 1,
683
- display: 'flex',
684
- alignItems: 'center',
685
- gap: '.5rem',
709
+ flex: '1 1 auto',
710
+ overflowY: 'auto',
686
711
  }}
687
712
  >
688
- <button
689
- type="button"
690
- onClick={() => {
691
- setShowMatches(false)
692
- }}
693
- disabled={!showMatches}
713
+ <div
694
714
  style={{
695
- appearance: 'none',
696
- opacity: showMatches ? 0.5 : 1,
697
- border: 0,
698
- background: 'transparent',
699
- color: 'inherit',
700
- cursor: 'pointer',
715
+ padding: '.5em',
716
+ background: theme.backgroundAlt,
717
+ position: 'sticky',
718
+ top: 0,
719
+ zIndex: 1,
720
+ display: 'flex',
721
+ alignItems: 'center',
722
+ gap: '.5rem',
701
723
  }}
702
724
  >
703
- Routes
704
- </button>
705
- /
706
- <button
707
- type="button"
708
- onClick={() => {
709
- setShowMatches(true)
710
- }}
711
- disabled={showMatches}
725
+ <button
726
+ type="button"
727
+ onClick={() => {
728
+ setShowMatches(false)
729
+ }}
730
+ disabled={!showMatches}
731
+ style={{
732
+ appearance: 'none',
733
+ opacity: showMatches ? 0.5 : 1,
734
+ border: 0,
735
+ background: 'transparent',
736
+ color: 'inherit',
737
+ cursor: 'pointer',
738
+ }}
739
+ >
740
+ Routes
741
+ </button>
742
+ /
743
+ <button
744
+ type="button"
745
+ onClick={() => {
746
+ setShowMatches(true)
747
+ }}
748
+ disabled={showMatches}
749
+ style={{
750
+ appearance: 'none',
751
+ opacity: !showMatches ? 0.5 : 1,
752
+ border: 0,
753
+ background: 'transparent',
754
+ color: 'inherit',
755
+ cursor: 'pointer',
756
+ }}
757
+ >
758
+ Matches
759
+ </button>
760
+ </div>
761
+ {!showMatches ? (
762
+ <RouteComp
763
+ route={router.routeTree}
764
+ router={router}
765
+ isRoot
766
+ activeRouteId={activeRouteId}
767
+ activeMatchId={activeMatchId}
768
+ setActiveRouteId={setActiveRouteId}
769
+ setActiveMatchId={setActiveMatchId}
770
+ />
771
+ ) : (
772
+ <div>
773
+ {router.state.matches.map((match, i) => {
774
+ return (
775
+ <div
776
+ key={match.routeId || i}
777
+ role="button"
778
+ aria-label={`Open match details for ${match.routeId}`}
779
+ onClick={() =>
780
+ setActiveRouteId(
781
+ activeRouteId === match.routeId ? '' : match.routeId,
782
+ )
783
+ }
784
+ style={{
785
+ display: 'flex',
786
+ borderBottom: `solid 1px ${theme.grayAlt}`,
787
+ cursor: 'pointer',
788
+ alignItems: 'center',
789
+ background:
790
+ match === activeMatch
791
+ ? 'rgba(255,255,255,.1)'
792
+ : undefined,
793
+ }}
794
+ >
795
+ <div
796
+ style={{
797
+ flex: '0 0 auto',
798
+ width: '1.3rem',
799
+ height: '1.3rem',
800
+ marginLeft: '.25rem',
801
+ background: getStatusColor(match, theme, router),
802
+ alignItems: 'center',
803
+ justifyContent: 'center',
804
+ fontWeight: 'bold',
805
+ borderRadius: '.25rem',
806
+ transition: 'all .2s ease-out',
807
+ }}
808
+ />
809
+
810
+ <Code
811
+ style={{
812
+ padding: '.5em',
813
+ fontSize: '0.7rem',
814
+ }}
815
+ >
816
+ {`${match.id}`}
817
+ </Code>
818
+ </div>
819
+ )
820
+ })}
821
+ </div>
822
+ )}
823
+ </div>
824
+ {preloadMatches?.length ? (
825
+ <div
712
826
  style={{
713
- appearance: 'none',
714
- opacity: !showMatches ? 0.5 : 1,
715
- border: 0,
716
- background: 'transparent',
717
- color: 'inherit',
718
- cursor: 'pointer',
827
+ flex: '1 1 auto',
828
+ overflowY: 'auto',
829
+ maxHeight: '50%',
719
830
  }}
720
831
  >
721
- Matches
722
- </button>
723
- </div>
724
- {!showMatches ? (
725
- <RouteComp
726
- route={router.routeTree}
727
- isRoot
728
- matches={allMatches}
729
- activeRouteId={activeRouteId}
730
- setActiveRouteId={setActiveRouteId}
731
- />
732
- ) : (
733
- <div>
734
- {router.state.matches.map((match, i) => {
832
+ <div
833
+ style={{
834
+ padding: '.5em',
835
+ background: theme.backgroundAlt,
836
+ position: 'sticky',
837
+ top: 0,
838
+ zIndex: 1,
839
+ display: 'flex',
840
+ alignItems: 'center',
841
+ gap: '.5rem',
842
+ }}
843
+ >
844
+ Preloaded Matches
845
+ </div>
846
+ {preloadMatches.map((match) => {
735
847
  return (
736
848
  <div
737
- key={match.routeId || i}
849
+ key={match.id}
738
850
  role="button"
739
851
  aria-label={`Open match details for ${match.routeId}`}
740
852
  onClick={() =>
741
- setActiveRouteId(
742
- activeRouteId === match.routeId ? '' : match.routeId,
853
+ setActiveMatchId(
854
+ activeMatchId === match.id ? '' : match.id,
743
855
  )
744
856
  }
745
857
  style={{
@@ -759,7 +871,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
759
871
  width: '1.3rem',
760
872
  height: '1.3rem',
761
873
  marginLeft: '.25rem',
762
- background: getStatusColor(match, theme),
874
+ background: getStatusColor(match, theme, router),
763
875
  alignItems: 'center',
764
876
  justifyContent: 'center',
765
877
  fontWeight: 'bold',
@@ -771,6 +883,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
771
883
  <Code
772
884
  style={{
773
885
  padding: '.5em',
886
+ fontSize: '0.7rem',
774
887
  }}
775
888
  >
776
889
  {`${match.id}`}
@@ -779,7 +892,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
779
892
  )
780
893
  })}
781
894
  </div>
782
- )}
895
+ ) : null}
783
896
  </div>
784
897
  {activeMatch ? (
785
898
  <ActivePanel>
package/src/utils.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import React from 'react'
2
- import { AnyRootRoute, AnyRoute, AnyRouteMatch } from '@tanstack/router'
2
+ import {
3
+ AnyRootRoute,
4
+ AnyRoute,
5
+ AnyRouteMatch,
6
+ AnyRouter,
7
+ } from '@tanstack/router'
3
8
 
4
9
  import { Theme, useTheme } from './theme'
5
10
  import useMediaQuery from './useMediaQuery'
@@ -25,9 +30,17 @@ type StyledComponent<T> = T extends 'button'
25
30
  ? React.HTMLAttributes<HTMLElementTagNameMap[T]>
26
31
  : never
27
32
 
28
- export function getStatusColor(match: AnyRouteMatch, theme: Theme) {
29
- return match.status === 'pending'
33
+ export function getStatusColor(
34
+ match: AnyRouteMatch,
35
+ theme: Theme,
36
+ router: AnyRouter,
37
+ ) {
38
+ return match.status === 'pending' || match.isFetching
30
39
  ? theme.active
40
+ : router.getIsInvalid({
41
+ matchId: match.id,
42
+ })
43
+ ? theme.warning
31
44
  : match.status === 'error'
32
45
  ? theme.danger
33
46
  : match.status === 'success'
@@ -39,18 +52,11 @@ export function getRouteStatusColor(
39
52
  matches: AnyRouteMatch[],
40
53
  route: AnyRoute | AnyRootRoute,
41
54
  theme: Theme,
55
+ router: AnyRouter,
42
56
  ) {
43
57
  const found = matches.find((d) => d.routeId === route.id)
44
-
45
- return found
46
- ? found.status === 'pending'
47
- ? theme.active
48
- : found.status === 'error'
49
- ? theme.danger
50
- : found.status === 'success'
51
- ? theme.success
52
- : theme.gray
53
- : theme.gray
58
+ if (!found) return theme.gray
59
+ return getStatusColor(found, theme, router)
54
60
  }
55
61
 
56
62
  type Styles =