2017-04-17 17:14:17 +03:00
|
|
|
import React, { Component, cloneElement } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2016-05-26 21:37:57 +03:00
|
|
|
import classnames from 'classnames';
|
|
|
|
import { themr } from 'react-css-themr';
|
2017-01-26 20:05:32 +03:00
|
|
|
import filterReactChildren from '../utils/filter-react-children';
|
|
|
|
import isComponentOfType from '../utils/is-component-of-type';
|
|
|
|
import { TABLE } from '../identifiers';
|
|
|
|
import InjectTableHead from './TableHead';
|
|
|
|
import InjectTableRow from './TableRow';
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2016-05-30 07:59:44 +03:00
|
|
|
const factory = (TableHead, TableRow) => {
|
2017-01-05 04:42:18 +03:00
|
|
|
const isTableHead = child => isComponentOfType(TableHead, child);
|
|
|
|
const isTableRow = child => isComponentOfType(TableRow, child);
|
|
|
|
|
2016-05-30 07:59:44 +03:00
|
|
|
class Table extends Component {
|
|
|
|
static propTypes = {
|
2017-01-05 04:42:18 +03:00
|
|
|
children: PropTypes.node,
|
2016-05-30 07:59:44 +03:00
|
|
|
className: PropTypes.string,
|
|
|
|
multiSelectable: PropTypes.bool,
|
2017-01-05 04:42:18 +03:00
|
|
|
onRowSelect: PropTypes.func,
|
2016-05-30 07:59:44 +03:00
|
|
|
selectable: PropTypes.bool,
|
|
|
|
theme: PropTypes.shape({
|
2017-01-05 04:42:18 +03:00
|
|
|
head: PropTypes.string,
|
2017-01-26 20:05:32 +03:00
|
|
|
table: PropTypes.string,
|
|
|
|
}),
|
2016-05-30 07:59:44 +03:00
|
|
|
};
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2016-05-30 07:59:44 +03:00
|
|
|
static defaultProps = {
|
|
|
|
className: '',
|
2017-01-05 04:42:18 +03:00
|
|
|
multiSelectable: false,
|
2017-01-26 20:05:32 +03:00
|
|
|
selectable: true,
|
2016-05-30 07:59:44 +03:00
|
|
|
};
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2017-01-05 04:42:18 +03:00
|
|
|
getRowTuples = () => React.Children
|
|
|
|
.toArray(filterReactChildren(this.props.children, isTableRow))
|
|
|
|
.map((child, index) => [index, Boolean(child.props.selected)]);
|
|
|
|
|
2017-01-26 20:05:32 +03:00
|
|
|
handleHeadSelect = (value) => {
|
2017-01-05 04:42:18 +03:00
|
|
|
if (this.props.onRowSelect) {
|
|
|
|
this.props.onRowSelect(value
|
|
|
|
? this.getRowTuples().map(item => item[0])
|
|
|
|
: []);
|
2016-05-30 07:59:44 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-26 20:05:32 +03:00
|
|
|
handleRowSelect = (idx) => {
|
2017-01-05 04:42:18 +03:00
|
|
|
if (this.props.onRowSelect) {
|
2016-08-04 22:06:20 +03:00
|
|
|
if (this.props.multiSelectable) {
|
2017-01-05 04:42:18 +03:00
|
|
|
const current = this.getRowTuples().filter(item => item[1]).map(item => item[0]);
|
|
|
|
const rowIndex = current.indexOf(idx);
|
|
|
|
const indexes = rowIndex !== -1
|
|
|
|
? [...current.slice(0, rowIndex), ...current.slice(rowIndex + 1)]
|
|
|
|
: [...current, idx];
|
|
|
|
this.props.onRowSelect(indexes);
|
2016-08-04 22:06:20 +03:00
|
|
|
} else {
|
2017-01-05 04:42:18 +03:00
|
|
|
this.props.onRowSelect([idx]);
|
2016-07-24 20:40:53 +03:00
|
|
|
}
|
2016-05-30 07:59:44 +03:00
|
|
|
}
|
|
|
|
};
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2017-01-05 04:42:18 +03:00
|
|
|
renderHead = () => {
|
|
|
|
const tuples = this.getRowTuples();
|
|
|
|
const selected = tuples.filter(item => item[1]).length === tuples.length;
|
|
|
|
return React.Children.map(
|
|
|
|
filterReactChildren(this.props.children, isTableHead),
|
|
|
|
child => cloneElement(child, {
|
|
|
|
selected,
|
|
|
|
multiSelectable: this.props.multiSelectable,
|
|
|
|
onSelect: this.handleHeadSelect,
|
2017-01-26 20:05:32 +03:00
|
|
|
selectable: this.props.selectable,
|
|
|
|
}),
|
2017-01-05 04:42:18 +03:00
|
|
|
);
|
2016-05-30 07:59:44 +03:00
|
|
|
};
|
|
|
|
|
2017-01-05 04:42:18 +03:00
|
|
|
renderRows = () => React.Children.map(
|
|
|
|
filterReactChildren(this.props.children, isTableRow),
|
|
|
|
(child, idx) => cloneElement(child, {
|
|
|
|
idx,
|
|
|
|
onSelect: this.handleRowSelect,
|
2017-01-26 20:05:32 +03:00
|
|
|
selectable: this.props.selectable,
|
|
|
|
}),
|
2017-01-05 04:42:18 +03:00
|
|
|
);
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2017-01-26 20:05:32 +03:00
|
|
|
render() {
|
2017-01-05 04:42:18 +03:00
|
|
|
const {
|
|
|
|
className,
|
|
|
|
multiSelectable, // eslint-disable-line
|
|
|
|
onRowSelect, // eslint-disable-line
|
|
|
|
selectable, // eslint-disable-line
|
|
|
|
theme,
|
|
|
|
...rest
|
|
|
|
} = this.props;
|
2015-11-22 23:41:28 +03:00
|
|
|
return (
|
2017-01-05 04:42:18 +03:00
|
|
|
<table {...rest} className={classnames(theme.table, className)}>
|
2018-11-28 15:43:44 +03:00
|
|
|
<thead>{this.renderHead()}</thead>
|
2017-01-05 04:42:18 +03:00
|
|
|
<tbody>{this.renderRows()}</tbody>
|
2016-05-30 07:59:44 +03:00
|
|
|
</table>
|
2015-11-22 23:41:28 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 07:59:44 +03:00
|
|
|
return Table;
|
|
|
|
};
|
2015-11-22 23:41:28 +03:00
|
|
|
|
2017-01-05 04:42:18 +03:00
|
|
|
const Table = factory(InjectTableHead, InjectTableRow);
|
2016-05-30 07:59:44 +03:00
|
|
|
export default themr(TABLE)(Table);
|
|
|
|
export { factory as tableFactory };
|
|
|
|
export { Table };
|