UNPKG

choerodon-ui

Version:

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

525 lines (462 loc) 19.1 kB
import _extends from "@babel/runtime/helpers/extends"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectSpread from "@babel/runtime/helpers/objectSpread2"; import React, { cloneElement, isValidElement, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; import { action } from 'mobx'; import { useInView } from 'react-intersection-observer'; import { observer } from 'mobx-react-lite'; import raf from 'raf'; import omit from 'lodash/omit'; import noop from 'lodash/noop'; import isString from 'lodash/isString'; import debounce from 'lodash/debounce'; import defaultTo from 'lodash/defaultTo'; import { pxToRem } from '../../../es/_util/UnitConvertor'; import measureScrollbar from '../../../es/_util/measureScrollbar'; import ConfigContext from '../../../es/config-provider/ConfigContext'; import { minColumnWidth } from './Column'; import TableContext from './TableContext'; import Icon from '../icon'; import EventManager from '../_util/EventManager'; import { getColumnLock, getHeader, getMaxClientWidth, isStickySupport } from './utils'; import { ColumnAlign, ColumnLock, TableColumnResizeTriggerType, TableColumnTooltip } from './enum'; import { ShowHelp } from '../field/enum'; import Tooltip from '../tooltip/Tooltip'; import transform from '../_util/transform'; import { hide, show } from '../tooltip/singleton'; import isOverflow from '../overflow-tip/util'; import { CUSTOMIZED_KEY } from './TableStore'; import { groupedAggregationTree } from './AggregationTree'; import TableCellInner from './TableCellInner'; var TableHeaderCell = function TableHeaderCell(props) { var columnGroup = props.columnGroup, rowSpan = props.rowSpan, colSpan = props.colSpan, className = props.className, rowIndex = props.rowIndex, _props$getHeaderNode = props.getHeaderNode, getHeaderNode = _props$getHeaderNode === void 0 ? noop : _props$getHeaderNode, scope = props.scope, expandIcon = props.children, isSearchCell = props.isSearchCell; var column = columnGroup.column, key = columnGroup.key, prev = columnGroup.prev; var _useContext = useContext(TableContext), rowHeight = _useContext.rowHeight, border = _useContext.border, prefixCls = _useContext.prefixCls, tableStore = _useContext.tableStore, dataSet = _useContext.dataSet, aggregation = _useContext.aggregation, autoMaxWidth = _useContext.autoMaxWidth; var _useContext2 = useContext(ConfigContext), getTooltipTheme = _useContext2.getTooltipTheme, getTooltipPlacement = _useContext2.getTooltipPlacement; var columnResizable = tableStore.columnResizable, headerRowHeight = tableStore.headerRowHeight; var headerClassName = column.headerClassName, _column$headerStyle = column.headerStyle, headerStyle = _column$headerStyle === void 0 ? {} : _column$headerStyle, name = column.name, align = column.align, children = column.children, command = column.command, lock = column.lock; var field = dataSet.getField(name); var needIntersection = tableStore.virtualCell && tableStore.overflowX; var _useInView = useInView({ root: needIntersection ? tableStore.node.wrapper : undefined, rootMargin: '100px', initialInView: true }), ref = _useInView.ref, inView = _useInView.inView; var aggregationTree = useMemo(function () { if (aggregation) { var $column = columnGroup.column, headerGroup = columnGroup.headerGroup; if (headerGroup) { var tableGroup = columnGroup.tableGroup; if (tableGroup) { var columnProps = tableGroup.columnProps; var totalRecords = headerGroup.totalRecords; if (columnProps && totalRecords.length) { var _children = columnProps.children; if (_children && _children.length) { var renderer = function renderer(_ref) { var colGroup = _ref.colGroup, style = _ref.style; return /*#__PURE__*/React.createElement(TableCellInner, { record: totalRecords[0], column: colGroup.column, style: style, inAggregation: true }); }; return groupedAggregationTree({ columns: _children, headerGroup: headerGroup, column: _objectSpread(_objectSpread({}, $column), columnProps), renderer: renderer }); } } } } } }, [columnGroup, aggregation]); var header = getHeader(_objectSpread(_objectSpread({}, column), {}, { dataSet: dataSet, aggregation: aggregation, group: columnGroup.headerGroup, aggregationTree: aggregationTree })); var globalRef = useRef({ bodyLeft: 0, resizeBoundary: 0 }); var resizeEvent = useMemo(function () { return new EventManager(); }, []); var setSplitLineHidden = useCallback(function (hidden) { var resizeLine = tableStore.node.resizeLine; if (resizeLine) { resizeLine.style.display = hidden ? 'none' : 'block'; } }, [tableStore]); var setSplitLinePosition = useCallback(action(function (left) { var resizeLine = tableStore.node.resizeLine; var bodyLeft = globalRef.current.bodyLeft; left -= bodyLeft; if (left < 0) { left = 0; } if (resizeLine) { transform("translateX(".concat(pxToRem(left, true) || 0, ")"), resizeLine.style); } return left + bodyLeft; }), [tableStore, globalRef]); var resize = useCallback(function (e) { var current = globalRef.current; var resizeColumnGroup = current.resizeColumnGroup; if (resizeColumnGroup) { var limit = current.resizeBoundary + minColumnWidth(resizeColumnGroup.column, tableStore); var left = e.clientX; if (left < limit) { left = limit; } current.resizePosition = setSplitLinePosition(left); } }, [globalRef, setSplitLinePosition]); var resizeEnd = useCallback(action(function () { tableStore.columnResizing = false; setSplitLineHidden(true); resizeEvent.removeEventListener('mousemove').removeEventListener('mouseup'); var _globalRef$current = globalRef.current, resizePosition = _globalRef$current.resizePosition, resizeColumnGroup = _globalRef$current.resizeColumnGroup; if (resizePosition !== undefined && resizeColumnGroup) { var resizeColumn = resizeColumnGroup.column; var newWidth = Math.round(Math.max(resizePosition - globalRef.current.resizeBoundary, minColumnWidth(resizeColumn, tableStore))); if (newWidth !== resizeColumn.width) { var width = resizeColumn.width; var group = resizeColumnGroup; var element = tableStore.node.element; while (group) { var _group = group, col = _group.column; if (col.width === undefined) { var th = element.querySelector(".".concat(prefixCls, "-thead .").concat(prefixCls, "-cell[data-index=\"").concat(col.name, "\"]")); if (th) { tableStore.setColumnWidth(group, th.offsetWidth); } } group = group.prev; } if (width === undefined) { raf(function () { tableStore.setColumnWidth(resizeColumnGroup, newWidth); }); } else { tableStore.setColumnWidth(resizeColumnGroup, newWidth); } } } }), [globalRef, tableStore, setSplitLineHidden, resizeEvent]); var resizeStart = useCallback(action(function (e) { tableStore.columnResizing = true; delete globalRef.current.resizePosition; setSplitLineHidden(false); var element = tableStore.node.element, tableColumnResizeTrigger = tableStore.tableColumnResizeTrigger; if (tableColumnResizeTrigger !== TableColumnResizeTriggerType.hover) { var _element$getBoundingC = element.getBoundingClientRect(), left = _element$getBoundingC.left; globalRef.current.bodyLeft = border ? left + 1 : left; } setSplitLinePosition(e.clientX); resizeEvent.setTarget(element.ownerDocument).addEventListener('mousemove', resize).addEventListener('mouseup', resizeEnd); }), [tableStore, globalRef, setSplitLineHidden, setSplitLinePosition, resizeEvent]); var delayResizeStart = useCallback(debounce(resizeStart, 300, { leading: true, trailing: false }), [resizeStart]); var prevColumnGroup = columnResizable ? prev && prev.lastLeaf : undefined; var currentColumnGroup = columnResizable ? columnGroup.lastLeaf : undefined; var handleClick = useCallback(function () { if (name) { dataSet.sort(name); } }, [dataSet, name]); var handleMouseEnter = useCallback(function (e) { var tooltip = tableStore.getColumnTooltip(column); var currentTarget = e.currentTarget; if (!tableStore.columnResizing && (tooltip === TableColumnTooltip.always || tooltip === TableColumnTooltip.overflow && isOverflow(currentTarget))) { show(currentTarget, { title: header, placement: getTooltipPlacement('table-cell') || 'right', theme: getTooltipTheme('table-cell') }); globalRef.current.tooltipShown = true; } }, [tableStore, column, globalRef, getTooltipTheme, getTooltipPlacement]); var handleMouseLeave = useCallback(function () { if (globalRef.current.tooltipShown) { hide(); delete globalRef.current.tooltipShown; } }, [globalRef]); var setResizeGroup = useCallback(function (group) { globalRef.current.resizeColumnGroup = group; var headerDom = getHeaderNode(); var node = headerDom && headerDom.querySelector("[data-index=\"".concat(group.key, "\"]")); if (node) { globalRef.current.resizeBoundary = Math.round(node.getBoundingClientRect().left); } }, [globalRef, getHeaderNode]); var handleLeftResize = useCallback(function (e) { if (prevColumnGroup) { setResizeGroup(prevColumnGroup); if (autoMaxWidth) { e.persist(); delayResizeStart(e); } else { resizeStart(e); } } }, [prevColumnGroup, setResizeGroup, autoMaxWidth, delayResizeStart, resizeStart]); var handleRightResize = useCallback(function (e) { if (currentColumnGroup) { setResizeGroup(currentColumnGroup); if (autoMaxWidth) { e.persist(); delayResizeStart(e); } else { resizeStart(e); } } }, [currentColumnGroup, setResizeGroup, autoMaxWidth, delayResizeStart, resizeStart]); var showSplitLine = useCallback(function (e, type) { var columnResizing = tableStore.columnResizing; if (columnResizing) return; setSplitLineHidden(false); var element = tableStore.node.element; var _element$getBoundingC2 = element.getBoundingClientRect(), left = _element$getBoundingC2.left; var _e$target$getBounding = e.target.getBoundingClientRect(), resizerLeft = _e$target$getBounding.left, width = _e$target$getBounding.width; var newLeft = resizerLeft + (type === 'pre' ? 0 : width); globalRef.current.bodyLeft = border ? left + 1 : left; setSplitLinePosition(newLeft); }, []); var delayShowSplitLine = useCallback(debounce(showSplitLine, 300), []); var handleShowSplitLine = useCallback(function (e, type) { var tableColumnResizeTrigger = tableStore.tableColumnResizeTrigger; if (tableColumnResizeTrigger !== TableColumnResizeTriggerType.hover) return; e.persist(); delayShowSplitLine(e, type); }, []); var handleHideSplitLine = useCallback(function () { var tableColumnResizeTrigger = tableStore.tableColumnResizeTrigger; if (tableColumnResizeTrigger !== TableColumnResizeTriggerType.hover) return; delayShowSplitLine.cancel(); var columnResizing = tableStore.columnResizing; if (columnResizing) return; setSplitLineHidden(true); }, []); var resizeDoubleClick = useCallback(action(function () { var resizeColumnGroup = globalRef.current.resizeColumnGroup; if (resizeColumnGroup) { var col = resizeColumnGroup.column; var element = tableStore.node.element; var maxWidth = Math.max.apply(Math, _toConsumableArray(_toConsumableArray(element.querySelectorAll("[data-index=\"".concat(resizeColumnGroup.key, "\"] > .").concat(prefixCls, "-cell-inner"))).map(function (node) { return node.parentNode.offsetWidth + getMaxClientWidth(node) - node.clientWidth + 1; })).concat([minColumnWidth(col, tableStore), col.width ? col.width : 0])); if (maxWidth !== col.width) { tableStore.setColumnWidth(resizeColumnGroup, maxWidth); } else if (col.minWidth) { tableStore.setColumnWidth(resizeColumnGroup, col.minWidth); } } }), [globalRef, prefixCls, tableStore]); var handleLeftDoubleClick = useCallback(function () { resizeDoubleClick(); }, [delayResizeStart, resizeDoubleClick]); var handleRightDoubleClick = useCallback(function () { resizeDoubleClick(); }, [delayResizeStart, resizeDoubleClick]); var renderResizer = function renderResizer() { var columns = tableStore.rightColumnGroups.columns, overflowX = tableStore.overflowX; var columnGroup = props.columnGroup; var resizerPrefixCls = "".concat(prefixCls, "-resizer"); var pre = prevColumnGroup && prevColumnGroup.column.resizable && /*#__PURE__*/React.createElement("div", { key: "pre", className: "".concat(resizerPrefixCls, " ").concat(resizerPrefixCls, "-left"), onDoubleClick: autoMaxWidth ? handleLeftDoubleClick : undefined, onMouseDown: handleLeftResize, onMouseEnter: function onMouseEnter(e) { return handleShowSplitLine(e, 'pre'); }, onMouseLeave: handleHideSplitLine }); var next = currentColumnGroup && currentColumnGroup.column.resizable && /*#__PURE__*/React.createElement("div", { key: "next", className: "".concat(resizerPrefixCls, " ").concat(resizerPrefixCls, "-right"), onDoubleClick: autoMaxWidth ? handleRightDoubleClick : undefined, onMouseDown: handleRightResize, onMouseEnter: function onMouseEnter(e) { return handleShowSplitLine(e, 'next'); }, onMouseLeave: handleHideSplitLine }); if (columns.length && overflowX && columns[0].key === columnGroup.key) return next; return [pre, next]; }; var getHelpIcon = function getHelpIcon() { if (column.showHelp !== ShowHelp.none) { var fieldHelp = defaultTo(field && field.get('help'), column.help); if (fieldHelp) { return /*#__PURE__*/React.createElement(Tooltip, { title: fieldHelp, placement: getTooltipPlacement('help'), theme: getTooltipTheme('help'), key: "help" }, /*#__PURE__*/React.createElement("span", { className: "".concat(prefixCls, "-help-icon") })); } } }; useEffect(function () { return function () { resizeEvent.clear(); delayResizeStart.cancel(); if (globalRef.current.tooltipShown) { hide(); delete globalRef.current.tooltipShown; } }; }, []); useEffect(function () { if (needIntersection) { columnGroup.setInView(inView); } else if (columnGroup.inView !== undefined) { columnGroup.setInView(undefined); } }, [needIntersection, columnGroup, inView]); var columnLock = isStickySupport() && tableStore.overflowX && getColumnLock(lock); var classList = ["".concat(prefixCls, "-cell")]; var cellStyle = _objectSpread({ textAlign: align || (command || children && children.length ? ColumnAlign.center : tableStore.getConfig('tableColumnAlign')(column, field)) }, headerStyle); if (columnLock) { classList.push("".concat(prefixCls, "-cell-fix-").concat(columnLock)); if (columnLock === ColumnLock.left) { cellStyle.left = pxToRem(columnGroup.left, true); } else if (columnLock === ColumnLock.right) { cellStyle.right = pxToRem(columnGroup.right + (rowIndex === 0 && tableStore.overflowY ? measureScrollbar() : 0), true); } } if (className) { classList.push(className); } if (headerClassName) { classList.push(headerClassName); } var headerNode = !isSearchCell ? /*#__PURE__*/isValidElement(header) ? /*#__PURE__*/cloneElement(header, { key: 'text' }) : isString(header) ? /*#__PURE__*/React.createElement("span", { key: "text" }, header) : header : null; // 帮助按钮 var helpIcon = getHelpIcon(); // 排序按钮 var sortIcon = !column.aggregation && column.sortable && name ? /*#__PURE__*/React.createElement(Icon, { key: "sort", type: "arrow_upward", className: "".concat(prefixCls, "-sort-icon") }) : undefined; var childNodes = [headerNode]; var innerClassNames = ["".concat(prefixCls, "-cell-inner")]; var innerProps = { children: childNodes, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }; if (helpIcon) { if (cellStyle.textAlign === ColumnAlign.right) { childNodes.unshift(helpIcon); } else { childNodes.push(helpIcon); } } if (sortIcon) { if (field && field.order) { classList.push("".concat(prefixCls, "-sort-").concat(field.order)); } innerProps.onClick = handleClick; if (cellStyle.textAlign === ColumnAlign.right) { childNodes.unshift(sortIcon); } else { childNodes.push(sortIcon); } } if (expandIcon) { childNodes.unshift( /*#__PURE__*/React.createElement("span", { key: "prefix", className: !isSearchCell ? "".concat(prefixCls, "-header-expand-icon") : undefined }, expandIcon)); } if (headerRowHeight !== 'auto' && rowHeight !== 'auto' && !isSearchCell) { var height = Number(cellStyle.height) || (headerRowHeight === undefined ? rowHeight : headerRowHeight) * (rowSpan || 1); innerProps.style = { height: pxToRem(height), lineHeight: pxToRem(height - 2) }; innerClassNames.push("".concat(prefixCls, "-cell-inner-row-height-fixed")); } if (isSearchCell) { innerClassNames.push("".concat(prefixCls, "-cell-search-header")); } if (key === CUSTOMIZED_KEY && isStickySupport() && tableStore.stickyRight && tableStore.overflowX && tableStore.columnGroups.rightLeafs.length === 1) { classList.push("".concat(prefixCls, "-cell-sticky-shadow")); } var thProps = { className: classList.join(' '), rowSpan: rowSpan, colSpan: colSpan, 'data-index': key, style: omit(cellStyle, ['width', 'height']), scope: scope }; if (needIntersection) { thProps.ref = ref; } return /*#__PURE__*/React.createElement("th", _extends({}, thProps), /*#__PURE__*/React.createElement("div", _extends({}, innerProps, { className: innerClassNames.join(' ') })), columnResizable && renderResizer()); }; TableHeaderCell.displayName = 'TableHeaderCell'; export default observer(TableHeaderCell); //# sourceMappingURL=TableHeaderCell.js.map