import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
import { Slice, Fragment } from 'prosemirror-model';
import { PluginKey, Plugin, NodeSelection, TextSelection, Selection } from 'prosemirror-state';
import { CellSelection } from 'prosemirror-tables';
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
import _createForOfIteratorHelper from '@babel/runtime/helpers/esm/createForOfIteratorHelper';
import { isPerformanceAPIAvailable, measureRender } from '@uidu/editor-common';
import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';
import _createClass from '@babel/runtime/helpers/esm/createClass';
import _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';
import _inherits from '@babel/runtime/helpers/esm/inherits';
import _createSuper from '@babel/runtime/helpers/esm/createSuper';
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { Step, StepResult, StepMap, ReplaceStep } from 'prosemirror-transform';
import { FabricChannel } from '@uidu/analytics-listeners';
import { findParentNode } from 'prosemirror-utils';
import { GapCursorSelection, Side } from '@uidu/editor-common/selection';
import { e as canMoveUp, h as canMoveDown } from './index-cfb3e237.esm.js';

var analyticsEventKey = 'EDITOR_ANALYTICS_EVENT';
var editorAnalyticsChannel = FabricChannel.editor;

var fireAnalyticsEvent = function fireAnalyticsEvent(createAnalyticsEvent) {
  return function (_ref) {
    var payload = _ref.payload,
      _ref$channel = _ref.channel,
      channel = _ref$channel === void 0 ? editorAnalyticsChannel : _ref$channel;
    return createAnalyticsEvent && createAnalyticsEvent(payload).fire(channel);
  };
};

