UNPKG

choerodon-ui

Version:

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

723 lines (637 loc) 25.1 kB
import _objectSpread from "@babel/runtime/helpers/objectSpread2"; import _regeneratorRuntime from "@babel/runtime/regenerator"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _extends from "@babel/runtime/helpers/extends"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import React, { cloneElement, isValidElement, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; import { observer } from 'mobx-react-lite'; import { isArrayLike } from 'mobx'; import raf from 'raf'; import classNames from 'classnames'; import isNil from 'lodash/isNil'; import isPlainObject from 'lodash/isPlainObject'; import isString from 'lodash/isString'; import isObject from 'lodash/isObject'; import { pxToRem } from '../../../es/_util/UnitConvertor'; import { getConfig } from '../../../es/configure'; import KeyCode from '../../../es/_util/KeyCode'; import measureScrollbar from '../../../es/_util/measureScrollbar'; import { getTooltip, getTooltipTheme } from '../../../es/_util/TooltipUtils'; import TableContext from './TableContext'; import { findCell, getColumnKey, getEditorByColumnAndRecord, isInCellEditor, isStickySupport } from './utils'; import { FieldType, RecordStatus } from '../data-set/enum'; import { SELECTION_KEY } from './TableStore'; import { ColumnAlign, SelectionMode, TableCommandType } from './enum'; import Tooltip from '../tooltip/Tooltip'; import ObserverCheckBox from '../check-box/CheckBox'; import { $l } from '../locale-context'; import Button from '../button/Button'; import { LabelLayout } from '../form/enum'; import { findFirstFocusableElement } from '../_util/focusable'; import SelectionTreeBox from './SelectionTreeBox'; import { getDateFormatByField, isFieldValueEmpty, processFieldValue, processValue as utilProcessValue, renderMultiLine, renderMultipleValues, renderRangeValue, renderValidationMessage as utilRenderValidationMessage, showValidationMessage, toMultipleValue, toRangeValue, transformHighlightProps } from '../field/utils'; import localeContext from '../locale-context/LocaleContext'; import isEmpty from '../_util/isEmpty'; import { Tooltip as TextTooltip } from '../core/enum'; import isOverflow from '../overflow-tip/util'; import { hide, show } from '../tooltip/singleton'; import useComputed from '../use-computed'; import { ShowHelp } from '../field/enum'; import { defaultOutputRenderer } from '../output/utils'; var inTab = false; var TableCellInner = observer(function TableCellInner(props) { var column = props.column, record = props.record, children = props.children, style = props.style, disabled = props.disabled, inAggregation = props.inAggregation, prefixCls = props.prefixCls, colSpan = props.colSpan; var multipleValidateMessageLengthRef = useRef(0); var tooltipShownRef = useRef(); var _useContext = useContext(TableContext), pristine = _useContext.pristine, aggregation = _useContext.aggregation, inlineEdit = _useContext.inlineEdit, rowHeight = _useContext.rowHeight, tableStore = _useContext.tableStore, dataSet = _useContext.dataSet, columnEditorBorder = _useContext.columnEditorBorder, indentSize = _useContext.indentSize, checkField = _useContext.checkField, selectionMode = _useContext.selectionMode; var innerPrefixCls = "".concat(prefixCls, "-inner"); var tooltip = tableStore.getColumnTooltip(column); var name = column.name, key = column.key, lock = column.lock, renderer = column.renderer, command = column.command, align = column.align; var columnKey = getColumnKey(column); var height = record.getState("__column_resize_height_".concat(name)); var currentEditRecord = tableStore.currentEditRecord; var field = record.getField(name); var fieldDisabled = disabled || field && field.get('disabled'); var columnCommand = useComputed(function () { if (typeof command === 'function') { return command({ dataSet: dataSet, record: record, aggregation: aggregation }); } return command; }, [record, command, dataSet, aggregation]); var canFocus = useMemo(function () { return !fieldDisabled && (!inlineEdit || record === currentEditRecord); }, [fieldDisabled, record, currentEditRecord, inlineEdit]); var cellEditor = getEditorByColumnAndRecord(column, record); var cellEditorInCell = isInCellEditor(cellEditor); var hasEditor = !pristine && cellEditor && !cellEditorInCell; var showEditor = useCallback(function (cell) { if (name && hasEditor) { if (!lock && tableStore.overflowX) { var tableBodyWrap = tableStore.virtual ? cell.offsetParent.parentNode.parentNode : cell.offsetParent; if (tableBodyWrap) { var _tableStore$columnGro = tableStore.columnGroups, leftLeafColumnsWidth = _tableStore$columnGro.leftLeafColumnsWidth, rightLeafColumnsWidth = _tableStore$columnGro.rightLeafColumnsWidth; var offsetLeft = cell.offsetLeft, offsetWidth = cell.offsetWidth; var scrollLeft = tableBodyWrap.scrollLeft; var _tableBodyWrap$getBou = tableBodyWrap.getBoundingClientRect(), width = _tableBodyWrap$getBou.width; var leftSide = offsetLeft - leftLeafColumnsWidth; var rightSide = offsetLeft + offsetWidth - width + rightLeafColumnsWidth + measureScrollbar(); var sl = scrollLeft; if (sl < rightSide) { sl = rightSide; } if (sl > leftSide) { sl = leftSide; } if (sl !== scrollLeft) { tableBodyWrap.scrollLeft = sl; } } } tableStore.showEditor(name); var editor = tableStore.editors.get(name); if (editor) { if (editor.cellNode) { if (tableStore.inlineEdit) { if (editor.inTab) { editor.inTab = false; } else { editor.focus(); } } else { editor.hideEditor(); } } else if (tableStore.inlineEdit) { editor.focus(); } else { raf(function () { editor.alignEditor(!isStickySupport() && lock ? findCell(tableStore, columnKey, lock) : cell); editor.focus(); }); } } } }, [column, name, hasEditor, columnKey, tableStore]); var handleFocus = useCallback(function (e) { if (canFocus) { if (key !== SELECTION_KEY) { dataSet.current = record; } showEditor(e.currentTarget); if (!isStickySupport() && (key === SELECTION_KEY || !hasEditor)) { var cell = findCell(tableStore, columnKey, lock); if (cell && !cell.contains(document.activeElement)) { var node = findFirstFocusableElement(cell); if (node && !inTab) { node.focus(); } } } } inTab = false; }, [tableStore, dataSet, record, lock, columnKey, canFocus, hasEditor, showEditor]); var handleEditorKeyDown = useCallback(function (e) { switch (e.keyCode) { case KeyCode.TAB: { var cell = findCell(tableStore, columnKey); if (cell) { if (cell.contains(document.activeElement)) { inTab = true; } else { var node = findFirstFocusableElement(cell); if (node) { inTab = true; node.focus(); } } } break; } default: } }, [tableStore, columnKey]); var handleCommandSave = useCallback(function () { return dataSet.submit().then(function (result) { if (result !== false) { tableStore.currentEditRecord = undefined; } }); }, [tableStore, dataSet]); var handleCommandCancel = useCallback(function () { if (record.status === RecordStatus.add) { dataSet.remove(record); } else { record.reset(); tableStore.currentEditRecord = undefined; } }, [tableStore, record, dataSet]); var handleCommandEdit = useCallback(function () { if (tableStore.inlineEdit) { tableStore.currentEditRecord = record; } }, [tableStore, record]); var handleCommandDelete = useCallback(function () { dataSet["delete"](record); }, [dataSet, record]); var multiLine = field && field.get('multiLine'); var fieldType = !aggregation && rowHeight !== 'auto' && field && field.type; var rows = multiLine ? _toConsumableArray(record.fields.values()).reduce(function (count, dsField) { var bind = dsField.get('bind'); if (bind && bind.startsWith("".concat(name, "."))) { return count + 1; } return count; }, 0) : 0; var checkBox = function () { if (children) { if (selectionMode === SelectionMode.treebox) { return React.createElement(SelectionTreeBox, { record: record }); } if (checkField && !tableStore.hasCheckFieldColumn) { return React.createElement(ObserverCheckBox, { name: checkField, record: record, disabled: disabled, indeterminate: record.isIndeterminate }); } } }(); var renderCommand = useCallback(function () { var tableCommandProps = getConfig('tableCommandProps'); var classString = classNames("".concat(prefixCls, "-command"), tableCommandProps && tableCommandProps.className); if (record.editing) { return [React.createElement(Tooltip, { key: "save", title: $l('Table', 'save_button') }, React.createElement(Button, _extends({}, tableCommandProps, { className: classString, icon: "finished", onClick: handleCommandSave }))), React.createElement(Tooltip, { key: "cancel", title: $l('Table', 'cancel_button') }, React.createElement(Button, _extends({}, tableCommandProps, { className: classString, icon: "cancle_a", onClick: handleCommandCancel })))]; } if (columnCommand) { var commands = []; columnCommand.forEach(function (button) { var tableButtonProps = {}; if (isArrayLike(button)) { tableButtonProps = button[1] || {}; button = button[0]; } if (isString(button) && button in TableCommandType) { var getButtonProps = function getButtonProps(type) { switch (type) { case TableCommandType.edit: return { icon: 'mode_edit', onClick: handleCommandEdit, disabled: disabled, title: $l('Table', 'edit_button') }; case TableCommandType["delete"]: return { icon: 'delete', onClick: handleCommandDelete, disabled: disabled, title: $l('Table', 'delete_button') }; default: } }; var defaultButtonProps = getButtonProps(button); if (defaultButtonProps) { var _tableButtonProps = tableButtonProps, afterClick = _tableButtonProps.afterClick, buttonProps = _objectWithoutProperties(_tableButtonProps, ["afterClick"]); if (afterClick) { var onClick = defaultButtonProps.onClick; defaultButtonProps.onClick = /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee(e) { return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: e.persist(); _context.prev = 1; _context.next = 4; return onClick(e); case 4: _context.prev = 4; afterClick(e); return _context.finish(4); case 7: case "end": return _context.stop(); } } }, _callee, null, [[1,, 4, 7]]); })); return function (_x) { return _ref.apply(this, arguments); }; }(); } var title = defaultButtonProps.title, otherProps = _objectWithoutProperties(defaultButtonProps, ["title"]); commands.push(React.createElement(Tooltip, { key: button, title: title }, React.createElement(Button, _extends({}, tableCommandProps, otherProps, buttonProps, { className: classNames(classString, otherProps.className, buttonProps.className) })))); } } else if (isValidElement(button)) { commands.push(cloneElement(button, _objectSpread({}, tableCommandProps, {}, button.props, { className: classNames(classString, button.props.className) }))); } else if (isObject(button)) { commands.push(React.createElement(Button, _extends({}, tableCommandProps, button, { className: classNames(classString, button.className) }))); } }); return commands; } }, [prefixCls, record, columnCommand, aggregation, disabled, handleCommandEdit, handleCommandDelete, handleCommandSave, handleCommandCancel]); var renderEditor = useCallback(function () { if (isValidElement(cellEditor)) { /** * 渲染多行编辑器 */ if (multiLine) { return cellEditor; } var newEditorProps = _objectSpread({}, cellEditor.props, { record: record, name: name, pristine: pristine, disabled: disabled || inlineEdit && !record.editing, indeterminate: checkField && checkField === name && record.isIndeterminate, labelLayout: LabelLayout.none, showHelp: ShowHelp.none }); return cloneElement(cellEditor, newEditorProps); } }, [disabled, cellEditor, checkField, multiLine, record, name, pristine, inlineEdit]); var cellRenderer = useMemo(function () { if (columnCommand) { return renderCommand; } if (cellEditorInCell) { return renderEditor; } if (aggregation && renderer) { return function (rendererProps) { return renderer(_objectSpread({}, rendererProps, { aggregation: aggregation })); }; } return renderer; }, [columnCommand, cellEditorInCell, renderEditor, renderCommand, renderer, field, aggregation]); var prefixStyle = useMemo(function () { if (!aggregation) { if (height !== undefined && rows === 0) { return _objectSpread({ height: pxToRem(height), lineHeight: 1 }, style); } if (rowHeight !== 'auto') { var isCheckBox = fieldType === FieldType["boolean"] || key === SELECTION_KEY; var borderPadding = isCheckBox ? 4 : 2; var heightPx = rows > 0 ? (rowHeight + 2) * rows + 1 : rowHeight; var lineHeightPx = hasEditor || isCheckBox ? rowHeight - borderPadding : rowHeight; return _objectSpread({ height: pxToRem(heightPx), lineHeight: rows > 0 ? 'inherit' : pxToRem(lineHeightPx) }, style); } } return style; }, [fieldType, key, rows, rowHeight, height, style, aggregation, hasEditor]); var textAlign = useMemo(function () { return align || (columnCommand ? ColumnAlign.center : getConfig('tableColumnAlign')(column, field)); }, [columnCommand, align, column, field]); var colSpanStyle = useMemo(function () { return colSpan && colSpan > 1 && (textAlign === ColumnAlign.right || textAlign === ColumnAlign.center) ? { width: "calc(100% - ".concat(pxToRem(30), ")") } : {}; }, [colSpan, textAlign]); var innerStyle = useMemo(function () { if (inAggregation) { return _objectSpread({}, prefixStyle, {}, colSpanStyle); } return _objectSpread({ textAlign: textAlign }, prefixStyle, {}, colSpanStyle); }, [inAggregation, textAlign, prefixStyle, colSpanStyle]); var value = name ? pristine ? record.getPristineValue(name) : record.get(name) : undefined; var renderValidationResult = useCallback(function (validationResult) { if (validationResult && validationResult.validationMessage) { return utilRenderValidationMessage(validationResult.validationMessage, true); } }, []); var isValidationMessageHidden = useCallback(function (message) { return !message || pristine; }, [pristine]); var editorBorder = !inlineEdit && hasEditor; var getRenderedValue = function getRenderedValue() { var processValue = function processValue(v) { if (!isNil(v)) { var _text = isPlainObject(v) ? v : utilProcessValue(v, getDateFormatByField(field)); return processFieldValue(_text, field, { getProp: function getProp(propName) { return field && field.get(propName); }, lang: dataSet && dataSet.lang || localeContext.locale.lang }, true); } return ''; }; var processRenderer = function processRenderer(v, repeat) { var processedValue; if (field && (field.lookup || field.get('options') || field.get('lovCode'))) { processedValue = field.getText(v); } // 值集中不存在 再去取直接返回的值 var text = isNil(processedValue) ? processValue(v) : processedValue; return (cellRenderer || defaultOutputRenderer)({ value: v, text: text, record: record, dataSet: dataSet, name: name, repeat: repeat }); }; if (field) { if (!cellEditorInCell) { var multiple = field.get('multiple'); var range = field.get('range'); if (multiple) { var _renderMultipleValues = renderMultipleValues(value, { disabled: disabled, readOnly: true, range: range, prefixCls: prefixCls, processRenderer: processRenderer, renderValidationResult: renderValidationResult, isValidationMessageHidden: isValidationMessageHidden, showValidationMessage: showValidationMessage, validator: field.validator }), tags = _renderMultipleValues.tags, multipleValidateMessageLength = _renderMultipleValues.multipleValidateMessageLength; multipleValidateMessageLengthRef.current = multipleValidateMessageLength; return tags; } if (range) { return renderRangeValue(toRangeValue(value, range), { processRenderer: processRenderer }); } } if (field.get('multiLine')) { var _renderMultiLine = renderMultiLine({ name: name, field: field, record: record, dataSet: dataSet, prefixCls: innerPrefixCls, renderer: cellRenderer, renderValidationResult: renderValidationResult, isValidationMessageHidden: isValidationMessageHidden, processValue: processValue, tooltip: tooltip, labelTooltip: getTooltip('label') }), lines = _renderMultiLine.lines, _multipleValidateMessageLength = _renderMultiLine.multipleValidateMessageLength; multipleValidateMessageLengthRef.current = _multipleValidateMessageLength; return lines; } } var textNode = processRenderer(value); return textNode === '' ? getConfig('tableDefaultRenderer') : textNode; }; var result = getRenderedValue(); var text = isEmpty(result) || isArrayLike(result) && !result.length ? editorBorder ? undefined : getConfig('renderEmpty')('Output') : result; var showTooltip = useCallback(function (e) { if (field && !(multipleValidateMessageLengthRef.current > 0 || !field.get('validator') && field.get('multiple') && toMultipleValue(value, field.get('range')).length)) { var validator = field.validator; var message = validator && renderValidationResult(validator.currentValidationResult); if (!isValidationMessageHidden(message)) { showValidationMessage(e, message); return true; } } var element = e.target; if (element && !multiLine && (tooltip === TextTooltip.always || tooltip === TextTooltip.overflow && isOverflow(element))) { if (text) { show(element, { title: text, placement: 'right', theme: getTooltipTheme('table-cell') }); return true; } } return false; }, [renderValidationResult, isValidationMessageHidden, field, tooltip, multiLine, text]); var handleMouseEnter = useCallback(function (e) { if (!tableStore.columnResizing && showTooltip(e)) { tooltipShownRef.current = true; } }, [tooltipShownRef, tableStore, showTooltip]); var handleMouseLeave = useCallback(function () { if (!tableStore.columnResizing && tooltipShownRef.current) { hide(); tooltipShownRef.current = false; } }, [tooltipShownRef, tableStore]); useEffect(function () { if (name && inlineEdit && record === currentEditRecord) { var currentEditor = tableStore.editors.get(name); if (currentEditor) { currentEditor.alignEditor(); } return function () { if (currentEditor) { currentEditor.hideEditor(); } }; } }, []); useEffect(function () { return function () { if (tooltipShownRef.current) { hide(); tooltipShownRef.current = false; } }; }, [tooltipShownRef]); var innerProps = { tabIndex: hasEditor && canFocus ? 0 : -1, onFocus: handleFocus, children: text }; var empty = field ? isFieldValueEmpty(value, field.get('range'), field.get('multiple'), field.type === FieldType.object ? field.get('valueField') : undefined, field.type === FieldType.object ? field.get('textField') : undefined) : false; var innerClassName = [innerPrefixCls]; if (columnEditorBorder) { innerClassName.push("".concat(prefixCls, "-inner-bordered")); } if (editorBorder) { innerClassName.push("".concat(prefixCls, "-inner-editable")); } var highlight; var inValid; if (field) { if (!pristine && field.dirty) { innerClassName.push("".concat(prefixCls, "-inner-dirty")); } if (!inlineEdit && !cellEditorInCell) { inValid = !field.valid; if (inValid) { innerClassName.push("".concat(prefixCls, "-inner-invalid")); } } if (editorBorder) { if (field.required && (empty || !getConfig('showRequiredColorsOnlyEmpty'))) { innerClassName.push("".concat(prefixCls, "-inner-required")); } highlight = field.get('highlight'); if (highlight) { innerClassName.push("".concat(prefixCls, "-inner-highlight")); } } } if (fieldDisabled) { innerClassName.push("".concat(prefixCls, "-inner-disabled")); } if (multiLine) { innerClassName.push("".concat(prefixCls, "-inner-multiLine")); } if (!isStickySupport() && !hasEditor) { innerProps.onKeyDown = handleEditorKeyDown; } if (inValid || tooltip) { innerProps.onMouseEnter = handleMouseEnter; innerProps.onMouseLeave = handleMouseLeave; } if (rowHeight === 'auto') { innerClassName.push("".concat(prefixCls, "-inner-auto-height")); } else { innerClassName.push("".concat(prefixCls, "-inner-row-height-fixed")); } if (height !== undefined && rows === 0) { innerClassName.push("".concat(prefixCls, "-inner-fixed-height")); } var indentText = children && React.createElement("span", { style: { paddingLeft: pxToRem(indentSize * record.level) } }); var prefix = (indentText || children || checkBox) && React.createElement("span", { key: "prefix", className: "".concat(prefixCls, "-prefix"), style: prefixStyle }, indentText, children, checkBox); var output = React.createElement("span", _extends({ key: "output" }, innerProps, { style: innerStyle, className: innerClassName.join(' ') })); return React.createElement(React.Fragment, null, prefix, highlight ? (column.highlightRenderer || tableStore.cellHighlightRenderer)(transformHighlightProps(highlight, { dataSet: dataSet, record: record, name: name }), output) : output); }); TableCellInner.displayName = 'TableCellInner'; export default TableCellInner; //# sourceMappingURL=TableCellInner.js.map