Skip to content

Commit e922897

Browse files
committed
chore: refactor columns as feature
1 parent 70713da commit e922897

9 files changed

Lines changed: 398 additions & 324 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"size-limit": [
3838
{
3939
"path": "packages/table-core/dist/cjs/index.cjs",
40-
"limit": "19 KB"
40+
"limit": "20 KB"
4141
},
4242
{
4343
"path": "packages/table-core/dist/esm/index.js",
Lines changed: 58 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,165 +1,68 @@
1-
import {
2-
Column,
3-
Table,
4-
AccessorFn,
5-
ColumnDef,
6-
RowData,
7-
ColumnDefResolved,
8-
} from '../../types'
91
import { getMemoOptions, memo } from '../../utils'
2+
import { Table, Column, RowData, TableFeature, CellData } from '../../types'
3+
import { _createColumn } from './CreateColumn'
4+
import {
5+
column_getFlatColumns,
6+
column_getLeafColumns,
7+
table_getAllColumns,
8+
table_getAllFlatColumns,
9+
table_getAllFlatColumnsById,
10+
table_getAllLeafColumns,
11+
table_getColumn,
12+
table_getDefaultColumnDef,
13+
} from './Columns.utils'
1014

11-
export interface Column_Core<TData extends RowData, TValue> {
12-
/**
13-
* The resolved accessor function to use when extracting the value for the column from each row. Will only be defined if the column def has a valid accessor key or function defined.
14-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#accessorfn)
15-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
16-
*/
17-
accessorFn?: AccessorFn<TData, TValue>
18-
/**
19-
* The original column def used to create the column.
20-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#columndef)
21-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
22-
*/
23-
columnDef: ColumnDef<TData, TValue>
24-
/**
25-
* The child column (if the column is a group column). Will be an empty array if the column is not a group column.
26-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#columns)
27-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
28-
*/
29-
columns: Column<TData, TValue>[]
30-
/**
31-
* The depth of the column (if grouped) relative to the root column def array.
32-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#depth)
33-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
34-
*/
35-
depth: number
36-
/**
37-
* Returns the flattened array of this column and all child/grand-child columns for this column.
38-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#getflatcolumns)
39-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
40-
*/
41-
getFlatColumns: () => Column<TData, TValue>[]
42-
/**
43-
* Returns an array of all leaf-node columns for this column. If a column has no children, it is considered the only leaf-node column.
44-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#getleafcolumns)
45-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
46-
*/
47-
getLeafColumns: () => Column<TData, TValue>[]
48-
/**
49-
* The resolved unique identifier for the column resolved in this priority:
50-
- A manual `id` property from the column def
51-
- The accessor key from the column def
52-
- The header string from the column def
53-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#id)
54-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
55-
*/
56-
id: string
57-
/**
58-
* The parent column for this column. Will be undefined if this is a root column.
59-
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#parent)
60-
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
61-
*/
62-
parent?: Column<TData, TValue>
63-
}
64-
65-
export function _createColumn<TData extends RowData, TValue>(
66-
table: Table<TData>,
67-
columnDef: ColumnDef<TData, TValue>,
68-
depth: number,
69-
parent?: Column<TData, TValue>
70-
): Column<TData, TValue> {
71-
const defaultColumn = table._getDefaultColumnDef()
72-
73-
const resolvedColumnDef = {
74-
...defaultColumn,
75-
...columnDef,
76-
} as ColumnDefResolved<TData>
77-
78-
const accessorKey = resolvedColumnDef.accessorKey
79-
80-
let id =
81-
resolvedColumnDef.id ??
82-
(accessorKey ? accessorKey.replace('.', '_') : undefined) ??
83-
(typeof resolvedColumnDef.header === 'string'
84-
? resolvedColumnDef.header
85-
: undefined)
86-
87-
let accessorFn: AccessorFn<TData> | undefined
88-
89-
if (resolvedColumnDef.accessorFn) {
90-
accessorFn = resolvedColumnDef.accessorFn
91-
} else if (accessorKey) {
92-
// Support deep accessor keys
93-
if (accessorKey.includes('.')) {
94-
accessorFn = (originalRow: TData) => {
95-
let result = originalRow as Record<string, any>
96-
97-
for (const key of accessorKey.split('.')) {
98-
result = result?.[key]
99-
if (process.env.NODE_ENV !== 'production' && result === undefined) {
100-
console.warn(
101-
`"${key}" in deeply nested key "${accessorKey}" returned undefined.`
102-
)
103-
}
104-
}
105-
106-
return result
107-
}
108-
} else {
109-
accessorFn = (originalRow: TData) =>
110-
(originalRow as any)[resolvedColumnDef.accessorKey]
111-
}
112-
}
113-
114-
if (!id) {
115-
if (process.env.NODE_ENV !== 'production') {
116-
throw new Error(
117-
resolvedColumnDef.accessorFn
118-
? `Columns require an id when using an accessorFn`
119-
: `Columns require an id when using a non-string header`
120-
)
121-
}
122-
throw new Error()
123-
}
124-
125-
let column: Column_Core<TData, any> = {
126-
id: `${String(id)}`,
127-
accessorFn,
128-
parent: parent as any,
129-
depth,
130-
columnDef: resolvedColumnDef as ColumnDef<TData, any>,
131-
columns: [],
132-
getFlatColumns: memo(
15+
export const Columns: TableFeature = {
16+
_createColumn: <TData extends RowData, TValue extends CellData>(
17+
column: Column<TData, TValue>,
18+
table: Table<TData>
19+
) => {
20+
column.getFlatColumns = memo(
13321
() => [true],
134-
() => {
135-
return [
136-
column as Column<TData, TValue>,
137-
...column.columns?.flatMap(d => d.getFlatColumns()),
138-
]
139-
},
22+
() => column_getFlatColumns(column),
14023
getMemoOptions(table.options, 'debugColumns', 'column.getFlatColumns')
141-
),
142-
getLeafColumns: memo(
24+
)
25+
26+
//@ts-ignore
27+
column.getLeafColumns = memo(
14328
() => [table._getOrderColumnsFn()],
144-
orderColumns => {
145-
if (column.columns?.length) {
146-
let leafColumns = column.columns.flatMap(column =>
147-
column.getLeafColumns()
148-
)
29+
orderColumns => column_getLeafColumns(column, orderColumns),
30+
getMemoOptions(table.options, 'debugColumns', 'column.getLeafColumns')
31+
)
32+
},
14933

150-
return orderColumns(leafColumns)
151-
}
34+
_createTable: <TData extends RowData>(table: Table<TData>) => {
35+
table._getDefaultColumnDef = memo(
36+
() => [table.options.defaultColumn],
37+
defaultColumn => table_getDefaultColumnDef(table, defaultColumn),
38+
getMemoOptions(table.options, 'debugColumns', '_getDefaultColumnDef')
39+
)
15240

153-
return [column as Column<TData, TValue>]
154-
},
155-
getMemoOptions(table.options, 'debugColumns', 'column.getLeafColumns')
156-
),
157-
}
41+
table.getAllColumns = memo(
42+
() => [table.options.columns],
43+
columnDefs => table_getAllColumns(table, columnDefs),
44+
getMemoOptions(table.options, 'debugColumns', 'getAllColumns')
45+
)
46+
47+
table.getAllFlatColumns = memo(
48+
() => [table.getAllColumns()],
49+
allColumns => table_getAllFlatColumns(allColumns),
50+
getMemoOptions(table.options, 'debugColumns', 'getAllFlatColumns')
51+
)
52+
53+
table._getAllFlatColumnsById = memo(
54+
() => [table.getAllFlatColumns()],
55+
flatColumns => table_getAllFlatColumnsById(flatColumns),
56+
getMemoOptions(table.options, 'debugColumns', 'getAllFlatColumnsById')
57+
)
15858

159-
for (const feature of table._features) {
160-
feature._createColumn?.(column as Column<TData, TValue>, table)
161-
}
59+
table.getAllLeafColumns = memo(
60+
() => [table.getAllColumns(), table._getOrderColumnsFn()],
61+
(allColumns, orderColumns) =>
62+
table_getAllLeafColumns(allColumns, orderColumns),
63+
getMemoOptions(table.options, 'debugColumns', 'getAllLeafColumns')
64+
)
16265

163-
// Yes, we have to convert table to unknown, because we know more than the compiler here.
164-
return column as Column<TData, TValue>
66+
table.getColumn = columnId => table_getColumn(table, columnId)
67+
},
16568
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { Column, AccessorFn, ColumnDef, RowData } from '../../types'
2+
3+
export interface Column_CoreProperties<TData extends RowData, TValue> {
4+
/**
5+
* The resolved accessor function to use when extracting the value for the column from each row. Will only be defined if the column def has a valid accessor key or function defined.
6+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#accessorfn)
7+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
8+
*/
9+
accessorFn?: AccessorFn<TData, TValue>
10+
/**
11+
* The original column def used to create the column.
12+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#columndef)
13+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
14+
*/
15+
columnDef: ColumnDef<TData, TValue>
16+
/**
17+
* The child column (if the column is a group column). Will be an empty array if the column is not a group column.
18+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#columns)
19+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
20+
*/
21+
columns: Column<TData, TValue>[]
22+
/**
23+
* The depth of the column (if grouped) relative to the root column def array.
24+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#depth)
25+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
26+
*/
27+
depth: number
28+
/**
29+
* The resolved unique identifier for the column resolved in this priority:
30+
- A manual `id` property from the column def
31+
- The accessor key from the column def
32+
- The header string from the column def
33+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#id)
34+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
35+
*/
36+
id: string
37+
/**
38+
* The parent column for this column. Will be undefined if this is a root column.
39+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#parent)
40+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
41+
*/
42+
parent?: Column<TData, TValue>
43+
}
44+
45+
export interface Column_Core<TData extends RowData, TValue>
46+
extends Column_CoreProperties<TData, TValue> {
47+
/**
48+
* Returns the flattened array of this column and all child/grand-child columns for this column.
49+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#getflatcolumns)
50+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
51+
*/
52+
getFlatColumns: () => Column<TData, TValue>[]
53+
/**
54+
* Returns an array of all leaf-node columns for this column. If a column has no children, it is considered the only leaf-node column.
55+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/column#getleafcolumns)
56+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/column-defs)
57+
*/
58+
getLeafColumns: () => Column<TData, TValue>[]
59+
}
60+
61+
export interface TableOptions_Columns<TData extends RowData> {
62+
/**
63+
* The array of column defs to use for the table.
64+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#columns)
65+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
66+
*/
67+
columns: ColumnDef<TData, any>[]
68+
/**
69+
* Set this option to `true` to output column debugging information to the console.
70+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#debugcolumns)
71+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
72+
*/
73+
debugColumns?: boolean
74+
/**
75+
* Default column options to use for all column defs supplied to the table.
76+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#defaultcolumn)
77+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
78+
*/
79+
defaultColumn?: Partial<ColumnDef<TData, unknown>>
80+
}
81+
82+
export interface Table_Columns<TData extends RowData> {
83+
_getAllFlatColumnsById: () => Record<string, Column<TData, unknown>>
84+
_getDefaultColumnDef: () => Partial<ColumnDef<TData, unknown>>
85+
/**
86+
* Returns all columns in the table in their normalized and nested hierarchy.
87+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#getallcolumns)
88+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
89+
*/
90+
getAllColumns: () => Column<TData, unknown>[]
91+
/**
92+
* Returns all columns in the table flattened to a single level.
93+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#getallflatcolumns)
94+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
95+
*/
96+
getAllFlatColumns: () => Column<TData, unknown>[]
97+
/**
98+
* Returns all leaf-node columns in the table flattened to a single level. This does not include parent columns.
99+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#getallleafcolumns)
100+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
101+
*/
102+
getAllLeafColumns: () => Column<TData, unknown>[]
103+
/**
104+
* Returns a single column by its ID.
105+
* @link [API Docs](https://tanstack.com/table/v8/docs/api/core/table#getcolumn)
106+
* @link [Guide](https://tanstack.com/table/v8/docs/guide/tables)
107+
*/
108+
getColumn: (columnId: string) => Column<TData, unknown> | undefined
109+
}

0 commit comments

Comments
 (0)