"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var gap_spacer_plugin_exports = {};
__export(gap_spacer_plugin_exports, {
  createSpacer: () => createSpacer,
  gapSpacer: () => gapSpacer
});
module.exports = __toCommonJS(gap_spacer_plugin_exports);
var import_keymap = require("./../../tiptap/pm/keymap.js");
var import_model = require("./../../tiptap/pm/model.js");
var import_state = require("./../../tiptap/pm/state.js");
var import_view = require("./../../tiptap/pm/view.js");
var import_is_inline_text_only = require("../transaction-predicates/is-inline-text-only.js");
var import_only_changes_unrelated_attrs = require("../transaction-predicates/only-changes-unrelated-attrs.js");
var import_gap_cursor_selection = require("./gap-cursor-selection.js");
var import_gap_spacer_html = require("./gap-spacer-component/gap-spacer-html.js");
var import_gap_spacer_styles_scss = __toESM(require("./gap-spacer-component/gap-spacer-styles-scss.js"));
var import_gap_spacer_nodes = require("./gap-spacer-nodes.js");
const gapSpacerPluginKey = new import_state.PluginKey("gap-spacer");
const RELEVANT_ATTRS = /* @__PURE__ */ new Set(["containerData"]);
const getFocusedPos = (state) => state.selection instanceof import_gap_cursor_selection.GapCursor ? state.selection.head : null;
const collectGapPositions = (doc) => {
  const positions = [];
  const seen = /* @__PURE__ */ new Set();
  const addPosition = (pos) => {
    if (!seen.has(pos)) {
      seen.add(pos);
      positions.push(pos);
    }
  };
  doc.descendants((node, pos) => {
    addPosition(pos);
    addPosition(pos + node.nodeSize);
  });
  return positions;
};
const computeGapSpacerPositions = (doc) => {
  const positions = [];
  const candidatePositions = collectGapPositions(doc);
  for (const pos of candidatePositions) {
    const $pos = doc.resolve(pos);
    if (!import_gap_cursor_selection.GapCursor.valid($pos)) {
      continue;
    }
    const bothFullWidth = (0, import_gap_spacer_nodes.isBetweenFullWidthNodes)($pos.nodeBefore, $pos.nodeAfter);
    const collapsed = (0, import_gap_spacer_nodes.isCollapsedBetween)(
      $pos.nodeBefore?.type.name,
      $pos.nodeAfter?.type.name,
      $pos.parent?.type.name,
      { bothFullWidth }
    );
    const betweenFloated = (0, import_gap_spacer_nodes.isBetweenFloatedNodes)($pos.nodeBefore, $pos.nodeAfter);
    const isFirstPosition = !$pos.nodeBefore && $pos.depth === 0;
    const hasTopOverflow = (0, import_gap_spacer_nodes.needsTopMarginForPmNode)($pos.nodeAfter);
    positions.push({
      pos,
      collapsed,
      betweenFloated,
      needsTopMargin: isFirstPosition && hasTopOverflow
    });
  }
  return positions;
};
const gapSpacer = (t) => {
  return new import_state.Plugin({
    key: gapSpacerPluginKey,
    state: {
      init: (_, state) => {
        const doc = state.doc;
        const positions = computeGapSpacerPositions(doc);
        const focusedPos = getFocusedPos(state);
        return {
          positions,
          focusedPos,
          decorations: buildGapSpacerDecorationSet({
            doc,
            t,
            positions,
            focusedPos
          })
        };
      },
      apply: (tr, prev, _oldState, newState) => {
        const newDoc = newState.doc;
        const newFocusedPos = getFocusedPos(newState);
        let nextPositions = prev.positions;
        let positionsChanged = false;
        if (tr.docChanged) {
          if ((0, import_is_inline_text_only.isInlineTextOnly)(tr)) {
            nextPositions = prev.positions.map((position) => ({
              ...position,
              pos: tr.mapping.map(position.pos)
            }));
            positionsChanged = true;
          } else if (!(0, import_only_changes_unrelated_attrs.onlyChangesUnrelatedAttrs)(tr, RELEVANT_ATTRS)) {
            nextPositions = computeGapSpacerPositions(newDoc);
            positionsChanged = true;
          }
        }
        if (!positionsChanged && prev.focusedPos === newFocusedPos) {
          return prev;
        }
        return {
          positions: nextPositions,
          focusedPos: newFocusedPos,
          decorations: buildGapSpacerDecorationSet({
            doc: newDoc,
            t,
            positions: nextPositions,
            focusedPos: newFocusedPos
          })
        };
      }
    },
    props: {
      decorations: (state) => {
        const pluginState = gapSpacerPluginKey.getState(state);
        return pluginState?.decorations ?? null;
      },
      handleKeyDown,
      handleDOMEvents: {
        beforeinput
      }
    }
  });
};
const arrow = (axis, dir) => {
  const direction = axis === "vertical" ? dir > 0 ? "down" : "up" : dir > 0 ? "right" : "left";
  return function(state, dispatch, view) {
    const sel = state.selection;
    let $start = dir > 0 ? sel.$to : sel.$from;
    let mustMove = sel.empty;
    if (sel instanceof import_state.TextSelection) {
      if (!view.endOfTextblock(direction) || $start.depth === 0) {
        return false;
      }
      mustMove = false;
      $start = state.doc.resolve(dir > 0 ? $start.after() : $start.before());
    }
    const $found = import_gap_cursor_selection.GapCursor.findGapCursorFrom($start, dir, mustMove);
    if (!$found) {
      return false;
    }
    if (dispatch) {
      dispatch(state.tr.setSelection(new import_gap_cursor_selection.GapCursor($found)));
    }
    return true;
  };
};
const handleKeyDown = (0, import_keymap.keydownHandler)({
  ArrowLeft: arrow("horizontal", -1),
  ArrowRight: arrow("horizontal", 1),
  ArrowUp: arrow("vertical", -1),
  ArrowDown: arrow("vertical", 1)
});
const beforeinput = (view, event) => {
  if (event.inputType !== "insertCompositionText" || !(view.state.selection instanceof import_gap_cursor_selection.GapCursor)) {
    return false;
  }
  const { $from } = view.state.selection;
  const insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text);
  if (!insert) {
    return false;
  }
  let frag = import_model.Fragment.empty;
  for (let i = insert.length - 1; i >= 0; i--) {
    frag = import_model.Fragment.from(insert[i].createAndFill(null, frag));
  }
  const tr = view.state.tr.replace($from.pos, $from.pos, new import_model.Slice(frag, 0, 0));
  tr.setSelection(import_state.TextSelection.near(tr.doc.resolve($from.pos + 1)));
  view.dispatch(tr);
  return false;
};
const buildGapSpacerDecorationSet = ({
  doc,
  t,
  positions,
  focusedPos
}) => {
  if (positions.length === 0) {
    return null;
  }
  const decorations = positions.map(
    ({ pos, collapsed, betweenFloated, needsTopMargin: topMargin }) => createSpacer({
      pos,
      isFocused: focusedPos === pos,
      t,
      collapsed,
      betweenFloated,
      needsTopMargin: topMargin
    })
  );
  return import_view.DecorationSet.create(doc, decorations);
};
const createSpacer = ({
  pos,
  isFocused = false,
  t,
  collapsed,
  betweenFloated,
  needsTopMargin: topMargin = false
}) => import_view.Decoration.widget(
  pos,
  (view) => {
    const container = document.createElement("div");
    if (betweenFloated) {
      container.className = import_gap_spacer_styles_scss.default.betweenFloated;
    }
    const gapSpacerElement = (0, import_gap_spacer_html.createGapSpacerElement)({
      collapsed,
      isFocused,
      tooltipContent: t("GapSpacer_Tooltip"),
      needsTopMargin: topMargin,
      onClick: (event) => {
        event?.preventDefault();
        event?.stopImmediatePropagation();
      },
      onMouseDown: (event) => {
        event?.preventDefault();
        event?.stopImmediatePropagation();
        const { state, dispatch } = view;
        const paragraph = state.schema.nodes.PARAGRAPH;
        const tr = state.tr.insert(pos, paragraph.create());
        tr.setSelection(import_state.TextSelection.create(tr.doc, pos, pos + 1));
        dispatch(tr);
      }
    });
    container.appendChild(gapSpacerElement);
    return container;
  },
  {
    key: `gapspacer-${pos}-${isFocused ? "focused" : "unfocused"}-${collapsed ? "collapsed" : "expanded"}-${betweenFloated ? "floated" : "static"}-${topMargin ? "topMargin" : "noTopMargin"}`
  }
);
//# sourceMappingURL=gap-spacer-plugin.js.map
