@tanstack/router-devtools-core 1.20.3-alpha.1
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/cjs/AgeTicker.cjs +47 -0
- package/dist/cjs/AgeTicker.cjs.map +1 -0
- package/dist/cjs/AgeTicker.d.cts +6 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs +602 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs.map +1 -0
- package/dist/cjs/BaseTanStackRouterDevtoolsPanel.d.cts +35 -0
- package/dist/cjs/Explorer.cjs +307 -0
- package/dist/cjs/Explorer.cjs.map +1 -0
- package/dist/cjs/Explorer.d.cts +43 -0
- package/dist/cjs/FloatingTanStackRouterDevtools.cjs +204 -0
- package/dist/cjs/FloatingTanStackRouterDevtools.cjs.map +1 -0
- package/dist/cjs/FloatingTanStackRouterDevtools.d.cts +48 -0
- package/dist/cjs/NavigateButton.cjs +30 -0
- package/dist/cjs/NavigateButton.cjs.map +1 -0
- package/dist/cjs/NavigateButton.d.cts +7 -0
- package/dist/cjs/TanStackRouterDevtoolsCore.cjs +107 -0
- package/dist/cjs/TanStackRouterDevtoolsCore.cjs.map +1 -0
- package/dist/cjs/TanStackRouterDevtoolsCore.d.cts +55 -0
- package/dist/cjs/TanStackRouterDevtoolsPanelCore.cjs +107 -0
- package/dist/cjs/TanStackRouterDevtoolsPanelCore.cjs.map +1 -0
- package/dist/cjs/TanStackRouterDevtoolsPanelCore.d.cts +43 -0
- package/dist/cjs/context.cjs +20 -0
- package/dist/cjs/context.cjs.map +1 -0
- package/dist/cjs/context.d.cts +13 -0
- package/dist/cjs/index.cjs +7 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/logo.cjs +92 -0
- package/dist/cjs/logo.cjs.map +1 -0
- package/dist/cjs/logo.d.cts +1 -0
- package/dist/cjs/theme.d.cts +34 -0
- package/dist/cjs/tokens.cjs +201 -0
- package/dist/cjs/tokens.cjs.map +1 -0
- package/dist/cjs/tokens.d.cts +298 -0
- package/dist/cjs/useLocalStorage.cjs +42 -0
- package/dist/cjs/useLocalStorage.cjs.map +1 -0
- package/dist/cjs/useLocalStorage.d.cts +2 -0
- package/dist/cjs/useMediaQuery.d.cts +2 -0
- package/dist/cjs/useStyles.cjs +607 -0
- package/dist/cjs/useStyles.cjs.map +1 -0
- package/dist/cjs/useStyles.d.cts +55 -0
- package/dist/cjs/utils.cjs +63 -0
- package/dist/cjs/utils.cjs.map +1 -0
- package/dist/cjs/utils.d.cts +25 -0
- package/dist/esm/AgeTicker.d.ts +6 -0
- package/dist/esm/AgeTicker.js +47 -0
- package/dist/esm/AgeTicker.js.map +1 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.d.ts +35 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.js +602 -0
- package/dist/esm/BaseTanStackRouterDevtoolsPanel.js.map +1 -0
- package/dist/esm/Explorer.d.ts +43 -0
- package/dist/esm/Explorer.js +290 -0
- package/dist/esm/Explorer.js.map +1 -0
- package/dist/esm/FloatingTanStackRouterDevtools.d.ts +48 -0
- package/dist/esm/FloatingTanStackRouterDevtools.js +204 -0
- package/dist/esm/FloatingTanStackRouterDevtools.js.map +1 -0
- package/dist/esm/NavigateButton.d.ts +7 -0
- package/dist/esm/NavigateButton.js +30 -0
- package/dist/esm/NavigateButton.js.map +1 -0
- package/dist/esm/TanStackRouterDevtoolsCore.d.ts +55 -0
- package/dist/esm/TanStackRouterDevtoolsCore.js +107 -0
- package/dist/esm/TanStackRouterDevtoolsCore.js.map +1 -0
- package/dist/esm/TanStackRouterDevtoolsPanelCore.d.ts +43 -0
- package/dist/esm/TanStackRouterDevtoolsPanelCore.js +107 -0
- package/dist/esm/TanStackRouterDevtoolsPanelCore.js.map +1 -0
- package/dist/esm/context.d.ts +13 -0
- package/dist/esm/context.js +20 -0
- package/dist/esm/context.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logo.d.ts +1 -0
- package/dist/esm/logo.js +92 -0
- package/dist/esm/logo.js.map +1 -0
- package/dist/esm/theme.d.ts +34 -0
- package/dist/esm/tokens.d.ts +298 -0
- package/dist/esm/tokens.js +201 -0
- package/dist/esm/tokens.js.map +1 -0
- package/dist/esm/useLocalStorage.d.ts +2 -0
- package/dist/esm/useLocalStorage.js +43 -0
- package/dist/esm/useLocalStorage.js.map +1 -0
- package/dist/esm/useMediaQuery.d.ts +2 -0
- package/dist/esm/useStyles.d.ts +55 -0
- package/dist/esm/useStyles.js +590 -0
- package/dist/esm/useStyles.js.map +1 -0
- package/dist/esm/utils.d.ts +25 -0
- package/dist/esm/utils.js +63 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +71 -0
- package/src/AgeTicker.tsx +59 -0
- package/src/BaseTanStackRouterDevtoolsPanel.tsx +632 -0
- package/src/Explorer.tsx +339 -0
- package/src/FloatingTanStackRouterDevtools.tsx +290 -0
- package/src/NavigateButton.tsx +25 -0
- package/src/TanStackRouterDevtoolsCore.tsx +152 -0
- package/src/TanStackRouterDevtoolsPanelCore.tsx +131 -0
- package/src/context.ts +24 -0
- package/src/index.tsx +2 -0
- package/src/logo.tsx +817 -0
- package/src/theme.tsx +36 -0
- package/src/tokens.ts +305 -0
- package/src/useLocalStorage.ts +52 -0
- package/src/useMediaQuery.ts +44 -0
- package/src/useStyles.tsx +614 -0
- package/src/utils.tsx +185 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import { clsx as cx } from 'clsx'
|
|
2
|
+
import { default as invariant } from 'tiny-invariant'
|
|
3
|
+
import { interpolatePath, rootRouteId, trimPath } from '@tanstack/router-core'
|
|
4
|
+
import { Show, createMemo } from 'solid-js'
|
|
5
|
+
import { useDevtoolsOnClose } from './context'
|
|
6
|
+
import { useStyles } from './useStyles'
|
|
7
|
+
import useLocalStorage from './useLocalStorage'
|
|
8
|
+
import { Explorer } from './Explorer'
|
|
9
|
+
import { getRouteStatusColor, getStatusColor, multiSortBy } from './utils'
|
|
10
|
+
import { AgeTicker } from './AgeTicker'
|
|
11
|
+
// import type { DevtoolsPanelOptions } from './TanStackRouterDevtoolsPanel'
|
|
12
|
+
|
|
13
|
+
import { NavigateButton } from './NavigateButton'
|
|
14
|
+
import type {
|
|
15
|
+
AnyContext,
|
|
16
|
+
AnyRoute,
|
|
17
|
+
AnyRouter,
|
|
18
|
+
FileRouteTypes,
|
|
19
|
+
MakeRouteMatchUnion,
|
|
20
|
+
Route,
|
|
21
|
+
RouterState,
|
|
22
|
+
} from '@tanstack/router-core'
|
|
23
|
+
import type { Accessor, JSX } from 'solid-js'
|
|
24
|
+
|
|
25
|
+
export interface BaseDevtoolsPanelOptions {
|
|
26
|
+
/**
|
|
27
|
+
* The standard React style object used to style a component with inline styles
|
|
28
|
+
*/
|
|
29
|
+
style?: Accessor<JSX.CSSProperties>
|
|
30
|
+
/**
|
|
31
|
+
* The standard React class property used to style a component with classes
|
|
32
|
+
*/
|
|
33
|
+
className?: Accessor<string>
|
|
34
|
+
/**
|
|
35
|
+
* A boolean variable indicating whether the panel is open or closed
|
|
36
|
+
*/
|
|
37
|
+
isOpen?: boolean
|
|
38
|
+
/**
|
|
39
|
+
* A function that toggles the open and close state of the panel
|
|
40
|
+
*/
|
|
41
|
+
setIsOpen?: (isOpen: boolean) => void
|
|
42
|
+
/**
|
|
43
|
+
* Handles the opening and closing the devtools panel
|
|
44
|
+
*/
|
|
45
|
+
handleDragStart?: (e: any) => void
|
|
46
|
+
/**
|
|
47
|
+
* A boolean variable indicating if the "lite" version of the library is being used
|
|
48
|
+
*/
|
|
49
|
+
router: Accessor<AnyRouter>
|
|
50
|
+
routerState: Accessor<any>
|
|
51
|
+
/**
|
|
52
|
+
* Use this to attach the devtool's styles to specific element in the DOM.
|
|
53
|
+
*/
|
|
54
|
+
shadowDOMTarget?: ShadowRoot
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function Logo(props: any) {
|
|
58
|
+
const { className, ...rest } = props
|
|
59
|
+
const styles = useStyles()
|
|
60
|
+
return (
|
|
61
|
+
<button {...rest} class={cx(styles().logo, className ? className() : '')}>
|
|
62
|
+
<div class={styles().tanstackLogo}>TANSTACK</div>
|
|
63
|
+
<div class={styles().routerLogo}>TanStack Router v1</div>
|
|
64
|
+
</button>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function NavigateLink(props: {
|
|
69
|
+
class?: string
|
|
70
|
+
left?: JSX.Element
|
|
71
|
+
children?: JSX.Element
|
|
72
|
+
right?: JSX.Element
|
|
73
|
+
}) {
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
class={props.class}
|
|
77
|
+
style={{
|
|
78
|
+
display: 'flex',
|
|
79
|
+
'align-items': 'center',
|
|
80
|
+
width: '100%',
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
{props.left}
|
|
84
|
+
<div style={{ 'flex-grow': 1, 'min-width': 0 }}>{props.children}</div>
|
|
85
|
+
{props.right}
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function RouteComp({
|
|
91
|
+
routerState,
|
|
92
|
+
router,
|
|
93
|
+
route,
|
|
94
|
+
isRoot,
|
|
95
|
+
activeId,
|
|
96
|
+
setActiveId,
|
|
97
|
+
}: {
|
|
98
|
+
routerState: Accessor<
|
|
99
|
+
RouterState<
|
|
100
|
+
Route<
|
|
101
|
+
any,
|
|
102
|
+
'/',
|
|
103
|
+
'/',
|
|
104
|
+
string,
|
|
105
|
+
'__root__',
|
|
106
|
+
undefined,
|
|
107
|
+
{},
|
|
108
|
+
{},
|
|
109
|
+
AnyContext,
|
|
110
|
+
AnyContext,
|
|
111
|
+
{},
|
|
112
|
+
undefined,
|
|
113
|
+
any,
|
|
114
|
+
FileRouteTypes
|
|
115
|
+
>,
|
|
116
|
+
MakeRouteMatchUnion
|
|
117
|
+
>
|
|
118
|
+
>
|
|
119
|
+
router: Accessor<AnyRouter>
|
|
120
|
+
route: AnyRoute
|
|
121
|
+
isRoot?: boolean
|
|
122
|
+
activeId: Accessor<string | undefined>
|
|
123
|
+
setActiveId: (id: string) => void
|
|
124
|
+
}) {
|
|
125
|
+
const styles = useStyles()
|
|
126
|
+
const matches = createMemo(
|
|
127
|
+
() => routerState().pendingMatches || routerState().matches,
|
|
128
|
+
)
|
|
129
|
+
const match = createMemo(() =>
|
|
130
|
+
routerState().matches.find((d) => d.routeId === route.id),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
const param = createMemo(() => {
|
|
134
|
+
try {
|
|
135
|
+
if (match()?.params) {
|
|
136
|
+
const p = match()?.params
|
|
137
|
+
const r: string = route.path || trimPath(route.id)
|
|
138
|
+
if (r.startsWith('$')) {
|
|
139
|
+
const trimmed = r.slice(1)
|
|
140
|
+
|
|
141
|
+
if (p[trimmed]) {
|
|
142
|
+
return `(${p[trimmed]})`
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return ''
|
|
147
|
+
} catch (error) {
|
|
148
|
+
return ''
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
const navigationTarget = createMemo<string | undefined>(() => {
|
|
153
|
+
if (isRoot) return undefined // rootRouteId has no path
|
|
154
|
+
if (!route.path) return undefined // no path to navigate to
|
|
155
|
+
|
|
156
|
+
// flatten all params in the router state, into a single object
|
|
157
|
+
const allParams = Object.assign({}, ...matches().map((m) => m.params))
|
|
158
|
+
|
|
159
|
+
// interpolatePath is used by router-core to generate the `to`
|
|
160
|
+
// path for the navigate function in the router
|
|
161
|
+
const interpolated = interpolatePath({
|
|
162
|
+
path: route.fullPath,
|
|
163
|
+
params: allParams,
|
|
164
|
+
leaveWildcards: false,
|
|
165
|
+
leaveParams: false,
|
|
166
|
+
decodeCharMap: router().pathParamsDecodeCharMap,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
// only if `interpolated` is not missing params, return the path since this
|
|
170
|
+
// means that all the params are present for a successful navigation
|
|
171
|
+
return !interpolated.isMissingParams
|
|
172
|
+
? interpolated.interpolatedPath
|
|
173
|
+
: undefined
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div>
|
|
178
|
+
<div
|
|
179
|
+
role="button"
|
|
180
|
+
aria-label={`Open match details for ${route.id}`}
|
|
181
|
+
onClick={() => {
|
|
182
|
+
if (match()) {
|
|
183
|
+
setActiveId(activeId() === route.id ? '' : route.id)
|
|
184
|
+
}
|
|
185
|
+
}}
|
|
186
|
+
class={cx(
|
|
187
|
+
styles().routesRowContainer(route.id === activeId(), !!match()),
|
|
188
|
+
)}
|
|
189
|
+
>
|
|
190
|
+
<div
|
|
191
|
+
class={cx(
|
|
192
|
+
styles().matchIndicator(getRouteStatusColor(matches(), route)),
|
|
193
|
+
)}
|
|
194
|
+
/>
|
|
195
|
+
<NavigateLink
|
|
196
|
+
class={cx(styles().routesRow(!!match()))}
|
|
197
|
+
left={
|
|
198
|
+
<Show when={navigationTarget()}>
|
|
199
|
+
{(navigate) => <NavigateButton to={navigate()} router={router} />}
|
|
200
|
+
</Show>
|
|
201
|
+
}
|
|
202
|
+
right={<AgeTicker match={match()} router={router} />}
|
|
203
|
+
>
|
|
204
|
+
<code class={styles().code}>
|
|
205
|
+
{isRoot ? rootRouteId : route.path || trimPath(route.id)}{' '}
|
|
206
|
+
</code>
|
|
207
|
+
<code class={styles().routeParamInfo}>{param()}</code>
|
|
208
|
+
</NavigateLink>
|
|
209
|
+
</div>
|
|
210
|
+
{route.children?.length ? (
|
|
211
|
+
<div class={styles().nestedRouteRow(!!isRoot)}>
|
|
212
|
+
{[...(route.children as Array<AnyRoute>)]
|
|
213
|
+
.sort((a, b) => {
|
|
214
|
+
return a.rank - b.rank
|
|
215
|
+
})
|
|
216
|
+
.map((r) => (
|
|
217
|
+
<RouteComp
|
|
218
|
+
routerState={routerState}
|
|
219
|
+
router={router}
|
|
220
|
+
route={r}
|
|
221
|
+
activeId={activeId}
|
|
222
|
+
setActiveId={setActiveId}
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</div>
|
|
226
|
+
) : null}
|
|
227
|
+
</div>
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export const BaseTanStackRouterDevtoolsPanel =
|
|
232
|
+
function BaseTanStackRouterDevtoolsPanel({
|
|
233
|
+
...props
|
|
234
|
+
}: BaseDevtoolsPanelOptions): JSX.Element {
|
|
235
|
+
const {
|
|
236
|
+
isOpen = true,
|
|
237
|
+
setIsOpen,
|
|
238
|
+
handleDragStart,
|
|
239
|
+
router,
|
|
240
|
+
routerState,
|
|
241
|
+
shadowDOMTarget,
|
|
242
|
+
...panelProps
|
|
243
|
+
} = props
|
|
244
|
+
|
|
245
|
+
const { onCloseClick } = useDevtoolsOnClose()
|
|
246
|
+
const styles = useStyles()
|
|
247
|
+
const { className, style, ...otherPanelProps } = panelProps
|
|
248
|
+
|
|
249
|
+
invariant(
|
|
250
|
+
router,
|
|
251
|
+
'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.',
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
// useStore(router.__store)
|
|
255
|
+
|
|
256
|
+
const [showMatches, setShowMatches] = useLocalStorage(
|
|
257
|
+
'tanstackRouterDevtoolsShowMatches',
|
|
258
|
+
true,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
const [activeId, setActiveId] = useLocalStorage(
|
|
262
|
+
'tanstackRouterDevtoolsActiveRouteId',
|
|
263
|
+
'',
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
const activeMatch = createMemo(() => {
|
|
267
|
+
const matches = [
|
|
268
|
+
...(routerState().pendingMatches ?? []),
|
|
269
|
+
...routerState().matches,
|
|
270
|
+
...routerState().cachedMatches,
|
|
271
|
+
]
|
|
272
|
+
return matches.find(
|
|
273
|
+
(d) => d.routeId === activeId() || d.id === activeId(),
|
|
274
|
+
)
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
const hasSearch = createMemo(
|
|
278
|
+
() => Object.keys(routerState().location.search).length,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
const explorerState = createMemo(() => {
|
|
282
|
+
return {
|
|
283
|
+
...router(),
|
|
284
|
+
state: routerState(),
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
const routerExplorerValue = createMemo(() =>
|
|
289
|
+
Object.fromEntries(
|
|
290
|
+
multiSortBy(
|
|
291
|
+
Object.keys(explorerState()),
|
|
292
|
+
(
|
|
293
|
+
[
|
|
294
|
+
'state',
|
|
295
|
+
'routesById',
|
|
296
|
+
'routesByPath',
|
|
297
|
+
'flatRoutes',
|
|
298
|
+
'options',
|
|
299
|
+
'manifest',
|
|
300
|
+
] as const
|
|
301
|
+
).map((d) => (dd) => dd !== d),
|
|
302
|
+
)
|
|
303
|
+
.map((key) => [key, (explorerState() as any)[key]])
|
|
304
|
+
.filter(
|
|
305
|
+
(d) =>
|
|
306
|
+
typeof d[1] !== 'function' &&
|
|
307
|
+
![
|
|
308
|
+
'__store',
|
|
309
|
+
'basepath',
|
|
310
|
+
'injectedHtml',
|
|
311
|
+
'subscribers',
|
|
312
|
+
'latestLoadPromise',
|
|
313
|
+
'navigateTimeout',
|
|
314
|
+
'resetNextScroll',
|
|
315
|
+
'tempLocationKey',
|
|
316
|
+
'latestLocation',
|
|
317
|
+
'routeTree',
|
|
318
|
+
'history',
|
|
319
|
+
].includes(d[0]),
|
|
320
|
+
),
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
const activeMatchLoaderData = createMemo(() => activeMatch()?.loaderData)
|
|
324
|
+
const activeMatchValue = createMemo(() => activeMatch())
|
|
325
|
+
const locationSearchValue = createMemo(() => routerState().location.search)
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<div
|
|
329
|
+
class={cx(
|
|
330
|
+
styles().devtoolsPanel,
|
|
331
|
+
'TanStackRouterDevtoolsPanel',
|
|
332
|
+
className ? className() : '',
|
|
333
|
+
)}
|
|
334
|
+
style={style ? style() : ''}
|
|
335
|
+
{...otherPanelProps}
|
|
336
|
+
>
|
|
337
|
+
{handleDragStart ? (
|
|
338
|
+
<div class={styles().dragHandle} onMouseDown={handleDragStart}></div>
|
|
339
|
+
) : null}
|
|
340
|
+
<button
|
|
341
|
+
class={styles().panelCloseBtn}
|
|
342
|
+
onClick={(e: any) => {
|
|
343
|
+
if (setIsOpen) {
|
|
344
|
+
setIsOpen(false)
|
|
345
|
+
}
|
|
346
|
+
onCloseClick(e)
|
|
347
|
+
}}
|
|
348
|
+
>
|
|
349
|
+
<svg
|
|
350
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
351
|
+
width="10"
|
|
352
|
+
height="6"
|
|
353
|
+
fill="none"
|
|
354
|
+
viewBox="0 0 10 6"
|
|
355
|
+
class={styles().panelCloseBtnIcon}
|
|
356
|
+
>
|
|
357
|
+
<path
|
|
358
|
+
stroke="currentColor"
|
|
359
|
+
stroke-linecap="round"
|
|
360
|
+
stroke-linejoin="round"
|
|
361
|
+
stroke-width="1.667"
|
|
362
|
+
d="M1 1l4 4 4-4"
|
|
363
|
+
></path>
|
|
364
|
+
</svg>
|
|
365
|
+
</button>
|
|
366
|
+
<div class={styles().firstContainer}>
|
|
367
|
+
<div class={styles().row}>
|
|
368
|
+
<Logo
|
|
369
|
+
aria-hidden
|
|
370
|
+
onClick={(e: any) => {
|
|
371
|
+
if (setIsOpen) {
|
|
372
|
+
setIsOpen(false)
|
|
373
|
+
}
|
|
374
|
+
onCloseClick(e)
|
|
375
|
+
}}
|
|
376
|
+
/>
|
|
377
|
+
</div>
|
|
378
|
+
<div class={styles().routerExplorerContainer}>
|
|
379
|
+
<div class={styles().routerExplorer}>
|
|
380
|
+
<Explorer
|
|
381
|
+
label="Router"
|
|
382
|
+
value={routerExplorerValue}
|
|
383
|
+
defaultExpanded={{
|
|
384
|
+
state: {} as any,
|
|
385
|
+
context: {} as any,
|
|
386
|
+
options: {} as any,
|
|
387
|
+
}}
|
|
388
|
+
filterSubEntries={(subEntries) => {
|
|
389
|
+
return subEntries.filter(
|
|
390
|
+
(d: any) => typeof d.value() !== 'function',
|
|
391
|
+
)
|
|
392
|
+
}}
|
|
393
|
+
/>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
<div class={styles().secondContainer}>
|
|
398
|
+
<div class={styles().matchesContainer}>
|
|
399
|
+
<div class={styles().detailsHeader}>
|
|
400
|
+
<span>Pathname</span>
|
|
401
|
+
{routerState().location.maskedLocation ? (
|
|
402
|
+
<div class={styles().maskedBadgeContainer}>
|
|
403
|
+
<span class={styles().maskedBadge}>masked</span>
|
|
404
|
+
</div>
|
|
405
|
+
) : null}
|
|
406
|
+
</div>
|
|
407
|
+
<div class={styles().detailsContent}>
|
|
408
|
+
<code>{routerState().location.pathname}</code>
|
|
409
|
+
{routerState().location.maskedLocation ? (
|
|
410
|
+
<code class={styles().maskedLocation}>
|
|
411
|
+
{routerState().location.maskedLocation?.pathname}
|
|
412
|
+
</code>
|
|
413
|
+
) : null}
|
|
414
|
+
</div>
|
|
415
|
+
<div class={styles().detailsHeader}>
|
|
416
|
+
<div class={styles().routeMatchesToggle}>
|
|
417
|
+
<button
|
|
418
|
+
type="button"
|
|
419
|
+
onClick={() => {
|
|
420
|
+
setShowMatches(false)
|
|
421
|
+
}}
|
|
422
|
+
disabled={!showMatches()}
|
|
423
|
+
class={cx(
|
|
424
|
+
styles().routeMatchesToggleBtn(!showMatches(), true),
|
|
425
|
+
)}
|
|
426
|
+
>
|
|
427
|
+
Routes
|
|
428
|
+
</button>
|
|
429
|
+
<button
|
|
430
|
+
type="button"
|
|
431
|
+
onClick={() => {
|
|
432
|
+
setShowMatches(true)
|
|
433
|
+
}}
|
|
434
|
+
disabled={showMatches()}
|
|
435
|
+
class={cx(
|
|
436
|
+
styles().routeMatchesToggleBtn(!!showMatches(), false),
|
|
437
|
+
)}
|
|
438
|
+
>
|
|
439
|
+
Matches
|
|
440
|
+
</button>
|
|
441
|
+
</div>
|
|
442
|
+
<div class={styles().detailsHeaderInfo}>
|
|
443
|
+
<div>age / staleTime / gcTime</div>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
<div class={cx(styles().routesContainer)}>
|
|
447
|
+
{!showMatches() ? (
|
|
448
|
+
<RouteComp
|
|
449
|
+
routerState={routerState}
|
|
450
|
+
router={router}
|
|
451
|
+
route={router().routeTree}
|
|
452
|
+
isRoot
|
|
453
|
+
activeId={activeId}
|
|
454
|
+
setActiveId={setActiveId}
|
|
455
|
+
/>
|
|
456
|
+
) : (
|
|
457
|
+
<div>
|
|
458
|
+
{(routerState().pendingMatches?.length
|
|
459
|
+
? routerState().pendingMatches
|
|
460
|
+
: routerState().matches
|
|
461
|
+
)?.map((match: any, _i: any) => {
|
|
462
|
+
return (
|
|
463
|
+
<div
|
|
464
|
+
role="button"
|
|
465
|
+
aria-label={`Open match details for ${match.id}`}
|
|
466
|
+
onClick={() =>
|
|
467
|
+
setActiveId(activeId() === match.id ? '' : match.id)
|
|
468
|
+
}
|
|
469
|
+
class={cx(styles().matchRow(match === activeMatch()))}
|
|
470
|
+
>
|
|
471
|
+
<div
|
|
472
|
+
class={cx(
|
|
473
|
+
styles().matchIndicator(getStatusColor(match)),
|
|
474
|
+
)}
|
|
475
|
+
/>
|
|
476
|
+
<NavigateLink
|
|
477
|
+
left={
|
|
478
|
+
<NavigateButton
|
|
479
|
+
to={match.pathname}
|
|
480
|
+
params={match.params}
|
|
481
|
+
search={match.search}
|
|
482
|
+
router={router}
|
|
483
|
+
/>
|
|
484
|
+
}
|
|
485
|
+
right={<AgeTicker match={match} router={router} />}
|
|
486
|
+
>
|
|
487
|
+
<code class={styles().matchID}>
|
|
488
|
+
{`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`}
|
|
489
|
+
</code>
|
|
490
|
+
</NavigateLink>
|
|
491
|
+
</div>
|
|
492
|
+
)
|
|
493
|
+
})}
|
|
494
|
+
</div>
|
|
495
|
+
)}
|
|
496
|
+
</div>
|
|
497
|
+
</div>
|
|
498
|
+
{routerState().cachedMatches.length ? (
|
|
499
|
+
<div class={styles().cachedMatchesContainer}>
|
|
500
|
+
<div class={styles().detailsHeader}>
|
|
501
|
+
<div>Cached Matches</div>
|
|
502
|
+
<div class={styles().detailsHeaderInfo}>
|
|
503
|
+
age / staleTime / gcTime
|
|
504
|
+
</div>
|
|
505
|
+
</div>
|
|
506
|
+
<div>
|
|
507
|
+
{routerState().cachedMatches.map((match: any) => {
|
|
508
|
+
return (
|
|
509
|
+
<div
|
|
510
|
+
role="button"
|
|
511
|
+
aria-label={`Open match details for ${match.id}`}
|
|
512
|
+
onClick={() =>
|
|
513
|
+
setActiveId(activeId() === match.id ? '' : match.id)
|
|
514
|
+
}
|
|
515
|
+
class={cx(styles().matchRow(match === activeMatch()))}
|
|
516
|
+
>
|
|
517
|
+
<div
|
|
518
|
+
class={cx(
|
|
519
|
+
styles().matchIndicator(getStatusColor(match)),
|
|
520
|
+
)}
|
|
521
|
+
/>
|
|
522
|
+
<NavigateLink
|
|
523
|
+
left={
|
|
524
|
+
<NavigateButton
|
|
525
|
+
to={match.pathname}
|
|
526
|
+
params={match.params}
|
|
527
|
+
search={match.search}
|
|
528
|
+
router={router}
|
|
529
|
+
/>
|
|
530
|
+
}
|
|
531
|
+
right={<AgeTicker match={match} router={router} />}
|
|
532
|
+
>
|
|
533
|
+
<code class={styles().matchID}>{`${match.id}`}</code>
|
|
534
|
+
</NavigateLink>
|
|
535
|
+
</div>
|
|
536
|
+
)
|
|
537
|
+
})}
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
) : null}
|
|
541
|
+
</div>
|
|
542
|
+
{activeMatch() && activeMatch()?.status ? (
|
|
543
|
+
<div class={styles().thirdContainer}>
|
|
544
|
+
<div class={styles().detailsHeader}>Match Details</div>
|
|
545
|
+
<div>
|
|
546
|
+
<div class={styles().matchDetails}>
|
|
547
|
+
<div
|
|
548
|
+
class={styles().matchStatus(
|
|
549
|
+
activeMatch()?.status,
|
|
550
|
+
activeMatch()?.isFetching,
|
|
551
|
+
)}
|
|
552
|
+
>
|
|
553
|
+
<div>
|
|
554
|
+
{activeMatch()?.status === 'success' &&
|
|
555
|
+
activeMatch()?.isFetching
|
|
556
|
+
? 'fetching'
|
|
557
|
+
: activeMatch()?.status}
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
<div class={styles().matchDetailsInfoLabel}>
|
|
561
|
+
<div>ID:</div>
|
|
562
|
+
<div class={styles().matchDetailsInfo}>
|
|
563
|
+
<code>{activeMatch()?.id}</code>
|
|
564
|
+
</div>
|
|
565
|
+
</div>
|
|
566
|
+
<div class={styles().matchDetailsInfoLabel}>
|
|
567
|
+
<div>State:</div>
|
|
568
|
+
<div class={styles().matchDetailsInfo}>
|
|
569
|
+
{routerState().pendingMatches?.find(
|
|
570
|
+
(d: any) => d.id === activeMatch()?.id,
|
|
571
|
+
)
|
|
572
|
+
? 'Pending'
|
|
573
|
+
: routerState().matches.find(
|
|
574
|
+
(d: any) => d.id === activeMatch()?.id,
|
|
575
|
+
)
|
|
576
|
+
? 'Active'
|
|
577
|
+
: 'Cached'}
|
|
578
|
+
</div>
|
|
579
|
+
</div>
|
|
580
|
+
<div class={styles().matchDetailsInfoLabel}>
|
|
581
|
+
<div>Last Updated:</div>
|
|
582
|
+
<div class={styles().matchDetailsInfo}>
|
|
583
|
+
{activeMatch()?.updatedAt
|
|
584
|
+
? new Date(activeMatch()?.updatedAt).toLocaleTimeString()
|
|
585
|
+
: 'N/A'}
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
</div>
|
|
589
|
+
</div>
|
|
590
|
+
{activeMatchLoaderData() ? (
|
|
591
|
+
<>
|
|
592
|
+
<div class={styles().detailsHeader}>Loader Data</div>
|
|
593
|
+
<div class={styles().detailsContent}>
|
|
594
|
+
<Explorer
|
|
595
|
+
label="loaderData"
|
|
596
|
+
value={activeMatchLoaderData}
|
|
597
|
+
defaultExpanded={{}}
|
|
598
|
+
/>
|
|
599
|
+
</div>
|
|
600
|
+
</>
|
|
601
|
+
) : null}
|
|
602
|
+
<div class={styles().detailsHeader}>Explorer</div>
|
|
603
|
+
<div class={styles().detailsContent}>
|
|
604
|
+
<Explorer
|
|
605
|
+
label="Match"
|
|
606
|
+
value={activeMatchValue}
|
|
607
|
+
defaultExpanded={{}}
|
|
608
|
+
/>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
) : null}
|
|
612
|
+
{hasSearch() ? (
|
|
613
|
+
<div class={styles().fourthContainer}>
|
|
614
|
+
<div class={styles().detailsHeader}>Search Params</div>
|
|
615
|
+
<div class={styles().detailsContent}>
|
|
616
|
+
<Explorer
|
|
617
|
+
value={locationSearchValue}
|
|
618
|
+
defaultExpanded={Object.keys(
|
|
619
|
+
routerState().location.search,
|
|
620
|
+
).reduce((obj: any, next) => {
|
|
621
|
+
obj[next] = {}
|
|
622
|
+
return obj
|
|
623
|
+
}, {})}
|
|
624
|
+
/>
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
) : null}
|
|
628
|
+
</div>
|
|
629
|
+
)
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export default BaseTanStackRouterDevtoolsPanel
|