@tanstack/router-devtools 1.112.0 → 1.112.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.
- package/dist/cjs/AgeTicker.cjs +58 -0
- package/dist/cjs/AgeTicker.cjs.map +1 -0
- package/dist/cjs/AgeTicker.d.cts +5 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs +438 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs.map +1 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.d.cts +5 -0
- package/dist/cjs/Explorer.cjs +1 -1
- package/dist/cjs/Explorer.cjs.map +1 -1
- package/dist/cjs/TanStackRouterDevtools.cjs +177 -0
- package/dist/cjs/TanStackRouterDevtools.cjs.map +1 -0
- package/dist/cjs/{devtools.d.cts → TanStackRouterDevtools.d.cts} +0 -31
- package/dist/cjs/TanStackRouterDevtoolsPanel.cjs +23 -0
- package/dist/cjs/TanStackRouterDevtoolsPanel.cjs.map +1 -0
- package/dist/cjs/TanStackRouterDevtoolsPanel.d.cts +35 -0
- package/dist/cjs/context.cjs +1 -1
- package/dist/cjs/context.cjs.map +1 -1
- package/dist/cjs/index.cjs +4 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -1
- package/dist/cjs/useStyles.cjs +570 -0
- package/dist/cjs/useStyles.cjs.map +1 -0
- package/dist/cjs/useStyles.d.cts +52 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +3 -1
- package/dist/esm/AgeTicker.d.ts +5 -0
- package/dist/esm/AgeTicker.js +58 -0
- package/dist/esm/AgeTicker.js.map +1 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.d.ts +5 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.js +438 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.js.map +1 -0
- package/dist/esm/Explorer.js +1 -1
- package/dist/esm/Explorer.js.map +1 -1
- package/dist/esm/{devtools.d.ts → TanStackRouterDevtools.d.ts} +0 -31
- package/dist/esm/TanStackRouterDevtools.js +177 -0
- package/dist/esm/TanStackRouterDevtools.js.map +1 -0
- package/dist/esm/TanStackRouterDevtoolsPanel.d.ts +35 -0
- package/dist/esm/TanStackRouterDevtoolsPanel.js +23 -0
- package/dist/esm/TanStackRouterDevtoolsPanel.js.map +1 -0
- package/dist/esm/context.js +1 -1
- package/dist/esm/context.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/useStyles.d.ts +52 -0
- package/dist/esm/useStyles.js +553 -0
- package/dist/esm/useStyles.js.map +1 -0
- package/dist/esm/utils.d.ts +3 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/AgeTicker.tsx +73 -0
- package/src/BaseTanStackRouterDevtoolsPanel.tsx +499 -0
- package/src/Explorer.tsx +1 -1
- package/src/TanStackRouterDevtools.tsx +250 -0
- package/src/TanStackRouterDevtoolsPanel.tsx +55 -0
- package/src/context.ts +1 -1
- package/src/index.tsx +2 -1
- package/src/theme.tsx +2 -2
- package/src/useStyles.tsx +589 -0
- package/src/utils.ts +38 -31
- package/dist/cjs/devtools.cjs +0 -1212
- package/dist/cjs/devtools.cjs.map +0 -1
- package/dist/esm/devtools.js +0 -1195
- package/dist/esm/devtools.js.map +0 -1
- package/src/devtools.tsx +0 -1443
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { clsx as cx } from 'clsx'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { useStyles } from './useStyles'
|
|
4
|
+
import type { AnyRouteMatch, AnyRouter } from '@tanstack/react-router'
|
|
5
|
+
|
|
6
|
+
function formatTime(ms: number) {
|
|
7
|
+
const units = ['s', 'min', 'h', 'd']
|
|
8
|
+
const values = [ms / 1000, ms / 60000, ms / 3600000, ms / 86400000]
|
|
9
|
+
|
|
10
|
+
let chosenUnitIndex = 0
|
|
11
|
+
for (let i = 1; i < values.length; i++) {
|
|
12
|
+
if (values[i]! < 1) break
|
|
13
|
+
chosenUnitIndex = i
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const formatter = new Intl.NumberFormat(navigator.language, {
|
|
17
|
+
compactDisplay: 'short',
|
|
18
|
+
notation: 'compact',
|
|
19
|
+
maximumFractionDigits: 0,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return formatter.format(values[chosenUnitIndex]!) + units[chosenUnitIndex]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function AgeTicker({
|
|
26
|
+
match,
|
|
27
|
+
router,
|
|
28
|
+
}: {
|
|
29
|
+
match?: AnyRouteMatch
|
|
30
|
+
router: AnyRouter
|
|
31
|
+
}) {
|
|
32
|
+
const styles = useStyles()
|
|
33
|
+
const rerender = React.useReducer(
|
|
34
|
+
() => ({}),
|
|
35
|
+
() => ({}),
|
|
36
|
+
)[1]
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
const interval = setInterval(() => {
|
|
40
|
+
rerender()
|
|
41
|
+
}, 1000)
|
|
42
|
+
|
|
43
|
+
return () => {
|
|
44
|
+
clearInterval(interval)
|
|
45
|
+
}
|
|
46
|
+
}, [rerender])
|
|
47
|
+
|
|
48
|
+
if (!match) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const route = router.looseRoutesById[match.routeId]!
|
|
53
|
+
|
|
54
|
+
if (!route.options.loader) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const age = Date.now() - match.updatedAt
|
|
59
|
+
const staleTime =
|
|
60
|
+
route.options.staleTime ?? router.options.defaultStaleTime ?? 0
|
|
61
|
+
const gcTime =
|
|
62
|
+
route.options.gcTime ?? router.options.defaultGcTime ?? 30 * 60 * 1000
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className={cx(styles.ageTicker(age > staleTime))}>
|
|
66
|
+
<div>{formatTime(age)}</div>
|
|
67
|
+
<div>/</div>
|
|
68
|
+
<div>{formatTime(staleTime)}</div>
|
|
69
|
+
<div>/</div>
|
|
70
|
+
<div>{formatTime(gcTime)}</div>
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { clsx as cx } from 'clsx'
|
|
3
|
+
import {
|
|
4
|
+
invariant,
|
|
5
|
+
rootRouteId,
|
|
6
|
+
trimPath,
|
|
7
|
+
useRouter,
|
|
8
|
+
useRouterState,
|
|
9
|
+
} from '@tanstack/react-router'
|
|
10
|
+
import { useDevtoolsOnClose } from './context'
|
|
11
|
+
import { useStyles } from './useStyles'
|
|
12
|
+
import useLocalStorage from './useLocalStorage'
|
|
13
|
+
import Explorer from './Explorer'
|
|
14
|
+
import { getRouteStatusColor, getStatusColor, multiSortBy } from './utils'
|
|
15
|
+
import { AgeTicker } from './AgeTicker'
|
|
16
|
+
import type { DevtoolsPanelOptions } from './TanStackRouterDevtoolsPanel'
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
AnyRootRoute,
|
|
20
|
+
AnyRoute,
|
|
21
|
+
AnyRouter,
|
|
22
|
+
Route,
|
|
23
|
+
} from '@tanstack/react-router'
|
|
24
|
+
|
|
25
|
+
function Logo(props: React.HTMLAttributes<HTMLButtonElement>) {
|
|
26
|
+
const { className, ...rest } = props
|
|
27
|
+
const styles = useStyles()
|
|
28
|
+
return (
|
|
29
|
+
<button {...rest} className={cx(styles.logo, className)}>
|
|
30
|
+
<div className={styles.tanstackLogo}>TANSTACK</div>
|
|
31
|
+
<div className={styles.routerLogo}>React Router v1</div>
|
|
32
|
+
</button>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function RouteComp({
|
|
37
|
+
router,
|
|
38
|
+
route,
|
|
39
|
+
isRoot,
|
|
40
|
+
activeId,
|
|
41
|
+
setActiveId,
|
|
42
|
+
}: {
|
|
43
|
+
router: AnyRouter
|
|
44
|
+
route: AnyRootRoute | AnyRoute
|
|
45
|
+
isRoot?: boolean
|
|
46
|
+
activeId: string | undefined
|
|
47
|
+
setActiveId: (id: string) => void
|
|
48
|
+
}) {
|
|
49
|
+
const routerState = useRouterState({
|
|
50
|
+
router,
|
|
51
|
+
} as any)
|
|
52
|
+
const styles = useStyles()
|
|
53
|
+
const matches = routerState.pendingMatches || routerState.matches
|
|
54
|
+
const match = routerState.matches.find((d) => d.routeId === route.id)
|
|
55
|
+
|
|
56
|
+
const param = React.useMemo(() => {
|
|
57
|
+
try {
|
|
58
|
+
if (match?.params) {
|
|
59
|
+
const p = match.params
|
|
60
|
+
const r: string = route.path || trimPath(route.id)
|
|
61
|
+
if (r.startsWith('$')) {
|
|
62
|
+
const trimmed = r.slice(1)
|
|
63
|
+
if (p[trimmed]) {
|
|
64
|
+
return `(${p[trimmed]})`
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return ''
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return ''
|
|
71
|
+
}
|
|
72
|
+
}, [match, route])
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div>
|
|
76
|
+
<div
|
|
77
|
+
role="button"
|
|
78
|
+
aria-label={`Open match details for ${route.id}`}
|
|
79
|
+
onClick={() => {
|
|
80
|
+
if (match) {
|
|
81
|
+
setActiveId(activeId === route.id ? '' : route.id)
|
|
82
|
+
}
|
|
83
|
+
}}
|
|
84
|
+
className={cx(
|
|
85
|
+
styles.routesRowContainer(route.id === activeId, !!match),
|
|
86
|
+
)}
|
|
87
|
+
>
|
|
88
|
+
<div
|
|
89
|
+
className={cx(
|
|
90
|
+
styles.matchIndicator(getRouteStatusColor(matches, route)),
|
|
91
|
+
)}
|
|
92
|
+
/>
|
|
93
|
+
<div className={cx(styles.routesRow(!!match))}>
|
|
94
|
+
<div>
|
|
95
|
+
<code className={styles.code}>
|
|
96
|
+
{isRoot ? rootRouteId : route.path || trimPath(route.id)}{' '}
|
|
97
|
+
</code>
|
|
98
|
+
<code className={styles.routeParamInfo}>{param}</code>
|
|
99
|
+
</div>
|
|
100
|
+
<AgeTicker match={match} router={router} />
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
{route.children?.length ? (
|
|
104
|
+
<div className={styles.nestedRouteRow(!!isRoot)}>
|
|
105
|
+
{[...(route.children as Array<Route>)]
|
|
106
|
+
.sort((a, b) => {
|
|
107
|
+
return a.rank - b.rank
|
|
108
|
+
})
|
|
109
|
+
.map((r) => (
|
|
110
|
+
<RouteComp
|
|
111
|
+
key={r.id}
|
|
112
|
+
router={router}
|
|
113
|
+
route={r}
|
|
114
|
+
activeId={activeId}
|
|
115
|
+
setActiveId={setActiveId}
|
|
116
|
+
/>
|
|
117
|
+
))}
|
|
118
|
+
</div>
|
|
119
|
+
) : null}
|
|
120
|
+
</div>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const BaseTanStackRouterDevtoolsPanel =
|
|
125
|
+
function BaseTanStackRouterDevtoolsPanel({
|
|
126
|
+
ref,
|
|
127
|
+
...props
|
|
128
|
+
}: DevtoolsPanelOptions & {
|
|
129
|
+
ref?: React.RefObject<HTMLDivElement | null>
|
|
130
|
+
}): React.ReactElement {
|
|
131
|
+
const {
|
|
132
|
+
isOpen = true,
|
|
133
|
+
setIsOpen,
|
|
134
|
+
handleDragStart,
|
|
135
|
+
router: userRouter,
|
|
136
|
+
shadowDOMTarget,
|
|
137
|
+
...panelProps
|
|
138
|
+
} = props
|
|
139
|
+
|
|
140
|
+
const { onCloseClick } = useDevtoolsOnClose()
|
|
141
|
+
const styles = useStyles()
|
|
142
|
+
const { className, ...otherPanelProps } = panelProps
|
|
143
|
+
|
|
144
|
+
const contextRouter = useRouter({ warn: false })
|
|
145
|
+
const router = userRouter ?? contextRouter
|
|
146
|
+
const routerState = useRouterState({
|
|
147
|
+
router,
|
|
148
|
+
} as any)
|
|
149
|
+
|
|
150
|
+
invariant(
|
|
151
|
+
router,
|
|
152
|
+
'No router was found for the TanStack Router Devtools. Please place the devtools in the <RouterProvider> component tree or pass the router instance to the devtools manually.',
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
// useStore(router.__store)
|
|
156
|
+
|
|
157
|
+
const [showMatches, setShowMatches] = useLocalStorage(
|
|
158
|
+
'tanstackRouterDevtoolsShowMatches',
|
|
159
|
+
true,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const [activeId, setActiveId] = useLocalStorage(
|
|
163
|
+
'tanstackRouterDevtoolsActiveRouteId',
|
|
164
|
+
'',
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
const activeMatch = React.useMemo(() => {
|
|
168
|
+
const matches = [
|
|
169
|
+
...(routerState.pendingMatches ?? []),
|
|
170
|
+
...routerState.matches,
|
|
171
|
+
...routerState.cachedMatches,
|
|
172
|
+
]
|
|
173
|
+
return matches.find((d) => d.routeId === activeId || d.id === activeId)
|
|
174
|
+
}, [
|
|
175
|
+
activeId,
|
|
176
|
+
routerState.cachedMatches,
|
|
177
|
+
routerState.matches,
|
|
178
|
+
routerState.pendingMatches,
|
|
179
|
+
])
|
|
180
|
+
|
|
181
|
+
const hasSearch = Object.keys(routerState.location.search).length
|
|
182
|
+
|
|
183
|
+
const explorerState = {
|
|
184
|
+
...router,
|
|
185
|
+
state: router.state,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div
|
|
190
|
+
ref={ref}
|
|
191
|
+
className={cx(
|
|
192
|
+
styles.devtoolsPanel,
|
|
193
|
+
'TanStackRouterDevtoolsPanel',
|
|
194
|
+
className,
|
|
195
|
+
)}
|
|
196
|
+
{...otherPanelProps}
|
|
197
|
+
>
|
|
198
|
+
{handleDragStart ? (
|
|
199
|
+
<div
|
|
200
|
+
className={styles.dragHandle}
|
|
201
|
+
onMouseDown={handleDragStart}
|
|
202
|
+
></div>
|
|
203
|
+
) : null}
|
|
204
|
+
<button
|
|
205
|
+
className={styles.panelCloseBtn}
|
|
206
|
+
onClick={(e) => {
|
|
207
|
+
setIsOpen(false)
|
|
208
|
+
onCloseClick(e)
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
<svg
|
|
212
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
213
|
+
width="10"
|
|
214
|
+
height="6"
|
|
215
|
+
fill="none"
|
|
216
|
+
viewBox="0 0 10 6"
|
|
217
|
+
className={styles.panelCloseBtnIcon}
|
|
218
|
+
>
|
|
219
|
+
<path
|
|
220
|
+
stroke="currentColor"
|
|
221
|
+
strokeLinecap="round"
|
|
222
|
+
strokeLinejoin="round"
|
|
223
|
+
strokeWidth="1.667"
|
|
224
|
+
d="M1 1l4 4 4-4"
|
|
225
|
+
></path>
|
|
226
|
+
</svg>
|
|
227
|
+
</button>
|
|
228
|
+
<div className={styles.firstContainer}>
|
|
229
|
+
<div className={styles.row}>
|
|
230
|
+
<Logo
|
|
231
|
+
aria-hidden
|
|
232
|
+
onClick={(e) => {
|
|
233
|
+
setIsOpen(false)
|
|
234
|
+
onCloseClick(e)
|
|
235
|
+
}}
|
|
236
|
+
/>
|
|
237
|
+
</div>
|
|
238
|
+
<div className={styles.routerExplorerContainer}>
|
|
239
|
+
<div className={styles.routerExplorer}>
|
|
240
|
+
<Explorer
|
|
241
|
+
label="Router"
|
|
242
|
+
value={Object.fromEntries(
|
|
243
|
+
multiSortBy(
|
|
244
|
+
Object.keys(explorerState),
|
|
245
|
+
(
|
|
246
|
+
[
|
|
247
|
+
'state',
|
|
248
|
+
'routesById',
|
|
249
|
+
'routesByPath',
|
|
250
|
+
'flatRoutes',
|
|
251
|
+
'options',
|
|
252
|
+
'manifest',
|
|
253
|
+
] as const
|
|
254
|
+
).map((d) => (dd) => dd !== d),
|
|
255
|
+
)
|
|
256
|
+
.map((key) => [key, (explorerState as any)[key]])
|
|
257
|
+
.filter(
|
|
258
|
+
(d) =>
|
|
259
|
+
typeof d[1] !== 'function' &&
|
|
260
|
+
![
|
|
261
|
+
'__store',
|
|
262
|
+
'basepath',
|
|
263
|
+
'injectedHtml',
|
|
264
|
+
'subscribers',
|
|
265
|
+
'latestLoadPromise',
|
|
266
|
+
'navigateTimeout',
|
|
267
|
+
'resetNextScroll',
|
|
268
|
+
'tempLocationKey',
|
|
269
|
+
'latestLocation',
|
|
270
|
+
'routeTree',
|
|
271
|
+
'history',
|
|
272
|
+
].includes(d[0]),
|
|
273
|
+
),
|
|
274
|
+
)}
|
|
275
|
+
defaultExpanded={{
|
|
276
|
+
state: {} as any,
|
|
277
|
+
context: {} as any,
|
|
278
|
+
options: {} as any,
|
|
279
|
+
}}
|
|
280
|
+
filterSubEntries={(subEntries) => {
|
|
281
|
+
return subEntries.filter((d) => typeof d.value !== 'function')
|
|
282
|
+
}}
|
|
283
|
+
/>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
<div className={styles.secondContainer}>
|
|
288
|
+
<div className={styles.matchesContainer}>
|
|
289
|
+
<div className={styles.detailsHeader}>
|
|
290
|
+
<span>Pathname</span>
|
|
291
|
+
{routerState.location.maskedLocation ? (
|
|
292
|
+
<div className={styles.maskedBadgeContainer}>
|
|
293
|
+
<span className={styles.maskedBadge}>masked</span>
|
|
294
|
+
</div>
|
|
295
|
+
) : null}
|
|
296
|
+
</div>
|
|
297
|
+
<div className={styles.detailsContent}>
|
|
298
|
+
<code>{routerState.location.pathname}</code>
|
|
299
|
+
{routerState.location.maskedLocation ? (
|
|
300
|
+
<code className={styles.maskedLocation}>
|
|
301
|
+
{routerState.location.maskedLocation.pathname}
|
|
302
|
+
</code>
|
|
303
|
+
) : null}
|
|
304
|
+
</div>
|
|
305
|
+
<div className={styles.detailsHeader}>
|
|
306
|
+
<div className={styles.routeMatchesToggle}>
|
|
307
|
+
<button
|
|
308
|
+
type="button"
|
|
309
|
+
onClick={() => {
|
|
310
|
+
setShowMatches(false)
|
|
311
|
+
}}
|
|
312
|
+
disabled={!showMatches}
|
|
313
|
+
className={cx(
|
|
314
|
+
styles.routeMatchesToggleBtn(!showMatches, true),
|
|
315
|
+
)}
|
|
316
|
+
>
|
|
317
|
+
Routes
|
|
318
|
+
</button>
|
|
319
|
+
<button
|
|
320
|
+
type="button"
|
|
321
|
+
onClick={() => {
|
|
322
|
+
setShowMatches(true)
|
|
323
|
+
}}
|
|
324
|
+
disabled={showMatches}
|
|
325
|
+
className={cx(
|
|
326
|
+
styles.routeMatchesToggleBtn(!!showMatches, false),
|
|
327
|
+
)}
|
|
328
|
+
>
|
|
329
|
+
Matches
|
|
330
|
+
</button>
|
|
331
|
+
</div>
|
|
332
|
+
<div className={styles.detailsHeaderInfo}>
|
|
333
|
+
<div>age / staleTime / gcTime</div>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
<div className={cx(styles.routesContainer)}>
|
|
337
|
+
{!showMatches ? (
|
|
338
|
+
<RouteComp
|
|
339
|
+
router={router}
|
|
340
|
+
route={router.routeTree}
|
|
341
|
+
isRoot
|
|
342
|
+
activeId={activeId}
|
|
343
|
+
setActiveId={setActiveId}
|
|
344
|
+
/>
|
|
345
|
+
) : (
|
|
346
|
+
<div>
|
|
347
|
+
{(routerState.pendingMatches?.length
|
|
348
|
+
? routerState.pendingMatches
|
|
349
|
+
: routerState.matches
|
|
350
|
+
).map((match, i) => {
|
|
351
|
+
return (
|
|
352
|
+
<div
|
|
353
|
+
key={match.id || i}
|
|
354
|
+
role="button"
|
|
355
|
+
aria-label={`Open match details for ${match.id}`}
|
|
356
|
+
onClick={() =>
|
|
357
|
+
setActiveId(activeId === match.id ? '' : match.id)
|
|
358
|
+
}
|
|
359
|
+
className={cx(styles.matchRow(match === activeMatch))}
|
|
360
|
+
>
|
|
361
|
+
<div
|
|
362
|
+
className={cx(
|
|
363
|
+
styles.matchIndicator(getStatusColor(match)),
|
|
364
|
+
)}
|
|
365
|
+
/>
|
|
366
|
+
|
|
367
|
+
<code
|
|
368
|
+
className={styles.matchID}
|
|
369
|
+
>{`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`}</code>
|
|
370
|
+
<AgeTicker match={match} router={router} />
|
|
371
|
+
</div>
|
|
372
|
+
)
|
|
373
|
+
})}
|
|
374
|
+
</div>
|
|
375
|
+
)}
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
{routerState.cachedMatches.length ? (
|
|
379
|
+
<div className={styles.cachedMatchesContainer}>
|
|
380
|
+
<div className={styles.detailsHeader}>
|
|
381
|
+
<div>Cached Matches</div>
|
|
382
|
+
<div className={styles.detailsHeaderInfo}>
|
|
383
|
+
age / staleTime / gcTime
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
<div>
|
|
387
|
+
{routerState.cachedMatches.map((match) => {
|
|
388
|
+
return (
|
|
389
|
+
<div
|
|
390
|
+
key={match.id}
|
|
391
|
+
role="button"
|
|
392
|
+
aria-label={`Open match details for ${match.id}`}
|
|
393
|
+
onClick={() =>
|
|
394
|
+
setActiveId(activeId === match.id ? '' : match.id)
|
|
395
|
+
}
|
|
396
|
+
className={cx(styles.matchRow(match === activeMatch))}
|
|
397
|
+
>
|
|
398
|
+
<div
|
|
399
|
+
className={cx(
|
|
400
|
+
styles.matchIndicator(getStatusColor(match)),
|
|
401
|
+
)}
|
|
402
|
+
/>
|
|
403
|
+
|
|
404
|
+
<code className={styles.matchID}>{`${match.id}`}</code>
|
|
405
|
+
|
|
406
|
+
<AgeTicker match={match} router={router} />
|
|
407
|
+
</div>
|
|
408
|
+
)
|
|
409
|
+
})}
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
) : null}
|
|
413
|
+
</div>
|
|
414
|
+
{activeMatch ? (
|
|
415
|
+
<div className={styles.thirdContainer}>
|
|
416
|
+
<div className={styles.detailsHeader}>Match Details</div>
|
|
417
|
+
<div>
|
|
418
|
+
<div className={styles.matchDetails}>
|
|
419
|
+
<div
|
|
420
|
+
className={styles.matchStatus(
|
|
421
|
+
activeMatch.status,
|
|
422
|
+
activeMatch.isFetching,
|
|
423
|
+
)}
|
|
424
|
+
>
|
|
425
|
+
<div>
|
|
426
|
+
{activeMatch.status === 'success' && activeMatch.isFetching
|
|
427
|
+
? 'fetching'
|
|
428
|
+
: activeMatch.status}
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
431
|
+
<div className={styles.matchDetailsInfoLabel}>
|
|
432
|
+
<div>ID:</div>
|
|
433
|
+
<div className={styles.matchDetailsInfo}>
|
|
434
|
+
<code>{activeMatch.id}</code>
|
|
435
|
+
</div>
|
|
436
|
+
</div>
|
|
437
|
+
<div className={styles.matchDetailsInfoLabel}>
|
|
438
|
+
<div>State:</div>
|
|
439
|
+
<div className={styles.matchDetailsInfo}>
|
|
440
|
+
{routerState.pendingMatches?.find(
|
|
441
|
+
(d) => d.id === activeMatch.id,
|
|
442
|
+
)
|
|
443
|
+
? 'Pending'
|
|
444
|
+
: routerState.matches.find((d) => d.id === activeMatch.id)
|
|
445
|
+
? 'Active'
|
|
446
|
+
: 'Cached'}
|
|
447
|
+
</div>
|
|
448
|
+
</div>
|
|
449
|
+
<div className={styles.matchDetailsInfoLabel}>
|
|
450
|
+
<div>Last Updated:</div>
|
|
451
|
+
<div className={styles.matchDetailsInfo}>
|
|
452
|
+
{activeMatch.updatedAt
|
|
453
|
+
? new Date(activeMatch.updatedAt).toLocaleTimeString()
|
|
454
|
+
: 'N/A'}
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
</div>
|
|
458
|
+
</div>
|
|
459
|
+
{activeMatch.loaderData ? (
|
|
460
|
+
<>
|
|
461
|
+
<div className={styles.detailsHeader}>Loader Data</div>
|
|
462
|
+
<div className={styles.detailsContent}>
|
|
463
|
+
<Explorer
|
|
464
|
+
label="loaderData"
|
|
465
|
+
value={activeMatch.loaderData}
|
|
466
|
+
defaultExpanded={{}}
|
|
467
|
+
/>
|
|
468
|
+
</div>
|
|
469
|
+
</>
|
|
470
|
+
) : null}
|
|
471
|
+
<div className={styles.detailsHeader}>Explorer</div>
|
|
472
|
+
<div className={styles.detailsContent}>
|
|
473
|
+
<Explorer
|
|
474
|
+
label="Match"
|
|
475
|
+
value={activeMatch}
|
|
476
|
+
defaultExpanded={{}}
|
|
477
|
+
/>
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
) : null}
|
|
481
|
+
{hasSearch ? (
|
|
482
|
+
<div className={styles.fourthContainer}>
|
|
483
|
+
<div className={styles.detailsHeader}>Search Params</div>
|
|
484
|
+
<div className={styles.detailsContent}>
|
|
485
|
+
<Explorer
|
|
486
|
+
value={routerState.location.search}
|
|
487
|
+
defaultExpanded={Object.keys(
|
|
488
|
+
routerState.location.search,
|
|
489
|
+
).reduce((obj: any, next) => {
|
|
490
|
+
obj[next] = {}
|
|
491
|
+
return obj
|
|
492
|
+
}, {})}
|
|
493
|
+
/>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
) : null}
|
|
497
|
+
</div>
|
|
498
|
+
)
|
|
499
|
+
}
|
package/src/Explorer.tsx
CHANGED
|
@@ -356,7 +356,7 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => {
|
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
function useStyles() {
|
|
359
|
-
const shadowDomTarget = React.
|
|
359
|
+
const shadowDomTarget = React.use(ShadowDomTargetContext)
|
|
360
360
|
const [_styles] = React.useState(() => stylesFactory(shadowDomTarget))
|
|
361
361
|
return _styles
|
|
362
362
|
}
|