-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Update column width calculation logic #3747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 42 commits
005c9f2
b66f3bd
51c2bdd
d4afa2b
ccaa437
69c46a2
f60e759
f736a3b
0e90906
523ec5a
8a6bb28
38e8d2f
6ced075
db17e49
f4e0cf2
d4dfc55
6ca4dd5
389c01e
2650ccb
2b338b0
20dd703
106842e
52b9237
a56574c
c90685c
4789821
d9063f6
fe0d696
d3b412d
e6bb382
03d9f61
0bc54d9
2522c3d
833b52d
b497648
42acc94
58b38d3
45bbadd
a905deb
ea69fac
a4672d6
852a7b5
b79becf
5bc91a8
aabb956
96887bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,28 +29,26 @@ export function useColumnWidths<R, SR>( | |
const newTemplateColumns = [...templateColumns]; | ||
const columnsToMeasure: string[] = []; | ||
|
||
for (const { key, idx, width } of viewportColumns) { | ||
for (const column of viewportColumns) { | ||
const { key, idx, width } = column; | ||
if (key === columnToAutoResize?.key) { | ||
newTemplateColumns[idx] = | ||
columnToAutoResize.width === 'max-content' | ||
? columnToAutoResize.width | ||
: `${columnToAutoResize.width}px`; | ||
newTemplateColumns[idx] = getColumnWidthForMeasurement(columnToAutoResize.width, column); | ||
columnsToMeasure.push(key); | ||
} else if ( | ||
typeof width === 'string' && | ||
(ignorePreviouslyMeasuredColumns || !measuredColumnWidths.has(key)) && | ||
// If the column is resized by the user, we don't want to measure it again | ||
!resizedColumnWidths.has(key) | ||
) { | ||
newTemplateColumns[idx] = width; | ||
newTemplateColumns[idx] = getColumnWidthForMeasurement(width, column); | ||
columnsToMeasure.push(key); | ||
} | ||
} | ||
|
||
const gridTemplateColumns = newTemplateColumns.join(' '); | ||
|
||
useLayoutEffect(updateMeasuredWidths); | ||
useLayoutEffect(updateMeasuredAndResizedWidths); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cannot inline this function as exhaustive deps rule complains. I can add |
||
|
||
function updateMeasuredWidths() { | ||
function updateMeasuredAndResizedWidths() { | ||
setPreviousGridWidth(gridWidth); | ||
if (columnsToMeasure.length === 0) return; | ||
|
||
|
@@ -112,8 +110,7 @@ export function useColumnWidths<R, SR>( | |
|
||
if (onColumnResize) { | ||
const previousWidth = resizedColumnWidths.get(resizingKey); | ||
const newWidth = | ||
typeof nextWidth === 'number' ? nextWidth : measureColumnWidth(gridRef, resizingKey); | ||
const newWidth = measureColumnWidth(gridRef, resizingKey); | ||
if (newWidth !== undefined && newWidth !== previousWidth) { | ||
onColumnResize(column, newWidth); | ||
} | ||
|
@@ -131,3 +128,47 @@ function measureColumnWidth(gridRef: React.RefObject<HTMLDivElement | null>, key | |
const measuringCell = gridRef.current?.querySelector(selector); | ||
return measuringCell?.getBoundingClientRect().width; | ||
} | ||
|
||
function getColumnWidthForMeasurement<R, SR>( | ||
width: number | string, | ||
{ minWidth, maxWidth }: CalculatedColumn<R, SR> | ||
) { | ||
const widthWithUnit = typeof width === 'number' ? `${width}px` : width; | ||
|
||
// don't break in Node.js (SSR) and jsdom | ||
if (typeof CSS === 'undefined') { | ||
return widthWithUnit; | ||
} | ||
|
||
const hasMaxWidth = maxWidth != null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to handle There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not 100% sure. My understanding is that grid computes the column widths and then apply min/max style from the measuring cell. This is the reason there was some left over space in the bug you found. I will check again There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, resizing does not work properly without this as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Found another edge case. |
||
const clampedWidth = hasMaxWidth | ||
? `clamp(${minWidth}px, ${widthWithUnit}, ${maxWidth}px)` | ||
: `max(${minWidth}px, ${widthWithUnit})`; | ||
|
||
// clamp() and max() do not handle all the css grid column width values | ||
if (isValidCSSGridColumnWidth(clampedWidth)) { | ||
return clampedWidth; | ||
} | ||
|
||
if ( | ||
hasMaxWidth && | ||
// ignore maxWidth if it less than minWidth | ||
maxWidth >= minWidth && | ||
// we do not want to use minmax with max-content as it | ||
// can result in width being larger than max-content | ||
widthWithUnit !== 'max-content' | ||
) { | ||
// We are setting maxWidth on the measuring cell but the browser only applies | ||
// it after all the widths are calculated. This results in left over space in some cases. | ||
const minMaxWidth = `minmax(${widthWithUnit}, ${maxWidth}px)`; | ||
if (isValidCSSGridColumnWidth(minMaxWidth)) { | ||
return minMaxWidth; | ||
} | ||
} | ||
|
||
return isValidCSSGridColumnWidth(widthWithUnit) ? widthWithUnit : 'auto'; | ||
} | ||
|
||
function isValidCSSGridColumnWidth(width: string) { | ||
return CSS.supports('grid-template-columns', width); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible that a column has a
width
less thanminWidth
or greater thanmaxWidth
so we may have more or less viewport columns initially but they will be updated once the actual width is measured. I think this scenario is unlikely so I removedclampColumnWidth
.getColumnWidthForMeasurement
handles it using cssclamp
function now. I am okay with adding it back if you prefer