choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
525 lines (462 loc) • 19.1 kB
JavaScript
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