@tanstack/react-router-devtools 0.0.1-alpha.6 → 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 +33 -40
- 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 +68 -40
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +2677 -2677
- package/build/umd/index.development.js +68 -40
- 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 +163 -179
- 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
|
@@ -3,7 +3,12 @@ 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'
|
|
@@ -363,37 +368,12 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
363
368
|
router,
|
|
364
369
|
...panelProps
|
|
365
370
|
} = props
|
|
366
|
-
const routerExplorerValue = React.useMemo(() => {
|
|
367
|
-
const {
|
|
368
|
-
listeners,
|
|
369
|
-
buildLocation,
|
|
370
|
-
mount,
|
|
371
|
-
update,
|
|
372
|
-
buildNext,
|
|
373
|
-
navigate,
|
|
374
|
-
cancelMatches,
|
|
375
|
-
loadLocation,
|
|
376
|
-
cleanPreloadCache,
|
|
377
|
-
loadRoute,
|
|
378
|
-
matchRoutes,
|
|
379
|
-
loadMatches,
|
|
380
|
-
invalidateRoute,
|
|
381
|
-
resolvePath,
|
|
382
|
-
matchRoute,
|
|
383
|
-
buildLink,
|
|
384
|
-
__experimental__createSnapshot,
|
|
385
|
-
destroy,
|
|
386
|
-
...rest
|
|
387
|
-
} = router
|
|
388
|
-
|
|
389
|
-
return rest
|
|
390
|
-
}, [router.state])
|
|
391
371
|
|
|
392
372
|
const rerender = React.useReducer(() => ({}), {})[1]
|
|
393
373
|
|
|
394
374
|
React.useEffect(() => {
|
|
395
375
|
let interval = setInterval(() => {
|
|
396
|
-
router.
|
|
376
|
+
router.cleanMatchCache()
|
|
397
377
|
// router.notify()
|
|
398
378
|
rerender()
|
|
399
379
|
}, 250)
|
|
@@ -408,30 +388,29 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
408
388
|
'',
|
|
409
389
|
)
|
|
410
390
|
|
|
411
|
-
const
|
|
412
|
-
|
|
391
|
+
const [activeMatchId, setActiveMatchId] = useLocalStorage(
|
|
392
|
+
'tanstackRouterDevtoolsActiveMatchId',
|
|
393
|
+
'',
|
|
413
394
|
)
|
|
414
395
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
return rest
|
|
434
|
-
}, [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
|
+
)
|
|
435
414
|
|
|
436
415
|
return (
|
|
437
416
|
<ThemeProvider theme={theme}>
|
|
@@ -550,11 +529,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
550
529
|
padding: '.5em',
|
|
551
530
|
}}
|
|
552
531
|
>
|
|
553
|
-
<Explorer
|
|
554
|
-
label="Router"
|
|
555
|
-
value={routerExplorerValue}
|
|
556
|
-
defaultExpanded={{}}
|
|
557
|
-
/>
|
|
532
|
+
<Explorer label="Router" value={router} defaultExpanded={{}} />
|
|
558
533
|
</div>
|
|
559
534
|
</div>
|
|
560
535
|
</div>
|
|
@@ -578,7 +553,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
578
553
|
zIndex: 1,
|
|
579
554
|
}}
|
|
580
555
|
>
|
|
581
|
-
|
|
556
|
+
Active Matches
|
|
582
557
|
</div>
|
|
583
558
|
{router.state.matches.map((match, i) => {
|
|
584
559
|
return (
|
|
@@ -625,153 +600,162 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
625
600
|
</div>
|
|
626
601
|
)
|
|
627
602
|
})}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
marginTop: '2rem',
|
|
631
|
-
padding: '.5em',
|
|
632
|
-
background: theme.backgroundAlt,
|
|
633
|
-
position: 'sticky',
|
|
634
|
-
top: 0,
|
|
635
|
-
zIndex: 1,
|
|
636
|
-
}}
|
|
637
|
-
>
|
|
638
|
-
Pending Matches
|
|
639
|
-
</div>
|
|
640
|
-
{router.state.pending?.matches.map((match, i) => {
|
|
641
|
-
return (
|
|
603
|
+
{router.state.pending?.matches.length ? (
|
|
604
|
+
<>
|
|
642
605
|
<div
|
|
643
|
-
key={match.routeId || i}
|
|
644
|
-
role="button"
|
|
645
|
-
aria-label={`Open match details for ${match.routeId}`}
|
|
646
|
-
onClick={() =>
|
|
647
|
-
setActiveRouteId(
|
|
648
|
-
activeRouteId === match.routeId ? '' : match.routeId,
|
|
649
|
-
)
|
|
650
|
-
}
|
|
651
606
|
style={{
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
607
|
+
marginTop: '2rem',
|
|
608
|
+
padding: '.5em',
|
|
609
|
+
background: theme.backgroundAlt,
|
|
610
|
+
position: 'sticky',
|
|
611
|
+
top: 0,
|
|
612
|
+
zIndex: 1,
|
|
657
613
|
}}
|
|
658
614
|
>
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
+
/>
|
|
673
652
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
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()
|
|
677
685
|
}}
|
|
678
686
|
>
|
|
679
|
-
|
|
680
|
-
</
|
|
687
|
+
Clear
|
|
688
|
+
</Button>
|
|
681
689
|
</div>
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
marginTop: '2rem',
|
|
687
|
-
padding: '.5em',
|
|
688
|
-
background: theme.backgroundAlt,
|
|
689
|
-
position: 'sticky',
|
|
690
|
-
top: 0,
|
|
691
|
-
zIndex: 1,
|
|
692
|
-
}}
|
|
693
|
-
>
|
|
694
|
-
Preloading Matches
|
|
695
|
-
</div>
|
|
696
|
-
{Object.keys(router.preloadCache)
|
|
697
|
-
.filter((key) => {
|
|
698
|
-
const cacheEntry = router.preloadCache[key]!
|
|
699
|
-
return (
|
|
700
|
-
(cacheEntry.match.updatedAt ?? Date.now()) + cacheEntry.maxAge >
|
|
701
|
-
Date.now()
|
|
702
|
-
)
|
|
703
|
-
})
|
|
704
|
-
.map((key, i) => {
|
|
705
|
-
const { match, maxAge } = router.preloadCache[key]!
|
|
706
|
-
|
|
707
|
-
return (
|
|
708
|
-
<div
|
|
709
|
-
key={match.matchId || i}
|
|
710
|
-
role="button"
|
|
711
|
-
aria-label={`Open match details for ${match.matchId}`}
|
|
712
|
-
onClick={() =>
|
|
713
|
-
setActiveRouteId(
|
|
714
|
-
activeRouteId === match.routeId ? '' : match.routeId,
|
|
715
|
-
)
|
|
716
|
-
}
|
|
717
|
-
style={{
|
|
718
|
-
display: 'flex',
|
|
719
|
-
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
720
|
-
cursor: 'pointer',
|
|
721
|
-
background:
|
|
722
|
-
match === activeMatch
|
|
723
|
-
? 'rgba(255,255,255,.1)'
|
|
724
|
-
: undefined,
|
|
725
|
-
}}
|
|
726
|
-
>
|
|
690
|
+
{matchCacheValues.map((d, i) => {
|
|
691
|
+
const { match, gc } = d
|
|
692
|
+
|
|
693
|
+
return (
|
|
727
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
|
+
}
|
|
728
703
|
style={{
|
|
729
704
|
display: 'flex',
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
705
|
+
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
706
|
+
cursor: 'pointer',
|
|
707
|
+
background:
|
|
708
|
+
match === activeMatch
|
|
709
|
+
? 'rgba(255,255,255,.1)'
|
|
710
|
+
: undefined,
|
|
733
711
|
}}
|
|
734
712
|
>
|
|
735
713
|
<div
|
|
736
714
|
style={{
|
|
737
715
|
display: 'flex',
|
|
738
|
-
|
|
739
|
-
|
|
716
|
+
flexDirection: 'column',
|
|
717
|
+
padding: '.5rem',
|
|
718
|
+
gap: '.3rem',
|
|
740
719
|
}}
|
|
741
720
|
>
|
|
742
721
|
<div
|
|
743
722
|
style={{
|
|
744
|
-
|
|
745
|
-
width: '1.3rem',
|
|
746
|
-
height: '1.3rem',
|
|
747
|
-
background: getStatusColor(match, theme),
|
|
723
|
+
display: 'flex',
|
|
748
724
|
alignItems: 'center',
|
|
749
|
-
|
|
750
|
-
fontWeight: 'bold',
|
|
751
|
-
borderRadius: '.25rem',
|
|
752
|
-
transition: 'all .2s ease-out',
|
|
725
|
+
gap: '.5rem',
|
|
753
726
|
}}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
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), {
|
|
767
750
|
addSuffix: true,
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
</
|
|
751
|
+
})}
|
|
752
|
+
</span>
|
|
753
|
+
</div>
|
|
771
754
|
</div>
|
|
772
|
-
|
|
773
|
-
)
|
|
774
|
-
|
|
755
|
+
)
|
|
756
|
+
})}
|
|
757
|
+
</>
|
|
758
|
+
) : null}
|
|
775
759
|
</div>
|
|
776
760
|
|
|
777
761
|
{activeMatch ? (
|
|
@@ -884,7 +868,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
884
868
|
>
|
|
885
869
|
<Explorer
|
|
886
870
|
label="Match"
|
|
887
|
-
value={
|
|
871
|
+
value={activeMatch}
|
|
888
872
|
defaultExpanded={{}}
|
|
889
873
|
/>
|
|
890
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
|
+
}
|