@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
375 lines (374 loc) • 13.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _isEqual2 = _interopRequireDefault(require("lodash/isEqual"));
var _merge2 = _interopRequireDefault(require("lodash/merge"));
var _omit2 = _interopRequireDefault(require("lodash/omit"));
var _set2 = _interopRequireDefault(require("lodash/set"));
var _noop2 = _interopRequireDefault(require("lodash/noop"));
var _get2 = _interopRequireDefault(require("lodash/get"));
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _constants = require("@douyinfe/semi-foundation/lib/cjs/table/constants");
var _cellFoundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/table/cellFoundation"));
var _utils = require("@douyinfe/semi-foundation/lib/cjs/table/utils");
var _baseComponent = _interopRequireDefault(require("../_base/baseComponent"));
var _tableContext = _interopRequireDefault(require("./table-context"));
var _utils2 = require("./utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function isInvalidRenderCellText(text) {
return text && ! /*#__PURE__*/_react.default.isValidElement(text) && Object.prototype.toString.call(text) === '[object Object]';
}
class TableCell extends _baseComponent.default {
get adapter() {
var _this = this;
return Object.assign(Object.assign({}, super.adapter), {
notifyClick: function () {
const {
onClick
} = _this.props;
if (typeof onClick === 'function') {
onClick(...arguments);
}
}
});
}
constructor(props) {
super(props);
this.setRef = ref => this.ref = ref;
this.handleClick = e => {
this.foundation.handleClick(e);
const customCellProps = this.adapter.getCache('customCellProps');
if (customCellProps && typeof customCellProps.onClick === 'function') {
customCellProps.onClick(e);
}
};
this.ref = /*#__PURE__*/(0, _react.createRef)();
this.foundation = new _cellFoundation.default(this.adapter);
}
/**
* Control whether to execute the render function of the cell
* 1. Scenes that return true
* - The cell contains the selection state, you need to calculate whether its selection state has changed during selection
* - The cell contains the folding state, it needs to be calculated when the folding state has changed
* 2. Scenarios that return false
* - Cells without table operation operation status, only need to judge that their props have changed
* At this time, the update of the table cell is controlled by the user. At this time, its update will not affect other cells
*
* 控制是否执行cell的render函数
* 1. 返回true的场景
* - cell内包含选择状态,需要在选择时计算它的选择态是否发生变化
* - cell内包含折叠状态,需要在折叠时计算它的折叠态是否发生了变化
* 2. 返回false的场景
* - 没有table操作操作状态的cell,只需判断自己的props发生了变化
* 此时table cell的更新由用户自己控制,此时它的更新不会影响其他cell
*
* @param {*} nextProps
* @returns
*/
shouldComponentUpdate(nextProps) {
const props = this.props;
const {
column,
expandIcon
} = props;
const cellInSelectionColumn = (0, _utils.isSelectionColumn)(column);
const {
shouldCellUpdate
} = column;
if (typeof shouldCellUpdate === 'function') {
return shouldCellUpdate(nextProps, props);
}
// The expand button may be in a separate column or in the first data column
const columnHasExpandIcon = (0, _utils.isExpandedColumn)(column) || expandIcon;
if ((cellInSelectionColumn || columnHasExpandIcon) && !(0, _isEqual2.default)(nextProps, this.props)) {
return true;
} else {
const omitProps = ['selected', 'expanded', 'expandIcon', 'disabled'];
const propsOmitSelected = (0, _omit2.default)(props, omitProps);
const nextPropsOmitSelected = (0, _omit2.default)(nextProps, omitProps);
if (!(0, _isEqual2.default)(nextPropsOmitSelected, propsOmitSelected)) {
return true;
}
}
return false;
}
componentDidUpdate() {
this.props.onDidUpdate(this.ref);
}
getTdProps() {
const {
record,
index,
column = {},
fixedLeft,
fixedRight,
width,
height
} = this.props;
let tdProps = {};
let customCellProps = {};
const {
direction
} = this.context;
const isRTL = direction === 'rtl';
const fixedLeftFlag = fixedLeft || typeof fixedLeft === 'number';
const fixedRightFlag = fixedRight || typeof fixedRight === 'number';
if (fixedLeftFlag) {
(0, _set2.default)(tdProps, isRTL ? 'style.right' : 'style.left', typeof fixedLeft === 'number' ? fixedLeft : 0);
} else if (fixedRightFlag) {
(0, _set2.default)(tdProps, isRTL ? 'style.left' : 'style.right', typeof fixedRight === 'number' ? fixedRight : 0);
}
if (width != null) {
(0, _set2.default)(tdProps, 'style.width', width);
}
if (height != null) {
(0, _set2.default)(tdProps, 'style.height', height);
}
if (column.onCell) {
customCellProps = column.onCell(record, index);
this.adapter.setCache('customCellProps', Object.assign({}, customCellProps));
tdProps = Object.assign(Object.assign({}, tdProps), (0, _omit2.default)(customCellProps, ['style', 'className', 'onClick']));
const customCellStyle = (0, _get2.default)(customCellProps, 'style') || {};
tdProps.style = Object.assign(Object.assign({}, tdProps.style), customCellStyle);
}
if (column.align) {
const textAlign = (0, _utils.getRTLAlign)(column.align, direction);
const justifyContent = (0, _utils.getRTLFlexAlign)(column.align, direction);
tdProps.style = Object.assign(Object.assign({}, tdProps.style), {
textAlign,
justifyContent
});
}
return {
tdProps,
customCellProps
};
}
/**
* We should return undefined if no dataIndex is specified, but in order to
* be compatible with object-path's behavior, we return the record object instead.
*/
renderText(tdProps) {
const {
record,
indentSize,
prefixCls,
indent,
index,
expandIcon,
renderExpandIcon,
column = {},
hovered
} = this.props;
const {
dataIndex,
render,
useFullRender
} = column;
let text, colSpan, rowSpan;
if (typeof dataIndex === 'number') {
text = (0, _get2.default)(record, dataIndex);
} else if (!dataIndex || dataIndex.length === 0) {
text = record;
} else {
text = (0, _get2.default)(record, dataIndex);
}
const indentText = indent && indentSize ? (/*#__PURE__*/_react.default.createElement("span", {
style: {
paddingLeft: `${indentSize * indent}px`
},
className: `${prefixCls}-row-indent indent-level-${indent}`
})) : null;
// column.render
const realExpandIcon = typeof renderExpandIcon === 'function' ? renderExpandIcon(record) : expandIcon;
if (render) {
const renderOptions = {
expandIcon: realExpandIcon,
isHovering: hovered
};
// column.useFullRender
if (useFullRender) {
const {
renderSelection
} = this.context;
const realSelection = typeof renderSelection === 'function' ? renderSelection(record) : null;
Object.assign(renderOptions, {
selection: realSelection,
indentText
});
}
text = render(text, record, index, renderOptions);
if (isInvalidRenderCellText(text)) {
tdProps = text.props ? (0, _merge2.default)(tdProps, text.props) : tdProps;
colSpan = tdProps.colSpan;
rowSpan = tdProps.rowSpan;
text = text.children;
}
}
return {
text,
indentText,
rowSpan,
colSpan,
realExpandIcon,
tdProps
};
}
renderInner(text, indentText, realExpandIcon) {
const {
prefixCls,
isSection,
expandIcon,
column = {}
} = this.props;
const {
tableWidth,
anyColumnFixed
} = this.context;
const {
useFullRender
} = column;
let inner = null;
if (useFullRender) {
inner = text;
} else {
inner = [/*#__PURE__*/_react.default.createElement(_react.Fragment, {
key: 'indentText'
}, indentText), /*#__PURE__*/_react.default.createElement(_react.Fragment, {
key: 'expandIcon'
}, expandIcon ? realExpandIcon : null), /*#__PURE__*/_react.default.createElement(_react.Fragment, {
key: 'text'
}, text)];
}
if (isSection) {
inner = /*#__PURE__*/_react.default.createElement("div", {
className: (0, _classnames.default)(`${prefixCls}-section-inner`),
style: {
width: anyColumnFixed ? (0, _utils2.amendTableWidth)(tableWidth) : undefined
}
}, inner);
}
return inner;
}
render() {
const {
prefixCls,
column = {},
component: BodyCell,
fixedLeft,
fixedRight,
lastFixedLeft,
firstFixedRight,
colIndex
} = this.props;
const {
direction
} = this.context;
const isRTL = direction === 'rtl';
const {
className,
ellipsis
} = column;
const fixedLeftFlag = fixedLeft || typeof fixedLeft === 'number';
const fixedRightFlag = fixedRight || typeof fixedRight === 'number';
const {
tdProps,
customCellProps
} = this.getTdProps();
const renderTextResult = this.renderText(tdProps);
let {
text
} = renderTextResult;
const {
indentText,
rowSpan,
colSpan,
realExpandIcon,
tdProps: newTdProps
} = renderTextResult;
let title;
const shouldShowTitle = (0, _utils.shouldShowEllipsisTitle)(ellipsis);
if (shouldShowTitle) {
if (typeof text === 'string') {
title = text;
}
}
if (rowSpan === 0 || colSpan === 0) {
return null;
}
if (isInvalidRenderCellText(text)) {
text = null;
}
const inner = this.renderInner(text, indentText, realExpandIcon);
let isFixedLeft, isFixedLeftLast, isFixedRight, isFixedRightFirst;
if (isRTL) {
isFixedLeft = fixedRightFlag;
isFixedLeftLast = firstFixedRight;
isFixedRight = fixedLeftFlag;
isFixedRightFirst = lastFixedLeft;
} else {
isFixedLeft = fixedLeftFlag;
isFixedLeftLast = lastFixedLeft;
isFixedRight = fixedRightFlag;
isFixedRightFirst = firstFixedRight;
}
const columnCls = (0, _classnames.default)(className, `${prefixCls}-row-cell`, (0, _get2.default)(customCellProps, 'className'), {
[`${prefixCls}-cell-fixed-left`]: isFixedLeft,
[`${prefixCls}-cell-fixed-left-last`]: isFixedLeftLast,
[`${prefixCls}-cell-fixed-right`]: isFixedRight,
[`${prefixCls}-cell-fixed-right-first`]: isFixedRightFirst,
[`${prefixCls}-row-cell-ellipsis`]: ellipsis
});
return /*#__PURE__*/_react.default.createElement(BodyCell, Object.assign({
role: "gridcell",
"aria-colindex": colIndex + 1,
className: columnCls,
onClick: this.handleClick,
title: title
}, newTdProps, {
ref: this.setRef
}), inner);
}
}
exports.default = TableCell;
TableCell.contextType = _tableContext.default;
TableCell.defaultProps = {
indent: 0,
indentSize: _constants.numbers.DEFAULT_INDENT_WIDTH,
onClick: _noop2.default,
prefixCls: _constants.cssClasses.PREFIX,
component: 'td',
onDidUpdate: _noop2.default,
column: {}
};
TableCell.propTypes = {
record: _propTypes.default.object,
prefixCls: _propTypes.default.string,
index: _propTypes.default.number,
fixedLeft: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.number]),
lastFixedLeft: _propTypes.default.bool,
fixedRight: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.number]),
firstFixedRight: _propTypes.default.bool,
indent: _propTypes.default.number,
indentSize: _propTypes.default.number,
column: _propTypes.default.object,
expandIcon: _propTypes.default.any,
renderExpandIcon: _propTypes.default.func,
hideExpandedColumn: _propTypes.default.bool,
component: _propTypes.default.any,
onClick: _propTypes.default.func,
onDidUpdate: _propTypes.default.func,
isSection: _propTypes.default.bool,
width: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
height: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
selected: _propTypes.default.bool,
expanded: _propTypes.default.bool,
colIndex: _propTypes.default.number,
hovered: _propTypes.default.bool
};