@@ -50,6 +50,7 @@ import type {
50
50
CellSelectArgs ,
51
51
Column ,
52
52
ColumnOrColumnGroup ,
53
+ ColumnWidths ,
53
54
Direction ,
54
55
FillEvent ,
55
56
Maybe ,
@@ -159,6 +160,10 @@ export interface DataGridProps<R, SR = unknown, K extends Key = Key> extends Sha
159
160
* @default 35
160
161
*/
161
162
summaryRowHeight ?: Maybe < number > ;
163
+ /** A map of column widths */
164
+ columnWidths ?: Maybe < ColumnWidths > ;
165
+ /** Callback triggered when column widths change */
166
+ onColumnWidthsChange ?: Maybe < ( columnWidths : ColumnWidths ) => void > ;
162
167
163
168
/**
164
169
* Feature props
@@ -258,6 +263,8 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
258
263
rowHeight : rawRowHeight ,
259
264
headerRowHeight : rawHeaderRowHeight ,
260
265
summaryRowHeight : rawSummaryRowHeight ,
266
+ columnWidths : columnWidthsRaw ,
267
+ onColumnWidthsChange : onColumnWidthsChangeRaw ,
261
268
// Feature props
262
269
selectedRows,
263
270
isRowSelectionDisabled,
@@ -320,25 +327,32 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
320
327
*/
321
328
const [ scrollTop , setScrollTop ] = useState ( 0 ) ;
322
329
const [ scrollLeft , setScrollLeft ] = useState ( 0 ) ;
323
- const [ resizedColumnWidths , setResizedColumnWidths ] = useState (
324
- ( ) : ReadonlyMap < string , number > => new Map ( )
325
- ) ;
326
- const [ measuredColumnWidths , setMeasuredColumnWidths ] = useState (
327
- ( ) : ReadonlyMap < string , number > => new Map ( )
330
+ const [ columnWidthsInternal , setColumnWidthsInternal ] = useState (
331
+ ( ) : ColumnWidths => columnWidthsRaw ?? new Map ( )
328
332
) ;
333
+ const [ isColumnResizing , setColumnResizing ] = useState ( false ) ;
329
334
const [ isDragging , setDragging ] = useState ( false ) ;
330
335
const [ draggedOverRowIdx , setOverRowIdx ] = useState < number | undefined > ( undefined ) ;
331
336
const [ scrollToPosition , setScrollToPosition ] = useState < PartialPosition | null > ( null ) ;
332
337
const [ shouldFocusCell , setShouldFocusCell ] = useState ( false ) ;
333
338
const [ previousRowIdx , setPreviousRowIdx ] = useState ( - 1 ) ;
334
339
340
+ const isColumnWidthsControlled =
341
+ columnWidthsRaw != null && onColumnWidthsChangeRaw != null && ! isColumnResizing ;
342
+ const columnWidths = isColumnWidthsControlled ? columnWidthsRaw : columnWidthsInternal ;
343
+ const onColumnWidthsChange = isColumnWidthsControlled
344
+ ? ( columnWidths : ColumnWidths ) => {
345
+ // we keep the internal state in sync with the prop but this prevents an extra render
346
+ setColumnWidthsInternal ( columnWidths ) ;
347
+ onColumnWidthsChangeRaw ( columnWidths ) ;
348
+ }
349
+ : setColumnWidthsInternal ;
350
+
335
351
const getColumnWidth = useCallback (
336
352
( column : CalculatedColumn < R , SR > ) => {
337
- return (
338
- resizedColumnWidths . get ( column . key ) ?? measuredColumnWidths . get ( column . key ) ?? column . width
339
- ) ;
353
+ return columnWidths . get ( column . key ) ?. width ?? column . width ;
340
354
} ,
341
- [ measuredColumnWidths , resizedColumnWidths ]
355
+ [ columnWidths ]
342
356
) ;
343
357
344
358
const [ gridRef , gridWidth , gridHeight , horizontalScrollbarHeight ] = useGridDimensions ( ) ;
@@ -458,11 +472,10 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
458
472
templateColumns ,
459
473
gridRef ,
460
474
gridWidth ,
461
- resizedColumnWidths ,
462
- measuredColumnWidths ,
463
- setResizedColumnWidths ,
464
- setMeasuredColumnWidths ,
465
- onColumnResize
475
+ columnWidths ,
476
+ onColumnWidthsChange ,
477
+ onColumnResize ,
478
+ setColumnResizing
466
479
) ;
467
480
468
481
const minColIdx = isTreeGrid ? - 1 : 0 ;
@@ -476,6 +489,7 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
476
489
* The identity of the wrapper function is stable so it won't break memoization
477
490
*/
478
491
const handleColumnResizeLatest = useLatestFunc ( handleColumnResize ) ;
492
+ const handleColumnResizeEndLatest = useLatestFunc ( handleColumnResizeEnd ) ;
479
493
const onColumnsReorderLastest = useLatestFunc ( onColumnsReorder ) ;
480
494
const onSortColumnsChangeLatest = useLatestFunc ( onSortColumnsChange ) ;
481
495
const onCellClickLatest = useLatestFunc ( onCellClick ) ;
@@ -714,6 +728,14 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
714
728
}
715
729
}
716
730
731
+ function handleColumnResizeEnd ( ) {
732
+ // This check is needed as double click on the resize handle triggers onPointerMove
733
+ if ( isColumnResizing ) {
734
+ onColumnWidthsChangeRaw ?.( columnWidths ) ;
735
+ setColumnResizing ( false ) ;
736
+ }
737
+ }
738
+
717
739
/**
718
740
* utils
719
741
*/
@@ -1052,6 +1074,11 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
1052
1074
setDraggedOverRowIdx ( undefined ) ;
1053
1075
}
1054
1076
1077
+ // Keep the state and prop in sync
1078
+ if ( isColumnWidthsControlled && columnWidthsInternal !== columnWidthsRaw ) {
1079
+ setColumnWidthsInternal ( columnWidthsRaw ) ;
1080
+ }
1081
+
1055
1082
let templateRows = `repeat(${ headerRowsCount } , ${ headerRowHeight } px)` ;
1056
1083
if ( topSummaryRowsCount > 0 ) {
1057
1084
templateRows += ` repeat(${ topSummaryRowsCount } , ${ summaryRowHeight } px)` ;
@@ -1135,6 +1162,7 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
1135
1162
rowIdx = { headerRowsCount }
1136
1163
columns = { getRowViewportColumns ( mainHeaderRowIdx ) }
1137
1164
onColumnResize = { handleColumnResizeLatest }
1165
+ onColumnResizeEnd = { handleColumnResizeEndLatest }
1138
1166
onColumnsReorder = { onColumnsReorderLastest }
1139
1167
sortColumns = { sortColumns }
1140
1168
onSortColumnsChange = { onSortColumnsChangeLatest }
0 commit comments