var EVENT_TYPE = /*#__PURE__*/function (EVENT_TYPE) {
  EVENT_TYPE["OPERATIONAL"] = "operational";
  EVENT_TYPE["SCREEN"] = "screen";
  EVENT_TYPE["TRACK"] = "track";
  EVENT_TYPE["UI"] = "ui";
  return EVENT_TYPE;
}({});
var ACTION = /*#__PURE__*/function (ACTION) {
  ACTION["ADDED"] = "added";
  ACTION["CHANGED_FULL_WIDTH_MODE"] = "changedFullWidthMode";
  ACTION["CHANGED_LAYOUT"] = "changedLayout";
  ACTION["CHANGED_TYPE"] = "changedType";
  ACTION["CHANGED_URL"] = "changedUrl";
  ACTION["CLEARED"] = "cleared";
  ACTION["CLICKED"] = "clicked";
  ACTION["CLOSED"] = "closed";
  ACTION["DELETED"] = "deleted";
  ACTION["DISPATCHED_INVALID_TRANSACTION"] = "dispatchedInvalidTransaction";
  ACTION["EDITED"] = "edited";
  ACTION["EDITOR_MOUNTED"] = "mounted";
  ACTION["EDITOR_CRASHED"] = "unhandledErrorCaught";
  ACTION["FAILED_TO_UNMOUNT"] = "failedToUnmount";
  ACTION["FORMATTED"] = "formatted";
  ACTION["INSERTED"] = "inserted";
  ACTION["INVOKED"] = "invoked";
  ACTION["OPENED"] = "opened";
  ACTION["PASTED"] = "pasted";
  ACTION["PASTED_AS_PLAIN"] = "pastedAsPlain";
  ACTION["PROSEMIRROR_RENDERED"] = "proseMirrorRendered";
  ACTION["REDID"] = "redid";
  ACTION["STARTED"] = "started";
  ACTION["STOPPED"] = "stopped";
  ACTION["SUBSTITUTED"] = "autoSubstituted";
  ACTION["TOGGLE_EXPAND"] = "toggleExpand";
  ACTION["UNDID"] = "undid";
  ACTION["UNLINK"] = "unlinked";
  ACTION["VISITED"] = "visited";
  ACTION["BROWSER_FREEZE"] = "browserFreeze";
  ACTION["SLOW_INPUT"] = "slowInput";
  ACTION["UPLOAD_EXTERNAL_FAIL"] = "uploadExternalFailed";
  ACTION["INPUT_PERF_SAMPLING"] = "inputPerfSampling";
  ACTION["HELP_OPENED"] = "helpOpened";
  ACTION["TRANSACTION_DISPATCHED"] = "transactionDispatched";
  return ACTION;
}({});
var INPUT_METHOD = /*#__PURE__*/function (INPUT_METHOD) {
  INPUT_METHOD["ASCII"] = "ascii";
  INPUT_METHOD["AUTO"] = "auto";
  INPUT_METHOD["AUTO_DETECT"] = "autoDetect";
  INPUT_METHOD["CARD"] = "card";
  INPUT_METHOD["CLIPBOARD"] = "clipboard";
  INPUT_METHOD["DRAG_AND_DROP"] = "dragAndDrop";
  INPUT_METHOD["EXTERNAL"] = "external";
  INPUT_METHOD["FORMATTING"] = "autoformatting";
  INPUT_METHOD["FLOATING_TB"] = "floatingToolbar";
  INPUT_METHOD["KEYBOARD"] = "keyboard";
  INPUT_METHOD["INSERT_MENU"] = "insertMenu";
  INPUT_METHOD["MANUAL"] = "manual";
  INPUT_METHOD["PICKER"] = "picker";
  INPUT_METHOD["PICKER_CLOUD"] = "cloudPicker";
  INPUT_METHOD["QUICK_INSERT"] = "quickInsert";
  INPUT_METHOD["SHORTCUT"] = "shortcut";
  INPUT_METHOD["TOOLBAR"] = "toolbar";
  INPUT_METHOD["TYPEAHEAD"] = "typeAhead";
  INPUT_METHOD["CONTEXT_MENU"] = "contextMenu";
  INPUT_METHOD["BUTTON"] = "button";
  return INPUT_METHOD;
}({});
var ACTION_SUBJECT = /*#__PURE__*/function (ACTION_SUBJECT) {
  ACTION_SUBJECT["BUTTON"] = "button";
  ACTION_SUBJECT["DOCUMENT"] = "document";
  ACTION_SUBJECT["EDITOR"] = "editor";
  ACTION_SUBJECT["EXPAND"] = "expand";
  ACTION_SUBJECT["FEEDBACK_DIALOG"] = "feedbackDialog";
  ACTION_SUBJECT["HELP"] = "help";
  ACTION_SUBJECT["LAYOUT"] = "layout";
  ACTION_SUBJECT["MEDIA"] = "media";
  ACTION_SUBJECT["MEDIA_SINGLE"] = "mediaSingle";
  ACTION_SUBJECT["NESTED_EXPAND"] = "nestedExpand";
  ACTION_SUBJECT["PANEL"] = "panel";
  ACTION_SUBJECT["PICKER"] = "picker";
  ACTION_SUBJECT["SMART_LINK"] = "smartLink";
  ACTION_SUBJECT["TEXT"] = "text";
  ACTION_SUBJECT["TYPEAHEAD"] = "typeAhead";
  ACTION_SUBJECT["TABLE"] = "table";
  ACTION_SUBJECT["TOOLBAR"] = "toolbar";
  return ACTION_SUBJECT;
}({});
var ACTION_SUBJECT_ID = /*#__PURE__*/function (ACTION_SUBJECT_ID) {
  ACTION_SUBJECT_ID["ACTION"] = "action";
  ACTION_SUBJECT_ID["ALT_TEXT"] = "altText";
  ACTION_SUBJECT_ID["ANNOTATE_BUTTON"] = "annotateButton";
  ACTION_SUBJECT_ID["BLOCK_QUOTE"] = "blockQuote";
  ACTION_SUBJECT_ID["BUTTON_HELP"] = "helpButton";
  ACTION_SUBJECT_ID["HELP_QUICK_INSERT"] = "helpQuickInsert";
  ACTION_SUBJECT_ID["BUTTON_FEEDBACK"] = "feedbackButton";
  ACTION_SUBJECT_ID["CANCEL"] = "cancel";
  ACTION_SUBJECT_ID["CARD_INLINE"] = "inlineCard";
  ACTION_SUBJECT_ID["CARD_BLOCK"] = "blockCard";
  ACTION_SUBJECT_ID["CODE_BLOCK"] = "codeBlock";
  ACTION_SUBJECT_ID["DATE"] = "date";
  ACTION_SUBJECT_ID["DECISION"] = "decision";
  ACTION_SUBJECT_ID["DIVIDER"] = "divider";
  ACTION_SUBJECT_ID["EMOJI"] = "emoji";
  ACTION_SUBJECT_ID["EXPAND"] = "expand";
  ACTION_SUBJECT_ID["EXTENSION"] = "extension";
  ACTION_SUBJECT_ID["FORMAT_BLOCK_QUOTE"] = "blockQuote";
  ACTION_SUBJECT_ID["FORMAT_CODE"] = "code";
  ACTION_SUBJECT_ID["FORMAT_COLOR"] = "color";
  ACTION_SUBJECT_ID["FORMAT_CLEAR"] = "clearFormatting";
  ACTION_SUBJECT_ID["FORMAT_HEADING"] = "heading";
  ACTION_SUBJECT_ID["FORMAT_INDENT"] = "indentation";
  ACTION_SUBJECT_ID["FORMAT_ITALIC"] = "italic";
  ACTION_SUBJECT_ID["FORMAT_LIST_NUMBER"] = "numberedList";
  ACTION_SUBJECT_ID["FORMAT_LIST_BULLET"] = "bulletedList";
  ACTION_SUBJECT_ID["FORMAT_STRIKE"] = "strike";
  ACTION_SUBJECT_ID["FORMAT_STRONG"] = "strong";
  ACTION_SUBJECT_ID["FORMAT_SUB"] = "subscript";
  ACTION_SUBJECT_ID["FORMAT_SUPER"] = "superscript";
  ACTION_SUBJECT_ID["FORMAT_UNDERLINE"] = "underline";
  ACTION_SUBJECT_ID["LAYOUT"] = "layout";
  ACTION_SUBJECT_ID["LINE_BREAK"] = "lineBreak";
  ACTION_SUBJECT_ID["LINK"] = "link";
  ACTION_SUBJECT_ID["MEDIA_LINK"] = "mediaLink";
  ACTION_SUBJECT_ID["NESTED_EXPAND"] = "nestedExpand";
  ACTION_SUBJECT_ID["LINK_PREVIEW"] = "linkPreview";
  ACTION_SUBJECT_ID["MEDIA"] = "media";
  ACTION_SUBJECT_ID["MENTION"] = "mention";
  ACTION_SUBJECT_ID["PICKER_CLOUD"] = "cloudPicker";
  ACTION_SUBJECT_ID["PICKER_EMOJI"] = "emojiPicker";
  ACTION_SUBJECT_ID["PRODUCT_NAME"] = "productName";
  ACTION_SUBJECT_ID["PANEL"] = "panel";
  ACTION_SUBJECT_ID["PASTE_BLOCK_CARD"] = "blockCard";
  ACTION_SUBJECT_ID["PASTE_BLOCKQUOTE"] = "blockQuote";
  ACTION_SUBJECT_ID["PASTE_BODIED_EXTENSION"] = "bodiedExtension";
  ACTION_SUBJECT_ID["PASTE_BULLET_LIST"] = "bulletList";
  ACTION_SUBJECT_ID["PASTE_CODE_BLOCK"] = "codeBlock";
  ACTION_SUBJECT_ID["PASTE_DECISION_LIST"] = "decisionList";
  ACTION_SUBJECT_ID["PASTE_EXTENSION"] = "extension";
  ACTION_SUBJECT_ID["PASTE_HEADING"] = "heading";
  ACTION_SUBJECT_ID["PASTE_MEDIA_GROUP"] = "mediaGroup";
  ACTION_SUBJECT_ID["PASTE_MEDIA_SINGLE"] = "mediaSingle";
  ACTION_SUBJECT_ID["PASTE_ORDERED_LIST"] = "orderedList";
  ACTION_SUBJECT_ID["PASTE_PANEL"] = "panel";
  ACTION_SUBJECT_ID["PASTE_PARAGRAPH"] = "paragraph";
  ACTION_SUBJECT_ID["PASTE_RULE"] = "rule";
  ACTION_SUBJECT_ID["PASTE_TABLE_HEADER"] = "tableHeader";
  ACTION_SUBJECT_ID["PASTE_TABLE_CELL"] = "tableCell";
  ACTION_SUBJECT_ID["PASTE_TABLE_ROW"] = "tableRow";
  ACTION_SUBJECT_ID["PASTE_TABLE"] = "table";
  ACTION_SUBJECT_ID["PASTE_TASK_LIST"] = "taskList";
  ACTION_SUBJECT_ID["PASTE_EXPAND"] = "expand";
  ACTION_SUBJECT_ID["PASTE_NESTED_EXPAND"] = "nestedExpand";
  ACTION_SUBJECT_ID["PUNC"] = "punctuation";
  ACTION_SUBJECT_ID["REACT_NODE_VIEW"] = "reactNodeView";
  ACTION_SUBJECT_ID["SAVE"] = "save";
  ACTION_SUBJECT_ID["SECTION"] = "section";
  ACTION_SUBJECT_ID["SMART_LINK"] = "smartLink";
  ACTION_SUBJECT_ID["STATUS"] = "status";
  ACTION_SUBJECT_ID["SYMBOL"] = "symbol";
  ACTION_SUBJECT_ID["TABLE"] = "table";
  ACTION_SUBJECT_ID["TYPEAHEAD_EMOJI"] = "emojiTypeAhead";
  ACTION_SUBJECT_ID["TYPEAHEAD_LINK"] = "linkTypeAhead";
  ACTION_SUBJECT_ID["TYPEAHEAD_MENTION"] = "mentionTypeAhead";
  ACTION_SUBJECT_ID["TYPEAHEAD_QUICK_INSERT"] = "quickInsertTypeAhead";
  return ACTION_SUBJECT_ID;
}({});

