import { U as UpdateCursorPositionAction, E as ElementToDTOStrategy, h as htmlElementToAnnotationGenerator, R as RTEListItemBlock } from './content-state-cc491c0b.js';
import { y as ModifyContentAction, c as ActionHandleStrategyRegistry, a as RTETextNode, M as ModifyContentActionType, A as ActionHandleStrategy, p as CustomAttributeAnnotation, R as RTETextBlock } from './code-block-363a1708.js';
import './global-slimmer-registry-0a7aa308.js';
import './ui-6dd51115.js';
import './type-guard-5e7bf13e.js';
import './internal-translation-controller-0776fa78.js';
import { V as VegaRTEToolbarButtonRenderer, a as VegaRTEExtensionRenderer, b as VegaRTEExtension } from './base-toolbar-button-renderer-74c2b49e.js';
import './internal-icon-manager-d55582f2.js';
import './vega-nonce-manager-209a4c0a.js';
import './function-extension-496aca45.js';
import './table-extension-8010b08c.js';
import { g as generateUUID } from './misc-9fdbcfbb.js';
import { c as cleanObject } from './object-0c277f57.js';

/**
 * Action to insert a token node at a specified range in the Rich Text Editor.
 *
 * @example block.apply(new InsertTokenNodeAction(rteRange, tokenNode));
 */
class InsertTokenNodeAction extends ModifyContentAction {
  constructor(rteRange, token) {
    super();
    this.type = 'INSERT_TOKEN_NODE';
    this.rteRange = null;
    this.actionHandleResult = false;
    this.rteRange = rteRange;
    this.token = token;
  }
}

/**
 * Renderer for the token toolbar button in the Vega Rich Text Editor.
 */
class RTETokenToolbarButtonRenderer extends VegaRTEToolbarButtonRenderer {
  constructor(tokenList) {
    super();
    this.tokenList = [];
    this.tokenList = tokenList;
  }
  /**
   * Renders the token toolbar button.
   *
   * @param {VegaRTECreateElementFunction} createElement Function to create elements in the rich text editor.
   * @param {VegaRTEToolbarRenderContext} editorContext The render context for the editor.
   * @returns {VegaRTERenderResult} Token toolbar button.
   */
  render(createElement, editorContext) {
    return this.renderDropdown(createElement, editorContext, {}, [
      this.renderButton(createElement, editorContext, { label: 'Tokens', showArrowIcon: true }),
      this.renderDropdownListTemplate(createElement, this.tokenList),
    ]);
  }
  /**
   * Checks if the token toolbar button is disabled.
   *
   * @param {VegaRTEToolbarRenderContext} editorContext The render context for the editor.
   * @returns {boolean} True if the button is disabled, false otherwise.
   */
  isDisabled(editorContext) {
    const context = this.getExtensionContext(editorContext.host);
    if (context) {
      const { host, getSelectedNodes } = context;
      const [startNode] = getSelectedNodes();
      return startNode
        ? host.disabled ||
          !ActionHandleStrategyRegistry.canHandle('INSERT_TOKEN_NODE', startNode.parent)
        : host.disabled;
    }
    return false;
  }
  /* istanbul ignore next */
  /**
   * Handles the button click event. No need this method for token button.
   *
   * @param {VegaRTEToolbarRenderContext} editorContext - The render context for the editor.
   */
  handleButtonClick(editorContext) {
  }
  /**
   * Handles the token item click event from the dropdown.
   *
   * @param {string} itemKey - The key of the clicked token item.
   * @param {VegaRTEToolbarRenderContext} editorContext - The render context for the editor.
   */
  handleDropdownClick(itemKey, editorContext) {
    const token = this.getListItemByKey(this.tokenList, itemKey);
    const { rteRange } = editorContext;
    const { startNode } = rteRange;
    if (startNode && startNode.parent) {
      const action = new InsertTokenNodeAction(rteRange, token);
      startNode.parent.apply(action);
      if (action.actionHandleResult) {
        this.flushEditorUI(editorContext);
      }
    }
  }
  /**
   * Refreshes the editor UI.
   *
   * @param {VegaRTEToolbarRenderContext} editorContext - The render context for the editor.
   */
  flushEditorUI(editorContext) {
    const context = this.getExtensionContext(editorContext.host);
    if (context) {
      const { host, flushValue } = context;
      flushValue(host.value);
    }
  }
}

/**
 * Token node for the Vega Rich Text Editor.
 */
