@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.
144 lines • 4.96 kB
JavaScript
import _isFunction from "lodash/isFunction";
import _noop from "lodash/noop";
import React from 'react';
import PropTypes from 'prop-types';
import BaseComponent from '../_base/baseComponent';
import { strings, cssClasses } from '@douyinfe/semi-foundation/lib/es/table/constants';
import { shouldShowEllipsisTitle } from '@douyinfe/semi-foundation/lib/es/table/utils';
import TableHeaderRow from './TableHeaderRow';
function parseHeaderRows(columns) {
const rows = [];
function fillRowCells(columns, colIndex) {
let parents = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
let rowIndex = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
let level = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
// Init rows
rows[rowIndex] = rows[rowIndex] || [];
let currentColIndex = colIndex;
const colSpans = columns.map(column => {
const cell = {
key: column.key,
className: column.className || '',
children: _isFunction(column.title) ? column.title() : column.title,
column,
colStart: currentColIndex,
level,
parents
};
let colSpan = 1;
/**
* Calculate header column merge colSpan
* - If the current cell has children, colSpan = the sum of children rowSpan
* - If the current cell has no children, colSpan = 1
*/
const subColumns = column.children;
if (subColumns && subColumns.length > 0) {
colSpan = fillRowCells(subColumns, currentColIndex, [...parents, cell], rowIndex + 1, level + 1).reduce((total, count) => total + count, 0);
cell.hasSubColumns = true;
}
if ('colSpan' in column) {
({
colSpan
} = column);
}
if ('rowSpan' in column) {
cell.rowSpan = column.rowSpan;
}
if (column.key === strings.DEFAULT_KEY_COLUMN_SCROLLBAR) {
cell['x-type'] = strings.DEFAULT_KEY_COLUMN_SCROLLBAR;
}
cell.colSpan = colSpan;
cell.colEnd = cell.colStart + colSpan - 1;
rows[rowIndex].push(cell);
currentColIndex += colSpan;
const ellipsis = column === null || column === void 0 ? void 0 : column.ellipsis;
const shouldShowTitle = shouldShowEllipsisTitle(ellipsis);
if (shouldShowTitle && typeof cell.children === 'string') {
cell.title = cell.children;
}
return colSpan;
});
return colSpans;
}
// Generate `rows` cell data
fillRowCells(columns, 0);
/**
* Calculate header row merge rowSpan
* - If the current cell has no children, you need to calculate rowSpan, rowSpan = the total number of rows in the header-which row currently belongs to
* - If the current cell has children, there is no need to calculate rowSpan
*
* 计算表头行合并 rowSpan
* - 如果当前cell没有children,则需要计算rowSpan,rowSpan = 表头总行数 - 当前属于第几行
* - 如果当前cell有children,则无需计算rowSpan
*/
const rowCount = rows.length;
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
rows[rowIndex].forEach(cell => {
if (!('rowSpan' in cell) && !cell.hasSubColumns) {
cell.rowSpan = rowCount - rowIndex;
}
});
}
return rows;
}
/**
* Render the header of the table header, and control the merging of the columns of the header
*/
class TableHeader extends BaseComponent {
get adapter() {
return Object.assign({}, super.adapter);
}
render() {
const {
components,
columns,
prefixCls,
fixed,
onHeaderRow,
forwardedRef,
selectedRowKeysSet
} = this.props;
const rows = parseHeaderRows(columns);
const HeaderWrapper = components.header.wrapper;
return /*#__PURE__*/React.createElement(HeaderWrapper, {
className: `${prefixCls}-thead`,
ref: forwardedRef
}, rows.map((row, idx) => (/*#__PURE__*/React.createElement(TableHeaderRow, {
prefixCls: prefixCls,
key: idx,
index: idx,
fixed: fixed,
columns: columns,
row: row,
components: components,
onHeaderRow: onHeaderRow,
selectedRowKeysSet: selectedRowKeysSet
}))));
}
}
TableHeader.propTypes = {
components: PropTypes.any,
columns: PropTypes.array,
columnManager: PropTypes.object,
prefixCls: PropTypes.string,
onHeaderRow: PropTypes.func,
onDidUpdate: PropTypes.func,
fixed: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
selectedRowKeysSet: PropTypes.instanceOf(Set).isRequired
};
TableHeader.defaultProps = {
columns: [],
prefixCls: cssClasses.PREFIX,
onHeaderRow: _noop,
onDidUpdate: _noop,
components: {
header: {
wrapper: 'thead',
row: 'tr',
cell: 'th'
}
}
};
export default /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(TableHeader, Object.assign({}, props, {
forwardedRef: ref
})));