@tanstack/react-router-devtools 0.0.1-alpha.5 → 0.0.1-alpha.7
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/build/cjs/packages/react-router-devtools/src/devtools.js +38 -46
- package/build/cjs/packages/react-router-devtools/src/devtools.js.map +1 -1
- package/build/cjs/packages/react-router-devtools/src/utils.js +36 -0
- package/build/cjs/packages/react-router-devtools/src/utils.js.map +1 -1
- package/build/esm/index.js +74 -47
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +2677 -2677
- package/build/types/index.d.ts +4 -3
- package/build/umd/index.development.js +73 -46
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/devtools.tsx +171 -189
- package/src/utils.ts +30 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router-devtools",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "0.0.1-alpha.
|
|
4
|
+
"version": "0.0.1-alpha.7",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://react-router.tanstack.com/",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"src"
|
|
36
36
|
],
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@tanstack/react-router": "0.0.1-alpha.
|
|
38
|
+
"@tanstack/react-router": "0.0.1-alpha.7",
|
|
39
39
|
"react": ">=16",
|
|
40
40
|
"react-dom": ">=16"
|
|
41
41
|
},
|
package/src/devtools.tsx
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { Router,
|
|
2
|
+
import { Router, last } from '@tanstack/react-router'
|
|
3
3
|
import { formatDistanceStrict } from 'date-fns'
|
|
4
4
|
|
|
5
5
|
import useLocalStorage from './useLocalStorage'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
getStatusColor,
|
|
8
|
+
multiSortBy,
|
|
9
|
+
useIsMounted,
|
|
10
|
+
useSafeState,
|
|
11
|
+
} from './utils'
|
|
7
12
|
import { Panel, Button, Code, ActivePanel } from './styledComponents'
|
|
8
13
|
import { ThemeProvider, defaultTheme as theme } from './theme'
|
|
9
14
|
// import { getQueryStatusLabel, getQueryStatusColor } from './utils'
|
|
@@ -52,7 +57,7 @@ interface DevtoolsOptions {
|
|
|
52
57
|
/**
|
|
53
58
|
* A boolean variable indicating if the "lite" version of the library is being used
|
|
54
59
|
*/
|
|
55
|
-
|
|
60
|
+
router: Router<any, any>
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
interface DevtoolsPanelOptions {
|
|
@@ -79,7 +84,7 @@ interface DevtoolsPanelOptions {
|
|
|
79
84
|
/**
|
|
80
85
|
* A boolean variable indicating if the "lite" version of the library is being used
|
|
81
86
|
*/
|
|
82
|
-
|
|
87
|
+
router: Router<any, any>
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
const isServer = typeof window === 'undefined'
|
|
@@ -91,7 +96,7 @@ export function TanStackRouterDevtools({
|
|
|
91
96
|
toggleButtonProps = {},
|
|
92
97
|
position = 'bottom-left',
|
|
93
98
|
containerElement: Container = 'footer',
|
|
94
|
-
|
|
99
|
+
router,
|
|
95
100
|
}: DevtoolsOptions): React.ReactElement | null {
|
|
96
101
|
const rootRef = React.useRef<HTMLDivElement>(null)
|
|
97
102
|
const panelRef = React.useRef<HTMLDivElement>(null)
|
|
@@ -230,7 +235,7 @@ export function TanStackRouterDevtools({
|
|
|
230
235
|
<TanStackRouterDevtoolsPanel
|
|
231
236
|
ref={panelRef as any}
|
|
232
237
|
{...otherPanelProps}
|
|
233
|
-
|
|
238
|
+
router={router}
|
|
234
239
|
style={{
|
|
235
240
|
position: 'fixed',
|
|
236
241
|
bottom: '0',
|
|
@@ -360,42 +365,15 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
360
365
|
isOpen = true,
|
|
361
366
|
setIsOpen,
|
|
362
367
|
handleDragStart,
|
|
363
|
-
|
|
368
|
+
router,
|
|
364
369
|
...panelProps
|
|
365
370
|
} = props
|
|
366
371
|
|
|
367
|
-
const router = useRouter() as Router
|
|
368
|
-
const routerExplorerValue = React.useMemo(() => {
|
|
369
|
-
const {
|
|
370
|
-
listeners,
|
|
371
|
-
buildLocation,
|
|
372
|
-
mount,
|
|
373
|
-
update,
|
|
374
|
-
buildNext,
|
|
375
|
-
navigate,
|
|
376
|
-
cancelMatches,
|
|
377
|
-
loadLocation,
|
|
378
|
-
cleanPreloadCache,
|
|
379
|
-
loadRoute,
|
|
380
|
-
matchRoutes,
|
|
381
|
-
loadMatches,
|
|
382
|
-
invalidateRoute,
|
|
383
|
-
resolvePath,
|
|
384
|
-
matchRoute,
|
|
385
|
-
buildLink,
|
|
386
|
-
__experimental__createSnapshot,
|
|
387
|
-
destroy,
|
|
388
|
-
...rest
|
|
389
|
-
} = router
|
|
390
|
-
|
|
391
|
-
return rest
|
|
392
|
-
}, [router.state])
|
|
393
|
-
|
|
394
372
|
const rerender = React.useReducer(() => ({}), {})[1]
|
|
395
373
|
|
|
396
374
|
React.useEffect(() => {
|
|
397
375
|
let interval = setInterval(() => {
|
|
398
|
-
router.
|
|
376
|
+
router.cleanMatchCache()
|
|
399
377
|
// router.notify()
|
|
400
378
|
rerender()
|
|
401
379
|
}, 250)
|
|
@@ -410,30 +388,29 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
410
388
|
'',
|
|
411
389
|
)
|
|
412
390
|
|
|
413
|
-
const
|
|
414
|
-
|
|
391
|
+
const [activeMatchId, setActiveMatchId] = useLocalStorage(
|
|
392
|
+
'tanstackRouterDevtoolsActiveMatchId',
|
|
393
|
+
'',
|
|
415
394
|
)
|
|
416
395
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return rest
|
|
436
|
-
}, [activeMatch])
|
|
396
|
+
React.useEffect(() => {
|
|
397
|
+
setActiveMatchId('')
|
|
398
|
+
}, [activeRouteId])
|
|
399
|
+
|
|
400
|
+
const activeMatch =
|
|
401
|
+
Object.values(router.matchCache)?.find(
|
|
402
|
+
(d) => d.match.matchId === activeMatchId,
|
|
403
|
+
)?.match ?? router.state.matches?.find((d) => d.routeId === activeRouteId)
|
|
404
|
+
|
|
405
|
+
const matchCacheValues = multiSortBy(
|
|
406
|
+
Object.keys(router.matchCache)
|
|
407
|
+
.filter((key) => {
|
|
408
|
+
const cacheEntry = router.matchCache[key]!
|
|
409
|
+
return cacheEntry.gc > Date.now()
|
|
410
|
+
})
|
|
411
|
+
.map((key) => router.matchCache[key]!),
|
|
412
|
+
[(d) => (d.match.isFetching ? -1 : 1), (d) => -d.match.updatedAt!],
|
|
413
|
+
)
|
|
437
414
|
|
|
438
415
|
return (
|
|
439
416
|
<ThemeProvider theme={theme}>
|
|
@@ -552,11 +529,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
552
529
|
padding: '.5em',
|
|
553
530
|
}}
|
|
554
531
|
>
|
|
555
|
-
<Explorer
|
|
556
|
-
label="Router"
|
|
557
|
-
value={routerExplorerValue}
|
|
558
|
-
defaultExpanded={{}}
|
|
559
|
-
/>
|
|
532
|
+
<Explorer label="Router" value={router} defaultExpanded={{}} />
|
|
560
533
|
</div>
|
|
561
534
|
</div>
|
|
562
535
|
</div>
|
|
@@ -580,7 +553,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
580
553
|
zIndex: 1,
|
|
581
554
|
}}
|
|
582
555
|
>
|
|
583
|
-
|
|
556
|
+
Active Matches
|
|
584
557
|
</div>
|
|
585
558
|
{router.state.matches.map((match, i) => {
|
|
586
559
|
return (
|
|
@@ -627,153 +600,162 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
627
600
|
</div>
|
|
628
601
|
)
|
|
629
602
|
})}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
marginTop: '2rem',
|
|
633
|
-
padding: '.5em',
|
|
634
|
-
background: theme.backgroundAlt,
|
|
635
|
-
position: 'sticky',
|
|
636
|
-
top: 0,
|
|
637
|
-
zIndex: 1,
|
|
638
|
-
}}
|
|
639
|
-
>
|
|
640
|
-
Pending Matches
|
|
641
|
-
</div>
|
|
642
|
-
{router.state.pending?.matches.map((match, i) => {
|
|
643
|
-
return (
|
|
603
|
+
{router.state.pending?.matches.length ? (
|
|
604
|
+
<>
|
|
644
605
|
<div
|
|
645
|
-
key={match.routeId || i}
|
|
646
|
-
role="button"
|
|
647
|
-
aria-label={`Open match details for ${match.routeId}`}
|
|
648
|
-
onClick={() =>
|
|
649
|
-
setActiveRouteId(
|
|
650
|
-
activeRouteId === match.routeId ? '' : match.routeId,
|
|
651
|
-
)
|
|
652
|
-
}
|
|
653
606
|
style={{
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
607
|
+
marginTop: '2rem',
|
|
608
|
+
padding: '.5em',
|
|
609
|
+
background: theme.backgroundAlt,
|
|
610
|
+
position: 'sticky',
|
|
611
|
+
top: 0,
|
|
612
|
+
zIndex: 1,
|
|
659
613
|
}}
|
|
660
614
|
>
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
615
|
+
Pending Matches
|
|
616
|
+
</div>
|
|
617
|
+
{router.state.pending?.matches.map((match, i) => {
|
|
618
|
+
return (
|
|
619
|
+
<div
|
|
620
|
+
key={match.routeId || i}
|
|
621
|
+
role="button"
|
|
622
|
+
aria-label={`Open match details for ${match.routeId}`}
|
|
623
|
+
onClick={() =>
|
|
624
|
+
setActiveRouteId(
|
|
625
|
+
activeRouteId === match.routeId ? '' : match.routeId,
|
|
626
|
+
)
|
|
627
|
+
}
|
|
628
|
+
style={{
|
|
629
|
+
display: 'flex',
|
|
630
|
+
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
631
|
+
cursor: 'pointer',
|
|
632
|
+
background:
|
|
633
|
+
match === activeMatch
|
|
634
|
+
? 'rgba(255,255,255,.1)'
|
|
635
|
+
: undefined,
|
|
636
|
+
}}
|
|
637
|
+
>
|
|
638
|
+
<div
|
|
639
|
+
style={{
|
|
640
|
+
flex: '0 0 auto',
|
|
641
|
+
width: '1.3rem',
|
|
642
|
+
height: '1.3rem',
|
|
643
|
+
marginLeft: '.25rem',
|
|
644
|
+
background: getStatusColor(match, theme),
|
|
645
|
+
alignItems: 'center',
|
|
646
|
+
justifyContent: 'center',
|
|
647
|
+
fontWeight: 'bold',
|
|
648
|
+
borderRadius: '.25rem',
|
|
649
|
+
transition: 'all .2s ease-out',
|
|
650
|
+
}}
|
|
651
|
+
/>
|
|
675
652
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
653
|
+
<Code
|
|
654
|
+
style={{
|
|
655
|
+
padding: '.5em',
|
|
656
|
+
}}
|
|
657
|
+
>
|
|
658
|
+
{`${match.matchId}`}
|
|
659
|
+
</Code>
|
|
660
|
+
</div>
|
|
661
|
+
)
|
|
662
|
+
})}
|
|
663
|
+
</>
|
|
664
|
+
) : null}
|
|
665
|
+
{matchCacheValues.length ? (
|
|
666
|
+
<>
|
|
667
|
+
<div
|
|
668
|
+
style={{
|
|
669
|
+
marginTop: '2rem',
|
|
670
|
+
padding: '.5em',
|
|
671
|
+
background: theme.backgroundAlt,
|
|
672
|
+
position: 'sticky',
|
|
673
|
+
top: 0,
|
|
674
|
+
zIndex: 1,
|
|
675
|
+
display: 'flex',
|
|
676
|
+
alignItems: 'center',
|
|
677
|
+
justifyContent: 'space-between',
|
|
678
|
+
}}
|
|
679
|
+
>
|
|
680
|
+
<div>Match Cache</div>
|
|
681
|
+
<Button
|
|
682
|
+
onClick={() => {
|
|
683
|
+
router.matchCache = {}
|
|
684
|
+
router.notify()
|
|
679
685
|
}}
|
|
680
686
|
>
|
|
681
|
-
|
|
682
|
-
</
|
|
687
|
+
Clear
|
|
688
|
+
</Button>
|
|
683
689
|
</div>
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
marginTop: '2rem',
|
|
689
|
-
padding: '.5em',
|
|
690
|
-
background: theme.backgroundAlt,
|
|
691
|
-
position: 'sticky',
|
|
692
|
-
top: 0,
|
|
693
|
-
zIndex: 1,
|
|
694
|
-
}}
|
|
695
|
-
>
|
|
696
|
-
Preloading Matches
|
|
697
|
-
</div>
|
|
698
|
-
{Object.keys(router.preloadCache)
|
|
699
|
-
.filter((key) => {
|
|
700
|
-
const cacheEntry = router.preloadCache[key]!
|
|
701
|
-
return (
|
|
702
|
-
(cacheEntry.match.updatedAt ?? Date.now()) + cacheEntry.maxAge >
|
|
703
|
-
Date.now()
|
|
704
|
-
)
|
|
705
|
-
})
|
|
706
|
-
.map((key, i) => {
|
|
707
|
-
const { match, maxAge } = router.preloadCache[key]!
|
|
708
|
-
|
|
709
|
-
return (
|
|
710
|
-
<div
|
|
711
|
-
key={match.matchId || i}
|
|
712
|
-
role="button"
|
|
713
|
-
aria-label={`Open match details for ${match.matchId}`}
|
|
714
|
-
onClick={() =>
|
|
715
|
-
setActiveRouteId(
|
|
716
|
-
activeRouteId === match.routeId ? '' : match.routeId,
|
|
717
|
-
)
|
|
718
|
-
}
|
|
719
|
-
style={{
|
|
720
|
-
display: 'flex',
|
|
721
|
-
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
722
|
-
cursor: 'pointer',
|
|
723
|
-
background:
|
|
724
|
-
match === activeMatch
|
|
725
|
-
? 'rgba(255,255,255,.1)'
|
|
726
|
-
: undefined,
|
|
727
|
-
}}
|
|
728
|
-
>
|
|
690
|
+
{matchCacheValues.map((d, i) => {
|
|
691
|
+
const { match, gc } = d
|
|
692
|
+
|
|
693
|
+
return (
|
|
729
694
|
<div
|
|
695
|
+
key={match.matchId || i}
|
|
696
|
+
role="button"
|
|
697
|
+
aria-label={`Open match details for ${match.matchId}`}
|
|
698
|
+
onClick={() =>
|
|
699
|
+
setActiveMatchId(
|
|
700
|
+
activeMatchId === match.matchId ? '' : match.matchId,
|
|
701
|
+
)
|
|
702
|
+
}
|
|
730
703
|
style={{
|
|
731
704
|
display: 'flex',
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
705
|
+
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
706
|
+
cursor: 'pointer',
|
|
707
|
+
background:
|
|
708
|
+
match === activeMatch
|
|
709
|
+
? 'rgba(255,255,255,.1)'
|
|
710
|
+
: undefined,
|
|
735
711
|
}}
|
|
736
712
|
>
|
|
737
713
|
<div
|
|
738
714
|
style={{
|
|
739
715
|
display: 'flex',
|
|
740
|
-
|
|
741
|
-
|
|
716
|
+
flexDirection: 'column',
|
|
717
|
+
padding: '.5rem',
|
|
718
|
+
gap: '.3rem',
|
|
742
719
|
}}
|
|
743
720
|
>
|
|
744
721
|
<div
|
|
745
722
|
style={{
|
|
746
|
-
|
|
747
|
-
width: '1.3rem',
|
|
748
|
-
height: '1.3rem',
|
|
749
|
-
background: getStatusColor(match, theme),
|
|
723
|
+
display: 'flex',
|
|
750
724
|
alignItems: 'center',
|
|
751
|
-
|
|
752
|
-
fontWeight: 'bold',
|
|
753
|
-
borderRadius: '.25rem',
|
|
754
|
-
transition: 'all .2s ease-out',
|
|
725
|
+
gap: '.5rem',
|
|
755
726
|
}}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
727
|
+
>
|
|
728
|
+
<div
|
|
729
|
+
style={{
|
|
730
|
+
flex: '0 0 auto',
|
|
731
|
+
width: '1.3rem',
|
|
732
|
+
height: '1.3rem',
|
|
733
|
+
background: getStatusColor(match, theme),
|
|
734
|
+
alignItems: 'center',
|
|
735
|
+
justifyContent: 'center',
|
|
736
|
+
fontWeight: 'bold',
|
|
737
|
+
borderRadius: '.25rem',
|
|
738
|
+
transition: 'all .2s ease-out',
|
|
739
|
+
}}
|
|
740
|
+
/>
|
|
741
|
+
<Code>{`${match.matchId}`}</Code>
|
|
742
|
+
</div>
|
|
743
|
+
<span
|
|
744
|
+
style={{
|
|
745
|
+
opacity: '.5',
|
|
746
|
+
}}
|
|
747
|
+
>
|
|
748
|
+
Expires{' '}
|
|
749
|
+
{formatDistanceStrict(new Date(), new Date(gc), {
|
|
769
750
|
addSuffix: true,
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
</
|
|
751
|
+
})}
|
|
752
|
+
</span>
|
|
753
|
+
</div>
|
|
773
754
|
</div>
|
|
774
|
-
|
|
775
|
-
)
|
|
776
|
-
|
|
755
|
+
)
|
|
756
|
+
})}
|
|
757
|
+
</>
|
|
758
|
+
) : null}
|
|
777
759
|
</div>
|
|
778
760
|
|
|
779
761
|
{activeMatch ? (
|
|
@@ -848,7 +830,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
848
830
|
<Button
|
|
849
831
|
type="button"
|
|
850
832
|
onClick={() => {
|
|
851
|
-
|
|
833
|
+
activeMatch.invalidate()
|
|
852
834
|
router.notify()
|
|
853
835
|
}}
|
|
854
836
|
style={{
|
|
@@ -860,7 +842,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
860
842
|
</Button>{' '}
|
|
861
843
|
<Button
|
|
862
844
|
type="button"
|
|
863
|
-
onClick={() =>
|
|
845
|
+
onClick={() => activeMatch.load()}
|
|
864
846
|
style={{
|
|
865
847
|
background: theme.gray,
|
|
866
848
|
}}
|
|
@@ -886,7 +868,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
886
868
|
>
|
|
887
869
|
<Explorer
|
|
888
870
|
label="Match"
|
|
889
|
-
value={
|
|
871
|
+
value={activeMatch}
|
|
890
872
|
defaultExpanded={{}}
|
|
891
873
|
/>
|
|
892
874
|
</div>
|
package/src/utils.ts
CHANGED
|
@@ -149,3 +149,33 @@ function scheduleMicrotask(callback: () => void) {
|
|
|
149
149
|
}),
|
|
150
150
|
)
|
|
151
151
|
}
|
|
152
|
+
|
|
153
|
+
export function multiSortBy<T>(
|
|
154
|
+
arr: T[],
|
|
155
|
+
accessors: ((item: T) => any)[] = [(d) => d],
|
|
156
|
+
): T[] {
|
|
157
|
+
return arr
|
|
158
|
+
.map((d, i) => [d, i] as const)
|
|
159
|
+
.sort(([a, ai], [b, bi]) => {
|
|
160
|
+
for (const accessor of accessors) {
|
|
161
|
+
const ao = accessor(a)
|
|
162
|
+
const bo = accessor(b)
|
|
163
|
+
|
|
164
|
+
if (typeof ao === 'undefined') {
|
|
165
|
+
if (typeof bo === 'undefined') {
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
return 1
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (ao === bo) {
|
|
172
|
+
continue
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return ao > bo ? 1 : -1
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return ai - bi
|
|
179
|
+
})
|
|
180
|
+
.map(([d]) => d)
|
|
181
|
+
}
|