Skip to content

Commit 0a89a97

Browse files
feat: initColumnInstanceData (#6349)
* feat: initColumnInstanceData * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 2ee9de4 commit 0a89a97

4 files changed

Lines changed: 265 additions & 21 deletions

File tree

‎packages/table-core/src/core/columns/constructColumn.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,11 @@ export function constructColumn<
115115
column.id = `${String(id)}`
116116
column.parent = parent
117117

118+
// Initialize instance-specific data for features that need it
119+
const features = Object.values(table._features)
120+
for (let i = 0; i < features.length; i++) {
121+
features[i]!.initColumnInstanceData?.(column)
122+
}
123+
118124
return column as Column<TFeatures, TData, TValue>
119125
}

‎packages/table-core/src/types/TableFeatures.ts‎

Lines changed: 161 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { CoreFeatures } from '../core/coreFeatures'
22
import type { CellData, RowData, UnionToIntersection } from './type-utils'
3+
import type { Column } from './Column'
34
import type { ColumnDefBase_All } from './ColumnDef'
45
import type { Row } from './Row'
56
import type { Table_Internal } from './Table'
@@ -11,11 +12,31 @@ import type { FilterFn } from '../features/column-filtering/columnFilteringFeatu
1112
import type { SortFn } from '../features/row-sorting/rowSortingFeature.types'
1213
import type { AggregationFn } from '../features/column-grouping/columnGroupingFeature.types'
1314

15+
/**
16+
* Detects whether a type is `any`.
17+
*
18+
* Several feature-map helpers need a separate `any` path so broad generic
19+
* usage still exposes all known feature APIs instead of narrowing to no keys.
20+
*/
1421
export type IsAny<T> = 0 extends 1 & T ? true : false
22+
23+
/**
24+
* Converts a union to an intersection, returning `{}` for `never`.
25+
*
26+
* This keeps empty feature-map lookups usable as an intersection member.
27+
*/
1528
type UnionToIntersectionOrEmpty<T> = [T] extends [never]
1629
? {}
1730
: UnionToIntersection<T> & {}
1831

32+
/**
33+
* Extracts the API/types contributed by the features present in `TFeatures`.
34+
*
35+
* `TFeatureMap` maps feature keys to the types they contribute. When
36+
* `TFeatures` is `any`, all feature-map entries are included to preserve the
37+
* permissive behavior expected by broad table types. Otherwise, only entries
38+
* whose keys are present in `TFeatures` are intersected together.
39+
*/
1940
export type ExtractFeatureMapTypes<
2041
TFeatures extends TableFeatures,
2142
TFeatureMap extends object,
@@ -27,7 +48,11 @@ export type ExtractFeatureMapTypes<
2748
>
2849

2950
/**
30-
* This is an interface that you can delcaration-merge into to allow for custom plugins to be added to the table.
51+
* Declaration-merge target for custom table features.
52+
*
53+
* Add custom feature keys here so `TableFeatures` can accept them in the
54+
* `features` option and use the same feature-map extraction system as built-in
55+
* features.
3156
*/
3257
export interface Plugins {}
3358

