@6thquake/react-material
Version:
React components that implement Google's Material Design.
896 lines (759 loc) • 26.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _react = _interopRequireDefault(require("react"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _immutabilityHelper = _interopRequireDefault(require("immutability-helper"));
var _Head = _interopRequireDefault(require("./Head"));
var _Body = _interopRequireDefault(require("./Body"));
var _TableToolbar = _interopRequireDefault(require("./TableToolbar"));
var _Pagination = _interopRequireDefault(require("./Pagination"));
var _filter = _interopRequireDefault(require("../../utils/filter"));
var _NoData = _interopRequireDefault(require("../../NoData"));
var _styles = require("../../styles");
var _colorManipulator = require("../../styles/colorManipulator");
/**
* @ignore - do not document.
*/
var styles = function styles(theme) {
return {
root: {
display: 'flex',
flexDirection: 'column',
height: '100%',
width: '100%'
},
spacer: {
flex: 1
},
tbodyRoot: {
position: 'relative',
// height: `calc(100% - 120px)`,
overflowY: 'hidden'
},
main: {
overflowX: 'auto',
width: '100%'
},
left: {
position: 'absolute',
left: 0,
top: 0,
background: '#fff'
},
leftShadow: {
'box-shadow': '6px 0 6px -4px rgba(0,0,0,.2)'
},
right: {
position: 'absolute',
right: 0,
top: 0,
background: '#fff'
},
rightShadow: {
'box-shadow': '-6px 0 6px -4px rgba(0,0,0,.2)'
},
footer: {
display: 'flex',
borderTop: "1px solid\n ".concat(theme.palette.type === 'light' ? (0, _colorManipulator.lighten)((0, _colorManipulator.fade)(theme.palette.divider, 1), 0.88) : (0, _colorManipulator.darken)((0, _colorManipulator.fade)(theme.palette.divider, 1), 0.8))
},
footerLeft: {
display: 'flex',
flex: 1,
alignItems: 'center',
borderBottom: "1px solid\n ".concat(theme.palette.type === 'light' ? (0, _colorManipulator.lighten)((0, _colorManipulator.fade)(theme.palette.divider, 1), 0.88) : (0, _colorManipulator.darken)((0, _colorManipulator.fade)(theme.palette.divider, 1), 0.8)),
paddingLeft: theme.spacing(2)
},
pagination: {
display: 'flex',
justifyContent: 'flex-end'
}
};
};
var AwesomeTable =
/*#__PURE__*/
function (_React$Component) {
(0, _inherits2.default)(AwesomeTable, _React$Component);
function AwesomeTable(_props) {
var _this;
(0, _classCallCheck2.default)(this, AwesomeTable);
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(AwesomeTable).call(this, _props));
_this.searchedData = {
data: _this.props.data
};
_this.getSortConfig = function (props) {
var columns = props.columns; // this.sortsBy = new Set()
var sorts = [];
columns.map(function (col) {
if (col.sortable && col.order !== undefined) {
if (col.order === 'asc') {
sorts.push({
index: 0,
key: col.key,
order: col.order,
orderList: ['asc', 'desc', '']
});
}
if (col.order === 'desc') {
sorts.push({
index: 0,
key: col.key,
order: col.order,
orderList: ['desc', 'asc', '']
});
} else {
sorts.push({
index: 0,
key: col.key,
order: col.order,
orderList: ['', 'asc', 'desc']
});
} // this.sortsBy.add(key)
}
});
return {
sorts: sorts
};
};
_this.sortArray = ['asc', 'desc', ''];
_this.tableRefs = {
root: _react.default.createRef('root'),
left: _react.default.createRef('left'),
main: _react.default.createRef('main'),
right: _react.default.createRef('right'),
head: _react.default.createRef('head'),
body: _react.default.createRef('body'),
toolbar: _react.default.createRef('toolbar'),
pagination: _react.default.createRef('pagination')
};
_this.dragIndex = {
targetIndex: '',
sourceIndex: ''
};
_this.propsCached = {};
_this.normalizeColumns = function (columns) {
var leftColumns = columns.filter(function (item) {
return item.fixed === 'left';
});
var rightColumns = columns.filter(function (item) {
return item.fixed === 'right';
});
var unfixed = columns.filter(function (item) {
return !item.fixed;
});
return [].concat((0, _toConsumableArray2.default)(leftColumns), (0, _toConsumableArray2.default)(unfixed), (0, _toConsumableArray2.default)(rightColumns));
};
_this.syncTableRowHeight = function (isResize) {
var head = _this.tableRefs.head.current;
var body = _this.tableRefs.body.current;
if (!head || !body) {
return;
}
var headDom = _reactDom.default.findDOMNode(head);
var headHeight = headDom.getBoundingClientRect().height;
var bodyDom = _reactDom.default.findDOMNode(body);
var bodyHeight = bodyDom.getBoundingClientRect().height;
if (isResize) {
// todo : Resizable only axis=x
_this.setState({
bodyRowHeight: bodyHeight / _this.state.data.length
});
return;
}
_this.setState({
bodyRowHeight: bodyHeight / _this.state.data.length,
headRowHeight: headHeight
});
};
_this.handleColDrag = function (config) {
var targetIndex = config.targetIndex,
sourceIndex = config.sourceIndex;
var columns = _this.state.columns;
var sourceColumn = columns[sourceIndex];
var targetColumn = columns[targetIndex];
var fixed = targetColumn.fixed;
sourceColumn.fixed = fixed;
_this.setState((0, _immutabilityHelper.default)(_this.state, {
columns: {
$splice: [[sourceIndex, 1], [targetIndex, 0, sourceColumn]]
}
}));
};
_this.handleSort = function (sort, column) {
var order = sort.order,
index = sort.index,
key = sort.key;
var OrderProps = _this.props.OrderProps;
var sorts = _this.state.sorts;
var onChangeOrder = OrderProps.onChangeOrder,
multiple = OrderProps.multiple;
index = (index + 1) % sort.orderList.length;
order = sort.orderList[index];
var flag = true;
if (multiple) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = sorts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var s = _step.value;
if (s.key === key) {
s.order = order;
s.index = index;
flag = false;
break;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
flag && sorts.push({
key: key,
order: order,
index: index,
orderList: sort.orderList
});
} else {
sorts = [{
key: key,
order: order,
index: index,
orderList: sort.orderList
}];
}
_this.setState({
sorts: sorts
});
var data = sorts.map(function (item) {
return {
key: item.key,
order: item.order
};
});
onChangeOrder && onChangeOrder(data);
};
_this.handleResize = function (index, colomn, size) {
_this.setState(function (_ref) {
var columns = _ref.columns;
var nextColumns = (0, _toConsumableArray2.default)(columns);
nextColumns[index] = (0, _extends2.default)({}, nextColumns[index], {
width: size.width
});
return {
columns: nextColumns
};
}, function () {
_this.syncTableRowHeight(true);
});
};
_this.onSearch = function (text) {
_this.setState({
search: text
}, function () {
_this.filteredData();
});
};
_this.dragSatrt = function (index) {
_this.dragIndex.sourceIndex = index;
};
_this.dragEnd = function (index) {
// todo : 每次拖拽执行了两次, 多执行了一次。而且返回值不对
// 这里先用类型过滤掉多余的一次
if ((0, _typeof2.default)(index) === 'object') {
return;
}
var onColDrag = _this.props.onColDrag;
_this.dragIndex.targetIndex = index;
onColDrag && onColDrag(_this.dragIndex);
_this.handleColDrag(_this.dragIndex);
};
_this.filteredData = function () {
var _this$props = _this.props,
data = _this$props.data,
sync = _this$props.sync;
var search = _this.state.search;
var searchData = data;
if (search && sync) {
searchData = (0, _filter.default)(data, search);
}
_this.searchedData.data = searchData;
var result = _this.handlePaginteData();
return result;
};
_this.handlePaginteData = function () {
var data = _this.searchedData.data;
var _this$props2 = _this.props,
paginatable = _this$props2.paginatable,
sync = _this$props2.sync;
if (!sync) {
_this.setState({
data: data
});
return;
}
var _this$state = _this.state,
page = _this$state.page,
rowsPerPage = _this$state.rowsPerPage;
if (paginatable) {
data = data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
} else {
return data;
}
_this.setState({
data: data
});
};
_this.createCsv = function () {
var head = _this.state.columns.reduce(function (pre, cur) {
var text = cur.title;
return "".concat(pre, ",").concat(text);
}, '');
var csv = "".concat(head.slice(1), "\r\n");
var columns = _this.state.columns;
var data = _this.searchedData.data;
data.map(function (entry) {
var row = '';
columns.map(function (column) {
if (typeof column.render === 'function') {
var c = column.render(entry);
if (typeof c === 'number' || typeof c === 'string') {
row += "".concat(c, ",");
} else {
row += ' ';
}
} else {
row += "".concat(entry[column.dataIndex] || ' ', ",");
}
});
csv += "".concat(row, "\r\n");
});
return csv;
};
_this.download = function () {
var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'table';
var CSV = _this.createCsv();
var link = document.createElement('a');
var csvData = new Blob(["\uFEFF".concat(CSV)], {
type: 'text/csv'
});
var csvUrl = URL.createObjectURL(csvData);
link.href = csvUrl;
link.style = 'visibility:hidden';
link.download = "".concat(fileName, ".csv"); // this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
_this.renderMainTable = function () {
var columns = _this.state.columns;
var result = _this.renderTable(columns, 'main');
return result;
};
_this.renderLeftTable = function () {
var columns = _this.state.columns.filter(function (column) {
return column.fixed === 'left';
});
return _this.renderTable(columns, 'left');
};
_this.renderRightTable = function () {
var columns = _this.state.columns.filter(function (column) {
return column.fixed === 'right';
});
var baseLength = _this.state.columns.length - columns.length;
return _this.renderTable(columns, 'right', baseLength);
};
_this.renderTable = function (columns, type) {
var baseLength = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var _this$props3 = _this.props,
classes = _this$props3.classes,
resizable = _this$props3.resizable,
dragable = _this$props3.dragable,
onRowClick = _this$props3.onRowClick,
noData = _this$props3.noData,
disableClickToFixColumn = _this$props3.disableClickToFixColumn,
OrderProps = _this$props3.OrderProps,
TableCellProps = _this$props3.TableCellProps,
TableRowProps = _this$props3.TableRowProps;
var _this$state2 = _this.state,
bodyRowHeight = _this$state2.bodyRowHeight,
headRowHeight = _this$state2.headRowHeight,
hasLeft = _this$state2.hasLeft,
hasRight = _this$state2.hasRight,
bodyData = _this$state2.data,
sorts = _this$state2.sorts;
var width = type === 'main' ? '' : columns.reduce(function (pre, cur) {
return pre + cur.width;
}, 0);
var style = {
height: '100%',
overflowY: 'hidden',
width: width
};
var head = _react.default.createElement(_Head.default, {
OrderProps: OrderProps,
onSort: _this.handleSort,
sorts: sorts,
baseLength: baseLength,
headRef: type === 'main' ? _this.tableRefs.head : '',
columns: columns,
onResize: _this.handleResize,
resizable: resizable,
dragable: dragable,
onDragStart: _this.dragSatrt,
onDragEnd: _this.dragEnd,
headRowHeight: headRowHeight,
onColumnFixChange: _this.handleColumnFixSwitch,
disableClickToFixColumn: disableClickToFixColumn,
TableCellProps: TableCellProps,
TableRowProps: TableRowProps
});
var body = _react.default.createElement(_Body.default, {
bodyRef: type === 'main' ? _this.tableRefs.body : '',
data: bodyData,
columns: columns,
type: type,
height: "calc(100% - ".concat(headRowHeight, "px)"),
scroll: _this.handlScrollY,
tableRef: _this.tableRefs[type],
bodyRowHeight: bodyRowHeight,
onRowClick: onRowClick,
noData: noData,
TableCellProps: TableCellProps,
TableRowProps: TableRowProps
});
var table = [head, body];
var className = (0, _classnames.default)(classes[type], (0, _defineProperty2.default)({}, classes.leftShadow, type === 'left' && hasLeft), (0, _defineProperty2.default)({}, classes.rightShadow, type === 'right' && hasRight));
var result = _react.default.createElement("div", {
style: style,
ref: type === 'main' ? _this.tableRefs.root : null,
className: className
}, table);
return result;
};
_this.handleColumnFixSwitch = function (index, fixed) {
var columns = _this.state.columns;
columns[index].fixed = fixed;
_this.setState({
columns: _this.normalizeColumns(columns)
});
};
_this.handlScrollY = function (e, t) {
var scrollTop = e.target.scrollTop;
t !== 'left' && (_this.tableRefs.left.current.scrollTop = scrollTop);
t !== 'right' && (_this.tableRefs.right.current.scrollTop = scrollTop);
t !== 'main' && (_this.tableRefs.main.current.scrollTop = scrollTop);
};
_this.handleScrollX = function (e) {
var scrollLeft = e.target.scrollLeft;
if (e.target !== _this.tableRefs.root.current) {
return;
}
_this.setTableShadow(scrollLeft);
};
_this.handleChangePage = function (event, page) {
var TablePaginationProps = _this.props.TablePaginationProps;
var onChangePage = TablePaginationProps.onChangePage;
_this.setState({
page: page
}, function () {
_this.handlePaginteData();
});
onChangePage && onChangePage(event, page);
};
_this.handleChangeRowsPerPage = function (event) {
var TablePaginationProps = _this.props.TablePaginationProps;
var onChangeRowsPerPage = TablePaginationProps.onChangeRowsPerPage;
_this.setState({
rowsPerPage: event.target.value
}, function () {
_this.handlePaginteData();
});
onChangeRowsPerPage && onChangeRowsPerPage(event);
};
_this.setTableShadow = function (left) {
var _this$tableRefs$root$ = _this.tableRefs.root.current,
scrollLeft = _this$tableRefs$root$.scrollLeft,
clientWidth = _this$tableRefs$root$.clientWidth;
scrollLeft = left || scrollLeft;
var hasLeft = scrollLeft > 0;
var hasRight = _this.tableRefs.main.current.clientWidth - clientWidth - scrollLeft > 0;
_this.setState({
hasLeft: hasLeft,
hasRight: hasRight
});
};
var _columns = _this.normalizeColumns(_props.columns);
_this.state = {
hasLeft: false,
hasRight: true,
columns: _columns,
search: '',
page: _props.TablePaginationProps.page,
rowsPerPage: _props.TablePaginationProps.rowsPerPage,
data: _props.data,
sorts: _this.getSortConfig(_props).sorts
};
return _this;
}
(0, _createClass2.default)(AwesomeTable, [{
key: "componentDidMount",
value: function componentDidMount() {
this.setTableShadow();
this.syncTableRowHeight();
this.handlePaginteData();
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(nextProps, nextState) {
var _this$props4 = this.props,
data = _this$props4.data,
paginatable = _this$props4.paginatable,
searchable = _this$props4.searchable;
if (data !== this.propsCached.data) {
this.propsCached.data = data;
this.filteredData();
this.syncTableRowHeight(true);
}
if (searchable !== this.propsCached.searchable) {
this.propsCached.searchable = searchable;
this.filteredData();
}
if (paginatable !== this.propsCached.paginatable) {
this.propsCached.paginatable = paginatable;
this.filteredData();
}
}
}, {
key: "render",
value: function render() {
var _this$props5 = this.props,
classes = _this$props5.classes,
width = _this$props5.width,
paginatable = _this$props5.paginatable,
searchable = _this$props5.searchable,
exportProps = _this$props5.exportProps,
SearchProps = _this$props5.SearchProps,
sync = _this$props5.sync,
title = _this$props5.title,
total = _this$props5.total;
var _this$state3 = this.state,
page = _this$state3.page,
rowsPerPage = _this$state3.rowsPerPage;
var h = 0;
if (this.tableRefs.toolbar.current) {
h += this.tableRefs.toolbar.current.clientHeight;
}
if (this.tableRefs.pagination.current) {
h += this.tableRefs.pagination.current.clientHeight;
}
var tbodyStyle = {
height: "calc(100% - ".concat(h, "px)"),
width: width
};
return _react.default.createElement("div", {
className: classes.root
}, _react.default.createElement("div", {
ref: this.tableRefs.toolbar
}, _react.default.createElement(_TableToolbar.default, {
title: title,
onSearch: this.onSearch,
headRef: this.tableRefs.head,
bodyRef: this.tableRefs.body,
download: this.download,
searchable: searchable,
exportProps: exportProps,
SearchProps: SearchProps,
width: width
})), _react.default.createElement("div", {
style: tbodyStyle,
className: classes.tbodyRoot,
onScroll: this.handleScrollX
}, [this.renderMainTable(), this.renderLeftTable(), this.renderRightTable()]), _react.default.createElement("div", {
className: classes.footer,
style: {
width: width
}
}, _react.default.createElement("div", {
className: classes.footerLeft
}, total), paginatable && _react.default.createElement("div", {
ref: this.tableRefs.pagination,
className: classes.pagination
}, !sync ? _react.default.createElement(_Pagination.default, this.props.TablePaginationProps) : _react.default.createElement(_Pagination.default, (0, _extends2.default)({}, this.props.TablePaginationProps, {
page: page,
rowsPerPage: rowsPerPage,
count: this.searchedData.data.length,
onChangePage: this.handleChangePage,
onChangeRowsPerPage: this.handleChangeRowsPerPage
})))));
}
}]);
return AwesomeTable;
}(_react.default.Component);
AwesomeTable.propTypes = {
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css-api) below for more details.
*/
classes: _propTypes.default.object.isRequired,
/**
* Columns of table
*/
columns: _propTypes.default.shape({
dataIndex: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
fixed: _propTypes.default.oneOf(['left', 'right']),
key: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
order: _propTypes.default.string,
render: _propTypes.default.func,
renderTitle: _propTypes.default.func,
resizable: _propTypes.default.bool,
sortable: _propTypes.default.bool,
title: _propTypes.default.node,
width: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])
}),
/**
* Data record array to be displayed
*/
data: _propTypes.default.array.isRequired,
/**
* @ignore
*/
disableClickToFixColumn: _propTypes.default.bool,
/**
* if true, all the columns is dragable
*/
dragable: _propTypes.default.bool,
/**
* export config
*/
exportProps: _propTypes.default.shape({
type: _propTypes.default.oneOf(['csv'])
}),
/**
* table height
* @ignore
*/
height: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.number]),
/**
* render when data length is 0
*/
noData: _propTypes.default.element,
/**
* Callback fired when you drag the column
*/
onColDrag: _propTypes.default.func,
/**
* Callback fired when you click the table row
*/
onRowClick: _propTypes.default.func,
/**
* Properties applied to the Order
*/
OrderProps: _propTypes.default.shape({
multiple: _propTypes.default.bool,
onChangeOrder: _propTypes.default.func
}),
/**
* if true, it will be a paginatable table
*/
paginatable: _propTypes.default.bool,
/**
* if true, all the columns is resizable
*/
resizable: _propTypes.default.bool,
/**
* if true, it will be a searchable table
*/
searchable: _propTypes.default.bool,
/**
* Properties applied to the Search Component
*/
SearchProps: _propTypes.default.object,
/**
* if sync is true, pagination and search will be automatical.
* you need to do these things by yourself
*/
sync: _propTypes.default.bool,
/**
* Properties applied to the TableCell element.
*/
TableCellProps: _propTypes.default.object,
/**
* Properties applied to the TablePagination Component
*/
TablePaginationProps: _propTypes.default.object,
/**
* Properties applied to the TableRow element.
*/
TableRowProps: _propTypes.default.object,
/**
* The title of table
*/
title: _propTypes.default.node,
/**
* total
*/
total: _propTypes.default.element,
/**
* table width
* @ignore
*/
width: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.number])
};
AwesomeTable.defaultProps = {
TablePaginationProps: {
rowsPerPage: 10,
page: 0
},
data: [],
width: '100%',
// height: 'auto',
SearchProps: {
isDark: true,
floatRight: true
},
paginatable: false,
searchable: false,
resizable: false,
dragable: false,
sync: false,
noData: _react.default.createElement(_NoData.default, null),
disableClickToFixColumn: true,
OrderProps: {
multiple: false,
onChangeOrder: function onChangeOrder() {
for (var _len = arguments.length, arg = new Array(_len), _key = 0; _key < _len; _key++) {
arg[_key] = arguments[_key];
}
return console.log(arg);
}
}
};
var _default = (0, _styles.withStyles)(styles, {
withTheme: true
})(AwesomeTable);
exports.default = _default;