var analyticsStepType = 'uidu-analytics';
var actionsToIgnore = [ACTION.INVOKED, ACTION.OPENED];

/** Creates undo event from a normal analytics event */
var createUndoEvent = function createUndoEvent(analyticsEvent) {
  return _objectSpread(_objectSpread({}, analyticsEvent), {}, {
    payload: {
      action: ACTION.UNDID,
      actionSubject: analyticsEvent.payload.actionSubject,
      actionSubjectId: analyticsEvent.payload.action,
      attributes: _objectSpread(_objectSpread({}, analyticsEvent.payload.attributes), {}, {
        actionSubjectId: analyticsEvent.payload.actionSubjectId
      }),
      eventType: EVENT_TYPE.TRACK
    }
  });
};

/** Toggles event action between undo & redo */
var toggleEventAction = function toggleEventAction(analyticsEvent) {
  return _objectSpread(_objectSpread({}, analyticsEvent), {}, {
    payload: _objectSpread(_objectSpread({}, analyticsEvent.payload), {}, {
      action: analyticsEvent.payload.action === ACTION.UNDID ? ACTION.REDID : ACTION.UNDID
    })
  });
};

/**
 * Custom Prosemirror Step to fire our GAS V3 analytics events
 * Using a Step means that it will work with prosemirror-history and we get
 * undo/redo events for free
 */
