terra-clinical-data-grid
Version:
An organizational component that renders a collection of data in a grid-like format.
140 lines (125 loc) • 4.26 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import IconCaretUp from 'terra-icon/lib/icon/IconCaretUp';
import IconCaretDown from 'terra-icon/lib/icon/IconCaretDown';
import ThemeContext from 'terra-theme-context';
import Cell from './Cell';
import ResizeHandle from './ResizeHandle';
import { SortIndicators } from '../proptypes/columnDataShape';
import styles from './HeaderCell.module.scss';
const cx = classNames.bind(styles);
const propTypes = {
/**
* String identifier of the column in which the HeaderCell will be rendered.
*/
columnId: PropTypes.string.isRequired,
/**
* String-formatted width that the HeaderCell should be rendered as. Values are suggested to be in `rem`s (ex `'5rem'`), but any valid CSS height value is accepted.
*/
width: PropTypes.string.isRequired,
/**
* String text that will be rendered within the HeaderCell's default text region.
*/
text: PropTypes.string,
/**
* String indicating the sort direction of the column. If provided, a sorting indicator will be
* rendered within in the header. However, if custom children are also provided, the sorting indicator will
* not be rendered.
*/
sortIndicator: PropTypes.oneOf(Object.values(SortIndicators)),
/**
* Boolean indicating whether or not the HeaderCell is selectable.
*/
isSelectable: PropTypes.bool,
/**
* Function that will be called when the HeaderCell is selected. The `isSelectable` prop must be true for
* this function to be called.
*/
onSelect: PropTypes.func,
/**
* Boolean indicating whether or not the HeaderCell is resizable. If true, a ResizeHandle will be rendered
* over the HeaderCell's contents.
*/
isResizable: PropTypes.bool,
/**
* Function that will be called upon the release of the ResizeHandle. The `isResizable` prop must be be true
* for this function to be called. Parameters: `onResizeEnd(columnId, resizeDelta)`
*/
onResizeEnd: PropTypes.func,
/**
* Content that will rendered within the HeaderCell. If provided, the `text` and `sortIndicator` props will be ignored.
*/
children: PropTypes.node,
/**
* Function that will be called with a ref to the HeaderCell's selectable element. Parameters: `selectableRefCallback(selectableRef)`
*/
selectableRefCallback: PropTypes.func,
};
class HeaderCell extends React.Component {
constructor(props) {
super(props);
this.handleCellSelect = this.handleCellSelect.bind(this);
}
handleCellSelect(sectionId, rowId, columnId) {
const { onSelect } = this.props;
if (onSelect) {
onSelect(columnId);
}
}
render() {
const {
columnId,
text,
sortIndicator,
isSelectable,
isResizable,
width,
children,
onResizeEnd,
selectableRefCallback,
} = this.props;
let content = children;
const theme = this.context;
if (!content && (text || sortIndicator)) {
let sortIndicatorComponent;
if (sortIndicator) {
sortIndicatorComponent = (
<div className={cx('sort-indicator')}>
{sortIndicator === SortIndicators.ASCENDING ? <IconCaretUp /> : null}
{sortIndicator === SortIndicators.DESCENDING ? <IconCaretDown /> : null}
</div>
);
}
content = (
<div className={cx('default-layout')}>
<div className={cx('text')}>
{text}
</div>
{sortIndicatorComponent}
</div>
);
}
return (
<Cell
className={cx('header-cell', theme.className)}
sectionId=""
rowId=""
columnId={columnId}
width={width}
isSelectable={isSelectable}
onSelect={this.handleCellSelect}
selectableRefCallback={selectableRefCallback}
aria-hidden={!content || undefined} // Using '|| undefined' to unset the attribute instead of setting it to false.
role="columnheader"
>
{content}
{isResizable ? <ResizeHandle id={columnId} onResizeStop={onResizeEnd} /> : null }
</Cell>
);
}
}
HeaderCell.propTypes = propTypes;
HeaderCell.contextType = ThemeContext;
export default HeaderCell;
export { SortIndicators };