import { createElement } from "react";
import { createEditor, Transforms, Editor, Element, Range, Path } from "slate";
import { withHistory } from "slate-history";
import { withReact } from "slate-react";
import { ContemberEditor } from "../ContemberEditor/index.js";
import { DefaultElement } from "./DefaultElement.js";
import { overrideDeleteBackward } from "./overrides/overrideDeleteBackward.js";
import { withPaste } from "./overrides/withPaste.js";
const createEditorWithEssentials = (defaultElementType) => {
  const underlyingEditor = withHistory(withReact(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);
      Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]), {
        at: targetPath,
        select: true
      });
    },
    canToggleMarks: () => true,
    canToggleElement: () => true,
    hasMarks: (marks2) => ContemberEditor.hasMarks(editor, marks2),
    isElementActive: (elementType, suchThat) => {
      return elements.get(elementType)?.isActive?.({ editor, suchThat }) ?? Array.from(Editor.nodes(editor, {
        match: (node) => Element.isElement(node) && 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) {
        ContemberEditor.removeMarks(editor, marks2);
        return false;
      }
      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 (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) => ContemberEditor.serializeNodes(editor, nodes, errorMessage),
    deserializeNodes: (serializedNodes, errorMessage) => ContemberEditor.permissivelyDeserializeNodes(editor, serializedNodes, errorMessage),
    upgradeFormatBySingleVersion: (node, oldVersion) => {
      if (Element.isElement(node)) {
        return {
          ...node,
          children: node.children.map((child) => editor.upgradeFormatBySingleVersion(child, oldVersion))
        };
      }
      return node;
    },
    renderElement: (props) => {
      return createElement(elements.get(props.element.type)?.render ?? DefaultElement, props);
    },
    renderLeafChildren: (props) => props.children,
    renderLeaf: (props) => {
      let el = 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) {
            el = markerEl;
          }
        }
      }
      return el;
    },
    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 && Range.isCollapsed(selection)) {
        const voidEntry = 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" ? Editor.point(editor, Path.next(nodePath), {
            edge: "start"
          }) : Editor.point(editor, Path.previous(nodePath), {
            edge: "end"
          });
          Transforms.select(editor, adjacentPoint);
        }
      }
    },
    onFocus: () => {
    },
    onBlur: () => {
    },
    normalizeNode: ([node, path]) => {
      if (Editor.isEditor(node) && node.children.length === 0) {
        Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]));
      }
      if (!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(editor);
  withPaste(editor);
  return editor;
};
export { createEditorWithEssentials };
//# sourceMappingURL=createEditorWithEssentials.js.map