var AnalyticsStep = /*#__PURE__*/function (_Step) {
  _inherits(AnalyticsStep, _Step);
  var _super = _createSuper(AnalyticsStep);
  function AnalyticsStep(createAnalyticsEvent, analyticsEvents, pos // Used to create the map, prevent splitting history.
  ) {
    var _this;
    _classCallCheck(this, AnalyticsStep);
    _this = _super.call(this);
    _defineProperty(_assertThisInitialized(_this), "analyticsEvents", []);
    _defineProperty(_assertThisInitialized(_this), "createAnalyticsEvent", void 0);
    _defineProperty(_assertThisInitialized(_this), "pos", void 0);
    _this.createAnalyticsEvent = createAnalyticsEvent;
    _this.analyticsEvents = analyticsEvents;
    _this.pos = pos;
    return _this;
  }

  /**
   * Generate new undo/redo analytics event when step is inverted
   */
  _createClass(AnalyticsStep, [{
    key: "invert",
    value: function invert() {
      var analyticsEvents = this.analyticsEvents.filter(function (analyticsEvent) {
        return actionsToIgnore.indexOf(analyticsEvent.payload.action) === -1;
      }).map(function (analyticsEvent) {
        if (analyticsEvent.payload.action === ACTION.UNDID || analyticsEvent.payload.action === ACTION.REDID) {
          return toggleEventAction(analyticsEvent);
        } else {
          return createUndoEvent(analyticsEvent);
        }
      });
      return new AnalyticsStep(this.createAnalyticsEvent, analyticsEvents);
    }
  }, {
    key: "apply",
    value: function apply(doc) {
      var _iterator = _createForOfIteratorHelper(this.analyticsEvents),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var analyticsEvent = _step.value;
          fireAnalyticsEvent(this.createAnalyticsEvent)(analyticsEvent);
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
      return StepResult.ok(doc);
    }
  }, {
    key: "map",
    value: function map(mapping) {
      var newPos = this.pos;
      if (typeof newPos === 'number') {
        newPos = mapping.map(newPos);
      }
      // Return the same events, this step will never be removed
      return new AnalyticsStep(this.createAnalyticsEvent, this.analyticsEvents, newPos);
    }
  }, {
    key: "getMap",
    value: function getMap() {
      if (typeof this.pos === 'number') {
        return new StepMap([this.pos, 0, 0]);
      }
      return new StepMap([]);
    }
  }, {
    key: "merge",
    value: function merge(other) {
      if (other instanceof AnalyticsStep) {
        var otherAnalyticsEvents = other.analyticsEvents;
        return new AnalyticsStep(this.createAnalyticsEvent, [].concat(_toConsumableArray(otherAnalyticsEvents), _toConsumableArray(this.analyticsEvents)));
      }
      return null;
    }
  }, {
    key: "toJSON",
    value: function toJSON() {
      return {
        stepType: analyticsStepType
      };
    }
  }], [{
    key: "fromJSON",
    value: function fromJSON() {
      return new ReplaceStep(0, 0, Slice.empty);
    }
  }]);
  return AnalyticsStep;
}(Step);