@@ -64,19 +89,61 @@ export type NonFeatureKeys =
6489
* interface to get the same validation from `tableFeatures()`.
6590
*/
6691
export interface FeatureSlotPrereqs {
92+
/**
93+
* Named aggregation functions are only meaningful when grouping is enabled.
94+
*/
6795
aggregationFns: 'columnGroupingFeature'
68-
columnResizingFeature: 'columnSizingFeature' // columnSizingFeature is required for columnResizingFeature
96+
/**
97+
* Column resizing builds on the column sizing state and APIs.
98+
*/
99+
columnResizingFeature: 'columnSizingFeature'
100+
/**
101+
* Expanded row-model factories require row expanding APIs and state.
102+
*/
69103
expandedRowModel: 'rowExpandingFeature'
104+
/**
105+
* Faceted min/max factories require column faceting APIs.
106+
*/
70107
facetedMinMaxValues: 'columnFacetingFeature'
108+
/**
109+
* Faceted row-model factories require column faceting APIs.
110+
*/
71111
facetedRowModel: 'columnFacetingFeature'
112+
/**
113+
* Faceted unique-value factories require column faceting APIs.
114+
*/
72115
facetedUniqueValues: 'columnFacetingFeature'
116+
/**
117+
* Filtered row-model factories require column filtering APIs and state.
118+
*/
73119
filteredRowModel: 'columnFilteringFeature'
120+
/**
121+
* Named filter functions are only meaningful when column filtering is enabled.
122+
*/
74123
filterFns: 'columnFilteringFeature'
124+
/**
125+
* Filter metadata types are only read and written by filtering features.
126+
*/
75127
filterMeta: 'columnFilteringFeature'
76-
globalFilteringFeature: 'columnFilteringFeature' // columnFilteringFeature is required for globalFilteringFeature
128+
/**
129+
* Global filtering builds on column filtering state and filter functions.
130+
*/
131+
globalFilteringFeature: 'columnFilteringFeature'
132+
/**
133+
* Grouped row-model factories require column grouping APIs and state.
134+
*/
77135
groupedRowModel: 'columnGroupingFeature'
136+
/**
137+
* Paginated row-model factories require row pagination APIs and state.
138+
*/
78139
paginatedRowModel: 'rowPaginationFeature'
140+
/**
141+
* Sorted row-model factories require row sorting APIs and state.
142+
*/
79143
sortedRowModel: 'rowSortingFeature'
144+
/**
145+
* Named sorting functions are only meaningful when row sorting is enabled.
146+
*/
80147
sortFns: 'rowSortingFeature'
81148
}
82149

@@ -102,6 +169,15 @@ export type ValidateFeatureSlots<TFeatures extends TableFeatures> =
102169
: never
103170
}
104171

