UNPKG

choerodon-ui

Version:

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

733 lines (649 loc) 27.3 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectSpread from "@babel/runtime/helpers/objectSpread2"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import React, { cloneElement, isValidElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import classNames from 'classnames'; import { action, runInAction } from 'mobx'; import { observer } from 'mobx-react-lite'; import raf from 'raf'; import omit from 'lodash/omit'; import isObject from 'lodash/isObject'; import noop from 'lodash/noop'; import isString from 'lodash/isString'; import debounce from 'lodash/debounce'; import defaultTo from 'lodash/defaultTo'; import isUndefined from 'lodash/isUndefined'; import { pxToRem } from '../../../es/_util/UnitConvertor'; import ReactResizeObserver from '../../../es/_util/resizeObserver'; import measureScrollbar from '../../../es/_util/measureScrollbar'; import Popover from '../../../es/popover'; import ConfigContext from '../../../es/config-provider/ConfigContext'; import { minColumnWidth } from './Column'; import TableContext from './TableContext'; import Icon from '../icon'; import EventManager, { stopEvent } 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 { transformZoomData } from '../_util/DocumentUtils'; 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'; import TextField from '../text-field'; import Button from '../button/Button'; import { SortOrder } from '../data-set/interface'; import { ButtonColor } from '../button/enum'; import { ValueChangeAction } from '../text-field/enum'; import { $l } from '../locale-context'; 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, intersectionRef = props.intersectionRef, isRenderCell = props.isRenderCell; var column = columnGroup.column, key = columnGroup.key, prev = columnGroup.prev; var tooltipProps = column.tooltipProps; 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, headerFilter = tableStore.headerFilter; 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, filter = column.filter; var field = dataSet.getField(name); var _useState = useState(), _useState2 = _slicedToArray(_useState, 2), filterText = _useState2[0], _setFilterText = _useState2[1]; 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, groups: columnGroup.headerGroups, 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.touches ? transformZoomData(e.touches[0].clientX) : transformZoomData(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('touchmove').removeEventListener('mouseup').removeEventListener('touchend'); var tableBodyWrap = tableStore.node.tableBodyWrap; if (tableBodyWrap) { tableBodyWrap.removeEventListener('scroll', stopEvent); } 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 _tableStore$node = tableStore.node, element = _tableStore$node.element, tableBodyWrap = _tableStore$node.tableBodyWrap, tableColumnResizeTrigger = tableStore.tableColumnResizeTrigger; if (tableColumnResizeTrigger !== TableColumnResizeTriggerType.hover) { var left = Math.round(element.getBoundingClientRect().left); globalRef.current.bodyLeft = border ? left + 1 : left; } setSplitLinePosition(transformZoomData(e.clientX)); resizeEvent.setTarget(element.ownerDocument).addEventListener('mousemove', resize).addEventListener('touchmove', resize).addEventListener('mouseup', resizeEnd).addEventListener('touchend', resizeEnd); e.stopPropagation(); if (tableBodyWrap) { tableBodyWrap.addEventListener('scroll', stopEvent, { passive: true }); } }), [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) { var sortable = column.sortable; if (typeof sortable === 'function') { var fieldProps = dataSet.props.fields ? dataSet.props.fields.find(function (f) { return f.name === name; }) : undefined; if (field && fieldProps) { var unOrder = field.order || fieldProps.order; runInAction(function () { var nowCombineSort = dataSet.combineSort; dataSet.fields.forEach(function (current) { if (current.order && (current !== field || nowCombineSort)) { current.order = undefined; } }); dataSet.combineSort = false; switch (unOrder) { case SortOrder.asc: field.order = SortOrder.desc; break; case SortOrder.desc: field.order = undefined; break; default: field.order = SortOrder.asc; } }); } runInAction(function () { dataSet.records = dataSet.records.sort(function (record1, record2) { return sortable(record1, record2, field.order); }); }); } else { dataSet.sort(name); } } }, [dataSet, name]); var handleMouseEnter = useCallback(function (e) { var tooltip = tableStore.getColumnTooltip(column); var currentTarget = e.currentTarget; var measureElement = currentTarget.getElementsByClassName("".concat(prefixCls, "-cell-inner-right-has-other"))[0] || currentTarget; if (!tableStore.columnResizing && (tooltip === TableColumnTooltip.always || tooltip === TableColumnTooltip.overflow && isOverflow(measureElement))) { var tooltipConfig = isObject(tooltipProps) ? tooltipProps : {}; show(currentTarget, _objectSpread({ title: header, placement: getTooltipPlacement('table-cell') || 'right', theme: getTooltipTheme('table-cell') }, tooltipConfig)); globalRef.current.tooltipShown = true; } }, [tableStore, column, globalRef, getTooltipTheme, getTooltipPlacement, header]); 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 left = Math.round(element.getBoundingClientRect().left); var rect = e.target.getBoundingClientRect(); var width = Math.round(rect.width); var resizerLeft = Math.round(rect.left); var newLeft = resizerLeft + (type === 'pre' ? 0 : width); globalRef.current.bodyLeft = border ? left + 1 : left; setSplitLinePosition(newLeft); }, []); var delayShowSplitLine = useCallback(debounce(showSplitLine, 300, { leading: true, trailing: false }), []); 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; 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 onReset = useCallback(function () { _setFilterText(''); runInAction(function () { tableStore.headerFilter = undefined; }); }, [_setFilterText, tableStore]); var doFilter = useCallback(function () { if (!isUndefined(filterText)) { runInAction(function () { tableStore.headerFilter = { fieldName: name, filterText: filterText === null ? '' : filterText, filter: filter }; }); } }, [filterText, tableStore, name, filter]); var handleResize = useCallback(function () { var clipboard = tableStore.clipboard, startChooseCell = tableStore.startChooseCell, endChooseCell = tableStore.endChooseCell, drawCopyBorder = tableStore.drawCopyBorder; if (clipboard && startChooseCell && endChooseCell) { drawCopyBorder(); } }, [column.width]); 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, onPointerDown: 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, onPointerDown: 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 && !isSearchCell) { var fieldHelp = defaultTo(column.help, field && field.get('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; } }; }, []); 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 getConstSortIcon = function getConstSortIcon() { var _classNames; var combineSort = dataSet.combineSort; var tableShowSortIcon = tableStore.getConfig('tableShowSortIcon'); var combineSortField = combineSort && field && field.order; var type = combineSortField ? field && field.order === 'asc' ? 'paixu-shang' : 'paixu-xia' : (tableShowSortIcon || combineSort) && !(field && field.order) ? 'sort-all' : 'arrow_upward'; var className = classNames("".concat(prefixCls, "-sort-icon"), (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-sort-icon-temp"), tableShowSortIcon || combineSort && !combineSortField), _defineProperty(_classNames, "".concat(prefixCls, "-sort-icon-combine"), combineSortField), _classNames)); return /*#__PURE__*/React.createElement(Icon, { key: "sort", type: type, className: className }); }; var getFilterIcon = function getFilterIcon() { if (column.filter) { var popoverContent; var footer = /*#__PURE__*/React.createElement("div", { className: "".concat(prefixCls, "-sort-popup-footer") }, /*#__PURE__*/React.createElement(Button, { onClick: onReset, key: 'reset' }, $l('Table', 'reset_button')), /*#__PURE__*/React.createElement(Button, { color: ButtonColor.primary, onClick: doFilter, key: 'filter' }, $l('Table', 'search'))); var columnFilterPopover = column.filterPopover || tableStore.getConfig('tableColumnFilterPopover'); if (typeof columnFilterPopover === 'function') { popoverContent = /*#__PURE__*/React.createElement("div", { onClick: function onClick(e) { return e.stopPropagation(); } }, columnFilterPopover({ setFilterText: function setFilterText(filterText) { return _setFilterText(filterText); }, dataSet: dataSet, field: field, filterText: filterText, clearFilters: onReset, confirm: doFilter, footer: footer })); } else { popoverContent = /*#__PURE__*/React.createElement("div", { onClick: function onClick(e) { return e.stopPropagation(); } }, /*#__PURE__*/React.createElement(TextField, { autoFocus: true, onEnterDown: doFilter, style: { width: '100%' }, valueChangeAction: ValueChangeAction.input, value: filterText, onChange: function onChange(value) { return _setFilterText(value); } }), footer); } return /*#__PURE__*/React.createElement(Popover, { content: popoverContent, overlayClassName: "".concat(prefixCls, "-sort-popup-content"), trigger: "click", onVisibleChange: function onVisibleChange() { if (headerFilter) { _setFilterText(headerFilter.fieldName === name ? String(headerFilter.filterText) : ''); } }, key: 'filter' }, /*#__PURE__*/React.createElement(Icon, { key: "filter", className: filterText && String(headerFilter && headerFilter.fieldName) === name ? "".concat(prefixCls, "-filter-icon ").concat(prefixCls, "-filter-icon-active") : "".concat(prefixCls, "-filter-icon"), type: "search", onClick: function onClick(e) { return e.stopPropagation(); } })); } return undefined; }; // 过滤按钮 var filterIcon = getFilterIcon(); // 帮助按钮 var helpIcon = getHelpIcon(); // 排序按钮 var sortIcon = !column.aggregation && column.sortable && name && !isSearchCell ? getConstSortIcon() : undefined; var headerNodePlaceholder = Symbol('headerNodePlaceholder'); var childNodes = [headerNodePlaceholder]; var innerClassNames = ["".concat(prefixCls, "-cell-inner")]; var innerProps = { children: childNodes, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }; var labelClassNames = []; if (helpIcon) { childNodes.push(helpIcon); labelClassNames.push("".concat(prefixCls, "-cell-inner-right-has-help")); } if (sortIcon) { if (field && field.order) { classList.push("".concat(prefixCls, "-sort-").concat(field.order)); var combineSort = dataSet.combineSort; if (combineSort) { classList.push("".concat(prefixCls, "-sort-").concat(field.order, "-combine")); } else { classList.push("".concat(prefixCls, "-sort-").concat(field.order, "-temp")); } } innerProps.onClick = handleClick; childNodes.push(sortIcon); labelClassNames.push("".concat(prefixCls, "-cell-inner-right-has-sort")); } if (filterIcon) { childNodes.push(filterIcon); labelClassNames.push("".concat(prefixCls, "-cell-inner-right-has-filter")); } if (expandIcon) { childNodes.unshift( /*#__PURE__*/React.createElement("span", { key: "prefix", className: !isSearchCell ? "".concat(prefixCls, "-header-expand-icon") : undefined }, expandIcon)); } // 兼容 label 超长 if (labelClassNames.length > 0) { labelClassNames.push("".concat(prefixCls, "-cell-inner-right-has-other")); } var labelClassNamesStr = labelClassNames.length > 0 ? labelClassNames.join(' ') : undefined; var headerNode = !isSearchCell ? /*#__PURE__*/isValidElement(header) ? /*#__PURE__*/cloneElement(header, { key: 'text', className: classNames(header.props && header.props.className, labelClassNamesStr) }) : isString(header) ? /*#__PURE__*/React.createElement("span", { key: "text", className: labelClassNamesStr }, header) : header : null; childNodes[childNodes.findIndex(function (item) { return item === headerNodePlaceholder; })] = headerNode; if (!isSearchCell) { var $rowHeight = headerRowHeight === undefined ? rowHeight : headerRowHeight; if ($rowHeight !== 'auto') { var height = Number(cellStyle.height) || $rowHeight * (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")); } if (!tableStore.tableColumnResizeTransition) { classList.push("".concat(prefixCls, "-cell-no-transition")); } var thProps = { className: classList.join(' '), rowSpan: rowSpan, colSpan: colSpan, 'data-index': key, style: omit(cellStyle, ['width', 'height']), scope: scope }; if (intersectionRef) { thProps.ref = intersectionRef; } if (!isRenderCell) { return /*#__PURE__*/React.createElement("th", _extends({}, thProps)); } return /*#__PURE__*/React.createElement(ReactResizeObserver, { onResize: handleResize }, /*#__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