@tanstack/router-devtools 0.0.1-beta.279 → 0.0.1-beta.281
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/devtools.js +172 -43
- package/build/cjs/devtools.js.map +1 -1
- package/build/cjs/utils.js +20 -0
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +191 -43
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +182 -182
- package/build/umd/index.development.js +191 -43
- 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 +272 -117
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.
|
|
4
|
+
"version": "0.0.1-beta.281",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://tanstack.com/router/",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@babel/runtime": "^7.16.7",
|
|
43
43
|
"date-fns": "^2.29.1",
|
|
44
|
-
"@tanstack/react-router": "0.0.1-beta.
|
|
44
|
+
"@tanstack/react-router": "0.0.1-beta.281"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "rollup --config rollup.config.js"
|
package/src/devtools.tsx
CHANGED
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
trimPath,
|
|
9
9
|
useRouter,
|
|
10
10
|
useRouterState,
|
|
11
|
+
AnyRouteMatch,
|
|
11
12
|
} from '@tanstack/react-router'
|
|
12
13
|
|
|
13
14
|
import useLocalStorage from './useLocalStorage'
|
|
14
15
|
import {
|
|
15
16
|
getRouteStatusColor,
|
|
16
17
|
getStatusColor,
|
|
18
|
+
multiSortBy,
|
|
17
19
|
useIsMounted,
|
|
18
20
|
useSafeState,
|
|
19
21
|
} from './utils'
|
|
@@ -409,13 +411,13 @@ export function TanStackRouterDevtools({
|
|
|
409
411
|
function RouteComp({
|
|
410
412
|
route,
|
|
411
413
|
isRoot,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
+
activeId,
|
|
415
|
+
setActiveId,
|
|
414
416
|
}: {
|
|
415
417
|
route: AnyRootRoute | AnyRoute
|
|
416
418
|
isRoot?: boolean
|
|
417
|
-
|
|
418
|
-
|
|
419
|
+
activeId: string | undefined
|
|
420
|
+
setActiveId: (id: string) => void
|
|
419
421
|
}) {
|
|
420
422
|
const routerState = useRouterState()
|
|
421
423
|
const matches =
|
|
@@ -432,7 +434,7 @@ function RouteComp({
|
|
|
432
434
|
aria-label={`Open match details for ${route.id}`}
|
|
433
435
|
onClick={() => {
|
|
434
436
|
if (match) {
|
|
435
|
-
|
|
437
|
+
setActiveId(activeId === route.id ? '' : route.id)
|
|
436
438
|
}
|
|
437
439
|
}}
|
|
438
440
|
style={{
|
|
@@ -441,7 +443,9 @@ function RouteComp({
|
|
|
441
443
|
cursor: match ? 'pointer' : 'default',
|
|
442
444
|
alignItems: 'center',
|
|
443
445
|
background:
|
|
444
|
-
route.id ===
|
|
446
|
+
route.id === activeId ? 'rgba(255,255,255,.1)' : undefined,
|
|
447
|
+
padding: '.25rem .5rem',
|
|
448
|
+
gap: '.5rem',
|
|
445
449
|
}}
|
|
446
450
|
>
|
|
447
451
|
{isRoot ? null : (
|
|
@@ -450,7 +454,6 @@ function RouteComp({
|
|
|
450
454
|
flex: '0 0 auto',
|
|
451
455
|
width: '.7rem',
|
|
452
456
|
height: '.7rem',
|
|
453
|
-
margin: '.5rem .75rem',
|
|
454
457
|
alignItems: 'center',
|
|
455
458
|
justifyContent: 'center',
|
|
456
459
|
fontWeight: 'bold',
|
|
@@ -461,20 +464,29 @@ function RouteComp({
|
|
|
461
464
|
}}
|
|
462
465
|
/>
|
|
463
466
|
)}
|
|
464
|
-
<
|
|
467
|
+
<div
|
|
465
468
|
style={{
|
|
466
469
|
flex: '1 0 auto',
|
|
467
470
|
display: 'flex',
|
|
468
471
|
justifyContent: 'space-between',
|
|
469
|
-
|
|
470
|
-
|
|
472
|
+
alignItems: 'center',
|
|
473
|
+
padding: isRoot ? '0 .25rem' : 0,
|
|
471
474
|
opacity: match ? 1 : 0.7,
|
|
472
475
|
fontSize: '0.7rem',
|
|
473
476
|
}}
|
|
474
477
|
>
|
|
475
|
-
<
|
|
476
|
-
|
|
477
|
-
|
|
478
|
+
<Code>{route.path || trimPath(route.id)} </Code>
|
|
479
|
+
<div
|
|
480
|
+
style={{
|
|
481
|
+
display: 'flex',
|
|
482
|
+
alignItems: 'center',
|
|
483
|
+
gap: '.5rem',
|
|
484
|
+
}}
|
|
485
|
+
>
|
|
486
|
+
{match ? <Code style={{ opacity: 0.3 }}>{match.id}</Code> : null}
|
|
487
|
+
<AgeTicker match={match} />
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
478
490
|
</div>
|
|
479
491
|
{(route.children as Route[])?.length ? (
|
|
480
492
|
<div
|
|
@@ -491,8 +503,8 @@ function RouteComp({
|
|
|
491
503
|
<RouteComp
|
|
492
504
|
key={r.id}
|
|
493
505
|
route={r}
|
|
494
|
-
|
|
495
|
-
|
|
506
|
+
activeId={activeId}
|
|
507
|
+
setActiveId={setActiveId}
|
|
496
508
|
/>
|
|
497
509
|
))}
|
|
498
510
|
</div>
|
|
@@ -519,6 +531,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
519
531
|
const matches = [
|
|
520
532
|
...(routerState.pendingMatches ?? []),
|
|
521
533
|
...routerState.matches,
|
|
534
|
+
...routerState.cachedMatches,
|
|
522
535
|
]
|
|
523
536
|
|
|
524
537
|
invariant(
|
|
@@ -533,32 +546,22 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
533
546
|
true,
|
|
534
547
|
)
|
|
535
548
|
|
|
536
|
-
const [
|
|
549
|
+
const [activeId, setActiveId] = useLocalStorage(
|
|
537
550
|
'tanstackRouterDevtoolsActiveRouteId',
|
|
538
551
|
'',
|
|
539
552
|
)
|
|
540
553
|
|
|
541
554
|
const activeMatch = React.useMemo(
|
|
542
|
-
() => matches.find((d) => d.routeId ===
|
|
543
|
-
[matches,
|
|
555
|
+
() => matches.find((d) => d.routeId === activeId || d.id === activeId),
|
|
556
|
+
[matches, activeId],
|
|
544
557
|
)
|
|
545
558
|
|
|
546
559
|
const hasSearch = Object.keys(routerState.location.search || {}).length
|
|
547
560
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
// )
|
|
553
|
-
// })
|
|
554
|
-
|
|
555
|
-
// React.useEffect(() => {
|
|
556
|
-
// const interval = setInterval(() => {
|
|
557
|
-
// router.cleanMatches()
|
|
558
|
-
// }, 1000)
|
|
559
|
-
|
|
560
|
-
// return () => clearInterval(interval)
|
|
561
|
-
// }, [router])
|
|
561
|
+
const explorerState = {
|
|
562
|
+
...router,
|
|
563
|
+
state: router.state,
|
|
564
|
+
}
|
|
562
565
|
|
|
563
566
|
return (
|
|
564
567
|
<ThemeProvider theme={theme}>
|
|
@@ -673,8 +676,43 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
673
676
|
>
|
|
674
677
|
<Explorer
|
|
675
678
|
label="Router"
|
|
676
|
-
value={
|
|
677
|
-
|
|
679
|
+
value={Object.fromEntries(
|
|
680
|
+
multiSortBy(
|
|
681
|
+
Object.keys(explorerState),
|
|
682
|
+
(
|
|
683
|
+
[
|
|
684
|
+
'state',
|
|
685
|
+
'routesById',
|
|
686
|
+
'routesByPath',
|
|
687
|
+
'flatRoutes',
|
|
688
|
+
'options',
|
|
689
|
+
] as const
|
|
690
|
+
).map((d) => (dd) => dd !== d),
|
|
691
|
+
)
|
|
692
|
+
.map((key) => [key, (explorerState as any)[key]])
|
|
693
|
+
.filter(
|
|
694
|
+
(d) =>
|
|
695
|
+
typeof d[1] !== 'function' &&
|
|
696
|
+
![
|
|
697
|
+
'__store',
|
|
698
|
+
'basepath',
|
|
699
|
+
'injectedHtml',
|
|
700
|
+
'subscribers',
|
|
701
|
+
'latestLoadPromise',
|
|
702
|
+
'navigateTimeout',
|
|
703
|
+
'resetNextScroll',
|
|
704
|
+
'tempLocationKey',
|
|
705
|
+
'latestLocation',
|
|
706
|
+
'routeTree',
|
|
707
|
+
'history',
|
|
708
|
+
].includes(d[0]),
|
|
709
|
+
),
|
|
710
|
+
)}
|
|
711
|
+
defaultExpanded={{
|
|
712
|
+
state: {} as any,
|
|
713
|
+
context: {} as any,
|
|
714
|
+
options: {} as any,
|
|
715
|
+
}}
|
|
678
716
|
filterSubEntries={(subEntries) => {
|
|
679
717
|
return subEntries.filter((d) => typeof d.value !== 'function')
|
|
680
718
|
}}
|
|
@@ -761,52 +799,70 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
761
799
|
zIndex: 1,
|
|
762
800
|
display: 'flex',
|
|
763
801
|
alignItems: 'center',
|
|
802
|
+
justifyContent: 'space-between',
|
|
764
803
|
gap: '.5rem',
|
|
765
804
|
fontWeight: 'bold',
|
|
766
805
|
}}
|
|
767
806
|
>
|
|
768
|
-
<
|
|
769
|
-
type="button"
|
|
770
|
-
onClick={() => {
|
|
771
|
-
setShowMatches(false)
|
|
772
|
-
}}
|
|
773
|
-
disabled={!showMatches}
|
|
807
|
+
<div
|
|
774
808
|
style={{
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
background: 'transparent',
|
|
779
|
-
color: 'inherit',
|
|
780
|
-
cursor: 'pointer',
|
|
809
|
+
display: 'flex',
|
|
810
|
+
alignItems: 'center',
|
|
811
|
+
gap: '.5rem',
|
|
781
812
|
}}
|
|
782
813
|
>
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
814
|
+
<button
|
|
815
|
+
type="button"
|
|
816
|
+
onClick={() => {
|
|
817
|
+
setShowMatches(false)
|
|
818
|
+
}}
|
|
819
|
+
disabled={!showMatches}
|
|
820
|
+
style={{
|
|
821
|
+
appearance: 'none',
|
|
822
|
+
opacity: showMatches ? 0.5 : 1,
|
|
823
|
+
border: 0,
|
|
824
|
+
background: 'transparent',
|
|
825
|
+
color: 'inherit',
|
|
826
|
+
cursor: 'pointer',
|
|
827
|
+
}}
|
|
828
|
+
>
|
|
829
|
+
Routes
|
|
830
|
+
</button>
|
|
831
|
+
/
|
|
832
|
+
<button
|
|
833
|
+
type="button"
|
|
834
|
+
onClick={() => {
|
|
835
|
+
setShowMatches(true)
|
|
836
|
+
}}
|
|
837
|
+
disabled={showMatches}
|
|
838
|
+
style={{
|
|
839
|
+
appearance: 'none',
|
|
840
|
+
opacity: !showMatches ? 0.5 : 1,
|
|
841
|
+
border: 0,
|
|
842
|
+
background: 'transparent',
|
|
843
|
+
color: 'inherit',
|
|
844
|
+
cursor: 'pointer',
|
|
845
|
+
}}
|
|
846
|
+
>
|
|
847
|
+
Matches
|
|
848
|
+
</button>
|
|
849
|
+
</div>
|
|
850
|
+
<div
|
|
792
851
|
style={{
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
background: 'transparent',
|
|
797
|
-
color: 'inherit',
|
|
798
|
-
cursor: 'pointer',
|
|
852
|
+
opacity: 0.3,
|
|
853
|
+
fontSize: '0.7rem',
|
|
854
|
+
fontWeight: 'normal',
|
|
799
855
|
}}
|
|
800
856
|
>
|
|
801
|
-
|
|
802
|
-
</
|
|
857
|
+
age / staleTime / gcTime
|
|
858
|
+
</div>
|
|
803
859
|
</div>
|
|
804
860
|
{!showMatches ? (
|
|
805
861
|
<RouteComp
|
|
806
862
|
route={router.routeTree}
|
|
807
863
|
isRoot
|
|
808
|
-
|
|
809
|
-
|
|
864
|
+
activeId={activeId}
|
|
865
|
+
setActiveId={setActiveId}
|
|
810
866
|
/>
|
|
811
867
|
) : (
|
|
812
868
|
<div>
|
|
@@ -816,13 +872,11 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
816
872
|
).map((match, i) => {
|
|
817
873
|
return (
|
|
818
874
|
<div
|
|
819
|
-
key={match.
|
|
875
|
+
key={match.id || i}
|
|
820
876
|
role="button"
|
|
821
|
-
aria-label={`Open match details for ${match.
|
|
877
|
+
aria-label={`Open match details for ${match.id}`}
|
|
822
878
|
onClick={() =>
|
|
823
|
-
|
|
824
|
-
activeRouteId === match.routeId ? '' : match.routeId,
|
|
825
|
-
)
|
|
879
|
+
setActiveId(activeId === match.id ? '' : match.id)
|
|
826
880
|
}
|
|
827
881
|
style={{
|
|
828
882
|
display: 'flex',
|
|
@@ -858,13 +912,14 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
858
912
|
>
|
|
859
913
|
{`${match.id}`}
|
|
860
914
|
</Code>
|
|
915
|
+
<AgeTicker match={match} />
|
|
861
916
|
</div>
|
|
862
917
|
)
|
|
863
918
|
})}
|
|
864
919
|
</div>
|
|
865
920
|
)}
|
|
866
921
|
</div>
|
|
867
|
-
{
|
|
922
|
+
{routerState.cachedMatches?.length ? (
|
|
868
923
|
<div
|
|
869
924
|
style={{
|
|
870
925
|
flex: '1 1 auto',
|
|
@@ -881,62 +936,76 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
881
936
|
zIndex: 1,
|
|
882
937
|
display: 'flex',
|
|
883
938
|
alignItems: 'center',
|
|
939
|
+
justifyContent: 'space-between',
|
|
884
940
|
gap: '.5rem',
|
|
885
941
|
fontWeight: 'bold',
|
|
886
942
|
}}
|
|
887
943
|
>
|
|
888
|
-
|
|
944
|
+
<div>Cached Matches</div>
|
|
945
|
+
<div
|
|
946
|
+
style={{
|
|
947
|
+
opacity: 0.3,
|
|
948
|
+
fontSize: '0.7rem',
|
|
949
|
+
fontWeight: 'normal',
|
|
950
|
+
}}
|
|
951
|
+
>
|
|
952
|
+
age / staleTime / gcTime
|
|
953
|
+
</div>
|
|
889
954
|
</div>
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
key={match.id}
|
|
894
|
-
role="button"
|
|
895
|
-
aria-label={`Open match details for ${match.routeId}`}
|
|
896
|
-
onClick={() =>
|
|
897
|
-
setActiveMatchId(
|
|
898
|
-
activeMatchId === match.id ? '' : match.id,
|
|
899
|
-
)
|
|
900
|
-
}
|
|
901
|
-
style={{
|
|
902
|
-
display: 'flex',
|
|
903
|
-
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
904
|
-
cursor: 'pointer',
|
|
905
|
-
alignItems: 'center',
|
|
906
|
-
background:
|
|
907
|
-
match === activeMatch
|
|
908
|
-
? 'rgba(255,255,255,.1)'
|
|
909
|
-
: undefined,
|
|
910
|
-
}}
|
|
911
|
-
>
|
|
955
|
+
<div>
|
|
956
|
+
{routerState.cachedMatches.map((match) => {
|
|
957
|
+
return (
|
|
912
958
|
<div
|
|
959
|
+
key={match.id}
|
|
960
|
+
role="button"
|
|
961
|
+
aria-label={`Open match details for ${match.id}`}
|
|
962
|
+
onClick={() =>
|
|
963
|
+
setActiveId(activeId === match.id ? '' : match.id)
|
|
964
|
+
}
|
|
913
965
|
style={{
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
marginLeft: '.25rem',
|
|
918
|
-
background: getStatusColor(match, theme),
|
|
966
|
+
display: 'flex',
|
|
967
|
+
borderBottom: `solid 1px ${theme.grayAlt}`,
|
|
968
|
+
cursor: 'pointer',
|
|
919
969
|
alignItems: 'center',
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
}}
|
|
925
|
-
/>
|
|
926
|
-
|
|
927
|
-
<Code
|
|
928
|
-
style={{
|
|
929
|
-
padding: '.5em',
|
|
970
|
+
background:
|
|
971
|
+
match === activeMatch
|
|
972
|
+
? 'rgba(255,255,255,.1)'
|
|
973
|
+
: undefined,
|
|
930
974
|
fontSize: '0.7rem',
|
|
931
975
|
}}
|
|
932
976
|
>
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
977
|
+
<div
|
|
978
|
+
style={{
|
|
979
|
+
flex: '0 0 auto',
|
|
980
|
+
width: '.75rem',
|
|
981
|
+
height: '.75rem',
|
|
982
|
+
marginLeft: '.25rem',
|
|
983
|
+
background: getStatusColor(match, theme),
|
|
984
|
+
alignItems: 'center',
|
|
985
|
+
justifyContent: 'center',
|
|
986
|
+
fontWeight: 'bold',
|
|
987
|
+
borderRadius: '100%',
|
|
988
|
+
transition: 'all 1s ease-out',
|
|
989
|
+
}}
|
|
990
|
+
/>
|
|
991
|
+
|
|
992
|
+
<Code
|
|
993
|
+
style={{
|
|
994
|
+
padding: '.5em',
|
|
995
|
+
}}
|
|
996
|
+
>
|
|
997
|
+
{`${match.id}`}
|
|
998
|
+
</Code>
|
|
999
|
+
|
|
1000
|
+
<div style={{ marginLeft: 'auto' }}>
|
|
1001
|
+
<AgeTicker match={match} />
|
|
1002
|
+
</div>
|
|
1003
|
+
</div>
|
|
1004
|
+
)
|
|
1005
|
+
})}
|
|
1006
|
+
</div>
|
|
938
1007
|
</div>
|
|
939
|
-
) : null}
|
|
1008
|
+
) : null}
|
|
940
1009
|
</div>
|
|
941
1010
|
{activeMatch ? (
|
|
942
1011
|
<ActivePanel>
|
|
@@ -953,7 +1022,11 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
953
1022
|
Match Details
|
|
954
1023
|
</div>
|
|
955
1024
|
<div>
|
|
956
|
-
<table
|
|
1025
|
+
<table
|
|
1026
|
+
style={{
|
|
1027
|
+
fontSize: '0.8rem',
|
|
1028
|
+
}}
|
|
1029
|
+
>
|
|
957
1030
|
<tbody>
|
|
958
1031
|
<tr>
|
|
959
1032
|
<td style={{ opacity: '.5' }}>ID</td>
|
|
@@ -969,7 +1042,18 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
969
1042
|
</tr>
|
|
970
1043
|
<tr>
|
|
971
1044
|
<td style={{ opacity: '.5' }}>Status</td>
|
|
972
|
-
<td>
|
|
1045
|
+
<td>
|
|
1046
|
+
{routerState.pendingMatches?.find(
|
|
1047
|
+
(d) => d.id === activeMatch.id,
|
|
1048
|
+
)
|
|
1049
|
+
? 'Pending'
|
|
1050
|
+
: routerState.matches?.find(
|
|
1051
|
+
(d) => d.id === activeMatch.id,
|
|
1052
|
+
)
|
|
1053
|
+
? 'Active'
|
|
1054
|
+
: 'Cached'}{' '}
|
|
1055
|
+
- {activeMatch.status}
|
|
1056
|
+
</td>
|
|
973
1057
|
</tr>
|
|
974
1058
|
{/* <tr>
|
|
975
1059
|
<td style={{ opacity: '.5' }}>Invalid</td>
|
|
@@ -1113,3 +1197,74 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
|
|
|
1113
1197
|
</ThemeProvider>
|
|
1114
1198
|
)
|
|
1115
1199
|
})
|
|
1200
|
+
|
|
1201
|
+
function AgeTicker({ match }: { match?: AnyRouteMatch }) {
|
|
1202
|
+
const router = useRouter()
|
|
1203
|
+
|
|
1204
|
+
const rerender = React.useReducer(
|
|
1205
|
+
() => ({}),
|
|
1206
|
+
() => ({}),
|
|
1207
|
+
)[1]
|
|
1208
|
+
|
|
1209
|
+
React.useEffect(() => {
|
|
1210
|
+
const interval = setInterval(() => {
|
|
1211
|
+
rerender()
|
|
1212
|
+
}, 1000)
|
|
1213
|
+
|
|
1214
|
+
return () => {
|
|
1215
|
+
clearInterval(interval)
|
|
1216
|
+
}
|
|
1217
|
+
}, [])
|
|
1218
|
+
|
|
1219
|
+
if (!match) {
|
|
1220
|
+
return null
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
const route = router.looseRoutesById[match?.routeId]!
|
|
1224
|
+
|
|
1225
|
+
if (!route.options.loader) {
|
|
1226
|
+
return null
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
const age = Date.now() - match?.updatedAt
|
|
1230
|
+
const staleTime =
|
|
1231
|
+
route.options.staleTime ?? router.options.defaultStaleTime ?? 0
|
|
1232
|
+
const gcTime =
|
|
1233
|
+
route.options.gcTime ?? router.options.defaultGcTime ?? 30 * 60 * 1000
|
|
1234
|
+
|
|
1235
|
+
return (
|
|
1236
|
+
<div
|
|
1237
|
+
style={{
|
|
1238
|
+
display: 'inline-flex',
|
|
1239
|
+
alignItems: 'center',
|
|
1240
|
+
gap: '.25rem',
|
|
1241
|
+
color: age > staleTime ? theme.warning : undefined,
|
|
1242
|
+
}}
|
|
1243
|
+
>
|
|
1244
|
+
<div style={{}}>{formatTime(age)}</div>
|
|
1245
|
+
<div>/</div>
|
|
1246
|
+
<div>{formatTime(staleTime)}</div>
|
|
1247
|
+
<div>/</div>
|
|
1248
|
+
<div>{formatTime(gcTime)}</div>
|
|
1249
|
+
</div>
|
|
1250
|
+
)
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function formatTime(ms: number) {
|
|
1254
|
+
const units = ['s', 'min', 'h', 'd']
|
|
1255
|
+
const values = [ms / 1000, ms / 60000, ms / 3600000, ms / 86400000]
|
|
1256
|
+
|
|
1257
|
+
let chosenUnitIndex = 0
|
|
1258
|
+
for (let i = 1; i < values.length; i++) {
|
|
1259
|
+
if (values[i]! < 1) break
|
|
1260
|
+
chosenUnitIndex = i
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
const formatter = new Intl.NumberFormat(navigator.language, {
|
|
1264
|
+
compactDisplay: 'short',
|
|
1265
|
+
notation: 'compact',
|
|
1266
|
+
maximumFractionDigits: 0,
|
|
1267
|
+
})
|
|
1268
|
+
|
|
1269
|
+
return formatter.format(values[chosenUnitIndex]!) + units[chosenUnitIndex]
|
|
1270
|
+
}
|