choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
407 lines (343 loc) • 14.7 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _get from "@babel/runtime/helpers/get";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
var _excluded = ["onMouseEnter", "onMouseLeave"];
import { __decorate } from "tslib";
import React from 'react';
import { findDOMNode } from 'react-dom';
import classes from 'component-classes';
import classNames from 'classnames';
import { action, autorun, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import defaultTo from 'lodash/defaultTo';
import isString from 'lodash/isString';
import noop from 'lodash/noop';
import KeyCode from '../../../es/_util/KeyCode';
import Icon from '../../../es/icon';
import { FormField } from '../field/FormField';
import { ThemeSwitch } from './enum';
import autobind from '../_util/autobind';
import { LabelLayout } from '../form/enum';
import Switch from '../switch';
var CodeMirror;
if (typeof window !== 'undefined') {
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
CodeMirror = require('react-codemirror2').Controlled; // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
require('codemirror/addon/display/placeholder.js');
}
export { ThemeSwitch };
var defaultCodeMirrorOptions = {
theme: 'idea',
lineNumbers: true,
lint: true,
gutters: ['CodeMirror-lint-markers']
};
var CodeArea = /*#__PURE__*/function (_FormField) {
_inherits(CodeArea, _FormField);
var _super = _createSuper(CodeArea);
function CodeArea(props, content) {
var _this;
_classCallCheck(this, CodeArea);
_this = _super.call(this, props, content);
_this.cmOptions = _this.getCodeMirrorOptions();
_this.handleThemeChange = function (value) {
_this.setTheme(value ? ThemeSwitch.idea : ThemeSwitch.material);
};
_this.getHeader = function () {
var _classNames;
var _this$props = _this.props,
title = _this$props.title,
options = _this$props.options,
themeSwitch = _this$props.themeSwitch;
if (!title && (options && options.theme || !themeSwitch)) {
return null;
}
var titleNode = title ? /*#__PURE__*/React.createElement("div", {
className: "".concat(_this.prefixCls, "-header-title")
}, title) : null;
var themeSwitchNode = (!options || !options.theme) && themeSwitch ? /*#__PURE__*/React.createElement("div", {
className: "".concat(_this.prefixCls, "-header-switch")
}, /*#__PURE__*/React.createElement(Switch, {
unCheckedChildren: /*#__PURE__*/React.createElement(Icon, {
type: "moon-circle"
}),
defaultChecked: _this.theme !== ThemeSwitch.material,
onChange: _this.handleThemeChange
}, /*#__PURE__*/React.createElement(Icon, {
type: "wb_sunny"
}))) : null;
var headerClassNames = classNames("".concat(_this.prefixCls, "-header"), (_classNames = {}, _defineProperty(_classNames, "".concat(_this.prefixCls, "-header-light"), _this.theme !== ThemeSwitch.material), _defineProperty(_classNames, "".concat(_this.prefixCls, "-header-dark"), _this.theme === ThemeSwitch.material), _classNames));
return /*#__PURE__*/React.createElement("div", {
className: headerClassNames
}, titleNode, themeSwitchNode);
};
/**
* 编辑器失去焦点时,调用父类方法,同步DataSet中的内容
*
* @memberof CodeArea
*/
_this.handleCodeMirrorBlur = action(function (codeMirrorInstance) {
var formatter = _this.props.formatter; // 更新DataSet的值之前,先去拿到原始的raw格式
var value = codeMirrorInstance.getValue();
if (formatter) {
var getRaw = formatter.getRaw,
getFormatted = formatter.getFormatted;
value = getRaw(getFormatted(value));
}
_this.midText = value;
_this.setValue(value);
_this.isFocused = false;
_this.isFocus = false;
var element = _this.wrapper || findDOMNode(_assertThisInitialized(_this));
if (element) {
classes(element).remove("".concat(_this.prefixCls, "-focused"));
}
});
/**
* 在CodeMirror编辑器实例挂载前添加额外配置
*
* @memberof CodeArea
*/
_this.handleCodeMirrorDidMount = function (editor, value, cb) {
var _this$props2 = _this.props,
formatter = _this$props2.formatter,
style = _this$props2.style,
formatHotKey = _this$props2.formatHotKey,
unFormatHotKey = _this$props2.unFormatHotKey,
editorDidMount = _this$props2.editorDidMount;
var _ref = style || {},
_ref$width = _ref.width,
width = _ref$width === void 0 ? '100%' : _ref$width,
_ref$height = _ref.height,
height = _ref$height === void 0 ? 100 : _ref$height;
var options = {
Tab: function Tab(cm) {
if (cm.somethingSelected()) {
cm.indentSelection('add'); // 有选中内容时整体缩进
} else {
// 使用空格代替缩进
var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
cm.replaceSelection(spaces);
}
}
};
if (formatter) {
if (formatHotKey) {
// default: 'Alt-F'
options[formatHotKey] = function (cm) {
return cm.setValue(formatter.getFormatted(cm.getValue()));
};
}
if (unFormatHotKey) {
// default: 'Alt-R'
options[unFormatHotKey] = function (cm) {
return cm.setValue(formatter.getRaw(cm.getValue()));
};
}
}
editor.setSize(width, height); // default size: ('100%', 100)
editor.setOption('extraKeys', options);
if (editorDidMount) {
editorDidMount(editor, value, cb);
}
if (_this.labelLayout === LabelLayout["float"]) {
var display = editor.display;
if (display) {
var gutters = display.gutters;
if (gutters) {
var offsetWidth = gutters.offsetWidth;
if (offsetWidth !== _this.floatLabelOffsetX) {
runInAction(function () {
_this.floatLabelOffsetX = offsetWidth;
});
}
}
}
}
};
var options = props.options;
var theme = options && options.theme ? options.theme : props.themeSwitch;
_this.setTheme(defaultTo(theme, defaultCodeMirrorOptions.theme));
_this.disposer = autorun(function () {
// 在绑定dataSet的情况下
// 当手动修改过codeArea里面的值以后 再使用record.set去更新值 组件不会更新
// 原因在于此时 this.text 不为 undefined 因此 getTextNode 的计算值不会进行改变 导致组件不重新渲染
// 其他的组件会对 this.text 在blur的时候进行undefined的修改 但是这个组件不能这么做
// 原因在于 record 中的值为 raw的非格式化数据 blur后因为进行了一次record数据的修改 所以再次重新那数据必然导致
// 当数据存在错误的时候 codeArea去格式化 因为格式化失败了
// 当数据不存在存在错误的时候即使特地将其去格式化也依旧会被格式化
var formatter = props.formatter;
var recordValue = _this.getValue();
var value = formatter ? formatter.getFormatted(recordValue) : recordValue; // 分别监听 受控 及 DataSet 进行管理时值的变化
if (recordValue !== _this.midText || _this.dataSet && _this.name) {
_this.setText(value);
}
});
return _this;
}
_createClass(CodeArea, [{
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.disposer();
}
}, {
key: "handleBeforeChange",
value: function handleBeforeChange(_editor, _data, value) {
this.setText(value);
}
}, {
key: "handleCodeMirrorKeyDown",
value: function handleCodeMirrorKeyDown(cm, e) {
var _this$props3 = this.props,
_this$props3$onKeyDow = _this$props3.onKeyDown,
onKeyDown = _this$props3$onKeyDow === void 0 ? noop : _this$props3$onKeyDow,
_this$props3$onEnterD = _this$props3.onEnterDown,
onEnterDown = _this$props3$onEnterD === void 0 ? noop : _this$props3$onEnterD;
switch (e.keyCode) {
case KeyCode.ENTER:
onEnterDown(e);
break;
case KeyCode.ESC:
cm.getInputField().blur();
break;
default:
}
onKeyDown(e);
}
}, {
key: "getCodeMirrorOptions",
value: function getCodeMirrorOptions() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props.options;
var placeholder = this.props.placeholder;
if (this.labelLayout === LabelLayout.placeholder && !this.isFocused) {
placeholder = this.getDisplayProp('label');
} else if (this.labelLayout === LabelLayout["float"] && !this.isFocused) {
placeholder = '';
}
return _objectSpread(_objectSpread({}, defaultCodeMirrorOptions), {}, {
placeholder: placeholder
}, options);
}
}, {
key: "getOmitPropsKeys",
value: function getOmitPropsKeys() {
return _get(_getPrototypeOf(CodeArea.prototype), "getOmitPropsKeys", this).call(this).concat(['formatHotKey', 'unFormatHotKey', 'editorDidMount']);
}
}, {
key: "getOtherProps",
value: function getOtherProps() {
var otherProps = _get(_getPrototypeOf(CodeArea.prototype), "getOtherProps", this).call(this);
delete otherProps.onChange;
otherProps.onKeyDown = this.handleCodeMirrorKeyDown;
otherProps.className = this.getOtherClassName(otherProps);
return otherProps;
}
}, {
key: "getOtherClassName",
value: function getOtherClassName(otherProps) {
var _classNames2;
return classNames(otherProps.className, (_classNames2 = {}, _defineProperty(_classNames2, "".concat(this.prefixCls, "-dark"), this.theme === ThemeSwitch.material), _defineProperty(_classNames2, "".concat(this.prefixCls, "-disabled"), this.disabled), _classNames2));
}
}, {
key: "setThemeWrapper",
value: function setThemeWrapper(nextProps) {
var options = nextProps.options,
themeSwitch = nextProps.themeSwitch;
var _this$props4 = this.props,
preOptions = _this$props4.options,
preThemeSwitch = _this$props4.themeSwitch;
var preOptionsTheme = preOptions && preOptions.theme;
var optionsTheme = options && options.theme;
if (preOptionsTheme !== optionsTheme || preThemeSwitch !== themeSwitch) {
this.setTheme(defaultTo(optionsTheme || themeSwitch, defaultCodeMirrorOptions.theme));
}
}
}, {
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps, nextContext) {
this.setThemeWrapper(nextProps);
_get(_getPrototypeOf(CodeArea.prototype), "componentWillReceiveProps", this).call(this, nextProps, nextContext);
}
}, {
key: "elementReference",
value: function elementReference(node) {
if (node && node.ref) {
this.element = node.ref;
}
}
}, {
key: "renderWrapper",
value: function renderWrapper() {
if (CodeMirror) {
this.cmOptions = this.getCodeMirrorOptions();
this.cmOptions.readOnly = this.disabled || this.readOnly;
this.cmOptions.theme = this.theme;
var text = this.getTextNode();
var header = this.getHeader();
var _this$getOtherProps = this.getOtherProps(),
onMouseEnter = _this$getOtherProps.onMouseEnter,
onMouseLeave = _this$getOtherProps.onMouseLeave,
otherProps = _objectWithoutProperties(_this$getOtherProps, _excluded);
return /*#__PURE__*/React.createElement("div", _extends({}, this.getWrapperProps()), header, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", {
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave
}, /*#__PURE__*/React.createElement(CodeMirror, _extends({}, otherProps, {
value: isString(text) ? text : this.processValue(this.getValue()),
options: this.cmOptions,
onBeforeChange: this.handleBeforeChange,
onBlur: this.handleCodeMirrorBlur,
editorDidMount: this.handleCodeMirrorDidMount
})), this.renderFloatLabel())));
}
}
}, {
key: "setTheme",
value: function setTheme(theme) {
if (theme !== this.theme) {
this.theme = theme;
}
}
}, {
key: "setText",
value: function setText(text) {
this.text = text;
}
}, {
key: "getTextNode",
value: function getTextNode(value) {
return this.text === undefined ? _get(_getPrototypeOf(CodeArea.prototype), "getTextNode", this).call(this, value) || '' : this.text;
}
}, {
key: "processValue",
value: function processValue(value) {
var text = _get(_getPrototypeOf(CodeArea.prototype), "processValue", this).call(this, value);
var formatter = this.props.formatter;
return formatter && isString(text) ? formatter.getFormatted(text) : text;
}
}]);
return CodeArea;
}(FormField);
CodeArea.displayName = 'CodeArea';
CodeArea.defaultProps = _objectSpread(_objectSpread({}, FormField.defaultProps), {}, {
suffixCls: 'code-area',
formatHotKey: 'Alt-F',
unFormatHotKey: 'Alt-R'
});
__decorate([observable], CodeArea.prototype, "text", void 0);
__decorate([observable], CodeArea.prototype, "theme", void 0);
__decorate([autobind], CodeArea.prototype, "handleBeforeChange", null);
__decorate([autobind], CodeArea.prototype, "handleCodeMirrorKeyDown", null);
__decorate([autobind], CodeArea.prototype, "elementReference", null);
__decorate([action], CodeArea.prototype, "setTheme", null);
__decorate([action], CodeArea.prototype, "setText", null);
CodeArea = __decorate([observer], CodeArea);
export default CodeArea;
//# sourceMappingURL=CodeArea.js.map