1- import { useLayoutEffect , useRef } from 'react' ;
2- import { flushSync } from 'react-dom' ;
1+ import { useLayoutEffect , useRef , useState } from 'react' ;
32
43import type { CalculatedColumn , StateSetter } from '../types' ;
54import type { DataGridProps } from '../DataGrid' ;
@@ -16,6 +15,7 @@ export function useColumnWidths<R, SR>(
1615 setMeasuredColumnWidths : StateSetter < ReadonlyMap < string , number > > ,
1716 onColumnResize : DataGridProps < R , SR > [ 'onColumnResize' ]
1817) {
18+ const [ columnToAutoresize , setColumnToAutoResize ] = useState < string | null > ( null ) ;
1919 const prevGridWidthRef = useRef ( gridWidth ) ;
2020 const columnsCanFlex : boolean = columns . length === viewportColumns . length ;
2121 // Allow columns to flex again when...
@@ -26,7 +26,10 @@ export function useColumnWidths<R, SR>(
2626 const columnsToMeasure : string [ ] = [ ] ;
2727
2828 for ( const { key, idx, width } of viewportColumns ) {
29- if (
29+ if ( key === columnToAutoresize ) {
30+ newTemplateColumns [ idx ] = 'max-content' ;
31+ columnsToMeasure . push ( key ) ;
32+ } else if (
3033 typeof width === 'string' &&
3134 ( ignorePreviouslyMeasuredColumns || ! measuredColumnWidths . has ( key ) ) &&
3235 ! resizedColumnWidths . has ( key )
@@ -62,40 +65,53 @@ export function useColumnWidths<R, SR>(
6265
6366 return hasChanges ? newMeasuredColumnWidths : measuredColumnWidths ;
6467 } ) ;
68+
69+ if ( columnToAutoresize !== null ) {
70+ setColumnToAutoResize ( null ) ;
71+ setResizedColumnWidths ( ( resizedColumnWidths ) => {
72+ const newResizedColumnWidths = new Map ( resizedColumnWidths ) ;
73+ newResizedColumnWidths . set (
74+ columnToAutoresize ,
75+ measureColumnWidth ( gridRef , columnToAutoresize ) !
76+ ) ;
77+ return newResizedColumnWidths ;
78+ } ) ;
79+ }
6580 }
6681
6782 function handleColumnResize ( column : CalculatedColumn < R , SR > , nextWidth : number | 'max-content' ) {
6883 const { key : resizingKey } = column ;
69- const newTemplateColumns = [ ...templateColumns ] ;
7084 const columnsToMeasure : string [ ] = [ ] ;
7185
72- for ( const { key, idx, width } of viewportColumns ) {
73- if ( resizingKey === key ) {
74- const width = typeof nextWidth === 'number' ? `${ nextWidth } px` : nextWidth ;
75- newTemplateColumns [ idx ] = width ;
76- } else if ( columnsCanFlex && typeof width === 'string' && ! resizedColumnWidths . has ( key ) ) {
77- newTemplateColumns [ idx ] = width ;
86+ for ( const { key, width } of viewportColumns ) {
87+ if (
88+ resizingKey !== key &&
89+ columnsCanFlex &&
90+ typeof width === 'string' &&
91+ ! resizedColumnWidths . has ( key )
92+ ) {
7893 columnsToMeasure . push ( key ) ;
7994 }
8095 }
8196
82- gridRef . current ! . style . gridTemplateColumns = newTemplateColumns . join ( ' ' ) ;
83- const measuredWidth =
84- typeof nextWidth === 'number' ? nextWidth : measureColumnWidth ( gridRef , resizingKey ) ! ;
97+ setMeasuredColumnWidths ( ( measuredColumnWidths ) => {
98+ const newMeasuredColumnWidths = new Map ( measuredColumnWidths ) ;
99+ for ( const columnKey of columnsToMeasure ) {
100+ newMeasuredColumnWidths . delete ( columnKey ) ;
101+ }
102+ return newMeasuredColumnWidths ;
103+ } ) ;
85104
86- // TODO: remove
87- // need flushSync to keep frozen column offsets in sync
88- // we may be able to use `startTransition` or even `requestIdleCallback` instead
89- flushSync ( ( ) => {
105+ if ( typeof nextWidth === 'number' ) {
90106 setResizedColumnWidths ( ( resizedColumnWidths ) => {
91107 const newResizedColumnWidths = new Map ( resizedColumnWidths ) ;
92- newResizedColumnWidths . set ( resizingKey , measuredWidth ) ;
108+ newResizedColumnWidths . set ( resizingKey , nextWidth ) ;
93109 return newResizedColumnWidths ;
94110 } ) ;
95- updateMeasuredWidths ( columnsToMeasure ) ;
96- } ) ;
97-
98- onColumnResize ?. ( column , measuredWidth ) ;
111+ onColumnResize ?. ( column , nextWidth ) ;
112+ } else {
113+ setColumnToAutoResize ( resizingKey ) ;
114+ }
99115 }
100116
101117 return {
0 commit comments