123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import React from 'react';
- import classnames from 'classnames';
- import PropTypes from 'prop-types';
- import { get, noop, map, set, omit, findIndex } from 'lodash';
- import { cssClasses } from '@douyinfe/semi-foundation/table/constants';
- import {
- arrayAdd,
- isFirstFixedRight,
- isLastLeftFixed,
- isFixedLeft,
- isFixedRight,
- sliceColumnsByLevel,
- getRTLAlign
- } from '@douyinfe/semi-foundation/table/utils';
- import BaseComponent from '../_base/baseComponent';
- import TableContext, { TableContextProps } from './table-context';
- import { TableComponents, OnHeaderRow, Fixed, TableLocale } from './interface';
- import type { TableHeaderCell } from './TableHeader';
- import Tooltip from '../tooltip';
- import LocaleConsumer from '../locale/localeConsumer';
- import { getNextSortOrder } from './utils';
- export interface TableHeaderRowProps {
- components?: TableComponents;
- row?: TableHeaderCell[];
- prefixCls?: string;
- onHeaderRow?: OnHeaderRow<any>;
- index?: number;
- style?: React.CSSProperties;
- columns?: any[];
- fixed?: Fixed;
- selectedRowKeysSet: Set<any>
- }
- export default class TableHeaderRow extends BaseComponent<TableHeaderRowProps, Record<string, any>> {
- static contextType = TableContext;
- static propTypes = {
- components: PropTypes.object,
- row: PropTypes.array,
- prefixCls: PropTypes.string,
- onHeaderRow: PropTypes.func,
- index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- style: PropTypes.object,
- columns: PropTypes.array,
- fixed: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
- selectedRowKeysSet: PropTypes.instanceOf(Set).isRequired,
- };
- static defaultProps = {
- onHeaderRow: noop,
- prefixCls: cssClasses.PREFIX,
- columns: [] as [],
- components: {
- header: {
- wrapper: 'thead',
- row: 'tr',
- cell: 'th',
- },
- },
- };
- get adapter() {
- return {
- ...super.adapter,
- };
- }
- headerNode: HTMLElement;
- context: TableContextProps;
- constructor(props: TableHeaderRowProps) {
- super(props);
- this.headerNode = null;
- }
- cacheRef = (node: HTMLElement) => {
- this.headerNode = node;
- if (node && this.context.setHeadWidths) {
- const { prefixCls, row, index } = this.props;
- const cellSelector = `.${prefixCls}-row-head`;
- const heads = node && node.querySelectorAll && node.querySelectorAll(cellSelector);
- this.context.setHeadWidths(
- map(heads, (head, headIndex) => {
- let configWidth = get(row, [headIndex, 'column', 'width']);
- const key = get(row, [headIndex, 'column', 'key']) as any;
- if (typeof configWidth !== 'number') {
- configWidth = (head && head.getBoundingClientRect().width) || 0;
- }
- return { width: configWidth, key };
- }),
- index
- );
- }
- };
- componentDidUpdate(prevProps: TableHeaderRowProps) {
- if (prevProps.columns !== this.props.columns && this.headerNode) {
- this.cacheRef(this.headerNode);
- }
- }
- render() {
- const { components, row, prefixCls, onHeaderRow, index, style, columns } = this.props;
- const { getCellWidths, direction } = this.context;
- const isRTL = direction === 'rtl';
- const slicedColumns = sliceColumnsByLevel(columns, index);
- const headWidths = getCellWidths(slicedColumns);
- const HeaderRow = get(components, 'header.row', 'tr');
- const HeaderCell = get(components, 'header.cell', 'th');
- const rowProps = onHeaderRow(columns, index) || {};
- set(rowProps, 'className', classnames(get(rowProps, 'className'), `${prefixCls}-row`));
- const cells = map(row, (cell, cellIndex) => {
- const { column, ...cellProps } = cell;
- const customProps =
- typeof column.onHeaderCell === 'function' ? column.onHeaderCell(column, cellIndex, index) : {};
- let cellStyle = { ...customProps.style };
- if (column.align) {
- const textAlign = getRTLAlign(column.align, direction);
- cellStyle = { ...cellStyle, textAlign };
- customProps.className = classnames(customProps.className, column.className, {
- [`${prefixCls}-align-${textAlign}`]: Boolean(textAlign),
- });
- }
- let fixedLeft, fixedRight, fixedLeftLast, fixedRightFirst;
- if (isRTL) {
- fixedLeft = isFixedRight(column);
- fixedRight = isFixedLeft(column);
- fixedLeftLast = isFirstFixedRight(slicedColumns, column);
- fixedRightFirst = isLastLeftFixed(slicedColumns, column);
- } else {
- fixedLeft = isFixedLeft(column);
- fixedRight = isFixedRight(column);
- fixedLeftLast = isLastLeftFixed(slicedColumns, column);
- fixedRightFirst = isFirstFixedRight(slicedColumns, column);
- }
- customProps.className = classnames(
- `${prefixCls}-row-head`,
- column.className,
- customProps.className,
- // `${prefixCls}-fixed-columns`,
- {
- [`${prefixCls}-cell-fixed-left`]: fixedLeft,
- [`${prefixCls}-cell-fixed-left-last`]: fixedLeftLast,
- [`${prefixCls}-cell-fixed-right`]: fixedRight,
- [`${prefixCls}-cell-fixed-right-first`]: fixedRightFirst,
- [`${prefixCls}-row-head-ellipsis`]: column.ellipsis,
- [`${prefixCls}-row-head-clickSort`]: column.clickToSort
- }
- );
- if (headWidths.length && slicedColumns.length) {
- const indexOfSlicedColumns = findIndex(
- slicedColumns,
- item => item && item.key != null && item.key === column.key
- );
- if (indexOfSlicedColumns > -1) {
- if (isFixedLeft(column)) {
- const xPositionKey = isRTL ? 'right' : 'left';
- cellStyle = {
- ...cellStyle,
- position: 'sticky',
- [xPositionKey]: arrayAdd(headWidths, 0, indexOfSlicedColumns),
- };
- } else if (isFixedRight(column)) {
- const xPositionKey = isRTL ? 'left' : 'right';
- cellStyle = {
- ...cellStyle,
- position: 'sticky',
- [xPositionKey]: arrayAdd(headWidths, indexOfSlicedColumns + 1),
- };
- }
- }
- }
- Object.assign(cellProps, { resize: column.resize });
- const props = omit({ ...cellProps, ...customProps }, [
- 'colStart',
- 'colEnd',
- 'hasSubColumns',
- 'parents',
- 'level',
- ]);
- const { rowSpan, colSpan } = props;
- if (rowSpan === 0 || colSpan === 0) {
- return null;
- }
-
- if (typeof column.clickToSort === 'function') {
- if (props.onClick) {
- const onClick = props.onClick;
- props.onClick = (e: any) => {
- onClick(e);
- column.clickToSort(e);
- };
- } else {
- props.onClick = column.clickToSort;
- }
- }
- if (typeof column.mouseDown === 'function') {
- if (props.onMouseDown) {
- const onMouseDown = props.onMouseDown;
- props.onMouseDown = (e: any) => {
- onMouseDown(e);
- column.mouseDown(e);
- };
- } else {
- props.onMouseDown = column.mouseDown;
- }
- }
- const headerCellNode = (<HeaderCell
- role="columnheader"
- aria-colindex={cellIndex + 1}
- {...props}
- style={cellStyle}
- key={column.key || column.dataIndex || cellIndex}
- />);
- if (typeof column.clickToSort === 'function' && column.showSortTip === true) {
- let content = getNextSortOrder(column.sortOrder);
- return (<LocaleConsumer
- componentName="Table"
- key={column.key || column.dataIndex || cellIndex}
- >
- {(locale: TableLocale, localeCode: string) => (
- <Tooltip content={locale[content]}>
- {headerCellNode}
- </Tooltip>
- )}
- </LocaleConsumer>);
- }
- return headerCellNode;
- });
- return (
- // @ts-ignore no need to do complex ts type checking and qualification
- <HeaderRow
- role="row"
- aria-rowindex={index + 1}
- {...rowProps}
- style={style}
- ref={this.cacheRef}
- >
- {cells}
- </HeaderRow>
- );
- }
- }
|