/** Register this step with Prosemirror */
Step.jsonID(analyticsStepType, AnalyticsStep);

var analyticsPluginKey$1 = new PluginKey('analyticsPlugin');
function createPlugin(createAnalyticsEvent) {
  if (!createAnalyticsEvent) {
    // @ts-ignore
    return;
  }
  var hasRequiredPerformanceAPIs = isPerformanceAPIAvailable();
  return new Plugin({
    key: analyticsPluginKey$1,
    state: {
      init: function init() {
        return null;
      },
      apply: function apply(tr) {
        var meta = tr.getMeta(analyticsPluginKey$1);
        if (meta) {
          var _iterator = _createForOfIteratorHelper(meta),
            _step;
          try {
            var _loop = function _loop() {
              var analytics = _step.value;
              var payload = analytics.payload,
                channel = analytics.channel;

              // Measures how much time it takes to update the DOM after each ProseMirror document update
              // that has an analytics event.
              if (hasRequiredPerformanceAPIs && tr.docChanged && payload.action !== ACTION.INSERTED && payload.action !== ACTION.DELETED) {
                var measureName = "".concat(payload.actionSubject, ":").concat(payload.action, ":").concat(payload.actionSubjectId);
                measureRender(measureName, function (duration) {
                  fireAnalyticsEvent(createAnalyticsEvent)({
                    payload: extendPayload(payload, duration),
                    channel: channel
                  });
                });
              }
            };
            for (_iterator.s(); !(_step = _iterator.n()).done;) {
              _loop();
            }
          } catch (err) {
            _iterator.e(err);
          } finally {
            _iterator.f();
          }
        }
      }
    },
    appendTransaction: function appendTransaction(transactions, oldState, newState) {
      var analyticsEvents = transactions.map(function (tr) {
        return tr.getMeta(analyticsPluginKey$1);
      }).filter(function (analyticsMeta) {
        return !!analyticsMeta;
      }).reduce(function (allAnalyticsEvents, trAnalyticsEvents) {
        return [].concat(_toConsumableArray(allAnalyticsEvents), _toConsumableArray(trAnalyticsEvents));
      }, []);
      if (analyticsEvents.length > 0) {
        var tr = newState.tr.step(new AnalyticsStep(createAnalyticsEvent, analyticsEvents));

        // Preserve marks eg. if user clicked bold button with no selection
        if (newState.tr.storedMarks) {
          tr.setStoredMarks(newState.tr.storedMarks);
        }

        // Preserve active input rule
        // Appending this transaction will deactivate an input rule, as a transaction
        // with steps is interpreted as the doc changing
        // This is needed so undo of autoformatting works as expected, this is a special
        // case handled by prosemirror-inputrules plugin
        var activeInputRulePlugin = newState.plugins.find(function (plugin) {
          return plugin.spec.isInputRules && plugin.getState(newState);
        });
        if (activeInputRulePlugin) {
          var inputRuleState = activeInputRulePlugin.getState(newState);
          inputRuleState.transform.step(new AnalyticsStep(createAnalyticsEvent, analyticsEvents));
          tr.setMeta(activeInputRulePlugin, inputRuleState);
        }
        return tr;
      }
      return null;
    }
  });
}
var analyticsPlugin = function analyticsPlugin(createAnalyticsEvent) {
  return {
    name: 'analytics',
    pmPlugins: function pmPlugins() {
      return [{
        name: 'analyticsPlugin',
        plugin: function plugin() {
          return createPlugin(createAnalyticsEvent);
        }
      }];
    }
  };
};
function extendPayload(payload, duration) {
  return _objectSpread(_objectSpread({}, payload), {}, {
    attributes: _objectSpread(_objectSpread({}, payload.attributes), {}, {
      duration: duration
    }),
    eventType: EVENT_TYPE.OPERATIONAL
  });
}

var analyticsPluginKey = new PluginKey('analyticsPlugin');

