choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
1,350 lines (1,110 loc) • 71.3 kB
JavaScript
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;