UNPKG

@6thquake/react-material

Version:

React components that implement Google's Material Design.

898 lines (759 loc) 26 kB
"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, length) { var head = _this.tableRefs.head.current; var body = _this.tableRefs.body.current; if (!head || !body) { return; } var len = length || _this.state.data.length; 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 / len }); return; } console.log('bodyHeight'); _this.setState({ bodyHeight: bodyHeight, bodyRowHeight: bodyHeight / len, 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) { if (cur.render || !cur.title) { return pre; } return "".concat(pre, ",").concat(cur.title); }, ''); 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) { 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, bodyHeight = _this$state2.bodyHeight, 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 + parseInt(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, { syncTableRowHeight: _this.syncTableRowHeight, 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, bodyHeight: bodyHeight, 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 = { bodyHeight: 0, 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() { 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, /** * Properties applied to the TablePagination Component */ disableClickToFixColumn: _propTypes.default.bool, /** * export config */ dragable: _propTypes.default.bool, /** * Properties applied to the Search Component */ exportProps: _propTypes.default.shape({ type: _propTypes.default.oneOf(['csv']) }), /** * if true, it will be a paginatable table */ height: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.number]), /** * if true, it will be a searchable table */ noData: _propTypes.default.element, /** * if true, all the columns is resizable */ onColDrag: _propTypes.default.func, /** * if true, all the columns is dragable */ onRowClick: _propTypes.default.func, /** * table width * @ignore */ OrderProps: _propTypes.default.shape({ multiple: _propTypes.default.bool, onChangeOrder: _propTypes.default.func }), /** * table height * @ignore */ paginatable: _propTypes.default.bool, /** * Callback fired when you drag the column */ resizable: _propTypes.default.bool, /** * Callback fired when you click the table row */ searchable: _propTypes.default.bool, /** * if sync is true, pagination and search will be automatical. * you needn't to do these things by yourself */ SearchProps: _propTypes.default.object, /** * The title of table */ sync: _propTypes.default.bool, /** * render when data length is 0 */ TableCellProps: _propTypes.default.object, /** * @ignore */ TablePaginationProps: _propTypes.default.object, /** * Properties applied to the Order */ TableRowProps: _propTypes.default.object, /** * total */ title: _propTypes.default.node, /** * Properties applied to the TableCell element. */ total: _propTypes.default.element, /** * Properties applied to the TableRow element. */ 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;