var SELECTION_TYPE = /*#__PURE__*/function (SELECTION_TYPE) {
  SELECTION_TYPE["CURSOR"] = "cursor";
  SELECTION_TYPE["RANGED"] = "ranged";
  SELECTION_TYPE["GAP_CURSOR"] = "gapCursor";
  SELECTION_TYPE["NODE"] = "node";
  SELECTION_TYPE["CELL"] = "cell";
  return SELECTION_TYPE;
}({});
var SELECTION_POSITION = /*#__PURE__*/function (SELECTION_POSITION) {
  SELECTION_POSITION["START"] = "start";
  SELECTION_POSITION["MIDDLE"] = "middle";
  SELECTION_POSITION["END"] = "end";
  SELECTION_POSITION["LEFT"] = "left";
  SELECTION_POSITION["RIGHT"] = "right";
  return SELECTION_POSITION;
}({});

function getAnalyticsState(editorState) {
  return analyticsPluginKey.getState(editorState);
}
function getStateContext(state, payload) {
  if (payload.action === ACTION.INSERTED && payload.actionSubject === ACTION_SUBJECT.DOCUMENT && payload.attributes) {
    var _getSelectionType = getSelectionType(state),
      type = _getSelectionType.type,
      position = _getSelectionType.position;
    payload.attributes.selectionType = type;
    if (position) {
      payload.attributes.selectionPosition = position;
    }
    payload.attributes.insertLocation = findInsertLocation(state);
  }
  return payload;
}
function getSelectionType(state) {
  var selection = state.selection;
  var type;
  var position;
  if (selection instanceof GapCursorSelection) {
    type = SELECTION_TYPE.GAP_CURSOR;
    position = selection.side === Side.LEFT ? SELECTION_POSITION.LEFT : SELECTION_POSITION.RIGHT;
  } else if (selection instanceof CellSelection) {
    type = SELECTION_TYPE.CELL;
  } else if (selection instanceof NodeSelection) {
    type = SELECTION_TYPE.NODE;
  } else if (selection.from !== selection.to) {
    type = SELECTION_TYPE.RANGED;
  } else {
    type = SELECTION_TYPE.CURSOR;
    var from = selection.from,
      $from = selection.$from;
    if (from === $from.start()) {
      position = SELECTION_POSITION.START;
    } else if (from === $from.end()) {
      position = SELECTION_POSITION.END;
    } else {
      position = SELECTION_POSITION.MIDDLE;
    }
  }
  return {
    type: type,
    position: position
  };
}
function findInsertLocation(state) {
  var selection = state.selection;
  if (selection instanceof NodeSelection) {
    return selection.node.type.name;
  }
  if (selection instanceof CellSelection) {
    return state.schema.nodes.table.name;
  }

  // Text selection
  var parentNodeInfo = findParentNode(function (node) {
    return node.type !== state.schema.nodes.paragraph;
  })(state.selection);
  return parentNodeInfo ? parentNodeInfo.node.type.name : state.doc.type.name;
}
function addAnalytics(state, tr, payload) {
  var channel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : editorAnalyticsChannel;
  var createAnalyticsEvent = getAnalyticsState(state);
  payload = getStateContext(state, payload);
  if (createAnalyticsEvent) {
    var storedMarks = tr.storedMarks;
    tr.step(new AnalyticsStep(createAnalyticsEvent, [{
      payload: payload,
      channel: channel
    }], tr.selection.$from.pos) // We need to create the step based on a position, this prevent split history for relative changes.
    );
    // When you add a new step all the storedMarks are removed it
    if (storedMarks) {
      tr.setStoredMarks(storedMarks);
    }
  }
  return tr;
}
function withAnalytics(payload, channel) {
  return function (command) {
    return function (state, dispatch, view) {
      return command(state, function (tr) {
        if (dispatch) {
          if (payload instanceof Function) {
            var dynamicPayload = payload(state);
            if (dynamicPayload) {
              dispatch(addAnalytics(state, tr, dynamicPayload, channel));
            }
          } else {
            dispatch(addAnalytics(state, tr, payload, channel));
          }
        }
      }, view);
    };
  };
}
function ruleWithAnalytics(getPayload) {
  return function (rule) {
    // Monkey patching handler to add analytics
    var handler = rule.handler;
    rule.handler = function (state, match, start, end) {
      var tr = handler(state, match, start, end);
      if (tr) {
        var payload = getPayload(state, match, start, end);
        tr = addAnalytics(state, tr, payload);
      }
      return tr;
    };
    return rule;
  };
}
function getAnalyticsEventsFromTransaction(tr) {
  return tr.steps.filter(function (step) {
    return step instanceof AnalyticsStep;
  }).reduce(function (acc, step) {
    return [].concat(_toConsumableArray(acc), _toConsumableArray(step.analyticsEvents));
  }, []);
}

