"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _typeof = require("@babel/runtime/helpers/typeof");

Object.defineProperty(exports, "__esModule", {
  value: true
});
Object.defineProperty(exports, "ALL_PLUGINS", {
  enumerable: true,
  get: function get() {
    return _plugins.ALL_PLUGINS;
  }
});
Object.defineProperty(exports, "DEFAULT_PLUGINS", {
  enumerable: true,
  get: function get() {
    return _plugins.DEFAULT_PLUGINS;
  }
});
exports.serialization = exports["default"] = exports.Editor = void 0;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _slateReact = require("slate-react");

var _slatePropTypes = _interopRequireDefault(require("slate-prop-types"));

var _isEqual = _interopRequireDefault(require("lodash/isEqual"));

var serialization = _interopRequireWildcard(require("./serialization"));

exports.serialization = serialization;

var _propTypes = _interopRequireDefault(require("prop-types"));

var _react = _interopRequireDefault(require("react"));

var _slate = require("slate");

var _plugins = require("./plugins");

var _debug = _interopRequireDefault(require("debug"));

var _styles = require("@material-ui/core/styles");

var _classnames = _interopRequireDefault(require("classnames"));

var _renderUi = require("../render-ui");

var _slatePlainSerializer = _interopRequireDefault(require("slate-plain-serializer"));

var _configUi = require("../config-ui");