class RTETokenNode extends RTETextNode {
  constructor(id, token, text, parentBlock, annotations) {
    super(id, text, parentBlock, annotations);
    this.type = 'token';
    this.token = token;
    this.text = text;
  }
  /**
   * @inheritDoc
   */
  static from(value, parent) {
    const node = new RTETokenNode(value.id, value.token, value.text, parent);
    if (value.annotations) {
      node.annotationMap = this.generateTextAnnotationMap(value.annotations);
    }
    return node;
  }
  /**
   * Converts the token node to a JSON representation.
   *
   * @returns {VegaRTETokenNode} - The JSON representation of the token node.
   */
  toJSON() {
    const json = super.toJSON();
    return Object.assign({ id: this.id, type: this.type, text: this.text, token: this.token }, (json.annotations ? { annotations: json.annotations } : {}));
  }
  /**
   * Determines if the token node is content editable.
   *
   * @returns {boolean} - Always returns false for token nodes.
   */
  isContentEditable() {
    return false;
  }
  /**
   * Clones the token node.
   *
   * @param {RTETextBlock} parent - The parent block for the cloned node.
   * @returns {RTETokenNode} - The cloned token node.
   */
  clone(parent) {
    return new RTETokenNode(this.id, this.token, this.text, parent, this.annotationMap);
  }
  /**
   * Converts the token node to an HTML representation.
   *
   * @returns {string} - The HTML representation of the token node.
   */
  toHtml() {
    return `<span class="token" contenteditable="false" template-token-key="${this.token}" token-key="${this.token}"${super.generateAttributeString()}>${this.text}</span>`;
  }
}

/**
 * Token node renderer for the rich text editor.
 */
class RTETokenNodeRenderer extends VegaRTEExtensionRenderer {
  /**
   * Renders the token node as a DOM element.
   *
   * @param {VegaRTECreateElementFunction} createElement - The function to create a DOM element.
   * @param {RTETokenNode} node - The token node to render.
   * @param {RTERenderContext} editorContent - The editor content context.
   * @returns {VegaRTERenderResult} - The rendered DOM element.
   */
  doRender(createElement, node, editorContent) {
    const { id, token } = node;
    return createElement('span', Object.assign(Object.assign({ 'key': id, 'template-token-key': token, 'token-key': token, 'contenteditable': 'false', 'style': node.getStyles(), 'class': `token ${node.getClasses()}` }, this.additionalAttributes(node)), { 'ref': this.useRef(node), 
      // eslint-disable-next-line jsdoc/require-jsdoc
      'onClick': (event) => {
        event.preventDefault();
        if (editorContent && editorContent.editable !== false) {
          this.handleTokenElementClick(event, node, editorContent.host);
        }
      } }), node.text);
  }
  /**
   * Override to inject RTE scope styles for the token node.
   *
   * @returns {string} The CSS styles for the token node.
   */
  injectRTEScopeStyles() {
    return `span[token-key]{padding: 0 2px; margin: 0 1px; background-color: rgba(var(--v-bg-status-info, 205,209,211))}`;
  }
  /**
   * Handle the click event on the token element.
   *
   * @typedef HTMLVegaRichTextEditorElement - The type definition for the rich text editor host element.
   * @param {MouseEvent} event - The click event.
   * @param {RTETokenNode} node - The token node that was clicked.
   * @param {HTMLVegaRichTextEditorElement} [richTextEditor] - The rich text editor host element.
   */
  handleTokenElementClick(event, node, richTextEditor) {
    event.preventDefault();
    if (richTextEditor) {
      richTextEditor.value.apply(new UpdateCursorPositionAction(node, undefined, true));
    }
  }
  /**
   * Additional attributes for the token node.
   *
   * @param {RTETokenNode} node - The token node.
   * @returns {Record<string, string>} Additional attributes
   */
  additionalAttributes(node) {
    const annotation = node.getCustomAttributesAnnotation();
    let result = { wrapped: 'true' };
    if (annotation) {
      result = Object.assign(Object.assign({}, result), annotation.render());
    }
    return result;
  }
}

/**
 * Insert a new children to the nearest position of the parent container
 *
 * @example parent.apply(new InsertNodeToNearestRoot(rteRange, nodeToBeInserted))
 */
class InsertNodeToNearestRootAction extends ModifyContentAction {
  constructor(rteRange, nodeToBeInserted) {
    super();
    this.type = ModifyContentActionType.INSERT_NODE_TO_NEAREST_ROOT;
    this.rteRange = rteRange;
    this.nodeToBeInserted = nodeToBeInserted;
  }
}

