Skip to content

Commit c4bbfd8

Browse files
committed
iterate on devtools a bit more
1 parent a2a063f commit c4bbfd8

File tree

8 files changed

+485
-14
lines changed

8 files changed

+485
-14
lines changed

packages/table-devtools/src/TableContextProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import type { Accessor, ParentComponent, Setter } from 'solid-js'
1414
import type { RowData, Table, TableFeatures } from '@tanstack/table-core'
1515

16-
export type TableDevtoolsTabId = 'features' | 'state' | 'rows'
16+
export type TableDevtoolsTabId = 'features' | 'state' | 'rows' | 'columns'
1717
type AnyTable = Table<TableFeatures, RowData>
1818

1919
interface TableDevtoolsContextValue {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { For } from 'solid-js'
2+
import { useTableDevtoolsContext } from '../TableContextProvider'
3+
import { useTableStore } from '../useTableStore'
4+
import { useStyles } from '../styles/use-styles'
5+
6+
import type { Column, RowData, TableFeatures } from '@tanstack/table-core'
7+
8+
type AnyColumn = Column<TableFeatures, RowData, unknown>
9+
10+
function getColumnDefSummary(column: AnyColumn): string {
11+
const def = column.columnDef as Record<string, unknown>
12+
const header = def.header
13+
const accessorKey = def.accessorKey
14+
const accessorFn = def.accessorFn
15+
const parts: Array<string> = []
16+
if (typeof accessorKey === 'string') parts.push(`key: ${accessorKey}`)
17+
if (typeof accessorFn === 'function') parts.push('accessorFn')
18+
if (header !== undefined) {
19+
const headerStr =
20+
typeof header === 'string'
21+
? header
22+
: typeof header === 'function'
23+
? '[fn]'
24+
: String(header)
25+
parts.push(`header: ${headerStr}`)
26+
}
27+
return parts.length > 0 ? parts.join(', ') : '-'
28+
}
29+
30+
export function ColumnsPanel() {
31+
const styles = useStyles()
32+
const { table } = useTableDevtoolsContext()
33+
34+
const tableInstance = table()
35+
const tableState = useTableStore(
36+
tableInstance ? tableInstance.store : undefined,
37+
(state) => state,
38+
)
39+
40+
const getColumns = (): Array<AnyColumn> => {
41+
tableState?.()
42+
if (!tableInstance) return []
43+
44+
const tableWithColumnFns = tableInstance as unknown as {
45+
getAllFlatColumns?: () => Array<AnyColumn>
46+
getAllLeafColumns?: () => Array<AnyColumn>
47+
}
48+
49+
return (
50+
tableWithColumnFns.getAllFlatColumns?.() ??
51+
tableWithColumnFns.getAllLeafColumns?.() ??
52+
[]
53+
)
54+
}
55+
56+
const columns = getColumns()
57+
58+
if (!tableInstance) {
59+
return (
60+
<div class={styles().panelScroll}>
61+
<div class={styles().sectionTitle}>Columns</div>
62+
<div class={styles().rowModelItem}>
63+
No table instance is connected. Pass a table instance to
64+
TableDevtoolsPanel.
65+
</div>
66+
</div>
67+
)
68+
}
69+
70+
return (
71+
<div class={styles().panelScroll}>
72+
<div class={styles().sectionTitle}>Columns ({columns.length})</div>
73+
<div class={styles().tableWrapper}>
74+
<table class={styles().rowsTable}>
75+
<thead>
76+
<tr>
77+
<th class={styles().headerCell}>#</th>
78+
<th class={styles().headerCell}>id</th>
79+
<th class={styles().headerCell}>depth</th>
80+
<th class={styles().headerCell}>accessor</th>
81+
<th class={styles().headerCell}>columnDef</th>
82+
</tr>
83+
</thead>
84+
<tbody>
85+
<For each={columns}>
86+
{(column, index) => (
87+
<tr>
88+
<td class={styles().bodyCellMono}>{index() + 1}</td>
89+
<td class={styles().bodyCellMono}>{column.id}</td>
90+
<td class={styles().bodyCellMono}>{column.depth}</td>
91+
<td class={styles().bodyCellMono}>
92+
{column.accessorFn ? '✓' : '○'}
93+
</td>
94+
<td class={styles().bodyCell}>
95+
{getColumnDefSummary(column)}
96+
</td>
97+
</tr>
98+
)}
99+
</For>
100+
</tbody>
101+
</table>
102+
</div>
103+
</div>
104+
)
105+
}

packages/table-devtools/src/components/FeaturesPanel.tsx

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { For } from 'solid-js'
2-
import { useStore } from '@tanstack/solid-store'
32
import { coreFeatures, stockFeatures } from '@tanstack/table-core'
43
import { useTableDevtoolsContext } from '../TableContextProvider'
4+
import { useTableStore } from '../useTableStore'
55
import { useStyles } from '../styles/use-styles'
66
import { ResizableSplit } from './ResizableSplit'
77

@@ -44,14 +44,40 @@ function getterToRowModelKey(getter: string): string | null {
4444
return withoutGet.charAt(0).toLowerCase() + withoutGet.slice(1)
4545
}
4646

47+
const ROW_MODEL_TO_GETTER: Record<
48+
string,
49+
(typeof EXECUTION_ORDER_GETTERS)[number]
50+
> = {
51+
coreRowModel: 'getCoreRowModel',
52+
filteredRowModel: 'getFilteredRowModel',
53+
preFilteredRowModel: 'getFilteredRowModel',
54+
groupedRowModel: 'getGroupedRowModel',
55+
preGroupedRowModel: 'getGroupedRowModel',
56+
sortedRowModel: 'getSortedRowModel',
57+
preSortedRowModel: 'getSortedRowModel',
58+
expandedRowModel: 'getExpandedRowModel',
59+
paginatedRowModel: 'getRowModel',
60+
}
61+
62+
function getRowCountForModel(
63+
tableInstance: { [key: string]: unknown } | undefined,
64+
rowModelName: string,
65+
): number {
66+
const getter = ROW_MODEL_TO_GETTER[rowModelName]
67+
if (!getter || typeof tableInstance?.[getter] !== 'function') return 0
68+
const result = (tableInstance[getter] as () => { rows?: Array<unknown> })()
69+
return result?.rows?.length ?? 0
70+
}
71+
4772
export function FeaturesPanel() {
4873
const styles = useStyles()
4974
const { table } = useTableDevtoolsContext()
5075

5176
const tableInstance = table()
52-
const tableState = tableInstance
53-
? useStore(tableInstance.store, (state) => state)
54-
: undefined
77+
const tableState = useTableStore(
78+
tableInstance ? tableInstance.store : undefined,
79+
(state) => state,
80+
)
5581

5682
const getTableFeatures = (): Set<string> => {
5783
tableState?.()
@@ -162,9 +188,15 @@ export function FeaturesPanel() {
162188
<For each={rowModelNames}>
163189
{(rowModelName) => {
164190
const fns = getRowModelFunctions(rowModelName)
191+
const count = getRowCountForModel(
192+
tableInstance as { [key: string]: unknown },
193+
rowModelName,
194+
)
165195
return (
166196
<div>
167-
<div class={styles().rowModelItem}>{rowModelName}</div>
197+
<div class={styles().rowModelItem}>
198+
{rowModelName} ({count.toLocaleString()} rows)
199+
</div>
168200
<For each={fns}>
169201
{(fnName) => (
170202
<div class={styles().rowModelFnItem}>{fnName}</div>

packages/table-devtools/src/components/RowsPanel.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { For, createSignal } from 'solid-js'
22
import { JsonTree } from '@tanstack/devtools-ui'
3-
import { useStore } from '@tanstack/solid-store'
43
import { useTableDevtoolsContext } from '../TableContextProvider'
4+
import { useTableStore } from '../useTableStore'
55
import { useStyles } from '../styles/use-styles'
66
import { ResizableSplit } from './ResizableSplit'
77

@@ -47,9 +47,10 @@ export function RowsPanel() {
4747
const styles = useStyles()
4848
const { table } = useTableDevtoolsContext()
4949
const tableInstance = table()
50-
const tableState = tableInstance
51-
? useStore(tableInstance.store, (state) => state)
52-
: undefined
50+
const tableState = useTableStore(
51+
tableInstance ? tableInstance.store : undefined,
52+
(state) => state,
53+
)
5354

5455
const [selectedRowModel, setSelectedRowModel] =
5556
createSignal<(typeof ROW_MODEL_GETTERS)[number]>('getRowModel')

packages/table-devtools/src/components/Shell.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Match, Switch } from 'solid-js'
22
import { Header, HeaderLogo, MainPanel } from '@tanstack/devtools-ui'
33
import { useTableDevtoolsContext } from '../TableContextProvider'
44
import { useStyles } from '../styles/use-styles'
5+
import { ColumnsPanel } from './ColumnsPanel'
56
import { FeaturesPanel } from './FeaturesPanel'
67
import { RowsPanel } from './RowsPanel'
78
import { StatePanel } from './StatePanel'
@@ -10,6 +11,7 @@ const tabs = [
1011
{ id: 'features', label: 'Features' },
1112
{ id: 'state', label: 'State' },
1213
{ id: 'rows', label: 'Rows' },
14+
{ id: 'columns', label: 'Columns' },
1315
] as const
1416

1517
export function Shell() {
@@ -55,6 +57,9 @@ export function Shell() {
5557
<Match when={activeTab() === 'rows'}>
5658
<RowsPanel />
5759
</Match>
60+
<Match when={activeTab() === 'columns'}>
61+
<ColumnsPanel />
62+
</Match>
5863
</Switch>
5964
</div>
6065
</div>

0 commit comments

Comments
 (0)