@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
183 lines (164 loc) • 4.96 kB
JSX
/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
// ### React
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
// ### classNames
import classNames from 'classnames';
// ### isFunction
import isFunction from 'lodash.isfunction';
// ## Children
import Icon from '../../icon';
// This component's `checkProps` which issues warnings to developers about properties when in development mode (similar to React's built in development tools)
import checkProps from '../column-check-props';
// ## Constants
import {
DATA_TABLE_HEADER_CELL,
DATA_TABLE_COLUMN
} from '../../../utilities/constants';
/**
* Used internally, renders each individual column heading.
*/
const DataTableHeaderCell = createReactClass({
// ### Display Name
// Always use the canonical component name as the React display name.
displayName: DATA_TABLE_HEADER_CELL,
// ### Prop Types
propTypes: {
/**
* Text for sort action on table column header
*
*/
assistiveTextForColumnSort: PropTypes.string,
/**
* Text announced once a column is sorted in ascending order
*/
assistiveTextForColumnSortedAscending: PropTypes.string,
/**
* Text announced once a column is sorted in descending order
*/
assistiveTextForColumnSortedDescending: PropTypes.string,
id: PropTypes.string.isRequired,
/**
* Indicates if column is sorted.
*/
isSorted: PropTypes.bool,
/**
* The column label.
*/
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
/**
* The function to execute on sort.
*/
onSort: PropTypes.func,
/**
* The property which corresponds to this column.
*/
property: PropTypes.string,
/**
* Whether or not the column is sortable.
*/
sortable: PropTypes.bool,
/**
* The current sort direction.
*/
sortDirection: PropTypes.oneOf(['desc', 'asc']),
/**
* Width of column. This is required for advanced/fixed layout tables. Please provide units. (`rems` are recommended)
*/
width: PropTypes.string
},
getInitialState () {
return {
sortDirection: null
};
},
componentDidMount () {
checkProps(DATA_TABLE_COLUMN, this.props);
},
componentDidUpdate (prevProps) {
// reset sort state when another column is sorted
if (prevProps.isSorted === true && this.props.isSorted === false) {
this.setState({ sortDirection: null }); // eslint-disable-line react/no-did-update-set-state
}
},
handleSort (e) {
const oldSortDirection =
this.props.sortDirection || this.state.sortDirection;
const sortDirection = oldSortDirection === 'asc' ? 'desc' : 'asc';
const data = {
property: this.props.property,
sortDirection
};
this.setState({
sortDirection
});
if (isFunction(this.props.onSort)) {
this.props.onSort(data, e);
}
},
// ### Render
// Should return a `<th></th>`.
render () {
const { isSorted, label, sortable, width } = this.props;
const labelType = typeof label;
const sortDirection = this.props.sortDirection || this.state.sortDirection;
const expandedSortDirection =
sortDirection === 'desc' ? 'descending' : 'ascending';
const ariaSort = isSorted ? expandedSortDirection : null;
return (
<th
aria-sort={ariaSort}
className={classNames({
'slds-is-sortable': sortable,
'slds-is-sorted': isSorted,
[`slds-is-sorted--${sortDirection}`]: sortDirection,
'slds-is-sorted--asc': isSorted && !sortDirection // default for hover, up arrow is ascending which means A is at the top of the table, and Z is at the bottom. You have to think about row numbers abstracting, and not the visual order on the table.
})}
focusable={sortable ? true : null}
scope="col"
style={width ? { width } : null}
>
{sortable ? (
<a
href="javascript:void(0)" // eslint-disable-line no-script-url
className="slds-th__action slds-text-link--reset"
onClick={this.handleSort}
tabIndex="0"
>
<span className="slds-assistive-text">
{this.props.assistiveTextForColumnSort}{' '}
</span>
<span
className="slds-truncate"
title={labelType === 'string' ? label : undefined}
>
{label}
</span>
<Icon
className="slds-is-sortable__icon"
category="utility"
name={sortDirection === 'desc' ? 'arrowdown' : 'arrowup'}
size="x-small"
/>
{sortDirection ? (
<span
className="slds-assistive-text"
aria-live="assertive"
aria-atomic="true"
>
{sortDirection === 'asc'
? this.props.assistiveTextForColumnSortedAscending
: this.props.assistiveTextForColumnSortedDescending}
</span>
) : null}
</a>
) : (
<div className="slds-truncate">{label}</div>
)}
</th>
);
}
});
export default DataTableHeaderCell;