/**
 * Strategy to handle the insertion of a token node into the nearest root block.
 */
class InsertTokenNodeStrategy extends ActionHandleStrategy {
  /**
   * @inheritDoc
   */
  handleAction(action, block) {
    const { rteRange, token } = action;
    if (rteRange && rteRange.startNode) {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      const { key, label, customAttrs = { wrapped: 'true' } } = token;
      const tokenNode = new RTETokenNode(generateUUID(), key, label, block);
      tokenNode.annotationMap.set('CUSTOM_ATTRIBUTE', new CustomAttributeAnnotation(customAttrs));
      block.apply(new InsertNodeToNearestRootAction(rteRange, tokenNode));
      action.actionHandleResult = true;
    }
  }
}

var __rest = (undefined && undefined.__rest) || function (s, e) {
  var t = {};
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
    t[p] = s[p];
  if (s != null && typeof Object.getOwnPropertySymbols === "function")
    for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
      if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
        t[p[i]] = s[p[i]];
    }
  return t;
};
/**
 * Strategy to convert <span class="token" token-key="...">...</span> to a token node
 */
class SpanToTokenNodeStrategy extends ElementToDTOStrategy {
  /**
   * @inheritDoc
   */
  canHandle(elementsArray, currentIndex) {
    const element = elementsArray[currentIndex];
    if (element.nodeName === 'SPAN' &&
      element.classList.contains('token') &&
      element.hasAttribute('token-key')) {
      return 1;
    }
    return 0;
  }
  /**
   * @inheritDoc
   */
  handle(elementsArray) {
    const element = elementsArray[0];
    const tokenKey = element.getAttribute('token-key');
    const text = element.textContent;
    const annotations = htmlElementToAnnotationGenerator.generate(RTETextNode, element);
    // Exclude customAttribute and customClass from annotations
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { customAttribute, customClass } = annotations, restAnnotations = __rest(annotations, ["customAttribute", "customClass"]);
    return {
      id: generateUUID(),
      type: 'token',
      token: tokenKey,
      text,
      annotations: Object.assign(Object.assign({}, restAnnotations), { customAttribute: this.createCustomAttrs(customAttribute) }),
    };
  }
  /**
   * @inheritDoc
   */
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  appendChildBlocks() { }
  /**
   * @inheritDoc
   */
  shouldProceedToElementChildren() {
    return false;
  }
  /**
   * Creates custom attributes record from the given custom attribute object, clean some fixed attributes.
   *
   * @param {Record<string, string>} customAttribute - The custom attribute object
   * @returns {Record<string, string>} The processed custom attributes
   */
  createCustomAttrs(customAttribute) {
    const result = Object.assign(Object.assign({}, customAttribute), { 'contenteditable': null, 'template-token-key': null, 'token-key': null, 'wrapped': customAttribute.wrapped === 'false' ? 'false' : 'true' });
    return cleanObject(result);
  }
}

const spanToTokenNodeStrategy = new SpanToTokenNodeStrategy();
/**
 * Vega Rich Text Editor Token Extension
 */
class VegaRTETokenExtension extends VegaRTEExtension {
  constructor(tokenList = []) {
    super();
    this.tokenRenderer = new RTETokenNodeRenderer();
    this.registerNode('token', RTETokenNode);
    this.registerRenderer('token', this.tokenRenderer);
    this.tokenToolbarButtonRenderer = new RTETokenToolbarButtonRenderer(tokenList);
    this.registerToolbarButtonRenderer('token', this.tokenToolbarButtonRenderer);
    this.registerElementToNodeDTOClassStrategy(spanToTokenNodeStrategy);
  }
}
(() => {
  const insertTokenNodeStrategy = new InsertTokenNodeStrategy();
  VegaRTEExtension.registerActionHandleStrategy(RTETextBlock.name, 'INSERT_TOKEN_NODE', insertTokenNodeStrategy);
  VegaRTEExtension.registerActionHandleStrategy(RTEListItemBlock.name, 'INSERT_TOKEN_NODE', insertTokenNodeStrategy);
})();

const tokenExtension = /*#__PURE__*/Object.freeze({
  __proto__: null,
  VegaRTETokenExtension: VegaRTETokenExtension
});

export { InsertNodeToNearestRootAction as I, RTETokenToolbarButtonRenderer as R, VegaRTETokenExtension as V, RTETokenNode as a, RTETokenNodeRenderer as b, tokenExtension as t };
