Skip to content

Commit

Permalink
fix: allow resize for columns without explicit width
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmufazalov committed Apr 12, 2024
1 parent b1951a2 commit 6f288b2
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 50 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ The `name` field is the only mandatory field. The remaining fields are described
| headerTitle | `string` | Header title |
| className | `string` | Column class |
| width         | `string \| number` | Column width |
| resizeable     | `boolean` | Determines whether column width can be changed. Applied only if numeric `width` is set and `onResize` function is passed. |
| resizeable     | `boolean` | Determines whether column width can be changed. Applied only if `onResize` function is passed. |
| resizeMinWidth | `number` | Min column width for resize. |
| resizeMaxWidth | `number` | Max column width for resize. |
| align | `DataTable.LEFT DataTable.CENTER DataTable.RIGHT` | Text alignment in a cell |
Expand Down
2 changes: 2 additions & 0 deletions src/lib/DataTable.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ $cell-border: 1px solid var(--data-table-border-color);
}

&__th {
box-sizing: border-box;
font-weight: 500;
cursor: default;
padding: var(--data-table-header-vertical-padding) var(--data-table-cell-horizontal-padding);
Expand Down Expand Up @@ -98,6 +99,7 @@ $cell-border: 1px solid var(--data-table-border-color);
}

&__td {
box-sizing: border-box;
padding: var(--data-table-cell-vertical-padding) var(--data-table-cell-horizontal-padding);
border: $cell-border;
vertical-align: var(--data-table-cell-align);
Expand Down
60 changes: 29 additions & 31 deletions src/lib/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,19 @@ class TableRow<T> extends React.PureComponent<TableRowProps<T>> {

const value = column._getValue(row);

let style = column.customStyle({
row,
index,
name: column.name,
header: false,
footer,
headerData,
});

// Fixed cell width for resizeable columns for proper content wrap
if (column.resizeable) {
style = {...style, width: column.width, maxWidth: column.width};
}
const style = {
...column.customStyle({
row,
index,
name: column.name,
header: false,
footer,
headerData,
}),
// Fixed cell width for proper content wrap
width: column.width,
maxWidth: column.width,
};

return (
<td
Expand Down Expand Up @@ -264,18 +264,12 @@ class TableHead<T> extends React.Component<TableHeadProps<T>> {

const {headerTitle = (typeof header === 'string' && header) || undefined} = column;

let style = column.customStyle?.({header: true, name});

// Fixed cell width for resizeable columns for proper content wrap
if (resizeable) {
style = {...style, width, maxWidth: width};
}

// We set proper resizeable property in DataTableView getColumn method
// check column.resizeable should be sufficient
// However, it doesn't imply proper types
// So additional conditions to not add additional logic into ResizeHandler
const withResizeHandler = resizeable && onResize && typeof width === 'number';
const style = {
...column.customStyle?.({header: true, name}),
// Fixed cell width for proper content wrap
width,
maxWidth: width,
};

return (
<th
Expand All @@ -293,11 +287,12 @@ class TableHead<T> extends React.Component<TableHeadProps<T>> {
{header}
{<ColumnSortIcon {...column} />}
</div>
{withResizeHandler && (
{resizeable && (
<ResizeHandler
getColumn={this._getRenderedColumn}
columnIndex={columnIndex}
onResize={onResize}
columnId={name}
initialWidth={width}
minWidth={resizeMinWidth}
maxWidth={resizeMaxWidth}
/>
Expand Down Expand Up @@ -325,6 +320,12 @@ class TableHead<T> extends React.Component<TableHeadProps<T>> {
this.renderedColumns[index] = node;
};
};
_getRenderedColumn = (index?: number) => {
if (index) {
return this.renderedColumns[index];
}
return undefined;
};
}

interface StickyHeadProps<T> {
Expand Down Expand Up @@ -1143,10 +1144,7 @@ class DataTableView<T> extends React.Component<DataTableProps<T>, DataTableViewS
const {sortAccessor, onClick} = column;
const _className = b('td', {align}, column.className);

const resizeable =
(column.resizeable ?? settings.defaultResizeable) &&
typeof column.width === 'number' &&
Boolean(onResize);
const resizeable = (column.resizeable ?? settings.defaultResizeable) && Boolean(onResize);

const _getValue =
typeof accessor === 'function'
Expand Down
29 changes: 18 additions & 11 deletions src/lib/ResizeHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import React from 'react';
import {b, calculateColumnWidth, rafThrottle} from './util';

interface ResizeHandlerProps {
getColumn: (index?: number) => HTMLTableCellElement | undefined;
columnIndex?: number;
columnId: string;
initialWidth: number;
maxWidth?: number;
minWidth?: number;
onResize: (columnId: string, width: number) => void;
onResize?: (columnId: string, width: number) => void;
}

export function ResizeHandler({
getColumn,
columnIndex,
columnId,
initialWidth,
minWidth,
maxWidth,
onResize,
Expand All @@ -28,14 +30,14 @@ export function ResizeHandler({
return undefined;
}

let mouseXPosition: number | null = null;
let initialColumnWidth = initialWidth;
let currentColumnWidth = initialWidth;
let mouseXPosition: number | undefined;
let initialColumnWidth: number | undefined;
let currentColumnWidth: number | undefined;

const onMouseMove = rafThrottle((e: MouseEvent) => {
restrictMouseEvent(e);

if (typeof mouseXPosition !== 'number') {
if (typeof mouseXPosition !== 'number' || typeof initialColumnWidth !== 'number') {
return;
}

Expand All @@ -48,22 +50,27 @@ export function ResizeHandler({
}

currentColumnWidth = newWidth;
onResize(columnId, currentColumnWidth);

onResize?.(columnId, currentColumnWidth);
});

const onMouseUp = (e: MouseEvent) => {
restrictMouseEvent(e);

onResize(columnId, currentColumnWidth);
initialColumnWidth = currentColumnWidth;
if (currentColumnWidth !== undefined) {
onResize?.(columnId, currentColumnWidth);
}

setResizing(false);
mouseXPosition = undefined;

document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};

const onMouseDown = (e: MouseEvent) => {
initialColumnWidth = getColumn(columnIndex)?.getBoundingClientRect().width;

restrictMouseEvent(e);

mouseXPosition = e.clientX;
Expand All @@ -81,7 +88,7 @@ export function ResizeHandler({
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
}, [columnId, onResize, minWidth, maxWidth]);
}, [columnId, onResize, minWidth, maxWidth, getColumn, columnIndex]);

return (
<span
Expand Down
4 changes: 2 additions & 2 deletions src/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export function rafThrottle<Fn extends (...args: any[]) => any>(fn: Fn) {
};
}

// 30px minWidth so sort icon won't overlap wrapped column title
export function calculateColumnWidth(newWidth: number, minWidth = 30, maxWidth = Infinity) {
// 40px minWidth so sort icon won't overlap wrapped column title
export function calculateColumnWidth(newWidth: number, minWidth = 40, maxWidth = Infinity) {
return Math.max(minWidth, Math.min(newWidth, maxWidth));
}
5 changes: 0 additions & 5 deletions src/stories/Resizeable/Resizeable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,12 @@ type RowType = typeof data[number];
const columns: Column<RowType>[] = [
{
name: 'number',
width: 100,
},
{
name: 'col1',
width: 100,
},
{
name: 'col2',
width: 100,
},
{
name: 'string',
Expand Down Expand Up @@ -90,15 +87,13 @@ const columns: Column<RowType>[] = [
{
name: 'sub3-1',
accessor: 'something1',
width: 100,
},
],
},
],
},
{
name: 'something2',
width: 100,
},
],
},
Expand Down

0 comments on commit 6f288b2

Please sign in to comment.