function preventDefault() {
  return function () {
    return true;
  };
}
function insertNewLine() {
  return function (state, dispatch) {
    var $from = state.selection.$from;
    var parent = $from.parent;
    var hardBreak = state.schema.nodes.hardBreak;
    if (hardBreak) {
      var hardBreakNode = hardBreak.createChecked();
      if (parent && parent.type.validContent(Fragment.from(hardBreakNode))) {
        if (dispatch) {
          dispatch(state.tr.replaceSelectionWith(hardBreakNode, false));
        }
        return true;
      }
    }
    if (state.selection instanceof TextSelection) {
      if (dispatch) {
        dispatch(state.tr.insertText('\n'));
      }
      return true;
    }
    return false;
  };
}
var insertNewLineWithAnalytics = withAnalytics({
  action: ACTION.INSERTED,
  actionSubject: ACTION_SUBJECT.TEXT,
  actionSubjectId: ACTION_SUBJECT_ID.LINE_BREAK,
  eventType: EVENT_TYPE.TRACK
})(insertNewLine());
function insertRule() {
  return function (state, dispatch) {
    var to = state.selection.to;
    var rule = state.schema.nodes.rule;
    if (rule) {
      var ruleNode = rule.create();
      if (dispatch) {
        dispatch(state.tr.insert(to + 1, ruleNode));
      }
      return true;
    }
    return false;
  };
}
var createNewParagraphAbove = function createNewParagraphAbove(state, dispatch) {
  var append = false;
  if (!canMoveUp(state) && canCreateParagraphNear(state)) {
    createParagraphNear(append)(state, dispatch);
    return true;
  }
  return false;
};
var createNewParagraphBelow = function createNewParagraphBelow(state, dispatch) {
  var append = true;
  if (!canMoveDown(state) && canCreateParagraphNear(state)) {
    createParagraphNear(append)(state, dispatch);
    return true;
  }
  return false;
};
function canCreateParagraphNear(state) {
  var $from = state.selection.$from;
  var node = $from.node($from.depth);
  var insideCodeBlock = !!node && node.type === state.schema.nodes.codeBlock;
  var isNodeSelection = state.selection instanceof NodeSelection;
  return $from.depth > 1 || isNodeSelection || insideCodeBlock;
}
function createParagraphNear() {
  var append = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  return function (state, dispatch) {
    var paragraph = state.schema.nodes.paragraph;
    if (!paragraph) {
      return false;
    }
    var insertPos;
    if (state.selection instanceof TextSelection) {
      if (topLevelNodeIsEmptyTextBlock(state)) {
        return false;
      }
      insertPos = getInsertPosFromTextBlock(state, append);
    } else {
      insertPos = getInsertPosFromNonTextBlock(state, append);
    }
    var tr = state.tr.insert(insertPos, paragraph.createAndFill());
    tr.setSelection(TextSelection.create(tr.doc, insertPos + 1));
    if (dispatch) {
      dispatch(tr);
    }
    return true;
  };
}
function getInsertPosFromTextBlock(state, append) {
  var _state$selection = state.selection,
    $from = _state$selection.$from,
    $to = _state$selection.$to;
  var pos;
  if (!append) {
    pos = $from.start(0);
  } else {
    pos = $to.end(0);
  }
  return pos;
}
function getInsertPosFromNonTextBlock(state, append) {
  var _state$selection2 = state.selection,
    $from = _state$selection2.$from,
    $to = _state$selection2.$to;
  var nodeAtSelection = state.selection instanceof NodeSelection && state.doc.nodeAt(state.selection.$anchor.pos);
  var isMediaSelection = nodeAtSelection && nodeAtSelection.type.name === 'mediaGroup';
  var pos;
  if (!append) {
    // The start position is different with text block because it starts from 0
    pos = $from.start($from.depth);
    // The depth is different with text block because it starts from 0
    pos = $from.depth > 0 && !isMediaSelection ? pos - 1 : pos;
  } else {
    pos = $to.end($to.depth);
    pos = $to.depth > 0 && !isMediaSelection ? pos + 1 : pos;
  }
  return pos;
}
function topLevelNodeIsEmptyTextBlock(state) {
  var topLevelNode = state.selection.$from.node(1);
  return topLevelNode.isTextblock && topLevelNode.type !== state.schema.nodes.codeBlock && topLevelNode.nodeSize === 2;
}
function createParagraphAtEnd() {
  return function (state, dispatch) {
    var doc = state.doc,
      tr = state.tr,
      nodes = state.schema.nodes;
    if (doc.lastChild && !(doc.lastChild.type === nodes.paragraph && doc.lastChild.content.size === 0)) {
      tr.insert(doc.content.size, nodes.paragraph.createAndFill());
    }
    tr.setSelection(TextSelection.create(tr.doc, tr.doc.content.size - 1));
    tr.scrollIntoView();
    if (dispatch) {
      dispatch(tr);
    }
    return true;
  };
}
var changeImageAlignment = function changeImageAlignment(align) {
  return function (state, dispatch) {
    var _state$selection3 = state.selection,
      from = _state$selection3.from,
      to = _state$selection3.to;
    var tr = state.tr;
    state.doc.nodesBetween(from, to, function (node, pos) {
      if (node.type === state.schema.nodes.mediaSingle) {
        tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
          layout: align === 'center' ? 'center' : "align-".concat(align)
        }));
      }
    });
    if (tr.docChanged && dispatch) {
      dispatch(tr.scrollIntoView());
      return true;
    }
    return false;
  };
};
var createToggleBlockMarkOnRange = function createToggleBlockMarkOnRange(markType, getAttrs, allowedBlocks) {
  return function (from, to, tr, state) {
    var markApplied = false;
    state.doc.nodesBetween(from, to, function (node, pos, parent) {
      if (!node.type.isBlock) {
        return false;
      }
      if ((!allowedBlocks || (Array.isArray(allowedBlocks) ? allowedBlocks.indexOf(node.type) > -1 : allowedBlocks(state.schema, node, parent))) && parent.type.allowsMarkType(markType)) {
        var oldMarks = node.marks.filter(function (mark) {
          return mark.type === markType;
        });
        var _prevAttrs = oldMarks.length ? oldMarks[0].attrs : undefined;
        var newAttrs = getAttrs(_prevAttrs, node);
        if (newAttrs !== undefined) {
          tr.setNodeMarkup(pos, node.type, node.attrs, node.marks.filter(function (mark) {
            return !markType.excludes(mark.type);
          }).concat(newAttrs === false ? [] : markType.create(newAttrs)));
          markApplied = true;
        }
      }
      return false;
    });
    return markApplied;
  };
};