var _insertImageHandler = _interopRequireDefault(require("./plugins/image/insert-image-handler"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

var log = (0, _debug["default"])('editable-html:editor');
var defaultToolbarOpts = {
  position: 'bottom',
  alignment: 'left',
  alwaysVisible: false,
  showDone: true,
  doneOn: 'blur'
};
var defaultResponseAreaProps = {
  options: {},
  respAreaToolbar: function respAreaToolbar() {},
  onHandleAreaChange: function onHandleAreaChange() {}
};
var defaultLanguageCharactersProps = [];

var createToolbarOpts = function createToolbarOpts(toolbarOpts, error, isHtmlMode) {
  return _objectSpread(_objectSpread(_objectSpread({}, defaultToolbarOpts), toolbarOpts), {}, {
    error: error,
    isHtmlMode: isHtmlMode
  });
};

var Editor = /*#__PURE__*/function (_React$Component) {
  (0, _inherits2["default"])(Editor, _React$Component);

  var _super = _createSuper(Editor);

  function Editor(_props) {
    var _this;

    (0, _classCallCheck2["default"])(this, Editor);
    _this = _super.call(this, _props);
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleAlertDialog", function (open, extraDialogProps, callback) {
      _this.setState({
        dialog: _objectSpread({
          open: open
        }, extraDialogProps),
        isEdited: false
      }, callback);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "toggleHtmlMode", function () {
      _this.setState(function (prevState) {
        return {
          isHtmlMode: !prevState.isHtmlMode
        };
      }, function () {
        var error = _this.props.error;
        var toolbarOpts = _this.state.toolbarOpts;
        var newToolbarOpts = createToolbarOpts(toolbarOpts, error, _this.state.isHtmlMode);

        _this.setState({
          toolbarOpts: newToolbarOpts
        });
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handlePlugins", function (props) {
      var normalizedResponseAreaProps = _objectSpread(_objectSpread({}, defaultResponseAreaProps), props.responseAreaProps);

      var htmlPluginOpts = {
        isHtmlMode: _this.state.isHtmlMode,
        isEdited: _this.state.isEdited,
        toggleHtmlMode: _this.toggleHtmlMode,
        handleAlertDialog: _this.handleAlertDialog
      };
      _this.plugins = (0, _plugins.buildPlugins)(props.activePlugins, {
        math: _objectSpread({
          onClick: _this.onMathClick,
          onFocus: _this.onPluginFocus,
          onBlur: _this.onPluginBlur
        }, props.mathMlOptions),
        html: htmlPluginOpts,
        image: {
          disableImageAlignmentButtons: props.disableImageAlignmentButtons,
          onDelete: props.imageSupport && props.imageSupport["delete"] && function (src, done) {
            props.imageSupport["delete"](src, function (e) {
              done(e, _this.state.value);
            });
          },
          insertImageRequested: props.imageSupport && function (addedImage, getHandler) {
            var pendingImages = _this.state.pendingImages;

            var onFinish = function onFinish(result) {
              var cb;

              if (_this.state.scheduled && result) {
                // finish editing only on success
                cb = _this.onEditingDone.bind((0, _assertThisInitialized2["default"])(_this));
              }

              var newPendingImages = _this.state.pendingImages.filter(function (img) {
                return img.key !== addedImage.key;
              });

              var newState = {
                pendingImages: newPendingImages
              };

              if (newPendingImages.length === 0) {
                newState.scheduled = false;
              }

              _this.setState(newState, cb);
            };

            var callback = function callback() {
              /**
               * The handler is the object through which the outer context
               * communicates file upload events like: fileChosen, cancel, progress
               */
              var handler = getHandler(onFinish, function () {
                return _this.state.value;
              });
              props.imageSupport.add(handler);
            };

            _this.setState({
              pendingImages: [].concat((0, _toConsumableArray2["default"])(pendingImages), [addedImage])
            }, callback);
          },
          onFocus: _this.onPluginFocus,
          onBlur: _this.onPluginBlur,
          maxImageWidth: _this.props.maxImageWidth,
          maxImageHeight: _this.props.maxImageHeight
        },
        toolbar: {
          /**
           * To minimize converting html -> state -> html
           * We only emit markup once 'done' is clicked.
           */
          disableScrollbar: !!props.disableScrollbar,
          disableUnderline: props.disableUnderline,
          autoWidth: props.autoWidthToolbar,
          onDone: function onDone() {
            var _this$state$value$sta, _this$state$value$sta2;

            var nonEmpty = props.nonEmpty;
            log('[onDone]');

            _this.setState({
              toolbarInFocus: false,
              focusedNode: null
            });

            _this.editor.blur();

            if (nonEmpty && ((_this$state$value$sta = _this.state.value.startText) === null || _this$state$value$sta === void 0 ? void 0 : (_this$state$value$sta2 = _this$state$value$sta.text) === null || _this$state$value$sta2 === void 0 ? void 0 : _this$state$value$sta2.length) === 0) {
              _this.resetValue(true).then(function () {
                _this.onEditingDone();
              });
            } else {
              _this.onEditingDone();
            }
          }
        },
        table: {
          onFocus: function onFocus() {
            log('[table:onFocus]...');

            _this.onPluginFocus();
          },
          onBlur: function onBlur() {
            log('[table:onBlur]...');

            _this.onPluginBlur();
          }
        },
        responseArea: {
          type: normalizedResponseAreaProps.type,
          options: normalizedResponseAreaProps.options,
          maxResponseAreas: normalizedResponseAreaProps.maxResponseAreas,
          respAreaToolbar: normalizedResponseAreaProps.respAreaToolbar,
          onHandleAreaChange: normalizedResponseAreaProps.onHandleAreaChange,
          error: normalizedResponseAreaProps.error,
          onFocus: function onFocus() {
            log('[table:onFocus]...');

            _this.onPluginFocus();
          },
          onBlur: function onBlur() {
            log('[table:onBlur]...');

            _this.onPluginBlur();
          }
        },
        languageCharacters: props.languageCharactersProps,
        media: {
          focus: _this.focus,
          createChange: function createChange() {
            return _this.state.value.change();
          },
          onChange: _this.onChange,
          uploadSoundSupport: props.uploadSoundSupport
        }
      });

      if (props.mathMlOptions.mmlOutput || props.mathMlOptions.mmlEditing) {
        _this.props.runSerializationOnMarkup();
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onPluginBlur", function (e) {
      log('[onPluginBlur]', e && e.relatedTarget);
      var target = e && e.relatedTarget;
      var node = target ? (0, _slateReact.findNode)(target, _this.state.value) : null;
      log('[onPluginBlur] node: ', node);

      _this.setState({
        focusedNode: node
      }, function () {
        _this.resetValue();
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onPluginFocus", function (e) {
      log('[onPluginFocus]', e && e.target);
      var target = e && e.target;

      if (target) {
        var node = (0, _slateReact.findNode)(target, _this.state.value);
        log('[onPluginFocus] node: ', node);
        var stashedValue = _this.state.stashedValue || _this.state.value;

        _this.setState({
          focusedNode: node,
          stashedValue: stashedValue
        });
      } else {
        _this.setState({
          focusedNode: null
        });
      }

      _this.stashValue();
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onMathClick", function (node) {
      _this.editor.change(function (c) {
        return c.collapseToStartOf(node);
      });

      _this.setState({
        selectedNode: node
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onEditingDone", function () {
      if (_this.state.isHtmlMode) {
        return;
      }

      var pendingImages = _this.state.pendingImages;

      if (pendingImages.length) {
        _this.setState({
          scheduled: true
        });

        return;
      }

      log('[onEditingDone]');

      _this.setState({
        pendingImages: [],
        stashedValue: null,
        focusedNode: null
      });

      log('[onEditingDone] value: ', _this.state.value);

      _this.props.onChange(_this.state.value, true);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleBlur", function (resolve) {
      var nonEmpty = _this.props.nonEmpty;
      var doneOn = _this.state.toolbarOpts.doneOn;

      _this.setState({
        toolbarInFocus: false,
        focusedNode: null
      });

      if (_this.editor) {
        _this.editor.blur();
      }

      if (doneOn === 'blur') {
        var _this$state$value$sta3, _this$state$value$sta4;

        if (nonEmpty && ((_this$state$value$sta3 = _this.state.value.startText) === null || _this$state$value$sta3 === void 0 ? void 0 : (_this$state$value$sta4 = _this$state$value$sta3.text) === null || _this$state$value$sta4 === void 0 ? void 0 : _this$state$value$sta4.length) === 0) {
          _this.resetValue(true).then(function () {
            _this.onEditingDone();

            resolve();
          });
        } else {
          _this.onEditingDone();

          resolve();
        }
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onBlur", function (event) {
      log('[onBlur]');
      var target = event.relatedTarget;
      var node = target ? (0, _slateReact.findNode)(target, _this.state.value) : null;
      log('[onBlur] node: ', node);
      return new Promise(function (resolve) {
        _this.setState({
          preBlurValue: _this.state.value,
          focusedNode: !node ? null : node
        }, _this.handleBlur.bind((0, _assertThisInitialized2["default"])(_this), resolve));

        _this.props.onBlur(event);
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleDomBlur", function (e) {
      var editorDOM = document.querySelector("[data-key=\"".concat(_this.state.value.document.key, "\"]"));
      setTimeout(function () {
        var stateValue = _this.state.value;

        if (!_this.wrapperRef) {
          return;
        }

        var editorElement = !editorDOM || document.activeElement.closest("[class*=\"".concat(editorDOM.className, "\"]"));
        var toolbarElement = !_this.toolbarRef || document.activeElement.closest("[class*=\"".concat(_this.toolbarRef.className, "\"]"));

        var isInCurrentComponent = _this.wrapperRef.contains(editorElement) || _this.wrapperRef.contains(toolbarElement);

        if (!isInCurrentComponent) {
          editorDOM.removeEventListener('blur', _this.handleDomBlur);

          if (stateValue.isFocused) {
            _this.onBlur(e);
          }
        }
      }, 50);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onFocus", function () {
      return new Promise(function (resolve) {
        var editorDOM = document.querySelector("[data-key=\"".concat(_this.state.value.document.key, "\"]"));
        log('[onFocus]', document.activeElement);
        /**
         * This is a temporary hack - @see changeData below for some more information.
         */

        if (_this.__TEMPORARY_CHANGE_DATA) {
          var _this$__TEMPORARY_CHA = _this.__TEMPORARY_CHANGE_DATA,
              key = _this$__TEMPORARY_CHA.key,
              data = _this$__TEMPORARY_CHA.data;
          var domEl = document.querySelector("[data-key=\"".concat(key, "\"]"));

          if (domEl) {
            var change = _this.state.value.change().setNodeByKey(key, {
              data: data
            });

            _this.setState({
              value: change.value
            }, function () {
              _this.__TEMPORARY_CHANGE_DATA = null;
            });
          }
        }
        /**
         * This is needed just in case the browser decides to make the editor
         * lose focus without triggering the onBlur event (can happen in a few cases).
         * This will also trigger onBlur if the user clicks outside of the page when the editor
         * is focused.
         */


        if (editorDOM === document.activeElement) {
          editorDOM.removeEventListener('blur', _this.handleDomBlur);
          editorDOM.addEventListener('blur', _this.handleDomBlur);
        }

        _this.stashValue();

        _this.props.onFocus();

        resolve();
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "stashValue", function () {
      log('[stashValue]');

      if (!_this.state.stashedValue) {
        _this.setState({
          stashedValue: _this.state.value
        });
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "resetValue", function (force) {
      var _this$state = _this.state,
          value = _this$state.value,
          focusedNode = _this$state.focusedNode;

      var stopReset = _this.plugins.reduce(function (s, p) {
        return s || p.stopReset && p.stopReset(_this.state.value);
      }, false);

      log('[resetValue]', value.isFocused, focusedNode, 'stopReset: ', stopReset);

      if (_this.state.stashedValue && !value.isFocused && !focusedNode && !stopReset || force) {
        log('[resetValue] resetting...');
        log('stashed', _this.state.stashedValue.document.toObject());
        log('current', _this.state.value.document.toObject());

        var newValue = _slate.Value.fromJSON(_this.state.stashedValue.toJSON());

        log('newValue: ', newValue.document);
        return new Promise(function (resolve) {
          setTimeout(function () {
            _this.setState({
              value: newValue,
              stashedValue: null
            }, function () {
              log('value now: ', _this.state.value.document.toJSON());
              resolve();
            });
          }, 50);
        });
      } else {
        return Promise.resolve({});
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onChange", function (change, done) {
      log('[onChange]');
      var value = change.value;
      var charactersLimit = _this.props.charactersLimit;

      if (value && value.document && value.document.text && value.document.text.length > charactersLimit) {
        return;
      }

      if (!_this.state.isHtmlMode) {
        _this.setState({
          isEdited: false
        });
      } // Mark the editor as edited when in HTML mode and its content has changed.
      // This status will later be used to decide whether to prompt a warning to the user when exiting HTML mode.


      if (_this.state.isHtmlMode && !_this.state.isEdited && !(0, _isEqual["default"])(_this.state.value.document.text, value.document.text)) {
        _this.setState({
          isEdited: true
        });
      }

      _this.setState({
        value: value
      }, function () {
        log('[onChange], call done()');

        if (done) {
          done();
        }
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getFocusedValue", function () {
      if (_this.state.value.isFocused) {
        return _this.state.value;
      }

      return _this.state.preBlurValue;
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "valueToSize", function (v) {
      if (!v) {
        return;
      }

      if (typeof v === 'string') {
        if (v.endsWith('%')) {
          return undefined;
        } else if (v.endsWith('px') || v.endsWith('vh') || v.endsWith('vw')) {
          return v;
        } else {
          var value = parseInt(v, 10);
          return isNaN(value) ? value : "".concat(value, "px");
        }
      }

      if (typeof v === 'number') {
        return "".concat(v, "px");
      }

      return;
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "validateNode", function (node) {
      if (node.object !== 'block') return;
      var last = node.nodes.last();
      if (!last) return;
      if (last.type !== 'image') return;
      log('[validateNode] last is image..');
      var parent = last.getParent(last.key);

      var p = _slate.Block.getParent(last.key);

      log('[validateNode] parent:', parent, p);
      return undefined;
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "changeData", function (key, data) {
      log('[changeData]. .. ', key, data);
      /**
       * HACK ALERT: We should be calling setState here and storing the change data:
       *
       * <code>this.setState({changeData: { key, data}})</code>
       * However this is causing issues with the Mathquill instance. The 'input' event stops firing on the element and no
       * more changes get through. The issues seem to be related to the promises in onBlur/onFocus. But removing these
       * brings it's own problems. A major clean up is planned for this component so I've decided to temporarily settle
       * on this hack rather than spend more time on this.
       */
      // Uncomment this line to see the bug described above.
      // this.setState({changeData: {key, data}})

      _this.__TEMPORARY_CHANGE_DATA = {
        key: key,
        data: data
      };
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "focus", function (pos, node) {
      var position = pos || 'end';

      _this.props.focus(position, node);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onDropPaste", /*#__PURE__*/function () {
      var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(event, change, dropContext) {
        var editor, transfer, file, type, fragment, text, src, inline, range, ch, handler, _change$value, _document, selection, startBlock, defaultBlock, defaultMarks, frag;

        return _regenerator["default"].wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                editor = change.editor;
                transfer = (0, _slateReact.getEventTransfer)(event);
                file = transfer.files && transfer.files[0];
                type = transfer.type;
                fragment = transfer.fragment;
                text = transfer.text;

                if (!(file && (file.type === 'image/jpeg' || file.type === 'image/jpg' || file.type === 'image/png'))) {
                  _context.next = 28;
                  break;
                }

                if (_this.props.imageSupport) {
                  _context.next = 9;
                  break;
                }

                return _context.abrupt("return");

              case 9:
                _context.prev = 9;
                log('[onDropPaste]');
                _context.next = 13;
                return (0, serialization.getBase64)(file);

              case 13:
                src = _context.sent;
                inline = _slate.Inline.create({
                  type: 'image',
                  isVoid: true,
                  data: {
                    loading: false,
                    src: src
                  }
                });

                if (dropContext) {
                  _this.focus();
                } else {
                  range = (0, _slateReact.getEventRange)(event, editor);

                  if (range) {
                    change.select(range);
                  }
                }

                ch = change.insertInline(inline);

                _this.onChange(ch);

                handler = new _insertImageHandler["default"](inline, function () {}, function () {
                  return _this.state.value;
                }, _this.onChange, true);
                handler.fileChosen(file);

                _this.props.imageSupport.add(handler);

                _context.next = 26;
                break;

              case 23:
                _context.prev = 23;
                _context.t0 = _context["catch"](9);
                log('[onDropPaste] error: ', _context.t0);

              case 26:
                _context.next = 42;
                break;

              case 28:
                if (!(type === 'fragment')) {
                  _context.next = 32;
                  break;
                }

                change.insertFragment(fragment);
                _context.next = 42;
                break;

              case 32:
                if (!(type === 'text' || type === 'html')) {
                  _context.next = 42;
                  break;
                }

                if (text) {
                  _context.next = 35;
                  break;
                }

                return _context.abrupt("return");

              case 35:
                _change$value = change.value, _document = _change$value.document, selection = _change$value.selection, startBlock = _change$value.startBlock;

                if (!startBlock.isVoid) {
                  _context.next = 38;
                  break;
                }

                return _context.abrupt("return");

              case 38:
                defaultBlock = startBlock;
                defaultMarks = _document.getInsertMarksAtRange(selection);
                frag = _slatePlainSerializer["default"].deserialize(text, {
                  defaultBlock: defaultBlock,
                  defaultMarks: defaultMarks
                }).document;
                change.insertFragment(frag);

              case 42:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, null, [[9, 23]]);
      }));

      return function (_x, _x2, _x3) {
        return _ref.apply(this, arguments);
      };
    }());
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "renderPlaceholder", function (props) {
      var editor = props.editor;
      var document = editor.value.document;

      if (!editor.props.placeholder || document.text !== '' || document.nodes.size !== 1) {
        return false;
      }

      return /*#__PURE__*/_react["default"].createElement("span", {
        contentEditable: false,
        style: {
          display: 'inline-block',
          width: 'fit-content',
          // for centering the placeholder if text-align is set to center
          maxWidth: '100%',
          whiteSpace: 'nowrap',
          opacity: '0.33',
          pointerEvents: 'none',
          userSelect: 'none'
        }
      }, editor.props.placeholder);
    });
    _this.state = {
      value: _props.value,
      toolbarOpts: createToolbarOpts(_props.toolbarOpts, _props.error),
      pendingImages: [],
      isHtmlMode: false,
      isEdited: false,
      dialog: {
        open: false
      }
    };
    _this.toggleHtmlMode = _this.toggleHtmlMode.bind((0, _assertThisInitialized2["default"])(_this));

    _this.onResize = function () {
      _props.onChange(_this.state.value, true);
    };

    _this.handlePlugins(_this.props);

    return _this;
  }

  (0, _createClass2["default"])(Editor, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;

      // onRef is needed to get the ref of the component because we export it using withStyles
      this.props.onRef(this);
      window.addEventListener('resize', this.onResize);

      if (this.editor && this.props.autoFocus) {
        Promise.resolve().then(function () {
          if (_this2.editor) {
            var editorDOM = document.querySelector("[data-key=\"".concat(_this2.editor.value.document.key, "\"]"));

            _this2.editor.focus();

            if (editorDOM) {
              editorDOM.focus();
            }
          }
        });
      }
    }
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      var _nextProps$value, _nextProps$value$docu, _this$props$value;

      var _this$state2 = this.state,
          isHtmlMode = _this$state2.isHtmlMode,
          toolbarOpts = _this$state2.toolbarOpts;
      var newToolbarOpts = createToolbarOpts(nextProps.toolbarOpts, nextProps.error, isHtmlMode);

      if (!(0, _isEqual["default"])(newToolbarOpts, toolbarOpts)) {
        this.setState({
          toolbarOpts: newToolbarOpts
        });
      }

      var differentCharacterProps = !(0, _isEqual["default"])(nextProps.languageCharactersProps, this.props.languageCharactersProps);
      var differentMathMlProps = !(0, _isEqual["default"])(nextProps.mathMlOptions, this.props.mathMlOptions);

      if (differentCharacterProps || differentMathMlProps) {
        this.handlePlugins(nextProps);
      }

      if (!((_nextProps$value = nextProps.value) !== null && _nextProps$value !== void 0 && (_nextProps$value$docu = _nextProps$value.document) !== null && _nextProps$value$docu !== void 0 && _nextProps$value$docu.equals((_this$props$value = this.props.value) === null || _this$props$value === void 0 ? void 0 : _this$props$value.document))) {
        this.setState({
          focus: false,
          value: nextProps.value
        });
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      // The cursor is on a zero width element and when that is placed near void elements, it is not visible
      // so we increase the width to at least 2px in order for the user to see it
      // Trigger plugins and finish editing if:
      // 1. The 'isHtmlMode' state has been toggled.
      // 2. We're currently in 'isHtmlMode' and the editor value has been modified.
      if (this.state.isHtmlMode !== prevState.isHtmlMode || this.state.isHtmlMode && !prevState.isEdited && this.state.isEdited) {
        this.handlePlugins(this.props);
        this.onEditingDone();
      }

      var zeroWidthEls = document.querySelectorAll('[data-slate-zero-width="z"]');
      Array.from(zeroWidthEls).forEach(function (el) {
        el.style.minWidth = '2px';
        el.style.display = 'inline-block';
      });
    }
  }, {
    key: "componentWillUnmount",
    value:
    /**
     * Remove onResize event listener
     */
    function componentWillUnmount() {
      window.removeEventListener('resize', this.onResize);
    } // Allowing time for onChange to take effect if it is called

  }, {
    key: "buildSizeStyle",
    value: function buildSizeStyle() {
      var _this$props = this.props,
          width = _this$props.width,
          minHeight = _this$props.minHeight,
          height = _this$props.height,
          maxHeight = _this$props.maxHeight;
      return {
        width: this.valueToSize(width),
        height: this.valueToSize(height),
        minHeight: this.valueToSize(minHeight),
        maxHeight: this.valueToSize(maxHeight)
      };
    }
  }, {
    key: "render",
    value: function render() {
      var _classNames,
          _this3 = this;

      var _this$props2 = this.props,
          disabled = _this$props2.disabled,
          spellCheck = _this$props2.spellCheck,
          highlightShape = _this$props2.highlightShape,
          classes = _this$props2.classes,
          className = _this$props2.className,
          placeholder = _this$props2.placeholder,
          pluginProps = _this$props2.pluginProps,
          onKeyDown = _this$props2.onKeyDown;
      var _this$state3 = this.state,
          value = _this$state3.value,
          focusedNode = _this$state3.focusedNode,
          toolbarOpts = _this$state3.toolbarOpts,
          dialog = _this$state3.dialog,
          scheduled = _this$state3.scheduled;
      log('[render] value: ', value);
      var sizeStyle = this.buildSizeStyle();
      var names = (0, _classnames["default"])((_classNames = {}, (0, _defineProperty2["default"])(_classNames, classes.withBg, highlightShape), (0, _defineProperty2["default"])(_classNames, classes.toolbarOnTop, toolbarOpts.alwaysVisible && toolbarOpts.position === 'top'), (0, _defineProperty2["default"])(_classNames, classes.scheduled, scheduled), _classNames), className);
      return /*#__PURE__*/_react["default"].createElement("div", {
        ref: function ref(_ref2) {
          return _this3.wrapperRef = _ref2;
        },
        style: {
          width: sizeStyle.width
        },
        className: names
      }, scheduled && /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.uploading
      }, "Uploading image and then saving..."), /*#__PURE__*/_react["default"].createElement(_slateReact.Editor, {
        plugins: this.plugins,
        innerRef: function innerRef(r) {
          if (r) {
            _this3.slateEditor = r;
          }
        },
        ref: function ref(r) {
          return _this3.editor = r && _this3.props.editorRef(r);
        },
        toolbarRef: function toolbarRef(r) {
          if (r) {
            _this3.toolbarRef = r;
          }
        },
        value: value,
        focus: this.focus,
        onKeyDown: onKeyDown,
        onChange: this.onChange,
        getFocusedValue: this.getFocusedValue,
        onBlur: this.onBlur,
        onDrop: function onDrop(event, editor) {
          return _this3.onDropPaste(event, editor, true);
        },
        onPaste: function onPaste(event, editor) {
          return _this3.onDropPaste(event, editor);
        },
        onFocus: this.onFocus,
        onEditingDone: this.onEditingDone,
        focusedNode: focusedNode,
        normalize: this.normalize,
        readOnly: disabled,
        spellCheck: spellCheck,
        autoCorrect: spellCheck,
        className: (0, _classnames["default"])((0, _defineProperty2["default"])({}, classes.noPadding, toolbarOpts && toolbarOpts.noBorder), classes.slateEditor),
        style: {
          minHeight: sizeStyle.minHeight,
          height: sizeStyle.height,
          maxHeight: sizeStyle.maxHeight
        },
        pluginProps: pluginProps,
        toolbarOpts: toolbarOpts,
        placeholder: placeholder,
        renderPlaceholder: this.renderPlaceholder,
        onDataChange: this.changeData
      }), /*#__PURE__*/_react["default"].createElement(_configUi.AlertDialog, {
        open: dialog.open,
        title: dialog.title,
        text: dialog.text,
        onClose: dialog.onClose,
        onConfirm: dialog.onConfirm
      }));
    }
  }]);
  return Editor;
}(_react["default"].Component); // TODO color - hardcoded gray background and keypad colors will need to change too


exports.Editor = Editor;
(0, _defineProperty2["default"])(Editor, "propTypes", {
  autoFocus: _propTypes["default"].bool,
  editorRef: _propTypes["default"].func.isRequired,
  error: _propTypes["default"].any,
  onRef: _propTypes["default"].func.isRequired,
  onChange: _propTypes["default"].func.isRequired,
  onFocus: _propTypes["default"].func,
  onBlur: _propTypes["default"].func,
  onKeyDown: _propTypes["default"].func,
  focus: _propTypes["default"].func.isRequired,
  value: _slatePropTypes["default"].value.isRequired,
  imageSupport: _propTypes["default"].object,
  mathMlOptions: _propTypes["default"].shape({
    mmlOutput: _propTypes["default"].bool,
    mmlEditing: _propTypes["default"].bool
  }),
  disableImageAlignmentButtons: _propTypes["default"].bool,
  uploadSoundSupport: _propTypes["default"].shape({
    add: _propTypes["default"].func,
    "delete": _propTypes["default"].func
  }),
  charactersLimit: _propTypes["default"].number,
  width: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
  height: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
  minHeight: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
  maxHeight: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
  classes: _propTypes["default"].object.isRequired,
  highlightShape: _propTypes["default"].bool,
  disabled: _propTypes["default"].bool,
  spellCheck: _propTypes["default"].bool,
  nonEmpty: _propTypes["default"].bool,
  disableScrollbar: _propTypes["default"].bool,
  disableUnderline: _propTypes["default"].bool,
  autoWidthToolbar: _propTypes["default"].bool,
  pluginProps: _propTypes["default"].any,
  placeholder: _propTypes["default"].string,
  responseAreaProps: _propTypes["default"].shape({
    type: _propTypes["default"].oneOf(['explicit-constructed-response', 'inline-dropdown', 'drag-in-the-blank']),
    options: _propTypes["default"].object,
    respAreaToolbar: _propTypes["default"].func,
    onHandleAreaChange: _propTypes["default"].func
  }),
  languageCharactersProps: _propTypes["default"].arrayOf(_propTypes["default"].shape({
    language: _propTypes["default"].string,
    characterIcon: _propTypes["default"].string,
    characters: _propTypes["default"].arrayOf(_propTypes["default"].arrayOf(_propTypes["default"].string))
  })),
  runSerializationOnMarkup: _propTypes["default"].func,
  toolbarOpts: _propTypes["default"].shape({
    position: _propTypes["default"].oneOf(['bottom', 'top']),
    alignment: _propTypes["default"].oneOf(['left', 'right']),
    alwaysVisible: _propTypes["default"].bool,
    showDone: _propTypes["default"].bool,
    doneOn: _propTypes["default"].string
  }),
  activePlugins: _propTypes["default"].arrayOf(function (values) {
    var allValid = values.every(function (v) {
      return _plugins.ALL_PLUGINS.includes(v);
    });
    return !allValid && new Error("Invalid values: ".concat(values, ", values must be one of [").concat(_plugins.ALL_PLUGINS.join(','), "]"));
  }),
  className: _propTypes["default"].string,
  maxImageWidth: _propTypes["default"].number,
  maxImageHeight: _propTypes["default"].number
});
(0, _defineProperty2["default"])(Editor, "defaultProps", {
  disableUnderline: true,
  onFocus: function onFocus() {},
  onBlur: function onBlur() {},
  onKeyDown: function onKeyDown() {},
  runSerializationOnMarkup: function runSerializationOnMarkup() {},
  mathMlOptions: {
    mmlOutput: false,
    mmlEditing: false
  },
  toolbarOpts: defaultToolbarOpts,
  responseAreaProps: defaultResponseAreaProps,
  languageCharactersProps: defaultLanguageCharactersProps
});
var styles = {
  withBg: {
    backgroundColor: 'rgba(0,0,0,0.06)'
  },
  scheduled: {
    opacity: 0.5,
    pointerEvents: 'none',
    position: 'relative'
  },
  uploading: {
    position: 'absolute',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)'
  },
  slateEditor: {
    fontFamily: 'Roboto, sans-serif',
    '& table': {
      tableLayout: 'fixed',
      width: '100%',
      borderCollapse: 'collapse',
      color: _renderUi.color.text(),
      backgroundColor: _renderUi.color.background()
    },
    '& table:not([border="1"]) tr': {
      borderTop: '1px solid #dfe2e5' // TODO perhaps secondary color for background, for now disable
      // '&:nth-child(2n)': {
      //   backgroundColor: '#f6f8fa'
      // }

    },
    '& td, th': {
      padding: '.6em 1em',
      textAlign: 'center'
    },
    '& table:not([border="1"]) td, th': {
      border: '1px solid #dfe2e5'
    }
  },
  toolbarOnTop: {
    marginTop: '45px'
  },
  noPadding: {
    padding: '0 !important'
  }
};

var _default = (0, _styles.withStyles)(styles)(Editor);

exports["default"] = _default;
//# sourceMappingURL=editor.js.map