UNPKG

choerodon-ui

Version:

An enterprise-class UI design language and React-based implementation

1,350 lines (1,110 loc) 71.3 kB
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _objectSpread from "@babel/runtime/helpers/objectSpread2"; import _extends from "@babel/runtime/helpers/extends"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _inherits from "@babel/runtime/helpers/inherits"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; function _createSuper(Derived) { function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } return function () { var Super = _getPrototypeOf(Derived), result; if (isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } import * as React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import isFunction from 'lodash/isFunction'; import flatten from 'lodash/flatten'; import debounce from 'lodash/debounce'; import isEqual from 'lodash/isEqual'; import eq from 'lodash/eq'; import omit from 'lodash/omit'; import merge from 'lodash/merge'; import bindElementResize, { unbind as unbindElementResize } from 'element-resize-event'; import { getTranslateDOMPositionXY } from "dom-lib/es/transition/translateDOMPositionXY"; import { addStyle, getHeight, getOffset, getWidth, on, scrollLeft, scrollTop, WheelHandler } from 'dom-lib'; import { toPx } from '../../../es/_util/UnitConvertor'; import LocaleReceiver from '../../../es/locale-provider/LocaleReceiver'; import defaultLocale from '../../../es/locale-provider/default'; import Row from './Row'; import CellGroup from './CellGroup'; import Scrollbar from './Scrollbar'; import TableContext from './TableContext'; import { CELL_PADDING_HEIGHT, SCROLLBAR_WIDTH } from './constants'; import { cancelAnimationTimeout, defaultClassPrefix, findAllParents, findRowKeys, flattenData, getTotalByColumns, getUnhandledProps, isNumberOrTrue, isRTL as _isRTL, mergeCells, prefix, requestAnimationTimeout, resetLeftForCells, shouldShowRowByExpanded, toggleClass } from './utils'; import ColumnGroup from './ColumnGroup'; import Column from './Column'; import Cell from './Cell'; import HeaderCell from './HeaderCell'; import Spin from '../spin'; var SORT_TYPE = { DESC: 'desc', ASC: 'asc' }; var PerformanceTable = /*#__PURE__*/ function (_React$Component) { _inherits(PerformanceTable, _React$Component); var _super = _createSuper(PerformanceTable); function PerformanceTable(props) { var _this; _classCallCheck(this, PerformanceTable); _this = _super.call(this, props); _this.translateDOMPositionXY = null; _this.scrollListener = null; _this.tableRows = {}; _this.mounted = false; _this.disableEventsTimeoutId = null; _this.scrollY = 0; _this.scrollX = 0; _this._cacheCells = null; _this._cacheChildrenSize = 0; _this._visibleRows = []; _this.listenWheel = function (deltaX, deltaY) { var _this$scrollbarXRef$c, _this$scrollbarXRef$c2, _this$scrollbarYRef$c, _this$scrollbarYRef$c2; _this.handleWheel(deltaX, deltaY); (_this$scrollbarXRef$c = _this.scrollbarXRef.current) === null || _this$scrollbarXRef$c === void 0 ? void 0 : (_this$scrollbarXRef$c2 = _this$scrollbarXRef$c.onWheelScroll) === null || _this$scrollbarXRef$c2 === void 0 ? void 0 : _this$scrollbarXRef$c2.call(_this$scrollbarXRef$c, deltaX); (_this$scrollbarYRef$c = _this.scrollbarYRef.current) === null || _this$scrollbarYRef$c === void 0 ? void 0 : (_this$scrollbarYRef$c2 = _this$scrollbarYRef$c.onWheelScroll) === null || _this$scrollbarYRef$c2 === void 0 ? void 0 : _this$scrollbarYRef$c2.call(_this$scrollbarYRef$c, deltaY); }; _this.setOffsetByAffix = function () { var _this$headerWrapperRe, _this$tableRef; var _this$props = _this.props, affixHeader = _this$props.affixHeader, affixHorizontalScrollbar = _this$props.affixHorizontalScrollbar; var headerNode = (_this$headerWrapperRe = _this.headerWrapperRef) === null || _this$headerWrapperRe === void 0 ? void 0 : _this$headerWrapperRe.current; if (isNumberOrTrue(affixHeader) && headerNode) { _this.setState(function () { return { headerOffset: getOffset(headerNode) }; }); } var tableNode = (_this$tableRef = _this.tableRef) === null || _this$tableRef === void 0 ? void 0 : _this$tableRef.current; if (isNumberOrTrue(affixHorizontalScrollbar) && tableNode) { _this.setState(function () { return { tableOffset: getOffset(tableNode) }; }); } }; _this.handleWindowScroll = function () { var _this$props2 = _this.props, affixHeader = _this$props2.affixHeader, affixHorizontalScrollbar = _this$props2.affixHorizontalScrollbar; if (isNumberOrTrue(affixHeader)) { _this.affixTableHeader(); } if (isNumberOrTrue(affixHorizontalScrollbar)) { _this.affixHorizontalScrollbar(); } }; _this.affixHorizontalScrollbar = function () { var _this$scrollbarXRef, _this$scrollbarXRef$c3, _this$scrollbarXRef$c4; var scrollY = window.scrollY || window.pageYOffset; var windowHeight = getHeight(window); var height = _this.getTableHeight(); var _this$state = _this.state, tableOffset = _this$state.tableOffset, fixedHorizontalScrollbar = _this$state.fixedHorizontalScrollbar; var affixHorizontalScrollbar = _this.props.affixHorizontalScrollbar; var headerHeight = _this.getTableHeaderHeight(); var bottom = typeof affixHorizontalScrollbar === 'number' ? affixHorizontalScrollbar : 0; var fixedScrollbar = // @ts-ignore scrollY + windowHeight < height + (tableOffset.top + bottom) && // @ts-ignore scrollY + windowHeight - headerHeight > (tableOffset === null || tableOffset === void 0 ? void 0 : tableOffset.top) + bottom; if (((_this$scrollbarXRef = _this.scrollbarXRef) === null || _this$scrollbarXRef === void 0 ? void 0 : (_this$scrollbarXRef$c3 = _this$scrollbarXRef.current) === null || _this$scrollbarXRef$c3 === void 0 ? void 0 : (_this$scrollbarXRef$c4 = _this$scrollbarXRef$c3.barRef) === null || _this$scrollbarXRef$c4 === void 0 ? void 0 : _this$scrollbarXRef$c4.current) && fixedHorizontalScrollbar !== fixedScrollbar) { _this.setState({ fixedHorizontalScrollbar: fixedScrollbar }); } }; _this.affixTableHeader = function () { var affixHeader = _this.props.affixHeader; var top = typeof affixHeader === 'number' ? affixHeader : 0; var _this$state2 = _this.state, headerOffset = _this$state2.headerOffset, contentHeight = _this$state2.contentHeight; var scrollY = window.scrollY || window.pageYOffset; var fixedHeader = // @ts-ignore scrollY - (headerOffset.top - top) >= 0 && scrollY < headerOffset.top - top + contentHeight; if (_this.affixHeaderWrapperRef.current) { toggleClass(_this.affixHeaderWrapperRef.current, 'fixed', fixedHeader); } }; _this.handleSortColumn = function (dataKey) { var _this$props$onSortCol, _this$props3; var sortType = _this.getSortType(); if (_this.props.sortColumn === dataKey) { sortType = sortType === SORT_TYPE.ASC ? SORT_TYPE.DESC : SORT_TYPE.ASC; _this.setState({ sortType: sortType }); } (_this$props$onSortCol = (_this$props3 = _this.props).onSortColumn) === null || _this$props$onSortCol === void 0 ? void 0 : _this$props$onSortCol.call(_this$props3, dataKey, sortType); }; _this.handleColumnResizeEnd = function (columnWidth, _cursorDelta, dataKey, index) { _this._cacheCells = null; _this.setState(_defineProperty({ isColumnResizing: false }, "".concat(dataKey, "_").concat(index, "_width"), columnWidth)); addStyle(_this.mouseAreaRef.current, { display: 'none' }); }; _this.handleColumnResizeStart = function (width, left, fixed) { _this.setState({ isColumnResizing: true }); _this.handleColumnResizeMove(width, left, fixed); }; _this.handleColumnResizeMove = function (width, left, fixed) { var mouseAreaLeft = width + left; var x = mouseAreaLeft; var dir = 'left'; if (_this.isRTL()) { mouseAreaLeft += _this.minScrollX + SCROLLBAR_WIDTH; dir = 'right'; } if (!fixed) { x = mouseAreaLeft + (_this.isRTL() ? -_this.scrollX : _this.scrollX); } addStyle(_this.mouseAreaRef.current, _defineProperty({ display: 'block' }, dir, "".concat(x, "px"))); }; _this.handleTreeToggle = function (rowKey, _rowIndex, rowData) { var _this$props$onExpandC, _this$props4; var expandedRowKeys = _this.getExpandedRowKeys(); var open = false; var nextExpandedRowKeys = []; for (var i = 0; i < expandedRowKeys.length; i++) { var key = expandedRowKeys[i]; if (key === rowKey) { open = true; } else { // @ts-ignore nextExpandedRowKeys.push(key); } } if (!open) { // @ts-ignore nextExpandedRowKeys.push(rowKey); } _this.setState({ expandedRowKeys: nextExpandedRowKeys }); (_this$props$onExpandC = (_this$props4 = _this.props).onExpandChange) === null || _this$props$onExpandC === void 0 ? void 0 : _this$props$onExpandC.call(_this$props4, !open, rowData); }; _this.handleScrollX = function (delta) { _this.handleWheel(delta, 0); }; _this.handleScrollY = function (delta) { _this.handleWheel(0, delta); }; _this.handleWheel = function (deltaX, deltaY) { var _this$props5 = _this.props, onScroll = _this$props5.onScroll, virtualized = _this$props5.virtualized; var _this$state3 = _this.state, contentWidth = _this$state3.contentWidth, width = _this$state3.width; if (!_this.tableRef.current) { return; } var nextScrollX = contentWidth <= width ? 0 : _this.scrollX - deltaX; var nextScrollY = _this.scrollY - deltaY; _this.scrollY = Math.min(0, nextScrollY < _this.minScrollY ? _this.minScrollY : nextScrollY); _this.scrollX = Math.min(0, nextScrollX < _this.minScrollX ? _this.minScrollX : nextScrollX); _this.updatePosition(); onScroll === null || onScroll === void 0 ? void 0 : onScroll(_this.scrollX, _this.scrollY); if (virtualized) { _this.setState({ isScrolling: true, scrollY: _this.scrollY }); if (_this.disableEventsTimeoutId) { // @ts-ignore cancelAnimationTimeout(_this.disableEventsTimeoutId); } // @ts-ignore _this.disableEventsTimeoutId = requestAnimationTimeout(_this.debounceScrollEndedCallback, 150); } }; _this.debounceScrollEndedCallback = function () { _this.disableEventsTimeoutId = null; _this.setState({ isScrolling: false }); }; // 处理移动端 Touch 事件, Start 的时候初始化 x,y _this.handleTouchStart = function (event) { var _this$props$onTouchSt, _this$props6; if (event.touches) { var _event$touches$ = event.touches[0], pageX = _event$touches$.pageX, pageY = _event$touches$.pageY; _this.touchX = pageX; _this.touchY = pageY; } (_this$props$onTouchSt = (_this$props6 = _this.props).onTouchStart) === null || _this$props$onTouchSt === void 0 ? void 0 : _this$props$onTouchSt.call(_this$props6, event); }; // 处理移动端 Touch 事件, Move 的时候初始化,更新 scroll _this.handleTouchMove = function (event) { var _this$props$onTouchMo, _this$props7; var autoHeight = _this.props.autoHeight; if (event.touches) { var _event$preventDefault, _this$scrollbarXRef$c5, _this$scrollbarXRef$c6, _this$scrollbarYRef$c3, _this$scrollbarYRef$c4; var _event$touches$2 = event.touches[0], pageX = _event$touches$2.pageX, pageY = _event$touches$2.pageY; var deltaX = _this.touchX - pageX; var deltaY = autoHeight ? 0 : _this.touchY - pageY; if (!_this.shouldHandleWheelY(deltaY) && !_this.shouldHandleWheelX(deltaX)) { return; } (_event$preventDefault = event.preventDefault) === null || _event$preventDefault === void 0 ? void 0 : _event$preventDefault.call(event); _this.handleWheel(deltaX, deltaY); (_this$scrollbarXRef$c5 = _this.scrollbarXRef.current) === null || _this$scrollbarXRef$c5 === void 0 ? void 0 : (_this$scrollbarXRef$c6 = _this$scrollbarXRef$c5.onWheelScroll) === null || _this$scrollbarXRef$c6 === void 0 ? void 0 : _this$scrollbarXRef$c6.call(_this$scrollbarXRef$c5, deltaX); (_this$scrollbarYRef$c3 = _this.scrollbarYRef.current) === null || _this$scrollbarYRef$c3 === void 0 ? void 0 : (_this$scrollbarYRef$c4 = _this$scrollbarYRef$c3.onWheelScroll) === null || _this$scrollbarYRef$c4 === void 0 ? void 0 : _this$scrollbarYRef$c4.call(_this$scrollbarYRef$c3, deltaY); _this.touchX = pageX; _this.touchY = pageY; } (_this$props$onTouchMo = (_this$props7 = _this.props).onTouchMove) === null || _this$props$onTouchMo === void 0 ? void 0 : _this$props$onTouchMo.call(_this$props7, event); }; /** * 当用户在 Table 内使用 tab 键,触发了 onScroll 事件,这个时候应该更新滚动条位置 * https://github.com/rsuite/rsuite/issues/234 */ _this.handleBodyScroll = function (event) { if (event.target !== _this.tableBodyRef.current) { return; } var left = scrollLeft(event.target); var top = scrollTop(event.target); if (top === 0 && left === 0) { return; } _this.listenWheel(left, top); scrollLeft(event.target, 0); scrollTop(event.target, 0); }; _this.shouldHandleWheelX = function (delta) { var _this$props8 = _this.props, disabledScroll = _this$props8.disabledScroll, loading = _this$props8.loading; if (delta === 0 || disabledScroll || loading) { return false; } return true; }; _this.shouldHandleWheelY = function (delta) { var _this$props9 = _this.props, disabledScroll = _this$props9.disabledScroll, loading = _this$props9.loading; if (delta === 0 || disabledScroll || loading) { return false; } return delta >= 0 && _this.scrollY > _this.minScrollY || delta < 0 && _this.scrollY < 0; }; // @ts-ignore _this.addPrefix = function (name) { return prefix(_this.props.classPrefix)(name); }; _this.calculateTableWidth = function () { var _this$tableRef2; var table = (_this$tableRef2 = _this.tableRef) === null || _this$tableRef2 === void 0 ? void 0 : _this$tableRef2.current; var width = _this.state.width; if (table) { var nextWidth = getWidth(table); if (width !== nextWidth) { var _this$scrollbarXRef2, _this$scrollbarXRef2$; _this.scrollX = 0; (_this$scrollbarXRef2 = _this.scrollbarXRef) === null || _this$scrollbarXRef2 === void 0 ? void 0 : (_this$scrollbarXRef2$ = _this$scrollbarXRef2.current) === null || _this$scrollbarXRef2$ === void 0 ? void 0 : _this$scrollbarXRef2$.resetScrollBarPosition(); } _this._cacheCells = null; if (nextWidth !== 0) { _this.setState({ width: nextWidth }); } } _this.setOffsetByAffix(); }; /** * public method */ _this.scrollTop = function () { var _this$scrollbarYRef, _this$scrollbarYRef$c5, _this$scrollbarYRef$c6; var top = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var _this$getControlledSc = _this.getControlledScrollTopValue(top), _this$getControlledSc2 = _slicedToArray(_this$getControlledSc, 2), scrollY = _this$getControlledSc2[0], handleScrollY = _this$getControlledSc2[1]; _this.scrollY = scrollY; (_this$scrollbarYRef = _this.scrollbarYRef) === null || _this$scrollbarYRef === void 0 ? void 0 : (_this$scrollbarYRef$c5 = _this$scrollbarYRef.current) === null || _this$scrollbarYRef$c5 === void 0 ? void 0 : (_this$scrollbarYRef$c6 = _this$scrollbarYRef$c5.resetScrollBarPosition) === null || _this$scrollbarYRef$c6 === void 0 ? void 0 : _this$scrollbarYRef$c6.call(_this$scrollbarYRef$c5, handleScrollY); _this.updatePosition(); /** * 当开启 virtualized,调用 scrollTop 后会出现白屏现象, * 原因是直接操作 DOM 的坐标,但是组件没有重新渲染,需要调用 forceUpdate 重新进入 render。 * Fix: rsuite#1044 */ if (_this.props.virtualized && _this.state.contentHeight > _this.props.height) { _this.forceUpdate(); } }; // public method _this.scrollLeft = function () { var _this$scrollbarXRef3, _this$scrollbarXRef3$, _this$scrollbarXRef3$2; var left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var _this$getControlledSc3 = _this.getControlledScrollLeftValue(left), _this$getControlledSc4 = _slicedToArray(_this$getControlledSc3, 2), scrollX = _this$getControlledSc4[0], handleScrollX = _this$getControlledSc4[1]; _this.scrollX = scrollX; (_this$scrollbarXRef3 = _this.scrollbarXRef) === null || _this$scrollbarXRef3 === void 0 ? void 0 : (_this$scrollbarXRef3$ = _this$scrollbarXRef3.current) === null || _this$scrollbarXRef3$ === void 0 ? void 0 : (_this$scrollbarXRef3$2 = _this$scrollbarXRef3$.resetScrollBarPosition) === null || _this$scrollbarXRef3$2 === void 0 ? void 0 : _this$scrollbarXRef3$2.call(_this$scrollbarXRef3$, handleScrollX); _this.updatePosition(); }; _this.scrollTo = function (coord) { var _ref = coord || {}, x = _ref.x, y = _ref.y; if (typeof x === 'number') { _this.scrollLeft(x); } if (typeof y === 'number') { _this.scrollTop(y); } }; _this.bindTableRowsRef = function (index, rowData) { return function (ref) { if (ref) { _this.tableRows[index] = [ref, rowData]; } }; }; _this.bindRowClick = function (rowData) { return function (event) { var _this$props$onRowClic, _this$props10; (_this$props$onRowClic = (_this$props10 = _this.props).onRowClick) === null || _this$props$onRowClic === void 0 ? void 0 : _this$props$onRowClic.call(_this$props10, rowData, event); }; }; _this.bindRowContextMenu = function (rowData) { return function (event) { var _this$props$onRowCont, _this$props11; (_this$props$onRowCont = (_this$props11 = _this.props).onRowContextMenu) === null || _this$props$onRowCont === void 0 ? void 0 : _this$props$onRowCont.call(_this$props11, rowData, event); }; }; var width = props.width, data = props.data, rowKey = props.rowKey, defaultExpandAllRows = props.defaultExpandAllRows, renderRowExpanded = props.renderRowExpanded, defaultExpandedRowKeys = props.defaultExpandedRowKeys, _props$children = props.children, children = _props$children === void 0 ? [] : _props$children, _props$columns = props.columns, columns = _props$columns === void 0 ? [] : _props$columns, isTree = props.isTree, defaultSortType = props.defaultSortType; var expandedRowKeys = defaultExpandAllRows ? findRowKeys(data, rowKey, isFunction(renderRowExpanded)) : defaultExpandedRowKeys || []; var shouldFixedColumn = Array.from(children).some(function (child) { return child && child.props && child.props.fixed; }); if (columns && columns.length) { shouldFixedColumn = Array.from(columns).some(function (child) { return child && child.fixed; }); } if (isTree && !rowKey) { throw new Error('The `rowKey` is required when set isTree'); } _this.state = { isTree: isTree, expandedRowKeys: expandedRowKeys, shouldFixedColumn: shouldFixedColumn, cacheData: data, data: isTree ? flattenData(data) : data, width: width || 0, columnWidth: 0, dataKey: 0, contentHeight: 0, contentWidth: 0, tableRowsMaxHeight: [], sortType: defaultSortType, scrollY: 0, isScrolling: false, fixedHeader: false }; _this.scrollY = 0; _this.scrollX = 0; _this.wheelHandler = new WheelHandler(_this.listenWheel, _this.shouldHandleWheelX, _this.shouldHandleWheelY, false); _this._cacheChildrenSize = flatten(children || columns).length; _this.translateDOMPositionXY = getTranslateDOMPositionXY({ enable3DTransform: props.translate3d }); _this.tableRef = React.createRef(); _this.scrollbarYRef = React.createRef(); _this.scrollbarXRef = React.createRef(); _this.tableBodyRef = React.createRef(); _this.affixHeaderWrapperRef = React.createRef(); _this.mouseAreaRef = React.createRef(); _this.headerWrapperRef = React.createRef(); _this.wheelWrapperRef = React.createRef(); _this.tableHeaderRef = React.createRef(); return _this; } _createClass(PerformanceTable, [{ key: "componentDidMount", value: function componentDidMount() { var _this$props13, _this$props13$bodyRef; this.calculateTableWidth(); this.calculateTableContextHeight(); this.calculateRowMaxHeight(); this.setOffsetByAffix(); this.initPosition(); bindElementResize(this.tableRef.current, debounce(this.calculateTableWidth, 400)); var options = { passive: false }; var tableBody = this.tableBodyRef.current; if (tableBody) { this.wheelListener = on(tableBody, 'wheel', this.wheelHandler.onWheel, options); this.touchStartListener = on(tableBody, 'touchstart', this.handleTouchStart, options); this.touchMoveListener = on(tableBody, 'touchmove', this.handleTouchMove, options); } var _this$props12 = this.props, affixHeader = _this$props12.affixHeader, affixHorizontalScrollbar = _this$props12.affixHorizontalScrollbar; if (isNumberOrTrue(affixHeader) || isNumberOrTrue(affixHorizontalScrollbar)) { this.scrollListener = on(window, 'scroll', this.handleWindowScroll); } (_this$props13 = this.props) === null || _this$props13 === void 0 ? void 0 : (_this$props13$bodyRef = _this$props13.bodyRef) === null || _this$props13$bodyRef === void 0 ? void 0 : _this$props13$bodyRef.call(_this$props13, this.wheelWrapperRef.current); } }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps, nextState) { var _cacheChildrenSize = flatten(nextProps.children || nextProps.columns || []).length; /** * 单元格列的信息在初始化后会被缓存,在某些属性被更新以后,需要清除缓存。 */ if (_cacheChildrenSize !== this._cacheChildrenSize) { this._cacheChildrenSize = _cacheChildrenSize; this._cacheCells = null; } else if (this.props.children !== nextProps.children || this.props.columns !== nextProps.columns || this.props.sortColumn !== nextProps.sortColumn || this.props.sortType !== nextProps.sortType) { this._cacheCells = null; } return !eq(this.props, nextProps) || !isEqual(this.state, nextState); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps, prevState) { var rowHeight = prevProps.rowHeight, data = prevProps.data, height = prevProps.height; if (data !== this.props.data) { var _this$props$onDataUpd, _this$props14; this.calculateRowMaxHeight(); (_this$props$onDataUpd = (_this$props14 = this.props).onDataUpdated) === null || _this$props$onDataUpd === void 0 ? void 0 : _this$props$onDataUpd.call(_this$props14, this.props.data, this.scrollTo); var maxHeight = this.props.data.length * (typeof rowHeight === 'function' ? rowHeight({}) : rowHeight); // 当开启允许更新滚动条,或者滚动条位置大于表格的最大高度,则初始滚动条位置 if (this.props.shouldUpdateScroll || Math.abs(this.scrollY) > maxHeight) { this.scrollTo({ x: 0, y: 0 }); } } else { this.updatePosition(); } if ( // 当 Table 的 data 发生变化,需要重新计算高度 data !== this.props.data || // 当 Table 内容区的高度发生变化需要重新计算 height !== this.props.height || // 当 Table 内容区的高度发生变化需要重新计算 prevState.contentHeight !== this.state.contentHeight || // 当 expandedRowKeys 发生变化,需要重新计算 Table 高度,如果重算会导致滚动条不显示。 prevState.expandedRowKeys !== this.state.expandedRowKeys || prevProps.expandedRowKeys !== this.props.expandedRowKeys) { this.calculateTableContextHeight(prevProps); } this.calculateTableContentWidth(prevProps); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this$wheelListener, _this$touchStartListe, _this$touchMoveListen, _this$scrollListener; this.wheelHandler = null; if (this.tableRef.current) { unbindElementResize(this.tableRef.current); } (_this$wheelListener = this.wheelListener) === null || _this$wheelListener === void 0 ? void 0 : _this$wheelListener.off(); (_this$touchStartListe = this.touchStartListener) === null || _this$touchStartListe === void 0 ? void 0 : _this$touchStartListe.off(); (_this$touchMoveListen = this.touchMoveListener) === null || _this$touchMoveListen === void 0 ? void 0 : _this$touchMoveListen.off(); (_this$scrollListener = this.scrollListener) === null || _this$scrollListener === void 0 ? void 0 : _this$scrollListener.off(); } }, { key: "getExpandedRowKeys", value: function getExpandedRowKeys() { var expandedRowKeys = this.props.expandedRowKeys; return typeof expandedRowKeys === 'undefined' ? this.state.expandedRowKeys : expandedRowKeys; } }, { key: "getSortType", value: function getSortType() { var sortType = this.props.sortType; return typeof sortType === 'undefined' ? this.state.sortType : sortType; } }, { key: "getScrollCellGroups", value: function getScrollCellGroups() { var _this$tableRef$curren; return (_this$tableRef$curren = this.tableRef.current) === null || _this$tableRef$curren === void 0 ? void 0 : _this$tableRef$curren.querySelectorAll(".".concat(this.addPrefix('cell-group-scroll'))); } }, { key: "getFixedLeftCellGroups", value: function getFixedLeftCellGroups() { var _this$tableRef$curren2; return (_this$tableRef$curren2 = this.tableRef.current) === null || _this$tableRef$curren2 === void 0 ? void 0 : _this$tableRef$curren2.querySelectorAll(".".concat(this.addPrefix('cell-group-fixed-left'))); } }, { key: "getFixedRightCellGroups", value: function getFixedRightCellGroups() { var _this$tableRef$curren3; return (_this$tableRef$curren3 = this.tableRef.current) === null || _this$tableRef$curren3 === void 0 ? void 0 : _this$tableRef$curren3.querySelectorAll(".".concat(this.addPrefix('cell-group-fixed-right'))); } }, { key: "isRTL", value: function isRTL() { return this.props.rtl || _isRTL(); } }, { key: "getRowHeight", value: function getRowHeight() { var rowData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var rowHeight = this.props.rowHeight; return typeof rowHeight === 'function' ? rowHeight(rowData) : rowHeight; } /** * 获取表头高度 */ }, { key: "getTableHeaderHeight", value: function getTableHeaderHeight() { var _this$props15 = this.props, headerHeight = _this$props15.headerHeight, showHeader = _this$props15.showHeader; return showHeader ? headerHeight : 0; } /** * 获取 Table 需要渲染的高度 */ }, { key: "getTableHeight", value: function getTableHeight() { var contentHeight = this.state.contentHeight; var _this$props16 = this.props, minHeight = _this$props16.minHeight, height = _this$props16.height, autoHeight = _this$props16.autoHeight, data = _this$props16.data; var headerHeight = this.getTableHeaderHeight(); if (data.length === 0 && autoHeight) { return height; } return autoHeight ? Math.max(headerHeight + contentHeight, minHeight) : height; } /** * 处理 column props * @param column */ }, { key: "getColumnProps", value: function getColumnProps(column) { return omit(column, ['title', 'dataIndex', 'key', 'render']); } /** * 处理columns json -> reactNode * @param columns */ }, { key: "processTableColumns", value: function processTableColumns(columns) { var _this2 = this; return columns && columns.map(function (column) { var dataKey = column.dataIndex; if (column.type === 'ColumnGroup') { return React.createElement(ColumnGroup, _extends({}, _this2.getColumnProps(column)), _this2.processTableColumns(column.children)); } return (// @ts-ignore React.createElement(Column, _extends({}, _this2.getColumnProps(column), { dataKey: dataKey }), // @ts-ignore React.createElement(HeaderCell, null, typeof column.title === 'function' ? column.title() : column.title), typeof column.render === 'function' ? // @ts-ignore React.createElement(Cell, { dataKey: dataKey }, function (rowData, rowIndex) { return column.render({ rowData: rowData, rowIndex: rowIndex, dataIndex: dataKey }); }) // @ts-ignore : React.createElement(Cell, { dataKey: dataKey })) ); }); } /** * 获取 columns ReactElement 数组 * - 处理 children 中存在 <Column> 数组的情况 * - 过滤 children 中的空项 */ }, { key: "getTableColumns", value: function getTableColumns() { var columns = this.props.columns; var children = this.props.children; if (columns && columns.length) { children = this.processTableColumns(columns); } if (!Array.isArray(children)) { return children; } // Fix that the `ColumnGroup` array cannot be rendered in the Table var flattenColumns = flatten(children).map(function (column) { if (column) { var _column$type; if ((_column$type = column.type) === null || _column$type === void 0 ? void 0 : _column$type.__PRO_TABLE_COLUMN_GROUP) { var _column$props = column.props, header = _column$props.header, childColumns = _column$props.children, align = _column$props.align, fixed = _column$props.fixed, verticalAlign = _column$props.verticalAlign; return childColumns.map(function (childColumn, index) { // 把 ColumnGroup 设置的属性覆盖到 Column var groupCellProps = { align: align, fixed: fixed, verticalAlign: verticalAlign }; /** * 为分组中的第一列设置属性: * groupCount: 分组子项个数 * groupHeader: 分组标题 * resizable: 设置为不可自定义列宽 */ if (index === 0) { groupCellProps.groupCount = childColumns.length; groupCellProps.groupHeader = header; groupCellProps.resizable = false; } return React.cloneElement(childColumn, groupCellProps); }); } } return column; }); // 把 Columns 中的数组,展平为一维数组,计算 lastColumn 与 firstColumn。 return flatten(flattenColumns).filter(function (col) { return col; }); } }, { key: "getCellDescriptor", value: function getCellDescriptor() { var _this3 = this; if (this._cacheCells) { return this._cacheCells; } var hasCustomTreeCol = false; var left = 0; // Cell left margin var headerCells = []; // Table header cell var bodyCells = []; // Table body cell var _this$props17 = this.props, children = _this$props17.children, columnsJson = _this$props17.columns; var columnHack = children; if (columnsJson && columnsJson.length) { columnHack = columnsJson; } if (!columnHack) { this._cacheCells = { headerCells: headerCells, bodyCells: bodyCells, hasCustomTreeCol: hasCustomTreeCol, allColumnsWidth: left }; return this._cacheCells; } var columns = this.getTableColumns(); var tableWidth = this.state.width; var _this$props18 = this.props, sortColumn = _this$props18.sortColumn, rowHeight = _this$props18.rowHeight, showHeader = _this$props18.showHeader; var _getTotalByColumns = getTotalByColumns(columns), totalFlexGrow = _getTotalByColumns.totalFlexGrow, totalWidth = _getTotalByColumns.totalWidth; var headerHeight = this.getTableHeaderHeight(); React.Children.forEach(columns, function (column, index) { if (React.isValidElement(column)) { var columnChildren = column.props.children; var _column$props2 = column.props, width = _column$props2.width, resizable = _column$props2.resizable, flexGrow = _column$props2.flexGrow, minWidth = _column$props2.minWidth, onResize = _column$props2.onResize, treeCol = _column$props2.treeCol; if (treeCol) { hasCustomTreeCol = true; } if (resizable && flexGrow) { console.warn("Cannot set 'resizable' and 'flexGrow' together in <Column>, column index: ".concat(index)); } if (columnChildren.length !== 2) { throw new Error("Component <HeaderCell> and <Cell> is required, column index: ".concat(index, " ")); } var nextWidth = _this3.state["".concat(columnChildren[1].props.dataKey, "_").concat(index, "_width")] || width || 0; if (tableWidth && flexGrow && totalFlexGrow) { nextWidth = Math.max((tableWidth - totalWidth) / totalFlexGrow * flexGrow, minWidth || 60); } var cellProps = _objectSpread({}, omit(column.props, ['children']), { 'aria-colindex': index + 1, left: left, index: index, headerHeight: headerHeight, key: index, width: nextWidth, height: rowHeight, firstColumn: index === 0, lastColumn: index === columns.length - 1 }); if (showHeader && headerHeight) { var headerCellProps = { // index 用于拖拽列宽时候(Resizable column),定义的序号 index: index, dataKey: columnChildren[1].props.dataKey, isHeaderCell: true, minWidth: column.props.minWidth, sortable: column.props.sortable, onSortColumn: _this3.handleSortColumn, sortType: _this3.getSortType(), sortColumn: sortColumn, flexGrow: flexGrow }; if (resizable) { merge(headerCellProps, { onResize: onResize, onColumnResizeEnd: _this3.handleColumnResizeEnd, onColumnResizeStart: _this3.handleColumnResizeStart, onColumnResizeMove: _this3.handleColumnResizeMove }); } headerCells.push( // @ts-ignore React.cloneElement(columnChildren[0], _objectSpread({}, cellProps, {}, headerCellProps))); } // @ts-ignore bodyCells.push(React.cloneElement(columnChildren[1], cellProps)); left += nextWidth; } }); return this._cacheCells = { headerCells: headerCells, bodyCells: bodyCells, allColumnsWidth: left, hasCustomTreeCol: hasCustomTreeCol }; } }, { key: "initPosition", value: function initPosition() { var _this4 = this; if (this.isRTL()) { setTimeout(function () { var _this4$scrollbarXRef, _this4$scrollbarXRef$, _this4$scrollbarXRef$2; var _this4$state = _this4.state, contentWidth = _this4$state.contentWidth, width = _this4$state.width; _this4.scrollX = width - contentWidth - SCROLLBAR_WIDTH; _this4.updatePosition(); (_this4$scrollbarXRef = _this4.scrollbarXRef) === null || _this4$scrollbarXRef === void 0 ? void 0 : (_this4$scrollbarXRef$ = _this4$scrollbarXRef.current) === null || _this4$scrollbarXRef$ === void 0 ? void 0 : (_this4$scrollbarXRef$2 = _this4$scrollbarXRef$.resetScrollBarPosition) === null || _this4$scrollbarXRef$2 === void 0 ? void 0 : _this4$scrollbarXRef$2.call(_this4$scrollbarXRef$, -_this4.scrollX); }, 0); } } }, { key: "updatePosition", value: function updatePosition() { var _this$tableHeaderRef; /** * 当存在锁定列情况处理 */ if (this.state.shouldFixedColumn) { this.updatePositionByFixedCell(); } else { var _this$wheelWrapperRef, _this$headerWrapperRe2, _this$affixHeaderWrap, _affixHeaderElement$h; var wheelStyle = {}; var headerStyle = {}; // @ts-ignore this.translateDOMPositionXY(wheelStyle, this.scrollX, this.scrollY); // @ts-ignore this.translateDOMPositionXY(headerStyle, this.scrollX, 0); var wheelElement = (_this$wheelWrapperRef = this.wheelWrapperRef) === null || _this$wheelWrapperRef === void 0 ? void 0 : _this$wheelWrapperRef.current; var headerElement = (_this$headerWrapperRe2 = this.headerWrapperRef) === null || _this$headerWrapperRe2 === void 0 ? void 0 : _this$headerWrapperRe2.current; var affixHeaderElement = (_this$affixHeaderWrap = this.affixHeaderWrapperRef) === null || _this$affixHeaderWrap === void 0 ? void 0 : _this$affixHeaderWrap.current; wheelElement && addStyle(wheelElement, wheelStyle); headerElement && addStyle(headerElement, headerStyle); if (affixHeaderElement === null || affixHeaderElement === void 0 ? void 0 : (_affixHeaderElement$h = affixHeaderElement.hasChildNodes) === null || _affixHeaderElement$h === void 0 ? void 0 : _affixHeaderElement$h.call(affixHeaderElement)) { addStyle(affixHeaderElement.firstChild, headerStyle); } } if ((_this$tableHeaderRef = this.tableHeaderRef) === null || _this$tableHeaderRef === void 0 ? void 0 : _this$tableHeaderRef.current) { toggleClass(this.tableHeaderRef.current, this.addPrefix('cell-group-shadow'), this.scrollY < 0); } } }, { key: "updatePositionByFixedCell", value: function updatePositionByFixedCell() { var _this$wheelWrapperRef2; var wheelGroupStyle = {}; var wheelStyle = {}; var scrollGroups = this.getScrollCellGroups(); var fixedLeftGroups = this.getFixedLeftCellGroups(); var fixedRightGroups = this.getFixedRightCellGroups(); var _this$state4 = this.state, contentWidth = _this$state4.contentWidth, width = _this$state4.width; // @ts-ignore this.translateDOMPositionXY(wheelGroupStyle, this.scrollX, 0); // @ts-ignore this.translateDOMPositionXY(wheelStyle, 0, this.scrollY); var scrollArrayGroups = Array.from(scrollGroups); for (var i = 0; i < scrollArrayGroups.length; i++) { var group = scrollArrayGroups[i]; addStyle(group, wheelGroupStyle); } if ((_this$wheelWrapperRef2 = this.wheelWrapperRef) === null || _this$wheelWrapperRef2 === void 0 ? void 0 : _this$wheelWrapperRef2.current) { addStyle(this.wheelWrapperRef.current, wheelStyle); } var leftShadowClassName = this.addPrefix('cell-group-left-shadow'); var rightShadowClassName = this.addPrefix('cell-group-right-shadow'); var showLeftShadow = this.scrollX < 0; var showRightShadow = width - contentWidth - SCROLLBAR_WIDTH !== this.scrollX; toggleClass(fixedLeftGroups, leftShadowClassName, showLeftShadow); toggleClass(fixedRightGroups, rightShadowClassName, showRightShadow); } }, { key: "shouldRenderExpandedRow", value: function shouldRenderExpandedRow(rowData) { var _this$props19 = this.props, rowKey = _this$props19.rowKey, renderRowExpanded = _this$props19.renderRowExpanded, isTree = _this$props19.isTree; var expandedRowKeys = this.getExpandedRowKeys() || []; return isFunction(renderRowExpanded) && !isTree && expandedRowKeys.some(function (key) { return key === rowData[rowKey]; }); } }, { key: "calculateRowMaxHeight", value: function calculateRowMaxHeight() { var wordWrap = this.props.wordWrap; if (wordWrap) { var tableRowsMaxHeight = []; var tableRows = Object.values(this.tableRows); for (var i = 0; i < tableRows.length; i++) { var _tableRows$i = _slicedToArray(tableRows[i], 1), row = _tableRows$i[0]; if (row) { var cells = row.querySelectorAll(".".concat(this.addPrefix('cell-wrap'))) || []; var cellArray = Array.from(cells); var maxHeight = 0; for (var j = 0; j < cellArray.length; j++) { var cell = cellArray[j]; var h = getHeight(cell); maxHeight = Math.max(maxHeight, h); } // @ts-ignore tableRowsMaxHeight.push(maxHeight); } } this.setState({ tableRowsMaxHeight: tableRowsMaxHeight }); } } }, { key: "calculateTableContentWidth", value: function calculateTableContentWidth(prevProps) { var _this$tableRef3; var table = (_this$tableRef3 = this.tableRef) === null || _this$tableRef3 === void 0 ? void 0 : _this$tableRef3.current; var row = table.querySelector(".".concat(this.addPrefix('row'), ":not(.virtualized)")); var contentWidth = row ? getWidth(row) : 0; this.setState({ contentWidth: contentWidth }); // 这里 -SCROLLBAR_WIDTH 是为了让滚动条不挡住内容部分 this.minScrollX = -(contentWidth - this.state.width) - SCROLLBAR_WIDTH; /** * 1.判断 Table 列数是否发生变化 * 2.判断 Table 内容区域是否宽度有变化 * * 满足 1 和 2 则更新横向滚动条位置 */ if (flatten(this.props.children).length !== flatten(prevProps.children).length && this.state.contentWidth !== contentWidth) { this.scrollLeft(0); } } }, { key: "calculateTableContextHeight", value: function calculateTableContextHeight(prevProps) { var table = this.tableRef.current; var rows = table.querySelectorAll(".".concat(this.addPrefix('row'))) || []; var _this$props20 = this.props, height = _this$props20.height, autoHeight = _this$props20.autoHeight, rowHeight = _this$props20.rowHeight, affixHeader = _this$props20.affixHeader; var headerHeight = this.getTableHeaderHeight(); var contentHeight = rows.length ? Array.from(rows).map(function (row) { return getHeight(row) || toPx(row.style.height) || rowHeight; }).reduce(function (x, y) { return x + y; }) : 0; // 当设置 affixHeader 属性后要减掉两个 header 的高度 var nextContentHeight = contentHeight - (affixHeader ? headerHeight * 2 : headerHeight); if (nextContentHeight !== this.state.contentHeight) { this.setState({ contentHeight: nextContentHeight }); } if (prevProps && ( // 当 data 更新,或者表格高度更新,则更新滚动条 prevProps.height !== height || prevProps.data !== this.props.data) && this.scrollY !== 0) { this.scrollTop(Math.abs(this.scrollY)); this.updatePosition(); } if (!autoHeight) { // 这里 -SCROLLBAR_WIDTH 是为了让滚动条不挡住内容部分 this.minScrollY = -(contentHeight - height) - SCROLLBAR_WIDTH; } // 如果内容区域的高度小于表格的高度,则重置 Y 坐标滚动条 if (contentHeight < height) { this.scrollTop(0); } // 如果 scrollTop 的值大于可以滚动的范围 ,则重置 Y 坐标滚动条 // 当 Table 为 virtualized 时, wheel 事件触发每次都会进入该逻辑, 避免在滚动到底部后滚动条重置, +SCROLLBAR_WIDTH if (Math.abs(this.scrollY) + height - headerHeight > nextContentHeight + SCROLLBAR_WIDTH) { this.scrollTop(this.scrollY); } } }, { key: "getControlledScrollTopValue", value: function getControlledScrollTopValue(value) { if (this.props.autoHeight) { return [0, 0]; } var contentHeight = this.state.contentHeight; var headerHeight = this.getTableHeaderHeight(); var height = this.getTableHeight(); // 滚动值的最大范围判断 value = Math.min(value, Math.max(0, contentHeight - (height - headerHeight))); // value 值是表格理论滚动位置的一个值,通过 value 计算出 scrollY 坐标值与滚动条位置的值 return [-value, value / contentHeight * (height - headerHeight)]; } }, { key: "getControlledScrollLeftValue", value: function getControlledScrollLeftValue(value) { var _this$state5 = this.state, contentWidth = _this$state5.contentWidth, width = _this$state5.width; // 滚动值的最大范围判断 value = Math.min(value, Math.max(0, contentWidth - width)); return [-value, value / contentWidth * width]; } }, { key: "renderRowData", value: function renderRowData(bodyCells, rowData, props, shouldRenderExpandedRow) { var _this$props21 = this.props, renderTreeToggle = _this$props21.renderTreeToggle, rowKey = _this$props21.rowKey, wordWrap = _this$props21.wordWrap, isTree = _this$props21.isTree; var hasChildren = isTree && rowData.children && Array.isArray(rowData.children); var nextRowKey = typeof rowData[rowKey] !== 'undefined' ? rowData[rowKey] : props.key; var rowProps = _objectSpread({}, props, { // Fixed Row missing custom rowKey key: nextRowKey, 'aria-rowindex': props.key + 2, rowRef: this.bindTableRowsRef(props.key, rowData), onClick: this.bindRowClick(rowData), onContextMenu: this.bindRowContextMenu(rowData) }); var expandedRowKeys = this.getExpandedRowKeys() || []; var expanded = expandedRowKeys.some(function (key) { return key === rowData[rowKey]; }); var cells = []; for (var i = 0; i < bodyCells.length; i++) { var cell = bodyCells[i]; cells.push( // @ts-ignore React.cloneElement(cell, { hasChildren: hasChildren, rowData: rowData, wordWrap: wordWrap, renderTreeToggle: renderTreeToggle, height: props.height, rowIndex: props.rowIndex, depth: props.depth, onTreeToggle: this.handleTreeToggle, rowKey: nextRowKey, expanded: expanded })); } return this.renderRow(rowProps, cells, shouldRenderExpandedRow, rowData); } }, { key: "renderRow", value: function renderRow(props, cells, shouldRenderExpandedRow, rowData) { var rowClassName = this.props.rowClassName; var _this$state6 = this.state, shouldFixedColumn = _this$state6.shouldFixedColumn, width = _this$state6.width, contentWidth = _this$state6.contentWidth; var depth = props.depth, restRowProps = _objectWithoutProperties(props, ["depth"]); if (typeof rowClassName === 'function') { restRowProps.className = rowClassName(rowData); } else { restRowProps.className = rowClassName; } var rowStyles = {}; var rowRight = 0; if (this.isRTL() && contentWidth > width) { rowRight = width - contentWidth; rowStyles.right = rowRight; } // IF there are fixed columns, add a fixed group if (shouldFixedColumn && contentWidth > width) { var fixedLeftCells = []; var fixedRightCells = []; var scrollCells = []; var fixedLeftCellGroupWidth = 0; var fixedRightCellGroupWidth = 0; for (var i = 0; i < cells.length; i++) { var cell = cells[i]; var _cell$props = cell.props, fixed = _cell$props.fixed, _width = _cell$props.width; var isFixedStart = fixed === 'left' || fixed === true; var isFixedEnd = fixed === 'right'; if (this.isRTL()) { isFixedStart = fixed === 'right'; isFixedEnd = fixed === 'left' || fixed === true; } if (isFixedStart) { // @ts-ignore fixedLeftCells.push(cell); fixedLeftCellGroupWidth += _width; } else if (isFixedEnd) { // @ts-ignore fixedRightCells.push(cell); fixedRightCellGroupWidth += _width;