"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.popupWithNestedElement = exports.getSelectionAncestorDOM = exports.getPopupContainerFromEditorView = exports.getNodeQuery = exports.containsPopupWithNestedElement = void 0;
/**
 * Finds the direct child of the ProseMirror root element that contains the current selection.
 *
 * Starting from the DOM node at the selection position, this function walks up the DOM tree
 * until it reaches the ProseMirror root, then returns the last element before the root
 * (i.e., the second top-level ancestor).
 *
 * This is useful for attaching MutationObservers to the narrowest subtree that contains
 * the selection, while still capturing all relevant mutations within that branch.
 *
 * @param editorView - The ProseMirror EditorView instance
 * @returns The direct child of PM root containing the selection, or null if not found
 */
var getSelectionAncestorDOM = exports.getSelectionAncestorDOM = function getSelectionAncestorDOM(editorView) {
  if (!editorView) {
    return null;
  }
  var pmDom = editorView.dom;
  var selection = editorView.state.selection;

  // nodeDOM can return null when editor loses focus (e.g. toolbar click) or for certain positions.
  // Fall back to domAtPos which resolves the DOM node at the given position.
  var currentNode = editorView.nodeDOM(selection.from);
  if (!currentNode) {
    try {
      var _editorView$domAtPos = editorView.domAtPos(selection.from),
        node = _editorView$domAtPos.node;
      currentNode = node instanceof HTMLElement ? node : node.parentElement;
    } catch (_unused) {
      return null;
    }
  }
  var lastValidAncestor = currentNode;
  while (currentNode instanceof HTMLElement && currentNode !== pmDom) {
    lastValidAncestor = currentNode;
    currentNode = currentNode.parentElement;
  }
  return lastValidAncestor instanceof HTMLElement ? lastValidAncestor : null;
};

/**
 * Checks if a given node contains a popup with a nested element identified by a specific test ID.
 *
 * @param node - The node to check.
 * @param nestedElementQuery - The query to look for the nested element.
 * @returns True if the node contains the popup, false otherwise.
 */
var containsPopupWithNestedElement = exports.containsPopupWithNestedElement = function containsPopupWithNestedElement(node, nestedElementQuery) {
  if (!(node instanceof HTMLElement)) {
    return false;
  }

  // Check if node itself has the popup attribute and contains the element matching the nestedElementQuery
  if (node.matches('[data-editor-popup="true"]')) {
    return !!node.querySelector(nestedElementQuery);
  }

  // Check if any direct child with popup attribute contains the element matching the nestedElementQuery
  return !!node.querySelector(":scope > [data-editor-popup=\"true\"] ".concat(nestedElementQuery));
};

/**
 * Returns the popup with a nested element identified by a specific test ID if it exists.
 *
 * @param node - The node to check.
 * @param nestedElementQuery - The query to look for the nested element.
 * @returns Element if the node contains the popup, undefined otherwise.
 */
var popupWithNestedElement = exports.popupWithNestedElement = function popupWithNestedElement(node, nestedElementQuery) {
  if (!(node instanceof HTMLElement)) {
    return undefined;
  }

  // Check if node itself has the popup attribute and contains the element matching the nestedElementQuery
  if (node.matches('[data-editor-popup="true"]')) {
    return node.querySelector(nestedElementQuery);
  }

  // Check if any direct child with popup attribute contains the element matching the nestedElementQuery
  return node.querySelector(":scope > [data-editor-popup=\"true\"] ".concat(nestedElementQuery));
};

/**
 * Searches for the popup container element relative to the provided editor view element.
 *
 * @param editorViewEl - The editor view HTMLElement.
 * @returns The popup container HTMLElement if found, otherwise undefined.
 */
var getPopupContainerFromEditorView = exports.getPopupContainerFromEditorView = function getPopupContainerFromEditorView(editorViewEl) {
  var editorContentArea = editorViewEl === null || editorViewEl === void 0 ? void 0 : editorViewEl.closest('.ak-editor-content-area');
  var pluginsComponentsWrapper = editorContentArea === null || editorContentArea === void 0 ? void 0 : editorContentArea.querySelector(':scope > [data-testid="plugins-components-wrapper"]');
  return pluginsComponentsWrapper || undefined;
};

/**
 * Checks if a node matches or contains the node given by the provided query css selector
 *
 * @param query - CSS selector string
 * @returns true if node matches or contains query or false otherwise
 */
var getNodeQuery = exports.getNodeQuery = function getNodeQuery(query) {
  return function (node) {
    if (!node || !(node instanceof Element)) {
      return false;
    }
    return node.matches(query) || node.querySelector(query) !== null;
  };
};