172+
/**
173+
* Complete feature registry for a table.
174+
*
175+
* This type combines core features, stock features, declaration-merged custom
176+
* plugins, row-model factory slots, function registries, and type-only meta
177+
* slots. The concrete `features` object passed to `tableFeatures()` determines
178+
* which feature APIs are included throughout table, row, column, cell, header,
179+
* options, and state types.
180+
*/
105181
export interface TableFeatures
106182
extends Partial<CoreFeatures>, Partial<StockFeatures>, Partial<Plugins> {
107183
/**
@@ -221,10 +297,22 @@ export interface TableFeatures
221297
tableMeta?: object
222298
}
223299

300+
/**
301+
* Lifecycle hooks and defaults contributed by a table feature.
302+
*
303+
* Feature objects are registered in the table's `features` option. They can
304+
* contribute default state/options, default column definitions, table APIs,
305+
* shared prototype APIs for rows/columns/headers/cells, and per-instance row
306+
* or column data.
307+
*/
224308
export interface TableFeature {
225309
/**
226-
* Assigns Cell APIs to the cell prototype for memory-efficient method sharing.
227-
* This is called once per table to build a shared prototype for all cells.
310+
* Adds feature methods to the shared cell prototype for a table.
311+
*
312+
* This runs lazily the first time a cell is constructed for a table. Methods
313+
* assigned here are shared by every cell instance created by that table, so
314+
* this hook should be used for APIs and memoized methods rather than
315+
* per-cell mutable data.
228316
*/
229317
assignCellPrototype?: <
230318
TFeatures extends TableFeatures,
@@ -234,8 +322,12 @@ export interface TableFeature {
234322
table: Table_Internal<TFeatures, TData>,
235323
) => void
236324
/**
237-
* Assigns Column APIs to the column prototype for memory-efficient method sharing.
238-
* This is called once per table to build a shared prototype for all columns.
325+
* Adds feature methods to the shared column prototype for a table.
326+
*
327+
* This runs lazily the first time a column is constructed for a table.
328+
* Methods assigned here are shared by every column instance created by that
329+
* table, so this hook should be used for APIs and memoized methods rather
330+
* than per-column mutable data.
239331
*/
240332
assignColumnPrototype?: <
241333
TFeatures extends TableFeatures,
@@ -245,8 +337,12 @@ export interface TableFeature {
245337
table: Table_Internal<TFeatures, TData>,
246338
) => void
247339
/**
248-
* Assigns Header APIs to the header prototype for memory-efficient method sharing.
249-
* This is called once per table to build a shared prototype for all headers.
340+
* Adds feature methods to the shared header prototype for a table.
341+
*
342+
* This runs lazily the first time a header is constructed for a table.
343+
* Methods assigned here are shared by every header instance created by that
344+
* table, so this hook should be used for APIs and memoized methods rather
345+
* than per-header mutable data.
250346
*/
251347
assignHeaderPrototype?: <
252348
TFeatures extends TableFeatures,
@@ -256,35 +352,85 @@ export interface TableFeature {
256352
table: Table_Internal<TFeatures, TData>,
257353
) => void
258354
/**
259-
* Assigns Row APIs to the row prototype for memory-efficient method sharing.
260-
* This is called once per table to build a shared prototype for all rows.
355+
* Adds feature methods to the shared row prototype for a table.
356+
*
357+
* This runs lazily the first time a row is constructed for a table. Methods
358+
* assigned here are shared by every row instance created by that table, so
359+
* this hook should be used for APIs and memoized methods rather than per-row
360+
* mutable data.
261361
*/
262362
assignRowPrototype?: <TFeatures extends TableFeatures, TData extends RowData>(
263363
prototype: Record<string, any>,
264364
table: Table_Internal<TFeatures, TData>,
265365
) => void
266366
/**
267-
* Assigns Table APIs to the table instance.
268-
* Unlike row/cell/column/header, the table is a singleton so methods are assigned directly.
367+
* Adds feature APIs directly to the table instance.
368+
*
369+
* The table is a singleton, unlike rows, columns, headers, and cells, so
370+
* table APIs are assigned directly instead of through a shared prototype.
371+
* This runs while the table is being constructed, after options and initial
372+
* state have been resolved.
269373
*/
270374
constructTableAPIs?: <TFeatures extends TableFeatures, TData extends RowData>(
271375
table: Table_Internal<TFeatures, TData>,
272376
) => void
377+
/**
378+
* Returns default column definition options contributed by this feature.
379+
*
380+
* These defaults are merged into the table's default column definition before
381+
* `options.defaultColumn` and before each user-supplied column definition is
382+
* resolved, so users can override values supplied here.
383+
*/
273384
getDefaultColumnDef?: <
274385
TFeatures extends TableFeatures,
275386
TData extends RowData,
276387
TValue extends CellData = CellData,
277388
>() => ColumnDefBase_All<TFeatures, TData, TValue>
389+
/**
390+
* Returns default table options contributed by this feature.
391+
*
392+
* This runs while table options are being resolved. Use it for option
393+
* defaults such as feature enablement flags and default state-updater
394+
* callbacks. User-supplied table options take precedence over values returned
395+
* here.
396+
*/
278397
getDefaultTableOptions?: <
279398
TFeatures extends TableFeatures,
280399
TData extends RowData,
281400
>(
282401
table: Table_Internal<TFeatures, TData>,
283402
) => Partial<TableOptions_All<TFeatures, TData>>
403+
/**
404+
* Returns this feature's initial table state.
405+
*
406+
* The incoming `initialState` contains state accumulated from earlier
407+
* features and user-provided initial state. Return a complete state object
408+
* for this feature, preserving `initialState` so user-provided values can
409+
* override feature defaults.
410+
*/
284411
getInitialState?: (initialState: Partial<TableState_All>) => TableState_All
285412
/**
286-
* Initializes instance-specific data on each row (e.g., caches).
287-
* Methods should be assigned via assignRowPrototype instead.
413+
* Initializes instance-specific data on each column.
414+
*
415+
* This runs for every constructed column after core column fields such as
416+
* `id`, `depth`, `parent`, `columnDef`, and `columns` have been assigned.
417+
* Use this for per-column mutable data, caches, or annotations. Shared
418+
* methods should be assigned via `assignColumnPrototype` instead.
419+
*/
420+
initColumnInstanceData?: <
421+
TFeatures extends TableFeatures,
422+
TData extends RowData,
423+
TValue extends CellData = CellData,
424+
>(
425+
column: Column<TFeatures, TData, TValue>,
426+
) => void
427+
/**
428+
* Initializes instance-specific data on each row.
429+
*
430+
* This runs for every constructed row after core row fields such as `id`,
431+
* `index`, `depth`, `original`, `parentId`, and `subRows` have been assigned.
432+
* Use this for per-row mutable data, caches, or annotations. Shared methods
433+
* should be assigned via `assignRowPrototype` instead.
288434
*/
289435
initRowInstanceData?: <
290436
TFeatures extends TableFeatures,

0 commit comments

Comments
 (0)