"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const react = require("react");
const Slate = require("slate");
const slateHistory = require("slate-history");
const slateReact = require("slate-react");
const index = require("../ContemberEditor/index.cjs");
const DefaultElement = require("./DefaultElement.cjs");
const overrideDeleteBackward = require("./overrides/overrideDeleteBackward.cjs");
const withPaste = require("./overrides/withPaste.cjs");
const createEditorWithEssentials = (defaultElementType) => {
  const underlyingEditor = slateHistory.withHistory(slateReact.withReact(Slate.createEditor()));
  const editor = underlyingEditor;
  const { normalizeNode, isInline, isVoid } = editor;
  const elements = /* @__PURE__ */ new Map();
  const marks = /* @__PURE__ */ new Map();
  Object.assign(editor, {
    formatVersion: 1,
    defaultElementType,
    isDefaultElement: (element) => "type" in element && element.type === defaultElementType,
    createDefaultElement: (children) => ({
      type: defaultElementType,
      children
    }),
    insertBetweenBlocks: ([element, path], edge) => {
      const edgeOffset = edge === "before" ? 0 : 1;
      const targetPath = path.slice(0, -1).concat(path[path.length - 1] + edgeOffset);
      Slate.Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]), {
        at: targetPath,
        select: true
      });
    },
    canToggleMarks: () => true,
    canToggleElement: () => true,
    hasMarks: (marks2) => index.ContemberEditor.hasMarks(editor, marks2),
    // TODO in the following function, we need to conditionally trim the selection so that it doesn't potentially
    // 	include empty strings at the edges of top-level elements.
    isElementActive: (elementType, suchThat) => {
      return elements.get(elementType)?.isActive?.({ editor, suchThat }) ?? Array.from(Slate.Editor.nodes(editor, {
        match: (node) => Slate.Element.isElement(node) && index.ContemberEditor.isElementType(node, elementType, suchThat),
        voids: false
      })).length > 0;
    },
    acceptsAttributes: (elementType, suchThat) => {
      return elements.get(elementType)?.acceptsAttributes?.({ editor, suchThat }) ?? false;
    },
    toggleMarks: (marks2) => {
      if (!editor.canToggleMarks(marks2)) {
        return;
      }
      const isActive = editor.hasMarks(marks2);
      if (isActive) {
        index.ContemberEditor.removeMarks(editor, marks2);
        return false;
      }
      index.ContemberEditor.addMarks(editor, marks2);
      return true;
    },
    toggleElement: (elementType, suchThat) => {
      elements.get(elementType)?.toggleElement?.({
        editor,
        suchThat
      });
    },
    isInline: (element) => {
      return elements.get(element.type)?.isInline ?? isInline(element);
    },
    isVoid: (element) => {
      const elIsVoid = elements.get(element.type)?.isVoid;
      if (elIsVoid === void 0) {
        return isVoid(element);
      }
      if (typeof elIsVoid === "boolean") {
        return elIsVoid;
      }
      return elIsVoid({ editor, element });
    },
    canContainAnyBlocks: (element) => {
      if (Slate.Editor.isEditor(element)) {
        return true;
      }
      return !editor.isInline(element) && !editor.isVoid(element) && (elements.has(element.type) ? elements.get(element.type).canContainAnyBlocks ?? false : true);
    },
    serializeNodes: (nodes, errorMessage) => index.ContemberEditor.serializeNodes(editor, nodes, errorMessage),
    deserializeNodes: (serializedNodes, errorMessage) => index.ContemberEditor.permissivelyDeserializeNodes(editor, serializedNodes, errorMessage),
    upgradeFormatBySingleVersion: (node, oldVersion) => {
      if (Slate.Element.isElement(node)) {
        return {
          ...node,
          children: node.children.map((child) => editor.upgradeFormatBySingleVersion(child, oldVersion))
        };
      }
      return node;
    },
    renderElement: (props) => {
      return react.createElement(elements.get(props.element.type)?.render ?? DefaultElement.DefaultElement, props);
    },
    renderLeafChildren: (props) => props.children,
    renderLeaf: (props) => {
      let el = react.createElement("span", props.attributes, editor.renderLeafChildren(props));
      for (const [, mark] of marks) {
        if (props.leaf[mark.type] === true) {
          const markerEl = mark.render({ ...props, children: el });
          if (markerEl !== null) {
            if (!react.isValidElement(markerEl)) {
              throw new Error(`Mark plugin ${mark.type} returned a non-React element`);
            }
            el = markerEl;
          }
        }
      }
      return el;
    },
    // Just noop functions so that other plugins can safely bubble-call
    onDOMBeforeInput: () => {
    },
    onKeyDown: (e) => {
      for (const [, mark] of marks) {
        if (mark.isHotKey(e.nativeEvent)) {
          editor.toggleMarks({ [mark.type]: true });
          e.preventDefault();
          return;
        }
      }
      if (e.key !== "Delete" && e.key !== "Backspace") {
        return;
      }
      const selection = editor.selection;
      if (selection && Slate.Range.isCollapsed(selection)) {
        const voidEntry = Slate.Editor.void(editor, {
          at: selection,
          mode: "lowest",
          voids: true
        });
        if (!voidEntry) {
          return;
        }
        const [node, nodePath] = voidEntry;
        if (editor.isInline(node)) {
          const adjacentPoint = e.key === "Backspace" ? Slate.Editor.point(editor, Slate.Path.next(nodePath), {
            edge: "start"
          }) : Slate.Editor.point(editor, Slate.Path.previous(nodePath), {
            edge: "end"
          });
          Slate.Transforms.select(editor, adjacentPoint);
        }
      }
    },
    onFocus: () => {
    },
    onBlur: () => {
    },
    normalizeNode: ([node, path]) => {
      if (Slate.Editor.isEditor(node) && node.children.length === 0) {
        Slate.Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]));
      }
      if (!Slate.Element.isElement(node)) {
        normalizeNode([node, path]);
        return;
      }
      let defaultPrevented = false;
      elements.get(node.type)?.normalizeNode?.({
        element: node,
        path,
        editor,
        preventDefault: () => {
          defaultPrevented = true;
        }
      });
      if (!defaultPrevented) {
        normalizeNode([node, path]);
      }
    },
    registerElement: (plugin) => {
      elements.set(plugin.type, plugin);
    },
    registerMark: (plugin) => {
      marks.set(plugin.type, plugin);
    }
  });
  overrideDeleteBackward.overrideDeleteBackward(editor);
  withPaste.withPaste(editor);
  return editor;
};
exports.createEditorWithEssentials = createEditorWithEssentials;
//# sourceMappingURL=createEditorWithEssentials.cjs.map
