UNPKG

feeles-ide

Version:

The hackable and serializable IDE to make learning material

340 lines (283 loc) 12.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDom = _interopRequireDefault(require("react-dom")); var _typestyle = require("typestyle"); var _core = require("@material-ui/core"); var _Backspace = _interopRequireDefault(require("@material-ui/icons/Backspace")); var _codemirror = require("codemirror"); var _includes = _interopRequireDefault(require("lodash/includes")); var _Cancel = _interopRequireDefault(require("@material-ui/icons/Cancel")); var _SubdirectoryArrowRight = _interopRequireDefault(require("@material-ui/icons/SubdirectoryArrowRight")); var _colorManipulator = require("@material-ui/core/styles/colorManipulator"); var _isNotDeletableLine = _interopRequireDefault(require("./isNotDeletableLine")); var _dec, _class, _class2, _temp; var dummyNode = document.createElement('div'); var cn = { background: (0, _typestyle.style)({ backgroundColor: 'rgba(0, 0, 0, 0.04)' }), blank: (0, _typestyle.style)({ flex: 1 }), parent: (0, _typestyle.style)({ display: 'flex', alignItems: 'center', position: 'relative', width: '100%' }) }; var getCn = function getCn(_ref, state) { var theme = _ref.theme; var backgroundColor = theme.palette.type === 'light' ? theme.palette.grey[300] : theme.palette.grey[700]; var deleteIconColor = (0, _colorManipulator.fade)(theme.palette.text.primary, 0.26); return { button: (0, _typestyle.style)({ margin: theme.spacing.unit, flexShrink: 0 }), copy: (0, _typestyle.style)({ transform: "rotateX(".concat(state.above ? 180 : 0, "deg)") // copy してくる方向 }), paste: (0, _typestyle.style)({ transform: "rotateZ(90deg) rotateY(".concat(state.above ? 180 : 0, "deg)") // paste する方向 }), clipboard: (0, _typestyle.style)({ textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden', height: 20, padding: 4, paddingBottom: 0, // buggy borderRadius: 14, fontSize: 10, flexGrow: 0, flexShrink: 1, transition: theme.transitions.create(['background-color', 'color']), backgroundColor: state.clipboard ? backgroundColor : 'transparent', color: state.clipboard ? theme.palette.text.primary : theme.palette.text.disabled }), cancel: (0, _typestyle.style)({ fontSize: 16, color: deleteIconColor, verticalAlign: 'middle', cursor: 'pointer', $nest: { '&:hover': { color: (0, _colorManipulator.fade)(deleteIconColor, 0.4) } } }) }; }; var LineWidget = (_dec = (0, _core.withTheme)(), _dec(_class = (_temp = _class2 = /*#__PURE__*/ function (_React$Component) { (0, _inherits2.default)(LineWidget, _React$Component); function LineWidget() { var _getPrototypeOf2; var _this; (0, _classCallCheck2.default)(this, LineWidget); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(LineWidget)).call.apply(_getPrototypeOf2, [this].concat(args))); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "state", { line: -1, above: false, widget: null, notDeletable: false, text: '', clipboard: null }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleLineWidget", function (cm) { if ((0, _includes.default)(cm.getSelection(), '\n')) return; // 複数行選択されている場合は omit // Delete line button var cursor = cm.getCursor(); if (!cursor.line && !cursor.ch && cursor.sticky === null) { // runApp した時に0行目に line widget が移るのを防ぐ // setValue すると LineWidget が消えるみたいなので作り直す _this.setLineWidget(cm, _this.state.line); return; } if (_this.state.line !== cursor.line) { // 行が変わっていたら LineWidget も作り直す必要がある _this.setLineWidget(cm, cursor.line); } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleDone", function () { // 現在の LineWidget を消す var _this$state = _this.state, line = _this$state.line, widget = _this$state.widget; if (line > -1) { _this.props.codemirror.removeLineClass(line, 'wrap', cn.background); // 背景色を戻す } if (widget) { widget.clear(); } _this.setState({ widget: null, line: -1 }); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleLineDeleteClick", function () { var cm = _this.props.codemirror; var line = _this.state.line; var cursor = cm.getCursor(); var from = new _codemirror.Pos(line, 0); var to = new _codemirror.Pos(line + 1, 0); cm.replaceRange('', from, to, 'change'); // 1行削除 cm.focus(); // ボタンを押したのでフォーカスが外れている. それを戻す cm.setCursor(new _codemirror.Pos(line, cursor.ch)); // カーソルを新しい位置に _this.setLineWidget(cm, line); // 次の行(消したのでlineは同じ)に移動 }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleBlur", function (cm) { // 背景色だけが残らないようにする if (!_this.props.show && _this.state.line > -1) { cm.removeLineClass(_this.state.line, 'wrap', cn.background); // 背景色を戻す } }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleLineCopyClick", function () { var cm = _this.props.codemirror; var line = _this.state.line; var text = cm.getLine(line); _this.setState({ clipboard: text }); cm.focus(); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "handleLinePasteClick", function () { var cm = _this.props.codemirror; var _this$state2 = _this.state, line = _this$state2.line, above = _this$state2.above, clipboard = _this$state2.clipboard; if (!clipboard) return; var pos = new _codemirror.Pos(above ? line : line + 1, 0); cm.replaceRange(clipboard + '\n', pos, pos); _this.setState({ clipboard: null }); _this.props.runApp(); }); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "clearClipboard", function () { _this.setState({ clipboard: null }); }); return _this; } (0, _createClass2.default)(LineWidget, [{ key: "componentDidMount", value: function componentDidMount() { var codemirror = this.props.codemirror; codemirror.on('cursorActivity', this.handleLineWidget); codemirror.on('blur', this.handleBlur); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var line = this.state.line; if (!prevProps.show && this.props.show && line > -1) { this.setLineWidget(this.props.codemirror, line); } if (prevProps.show && !this.props.show && line > -1) { this.handleDone(); } } }, { key: "setLineWidget", value: function setLineWidget(cm, line) { if (!this.props.show) return; // 前回の Widget を消す if (this.state.line > -1) { cm.removeLineClass(this.state.line, 'wrap', cn.background); // 背景色を戻す } if (this.state.widget) { this.state.widget.clear(); } if (line === -1) return; // カーソルが定まっていない // Widget を作って出す cm.addLineClass(line, 'wrap', cn.background); // 背景色をつける var parent = document.createElement('div'); parent.classList.add(cn.parent); var above = this.state.line > -1 ? line === this.state.line ? this.state.above : line > this.state.line : false; var widget = cm.addLineWidget(line, parent, { noHScroll: true, above: above }); this.setState({ widget: widget, line: line, above: above, text: widget.line.text, notDeletable: (0, _isNotDeletableLine.default)(cm.getLine(line)) // 削除できるかどうか }); } }, { key: "render", value: function render() { var _this$state3 = this.state, widget = _this$state3.widget, clipboard = _this$state3.clipboard, text = _this$state3.text; if (!this.props.show) return null; var node = widget ? widget.node : dummyNode; var dcn = getCn(this.props, this.state); var chipText = clipboard || text; return _reactDom.default.createPortal(_react.default.createElement(_react.default.Fragment, null, !clipboard ? _react.default.createElement(_core.Button, { variant: "text", size: "small", className: dcn.button, onClick: this.handleLineCopyClick, disabled: !text || this.state.notDeletable }, _react.default.createElement(_SubdirectoryArrowRight.default, { className: dcn.copy, fontSize: "small" }), this.props.localization.editorCard.copyLine) : _react.default.createElement(_core.Button, { variant: "text", size: "small", className: dcn.button, onClick: this.handleLinePasteClick }, _react.default.createElement(_SubdirectoryArrowRight.default, { className: dcn.paste, fontSize: "small" }), this.props.localization.editorCard.pasteLine), chipText && _react.default.createElement("div", { className: dcn.clipboard }, clipboard ? _react.default.createElement(_Cancel.default, { className: dcn.cancel, onClick: this.clearClipboard }) : null, chipText), _react.default.createElement("div", { className: cn.blank }), _react.default.createElement(_core.Button, { variant: "text", size: "small", className: dcn.button, onClick: this.handleLineDeleteClick, disabled: this.state.notDeletable }, _react.default.createElement(_Backspace.default, { fontSize: "small" }), this.props.localization.editorCard.deleteLine)), node); } }]); return LineWidget; }(_react.default.Component), (0, _defineProperty2.default)(_class2, "propTypes", { show: _propTypes.default.bool.isRequired, codemirror: _propTypes.default.object.isRequired, runApp: _propTypes.default.func.isRequired, localization: _propTypes.default.object.isRequired }), _temp)) || _class); exports.default = LineWidget;