horizontal scrolling
Summary: Adding a property `horizontallyScrollable` the `ManagedTable` that enables horizontal scrolling, if that is required by the table's contents. By default this behaviour is disabled to not break existing tables. Reviewed By: jknoxville Differential Revision: D15166144 fbshipit-source-id: 7a9b76facdbe717deb3d097e0b8883d4b0732d51
This commit is contained in:
committed by
Facebook Github Bot
parent
da44a02cad
commit
fca7bc93ee
@@ -116,6 +116,10 @@ export type ManagedTableProps = {|
|
||||
* Callback when sorting changes
|
||||
*/
|
||||
onSort?: (order: TableRowSortOrder) => void,
|
||||
/**
|
||||
* Table scroll horizontally, if needed
|
||||
*/
|
||||
horizontallyScrollable?: boolean,
|
||||
|};
|
||||
|
||||
type ManagedTableState = {|
|
||||
@@ -126,9 +130,10 @@ type ManagedTableState = {|
|
||||
shouldScrollToBottom: boolean,
|
||||
|};
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
const Container = styled(FlexColumn)(props => ({
|
||||
overflow: props.overflow ? 'scroll' : 'visible',
|
||||
flexGrow: 1,
|
||||
});
|
||||
}));
|
||||
|
||||
class ManagedTable extends React.Component<
|
||||
ManagedTableProps,
|
||||
@@ -318,8 +323,13 @@ class ManagedTable extends React.Component<
|
||||
);
|
||||
};
|
||||
|
||||
onColumnResize = (columnSizes: TableColumnSizes) => {
|
||||
this.setState({columnSizes});
|
||||
onColumnResize = (id: string, width: number | string) => {
|
||||
this.setState(({columnSizes}) => ({
|
||||
columnSizes: {
|
||||
...columnSizes,
|
||||
[id]: width,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
scrollToBottom() {
|
||||
@@ -499,7 +509,13 @@ class ManagedTable extends React.Component<
|
||||
);
|
||||
|
||||
getRow = ({index, style}) => {
|
||||
const {onAddFilter, multiline, zebra, rows} = this.props;
|
||||
const {
|
||||
onAddFilter,
|
||||
multiline,
|
||||
zebra,
|
||||
rows,
|
||||
horizontallyScrollable,
|
||||
} = this.props;
|
||||
const {columnOrder, columnSizes, highlightedRows} = this.state;
|
||||
const columnKeys = columnOrder
|
||||
.map(k => (k.visible ? k.key : null))
|
||||
@@ -520,16 +536,37 @@ class ManagedTable extends React.Component<
|
||||
style={style}
|
||||
onAddFilter={onAddFilter}
|
||||
zebra={zebra}
|
||||
horizontallyScrollable={horizontallyScrollable}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {columns, rows, rowLineHeight, hideHeader} = this.props;
|
||||
const {
|
||||
columns,
|
||||
rows,
|
||||
rowLineHeight,
|
||||
hideHeader,
|
||||
horizontallyScrollable,
|
||||
} = this.props;
|
||||
const {columnOrder, columnSizes} = this.state;
|
||||
|
||||
let computedWidth = 0;
|
||||
if (horizontallyScrollable) {
|
||||
for (const col in columnSizes) {
|
||||
const width = columnSizes[col];
|
||||
if (isNaN(width)) {
|
||||
// non-numeric columns with, can't caluclate
|
||||
computedWidth = 0;
|
||||
break;
|
||||
} else {
|
||||
computedWidth += parseInt(width, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Container overflow={horizontallyScrollable}>
|
||||
{hideHeader !== true && (
|
||||
<TableHead
|
||||
columnOrder={columnOrder}
|
||||
@@ -539,6 +576,7 @@ class ManagedTable extends React.Component<
|
||||
sortOrder={this.state.sortOrder}
|
||||
columnSizes={columnSizes}
|
||||
onSort={this.onSort}
|
||||
horizontallyScrollable={horizontallyScrollable}
|
||||
/>
|
||||
)}
|
||||
<Container>
|
||||
@@ -560,7 +598,7 @@ class ManagedTable extends React.Component<
|
||||
DEFAULT_ROW_HEIGHT
|
||||
}
|
||||
ref={this.tableRef}
|
||||
width={width}
|
||||
width={Math.max(width, computedWidth)}
|
||||
estimatedItemSize={rowLineHeight || DEFAULT_ROW_HEIGHT}
|
||||
overscanCount={5}
|
||||
innerRef={this.scrollRef}
|
||||
|
||||
@@ -43,7 +43,7 @@ const TableHeaderColumnContainer = styled('div')({
|
||||
padding: '0 8px',
|
||||
});
|
||||
|
||||
const TableHeadContainer = styled(FlexRow)({
|
||||
const TableHeadContainer = styled(FlexRow)(props => ({
|
||||
borderBottom: `1px solid ${colors.sectionHeaderBorder}`,
|
||||
color: colors.light50,
|
||||
flexShrink: 0,
|
||||
@@ -53,7 +53,8 @@ const TableHeadContainer = styled(FlexRow)({
|
||||
textAlign: 'left',
|
||||
top: 0,
|
||||
zIndex: 2,
|
||||
});
|
||||
minWidth: props.horizontallyScrollable ? 'min-content' : 0,
|
||||
}));
|
||||
|
||||
const TableHeadColumnContainer = styled('div')(props => ({
|
||||
position: 'relative',
|
||||
@@ -97,9 +98,17 @@ class TableHeadColumn extends PureComponent<{
|
||||
onColumnResize: ?TableOnColumnResize,
|
||||
children?: React$Node,
|
||||
title?: string,
|
||||
horizontallyScrollable?: boolean,
|
||||
}> {
|
||||
ref: HTMLElement;
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.horizontallyScrollable) {
|
||||
// measure initial width
|
||||
this.onResize(this.ref.offsetWidth);
|
||||
}
|
||||
}
|
||||
|
||||
onClick = () => {
|
||||
const {id, onSort, sortOrder} = this.props;
|
||||
|
||||
@@ -117,7 +126,7 @@ class TableHeadColumn extends PureComponent<{
|
||||
};
|
||||
|
||||
onResize = (newWidth: number) => {
|
||||
const {id, columnSizes, onColumnResize, width} = this.props;
|
||||
const {id, onColumnResize, width} = this.props;
|
||||
if (!onColumnResize) {
|
||||
return;
|
||||
}
|
||||
@@ -143,10 +152,7 @@ class TableHeadColumn extends PureComponent<{
|
||||
}
|
||||
}
|
||||
|
||||
onColumnResize({
|
||||
...columnSizes,
|
||||
[id]: normalizedWidth,
|
||||
});
|
||||
onColumnResize(id, normalizedWidth);
|
||||
};
|
||||
|
||||
setRef = (ref: HTMLElement) => {
|
||||
@@ -191,6 +197,7 @@ export default class TableHead extends PureComponent<{
|
||||
onSort: ?TableOnSort,
|
||||
columnSizes: TableColumnSizes,
|
||||
onColumnResize: ?TableOnColumnResize,
|
||||
horizontallyScrollable?: boolean,
|
||||
}> {
|
||||
buildContextMenu = (): MenuTemplate => {
|
||||
const visibles = this.props.columnOrder
|
||||
@@ -237,6 +244,7 @@ export default class TableHead extends PureComponent<{
|
||||
onColumnResize,
|
||||
onSort,
|
||||
sortOrder,
|
||||
horizontallyScrollable,
|
||||
} = this.props;
|
||||
const elems = [];
|
||||
|
||||
@@ -284,7 +292,8 @@ export default class TableHead extends PureComponent<{
|
||||
onSort={onSort}
|
||||
columnSizes={columnSizes}
|
||||
onColumnResize={onColumnResize}
|
||||
title={key}>
|
||||
title={key}
|
||||
horizontallyScrollable={horizontallyScrollable}>
|
||||
{col.value}
|
||||
{arrow}
|
||||
</TableHeadColumn>
|
||||
@@ -296,10 +305,11 @@ export default class TableHead extends PureComponent<{
|
||||
|
||||
lastResizable = isResizable;
|
||||
}
|
||||
|
||||
return (
|
||||
<ContextMenu buildItems={this.buildContextMenu}>
|
||||
<TableHeadContainer>{elems}</TableHeadContainer>
|
||||
<TableHeadContainer horizontallyScrollable={horizontallyScrollable}>
|
||||
{elems}
|
||||
</TableHeadContainer>
|
||||
</ContextMenu>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export type TableHighlightedRows = Array<string>;
|
||||
|
||||
export type TableColumnKeys = Array<string>;
|
||||
|
||||
export type TableOnColumnResize = (sizes: TableColumnSizes) => void;
|
||||
export type TableOnColumnResize = (id: string, size: number | string) => void;
|
||||
export type TableOnColumnOrder = (order: TableColumnOrder) => void;
|
||||
export type TableOnSort = (order: TableRowSortOrder) => void;
|
||||
export type TableOnHighlight = (
|
||||
|
||||
Reference in New Issue
Block a user