/**
 * Toggles block mark based on the return type of `getAttrs`.
 * This is similar to ProseMirror's `getAttrs` from `AttributeSpec`
 * return `false` to remove the mark.
 * return `undefined for no-op.
 * return an `object` to update the mark.
 */
var toggleBlockMark = function toggleBlockMark(markType, getAttrs, allowedBlocks) {
  return function (state, dispatch) {
    var markApplied = false;
    var tr = state.tr;
    var toggleBlockMarkOnRange = createToggleBlockMarkOnRange(markType, getAttrs, allowedBlocks);
    if (state.selection instanceof CellSelection) {
      state.selection.forEachCell(function (cell, pos) {
        markApplied = toggleBlockMarkOnRange(pos, pos + cell.nodeSize, tr, state);
      });
    } else {
      var _state$selection4 = state.selection,
        from = _state$selection4.from,
        to = _state$selection4.to;
      markApplied = toggleBlockMarkOnRange(from, to, tr, state);
    }
    if (markApplied && tr.docChanged) {
      if (dispatch) {
        dispatch(tr.scrollIntoView());
      }
      return true;
    }
    return false;
  };
};
var clearEditorContent = function clearEditorContent(state, dispatch) {
  var tr = state.tr;
  tr.replace(0, state.doc.nodeSize - 2);
  tr.setSelection(Selection.atStart(tr.doc));
  if (dispatch) {
    dispatch(tr);
    return true;
  }
  return false;
};

export { ACTION as A, EVENT_TYPE as E, INPUT_METHOD as I, ACTION_SUBJECT as a, analyticsEventKey as b, createParagraphAtEnd as c, ACTION_SUBJECT_ID as d, clearEditorContent as e, fireAnalyticsEvent as f, getAnalyticsEventsFromTransaction as g, changeImageAlignment as h, insertNewLineWithAnalytics as i, createNewParagraphAbove as j, createNewParagraphBelow as k, addAnalytics as l, createParagraphNear as m, createToggleBlockMarkOnRange as n, insertRule as o, preventDefault as p, analyticsPlugin as q, ruleWithAnalytics as r, insertNewLine as s, toggleBlockMark as t, withAnalytics as w };
