choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
766 lines (638 loc) • 24.1 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
var _excluded = ["style"],
_excluded2 = ["style", "tagRenderer"];
import { __decorate } from "tslib";
import React, { cloneElement, Component, isValidElement } from 'react';
import { action, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import classNames from 'classnames';
import raf from 'raf';
import noop from 'lodash/noop';
import KeyCode from '../../../es/_util/KeyCode';
import { pxToRem } from '../../../es/_util/UnitConvertor';
import Row from '../../../es/row';
import Col from '../../../es/col';
import TableContext from './TableContext';
import { findCell, findIndexedSibling, findRow, getColumnKey, getEditorByColumnAndRecord, getEditorByField, isInCellEditor, isStickySupport } from './utils';
import { stopEvent } from '../_util/EventManager';
import { ShowHelp } from '../field/enum';
import autobind from '../_util/autobind';
import { ResizeType } from '../text-area/enum';
import transform from '../_util/transform';
import { LabelLayout, ShowValidation } from '../form/enum';
function isTextArea(editor) {
return editor.type.__PRO_TEXTAREA;
}
function isHTMLElement(el) {
return el;
}
function offset(node, topNode) {
var initialize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [node.offsetLeft, node.offsetTop];
if (topNode) {
var offsetParent = node.offsetParent;
if (isHTMLElement(offsetParent)) {
if (offsetParent === topNode) {
return initialize;
}
return offset(offsetParent, topNode, [offsetParent.offsetLeft + initialize[0], offsetParent.offsetTop + initialize[1]]);
}
}
return initialize;
}
var TableEditor = /*#__PURE__*/function (_Component) {
_inherits(TableEditor, _Component);
var _super = _createSuper(TableEditor);
function TableEditor() {
var _this;
_classCallCheck(this, TableEditor);
_this = _super.apply(this, arguments);
_this.inTab = false;
return _this;
}
_createClass(TableEditor, [{
key: "lock",
get: function get() {
var column = this.props.column;
return column.lock;
}
}, {
key: "handleWindowResize",
value: function handleWindowResize() {
if (this.cellNode) {
this.alignEditor();
}
}
/**
* 触发多行编辑器失焦切换编辑/只读模式
* @param e
*/
}, {
key: "handleWindowClick",
value: function handleWindowClick(e) {
var prefixCls = this.context.prefixCls;
if (e.target.className !== "".concat(prefixCls, "-content") && e.target.className !== "".concat(prefixCls, "-body")) {
this.handleEditorBlur(e);
}
}
}, {
key: "connect",
value: function connect() {
var _this2 = this;
this.disconnect();
var tableStore = this.context.tableStore;
var dataSet = tableStore.dataSet,
virtual = tableStore.virtual;
if (virtual) {
this.reaction = reaction(function () {
return [tableStore.virtualVisibleStartIndex, tableStore.virtualVisibleEndIndex];
}, function () {
var current = dataSet.current;
if (current && findRow(tableStore, current)) {
var cellNode = _this2.cellNode,
keep = _this2.keep;
if (cellNode || keep) {
raf(function () {
_this2.alignEditor(cellNode);
if (keep) {
delete _this2.keep;
}
});
}
} else if (!_this2.keep) {
_this2.hideEditor(true);
}
});
} else {
this.reaction = reaction(function () {
return dataSet.current;
}, function (r) {
return r && _this2.cellNode ? raf(function () {
return _this2.alignEditor();
}) : _this2.hideEditor();
});
}
}
}, {
key: "disconnect",
value: function disconnect() {
if (this.reaction) {
this.reaction();
}
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
var _this3 = this;
var name = this.props.column.name;
if (name) {
var tableStore = this.context.tableStore;
var dataSet = tableStore.dataSet,
currentEditRecord = tableStore.currentEditRecord,
editors = tableStore.editors;
var record = currentEditRecord || dataSet.current;
var field = dataSet.getField(name);
if (field && field.get('multiLine', record)) {
window.addEventListener('click', this.handleWindowClick);
}
window.addEventListener('resize', this.handleWindowResize);
if (tableStore.inlineEdit) {
this.reaction = reaction(function () {
return tableStore.currentEditRecord;
}, function (r) {
return r ? raf(function () {
return _this3.alignEditor();
}) : _this3.hideEditor();
});
}
editors.set(name, this);
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
var name = this.props.column.name;
if (name) {
var editors = this.context.tableStore.editors;
editors["delete"](name);
window.removeEventListener('resize', this.handleWindowResize);
window.removeEventListener('click', this.handleWindowClick);
this.disconnect();
}
}
}, {
key: "saveRef",
value: function saveRef(node) {
this.editor = node;
}
}, {
key: "saveWrap",
value: function saveWrap(node) {
this.wrap = node;
var _this$context$tableSt = this.context.tableStore,
inlineEdit = _this$context$tableSt.inlineEdit,
currentEditRecord = _this$context$tableSt.currentEditRecord;
if (node && (!inlineEdit || currentEditRecord)) {
this.alignEditor(this.cellNode);
}
}
}, {
key: "handleEditorKeyEnterDown",
value: function handleEditorKeyEnterDown(e) {
var tableStore = this.context.tableStore;
var editorNextKeyEnterDown = tableStore.editorNextKeyEnterDown;
if (!e.isDefaultPrevented() && editorNextKeyEnterDown) {
this.showNextEditor(e.shiftKey);
}
} // copy the previous tr value to to this cell value
}, {
key: "handleKeyDownCTRLD",
value: function handleKeyDownCTRLD(e) {
e.preventDefault();
var cellNode = this.cellNode,
tableStore = this.context.tableStore;
var name = this.props.column.name;
var dataSet = tableStore.dataSet;
if (cellNode && tableStore && dataSet) {
var parentTdNode = cellNode.parentNode;
if (parentTdNode) {
var parentTrNode = parentTdNode.parentNode;
if (parentTrNode) {
var previousElementSibling = findIndexedSibling(parentTrNode, -1);
if (previousElementSibling) {
var index = previousElementSibling.dataset.index;
var currentIndex = parentTrNode.dataset.index;
if (index && currentIndex) {
var record = dataSet.findRecordById(index);
var currentRecord = dataSet.findRecordById(currentIndex);
if (record && currentRecord && tableStore) {
var cloneRecordData = record.clone().toData() || {};
var dealCloneRecordData = {};
if (name) {
dealCloneRecordData[name] = cloneRecordData[name];
currentRecord.set(dealCloneRecordData);
}
}
}
}
}
}
}
}
}, {
key: "handleKeyDownCTRLS",
value: function handleKeyDownCTRLS(e) {
e.preventDefault();
var dataSet = this.context.tableStore.dataSet;
dataSet.submit();
}
}, {
key: "handleEditorKeyDown",
value: function handleEditorKeyDown(e) {
if (![KeyCode.ESC, KeyCode.TAB].includes(e.keyCode) || !e.isDefaultPrevented()) {
var ctrlKey = e.ctrlKey || e.metaKey;
var tableStore = this.context.tableStore;
var keyboard = tableStore.keyboard;
switch (e.keyCode) {
case KeyCode.ESC:
this.blur();
break;
case KeyCode.TAB:
{
this.inTab = true;
var column = this.props.column;
var cellNode = !isStickySupport() && column.lock ? findCell(tableStore, getColumnKey(column), undefined, undefined, true) : this.cellNode;
if (cellNode && cellNode.parentElement) {
cellNode.focus();
} else {
var tdNode = this.tdNode;
if (tdNode) {
tdNode.focus();
this.hideEditor();
}
}
break;
}
case KeyCode.PAGE_UP:
case KeyCode.PAGE_DOWN:
stopEvent(e);
break;
case KeyCode.D:
if (ctrlKey === true && keyboard) this.handleKeyDownCTRLD(e);
break;
case KeyCode.S:
if (ctrlKey === true && keyboard) this.handleKeyDownCTRLS(e);
break;
default:
}
}
var editorProps = this.editorProps;
if (editorProps) {
var _editorProps$onKeyDow = editorProps.onKeyDown,
onKeyDown = _editorProps$onKeyDow === void 0 ? noop : _editorProps$onKeyDow;
onKeyDown(e);
}
}
}, {
key: "handleEditorBlur",
value: function handleEditorBlur(e) {
var editorProps = this.editorProps,
inTab = this.inTab,
inlineEdit = this.context.tableStore.inlineEdit;
if (!inTab && !inlineEdit) {
this.hideEditor();
}
if (editorProps) {
var _editorProps$onBlur = editorProps.onBlur,
onBlur = _editorProps$onBlur === void 0 ? noop : _editorProps$onBlur;
onBlur(e);
}
}
/**
* 多行编辑切换编辑器阻止冒泡
* @param e
*/
}, {
key: "handleEditorClick",
value: function handleEditorClick(e) {
var editorProps = this.editorProps;
if (editorProps) {
var _editorProps$onClick = editorProps.onClick,
onClick = _editorProps$onClick === void 0 ? noop : _editorProps$onClick;
onClick(e);
}
stopEvent(e);
}
}, {
key: "handleEditorResize",
value: function handleEditorResize(width, height, target) {
var _this4 = this;
var editorProps = this.editorProps,
cellNode = this.cellNode;
var name = this.props.column.name;
if (editorProps) {
var _this$context = this.context,
tableStore = _this$context.tableStore,
dataSet = _this$context.dataSet,
inlineEdit = _this$context.inlineEdit,
rowHeight = _this$context.rowHeight;
var currentEditRecord = tableStore.currentEditRecord;
var _editorProps$onResize = editorProps.onResize,
onResize = _editorProps$onResize === void 0 ? noop : _editorProps$onResize;
onResize(width, height, target);
var current = currentEditRecord || dataSet.current;
if (current && name && (rowHeight !== height || current.getState("__column_resize_height_".concat(name)) !== undefined)) {
current.setState("__column_resize_height_".concat(name), height);
}
if (inlineEdit) {
raf(function () {
tableStore.editors.forEach(function (editor) {
var editorCellNode = editor.cellNode;
if (editorCellNode) {
editor.alignEditor(editorCellNode, editor === _this4 ? height : undefined);
}
});
});
} else if (cellNode) {
this.alignEditor(cellNode, height);
}
}
}
}, {
key: "blur",
value: function blur() {
var editor = this.editor;
if (editor && editor.blur) {
editor.blur();
}
}
}, {
key: "focus",
value: function focus() {
var editor = this.editor;
if (editor && editor.focus) {
editor.focus();
}
}
}, {
key: "alignEditor",
value: function alignEditor(cellNode, height) {
var wrap = this.wrap,
editor = this.editor;
var tableStore = this.context.tableStore;
if (!cellNode || !cellNode.offsetParent) {
var column = this.props.column;
cellNode = findCell(tableStore, getColumnKey(column), undefined, undefined, true);
}
if (!this.cellNode && !tableStore.inlineEdit) {
this.connect();
}
this.cellNode = undefined;
if (cellNode) {
var _cellNode = cellNode,
parentElement = _cellNode.parentElement;
this.tdNode = parentElement;
if (parentElement) {
this.cellNode = cellNode;
if (height === undefined) {
var _cellNode2 = cellNode,
offsetHeight = _cellNode2.offsetHeight;
if (offsetHeight !== this.height) {
this.height = offsetHeight;
}
} else {
this.height = height;
}
if (!this.rendered) {
this.rendered = true;
} else if (wrap) {
var _cellNode3 = cellNode,
offsetWidth = _cellNode3.offsetWidth;
var _offset = offset(cellNode, wrap.parentElement),
_offset2 = _slicedToArray(_offset, 2),
left = _offset2[0],
top = _offset2[1];
if (this.originalCssText === undefined) {
this.originalCssText = wrap.style.cssText;
}
var width = pxToRem(offsetWidth, true);
if (width !== this.width) {
this.width = width;
}
wrap.style.cssText = "width:".concat(width, ";").concat(transform("translate(".concat(pxToRem(left, true), ", ").concat(pxToRem(top, true), ")")));
if (editor && editor.forcePositionChanged) {
editor.forcePositionChanged();
}
}
}
}
}
}, {
key: "hideEditor",
value: function hideEditor(keep) {
this.inTab = false;
if (keep) {
this.keep = true;
}
if (this.cellNode) {
var tableStore = this.context.tableStore;
tableStore.hideEditor();
var wrap = this.wrap;
if (wrap) {
if (this.originalCssText !== undefined) {
wrap.style.cssText = "width:".concat(this.width, ";").concat(this.originalCssText);
this.originalCssText = undefined;
}
}
this.cellNode = undefined;
if (!keep && !tableStore.inlineEdit) {
this.disconnect();
}
}
}
}, {
key: "showNextEditor",
value: function showNextEditor(reserve) {
var name = this.props.column.name;
if (name) {
this.blur();
var tableStore = this.context.tableStore;
if (tableStore.showNextEditor(name, reserve)) {
this.alignEditor();
this.focus();
}
}
}
/**
* 渲染多行编辑单元格
*/
}, {
key: "renderMultiLineEditor",
value: function renderMultiLineEditor() {
var _this5 = this;
var name = this.props.column.name;
if (name) {
var _this$context2 = this.context,
prefixCls = _this$context2.prefixCls,
dataSet = _this$context2.dataSet,
inlineEdit = _this$context2.inlineEdit,
rowHeight = _this$context2.rowHeight,
currentEditRecord = _this$context2.tableStore.currentEditRecord;
var record = currentEditRecord || dataSet.current;
if (record) {
var multiLineFields = [];
var ref = true;
dataSet.fields.forEach(function (dsField, fieldName) {
var bind = dsField.get('bind', record);
if (bind && bind.split('.')[0] === name) {
var field = record.fields.get(fieldName) || dsField;
var editor = getEditorByField(field, record);
_this5.editorProps = editor.props;
var _this5$editorProps = _this5.editorProps,
_this5$editorProps$st = _this5$editorProps.style,
style = _this5$editorProps$st === void 0 ? {} : _this5$editorProps$st,
otherProps = _objectWithoutProperties(_this5$editorProps, _excluded);
if (rowHeight !== 'auto') {
style.height = pxToRem(rowHeight);
}
var newEditorProps = _objectSpread(_objectSpread({}, otherProps), {}, {
style: style,
ref: ref ? _this5.saveRef : undefined,
record: record,
name: fieldName,
onKeyDown: _this5.handleEditorKeyDown,
onEnterDown: _this5.handleEditorKeyEnterDown,
onClick: _this5.handleEditorClick,
tabIndex: -1,
showHelp: ShowHelp.none,
showValidation: ShowValidation.tooltip,
labelLayout: LabelLayout.none,
// 目前测试inline时候需要放开限制
_inTable: !inlineEdit,
preventRenderer: true
});
ref = false;
var label = field.get('label', record);
var key = "".concat(record.index, "-multi-").concat(fieldName);
multiLineFields.push( /*#__PURE__*/React.createElement(Row, {
key: key,
className: "".concat(prefixCls, "-multi")
}, label && /*#__PURE__*/React.createElement(Col, {
span: 8,
className: "".concat(prefixCls, "-multi-label")
}, label), /*#__PURE__*/React.createElement(Col, {
span: label ? 16 : 24,
className: "".concat(prefixCls, "-multi-value")
}, /*#__PURE__*/cloneElement(editor, newEditorProps))));
}
});
if (multiLineFields.length) {
return /*#__PURE__*/React.createElement("div", null, multiLineFields);
}
}
}
}
}, {
key: "renderEditor",
value: function renderEditor() {
var column = this.props.column;
var name = column.name;
if (name) {
var _this$context3 = this.context,
dataSet = _this$context3.dataSet,
pristine = _this$context3.pristine,
inlineEdit = _this$context3.inlineEdit,
_this$context3$tableS = _this$context3.tableStore,
currentEditRecord = _this$context3$tableS.currentEditRecord,
currentEditorName = _this$context3$tableS.currentEditorName,
getColumnTagRenderer = _this$context3$tableS.getColumnTagRenderer,
rowHeight = _this$context3.rowHeight;
var record = currentEditRecord || dataSet.current;
var field = dataSet.getField(name); // 多行编辑拦截返回渲染器
if (!pristine && field && field.get('multiLine', record)) {
return this.renderMultiLineEditor();
}
var cellEditor = getEditorByColumnAndRecord(column, record);
if (!pristine && /*#__PURE__*/isValidElement(cellEditor) && !isInCellEditor(cellEditor)) {
this.editorProps = cellEditor.props;
var height = this.height;
var _this$editorProps = this.editorProps,
_this$editorProps$sty = _this$editorProps.style,
style = _this$editorProps$sty === void 0 ? {} : _this$editorProps$sty,
editorTagRenderer = _this$editorProps.tagRenderer,
otherProps = _objectWithoutProperties(_this$editorProps, _excluded2);
var tagRenderer = editorTagRenderer || getColumnTagRenderer(column);
if (height !== undefined) {
style.height = pxToRem(height, true);
}
var newEditorProps = _objectSpread(_objectSpread({}, otherProps), {}, {
style: style,
ref: this.saveRef,
record: record,
name: name,
tagRenderer: tagRenderer,
onKeyDown: this.handleEditorKeyDown,
onEnterDown: isTextArea(cellEditor) ? undefined : this.handleEditorKeyEnterDown,
onBlur: this.handleEditorBlur,
tabIndex: currentEditorName ? 0 : -1,
showHelp: ShowHelp.none,
showValidation: ShowValidation.tooltip,
labelLayout: LabelLayout.none,
// 目前测试inline时候需要放开限制
_inTable: !inlineEdit,
preventRenderer: true
});
if (isTextArea(cellEditor)) {
var resize = newEditorProps.resize || cellEditor.props.resize || ResizeType.vertical;
newEditorProps.resize = resize;
if (resize !== ResizeType.none) {
newEditorProps.onResize = this.handleEditorResize;
if (rowHeight === 'auto') {
newEditorProps.autoSize = true;
}
}
}
return /*#__PURE__*/cloneElement(cellEditor, newEditorProps);
}
}
this.cellNode = undefined;
}
}, {
key: "render",
value: function render() {
var _this6 = this;
if (this.rendered) {
var editor = this.renderEditor();
if (editor) {
var lock = this.props.column.lock;
var prefixCls = this.context.prefixCls;
var props = {
className: classNames("".concat(prefixCls, "-editor"), _defineProperty({}, "".concat(prefixCls, "-editor-lock"), isStickySupport() && lock))
};
return /*#__PURE__*/React.createElement("div", _extends({}, props, {
ref: this.saveWrap
}), editor);
}
var tableStore = this.context.tableStore;
if (!tableStore.inlineEdit) {
runInAction(function () {
_this6.rendered = false;
});
}
}
return null;
}
}], [{
key: "contextType",
get: function get() {
return TableContext;
}
}]);
return TableEditor;
}(Component);
TableEditor.displayName = 'TableEditor';
__decorate([observable], TableEditor.prototype, "height", void 0);
__decorate([observable], TableEditor.prototype, "rendered", void 0);
__decorate([autobind], TableEditor.prototype, "handleWindowResize", null);
__decorate([autobind], TableEditor.prototype, "handleWindowClick", null);
__decorate([autobind], TableEditor.prototype, "saveRef", null);
__decorate([autobind], TableEditor.prototype, "saveWrap", null);
__decorate([autobind], TableEditor.prototype, "handleEditorKeyEnterDown", null);
__decorate([autobind], TableEditor.prototype, "handleKeyDownCTRLD", null);
__decorate([autobind], TableEditor.prototype, "handleKeyDownCTRLS", null);
__decorate([autobind], TableEditor.prototype, "handleEditorKeyDown", null);
__decorate([autobind], TableEditor.prototype, "handleEditorBlur", null);
__decorate([autobind], TableEditor.prototype, "handleEditorClick", null);
__decorate([autobind], TableEditor.prototype, "handleEditorResize", null);
__decorate([action], TableEditor.prototype, "alignEditor", null);
__decorate([autobind], TableEditor.prototype, "hideEditor", null);
TableEditor = __decorate([observer], TableEditor);
export default TableEditor;
//# sourceMappingURL=TableEditor.js.map