'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-58ea899e.js');
const globalSlimmerRegistry = require('./global-slimmer-registry-b3bce7e0.js');
const componentUsageRuntimeMetrics = require('./component-usage-runtime-metrics-4572c5b7.js');
const component = require('./component-1e352960.js');
const darkModeStyleController = require('./dark-mode-style-controller-bd765afb.js');
const imageAnnotationAction = require('./image-annotation-action-93bace08.js');
const contentState = require('./content-state-efd3b1a7.js');
const codeBlock = require('./code-block-c6c70464.js');
const baseRenderer = require('./base-renderer-0a3b62b7.js');
const accessibility = require('./accessibility-a5ef2038.js');
const domNodeSubjectObserverFactory = require('./dom-node-subject-observer-factory-9110cb94.js');
const vegaEventId = require('./vega-event-id-d9994eb3.js');
const typeGuard = require('./type-guard-2e97fc56.js');
const dtoRendererManager = require('./dto-renderer-manager-7eb5c5ce.js');
const vegaInternalEventId = require('./vega-internal-event-id-87014e4f.js');
const tryGetDocument = require('./try-get-document-c0ebd39a.js');
const vegaNonceManager = require('./vega-nonce-manager-df69d3ed.js');
const subStateObserverSlimmer = require('./sub-state-observer-slimmer-b8f6f27b.js');
const ui = require('./ui-ae4ee13d.js');
const waitForComponentDidRender = require('./wait-for-component-did-render-16863a21.js');
const array = require('./array-249289f2.js');
const darkModeStateControllerSlimmer = require('./dark-mode-state-controller-slimmer-8a87ec08.js');
require('./static-subject-title-5829a298.js');
require('./change-manager-a297e4d2.js');
require('./observer-f49483e8.js');
require('./tinycolor-polyfill-502efaa8.js');
require('./index-592b4052.js');
require('./internal-icon-manager-c989189a.js');
require('./icon-manager-c12c6ea9.js');
require('./create-public-api-runtime-metrics-slimmer-9cb09fb2.js');
require('./dynamic-slimmer-f31fdfd7.js');
require('./misc-3d30df91.js');
require('./object-b53e9416.js');
require('./string-39438062.js');
require('./typography-4560e7f1.js');
require('./breakpoints-ebde4837.js');
require('./ui-32120990.js');
require('./internal-translation-controller-8360a89c.js');
require('./number-4816603d.js');

class RTEBlockRenderer extends baseRenderer.VegaRTEBaseRenderer {
  registerRef(ref, block) {
    if (ref) {
      codeBlock.stateEntityRenderingRegistry.register(ref, block);
    }
  }
  /**
   * The attributes of the element rendered by the block
   *
   * @param {RTEBlock} block - RTE block entity
   * @returns {Record<string, string>} - element  props
   */
  getCustomAttrs(block) {
    var _a;
    return ((_a = block.getCustomAttributesAnnotation()) === null || _a === void 0 ? void 0 : _a.render()) || {};
  }
}

class RTENodeRenderer extends baseRenderer.VegaRTEBaseRenderer {
  registerRef(ref, node) {
    if (ref) {
      codeBlock.stateEntityRenderingRegistry.register(ref, node);
    }
  }
}

class RTETextNodeRenderer extends RTENodeRenderer {
  /**
   * Renders the text node wrapped in the given annotation chain starting from the
   * provided annotation level. Used by the grouped node renderer to render a node
   * inside an already-emitted outer wrapper.
   *
   * @param {RTETextNode} node - The text node to render.
   * @param {Nullable<InlineHtmlAnnotation>} annotation - Starting annotation, or null for text-only.
   * @returns {HTMLElement} The rendered element.
   */
  renderFromAnnotation(node, annotation) {
    const textNodeDom = this.renderText(node);
    return annotation ? this.renderWithWrapper(textNodeDom, annotation) : textNodeDom;
  }
  render(node) {
    return this.renderFromAnnotation(node, node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.INLINE_HTML));
  }
  renderWithWrapper(textNodeDom, inlineHtmlNode) {
    const { htmlTag: HtmlTag, customStyle, customAttribute, customClass, } = inlineHtmlNode;
    const attrs = Object.assign(Object.assign({}, customAttribute === null || customAttribute === void 0 ? void 0 : customAttribute.render()), { style: customStyle === null || customStyle === void 0 ? void 0 : customStyle.renderStyle(), class: customClass === null || customClass === void 0 ? void 0 : customClass.renderClass().join(' ') });
    if (!inlineHtmlNode.child) {
      return index.h(HtmlTag, Object.assign({}, attrs), textNodeDom);
    }
    return index.h(HtmlTag, Object.assign({}, attrs), this.renderWithWrapper(textNodeDom, inlineHtmlNode.child));
  }
  renderText(node) {
    var _a, _b;
    const HtmlTag = ((_a = node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.CODE)) === null || _a === void 0 ? void 0 : _a.code)
      ? 'code'
      : 'span';
    const attrs = Object.assign(Object.assign({}, (_b = node.getCustomAttributesAnnotation()) === null || _b === void 0 ? void 0 : _b.render()), { key: node.id, style: node.getStyles(), class: node.getClasses(), ref: (ref) => this.registerRef(ref, node) });
    return index.h(HtmlTag, Object.assign({}, attrs), node.text || codeBlock.ZERO_WIDTH_SPACE);
  }
}
const TextNodeRenderer = new RTETextNodeRenderer();

/**
 * Unlink the corresponding link group according to the group key *
 */
class UnlinkLinkGroupAction extends codeBlock.ModifyContentAction {
  constructor(groupKey) {
    super();
    this.type = codeBlock.ModifyContentActionType.UNLINK_LINK_GROUP;
    this.groupKey = groupKey;
  }
}

/**
 * Renders link nodes and wraps them with link editor or anchor element based on edit mode.
 */
class RTELinkWrapperRenderer {
  constructor() {
    this.handleChange = ({ detail }, textFromNodes, linkNodes) => {
      switch (detail.action) {
        case 'link': {
          const { url, text } = detail.payload;
          const textChanged = text !== textFromNodes;
          linkNodes.forEach((node) => {
            const groupKey = node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.LINK).link.groupKey;
            const linkAnnotationAction = new codeBlock.LinkAnnotationAction({
              link: { href: url, groupKey: groupKey },
              newText: textChanged ? text : undefined,
              needMergeNode: textChanged && linkNodes.length > 1,
              doSplit: false,
              type: 'update_link',
            });
            node.apply(linkAnnotationAction);
          });
          return;
        }
        case 'unlink': {
          linkNodes.forEach((node) => {
            node.parent.apply(new UnlinkLinkGroupAction(node.annotationMap.get(codeBlock.NodeAnnotationTypeEnum.LINK).link.groupKey));
            node.deleteAnnotationByType(codeBlock.NodeAnnotationTypeEnum.LINK);
          });
          return;
        }
      }
    };
  }
  /**
   * Render link nodes, grouping them by link group annotation if necessary.
   *
   * @param {RTETextNode[]} nodes - Array of text nodes to render.
   * @param {LinkGroupAnnotation} linkGroupAnnotation - link group annotation
   * @param {RTERenderContext} context - Context containing render options.
   * @returns {VegaRTERenderResult[]} - Array of rendered HTML elements.
   */
  render(nodes, linkGroupAnnotation, { editable }) {
    const blockNodes = this.groupNodesByLink(nodes);
    return blockNodes
      .flatMap((item) => {
      if (this.isLinkGroup(item)) {
        // TODO: should revert to above code while https://gethired.atlassian.net/browse/VD-6513 have be fixed.
        // 	const linkAnnotation: LinkAnnotation = item[0].getAnnotationByType<LinkAnnotation>(
        // 		NodeAnnotationTypeEnum.LINK,
        // 	) as LinkAnnotation;
        let linkAnnotation;
        item.find((node) => {
          const link = node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.LINK);
          if (link) {
            linkAnnotation = link;
            return true;
          }
        });
        return editable
          ? this.renderLinkEditorWrapper(item, linkAnnotation, linkGroupAnnotation)
          : this.renderLink(item, linkAnnotation, linkGroupAnnotation);
      }
      const nodeRenderer = dtoRendererManager.RTEDTORendererManager.getRTERenderer(item.type);
      if (nodeRenderer) {
        return nodeRenderer.render(item, { editable }, index.h);
      }
    })
      .filter(typeGuard.isNonNullable);
  }
  groupNodesByLink(nodes) {
    return nodes.reduce((acc, node) => {
      const nodeLinkAnnotation = node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.LINK);
      const lastGroup = acc[acc.length - 1];
      if (typeGuard.isNonNullable(nodeLinkAnnotation)) {
        if (lastGroup &&
          this.isLinkGroup(lastGroup) &&
          lastGroup[0].getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.LINK).toEqual(nodeLinkAnnotation)) {
          lastGroup.push(node);
        }
        else {
          acc.push([node]);
        }
      }
      else {
        acc.push(node);
      }
      return acc;
    }, []);
  }
  isLinkGroup(item) {
    return Array.isArray(item);
  }
  renderLinkEditorWrapper(linkNodes, linkAnnotation, linkGroupAnnotation) {
    const { href } = linkAnnotation.link;
    const textFromNodes = linkNodes.map((node) => node.text).join('');
    let linkWrapperRef;
    return (index.h("span", { class: "link-editor-wrapper", role: "link", tabIndex: 0, onKeyDown: accessibility.createEnterKeyHandlerToTriggerClick(), ref: (ref) => {
        if (ref) {
          linkWrapperRef = ref;
          codeBlock.stateEntityRenderingRegistry.removeDirtyDomRef(ref);
        }
      } },
      this.renderLink(linkNodes, linkAnnotation, linkGroupAnnotation),
      index.h("vega-rich-text-link-editor", { record: {
          text: textFromNodes,
          url: href,
        }, ref: (ref) => {
          if (ref) {
            ref.target = linkWrapperRef;
            domNodeSubjectObserverFactory.DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, vegaEventId.VegaChange, (e) => {
              this.handleChange(e, textFromNodes, linkNodes);
            });
          }
        } })));
  }
  renderLink(linkNodes, linkAnnotation, linkGroupAnnotation) {
    return (index.h("a", Object.assign({}, linkGroupAnnotation.toJsx(linkAnnotation)), linkNodes.map((node) => TextNodeRenderer.render(node))));
  }
}
const RTELinkWrapperRenderer$1 = new RTELinkWrapperRenderer();

/**
 * Abstract class for rendering blocks that contain text nodes with support for rendering text with link styles.
 */
class RTEBlockTextNodesRenderer extends RTEBlockRenderer {
  /**
   * Renders the text nodes of the block(RTETextBlock, RTEListItemBlock), applying link group annotation rendering if present.
   *
   * @param {RTETextBlock} block - The text block containing nodes to render.
   * @param {RTERenderContext} renderContext - The context for rendering.
   * @returns {(HTMLElement | VNode)[]} An array of rendered HTMLElements.
   */
  renderNodes(block, renderContext) {
    const linkGroupAnnotation = block.getAnnotationByType(codeBlock.InternalAnnotationTypeEnum.LINK_GROUP);
    return linkGroupAnnotation
      ? RTELinkWrapperRenderer$1.render(block.children, linkGroupAnnotation, renderContext)
      : this.renderGroupedNodesAtDepth(block.children, 0, renderContext);
  }
  /**
   * Recursively groups `nodes` by their inline HTML wrapper `groupId` at the given
   * `depth`, emitting a single shared wrapper element for adjacent siblings and
   * descending into the next depth for each group.  Nodes without a `groupId` at
   * the current depth are rendered individually (same as the non-grouped path).
   *
   * @param {RTETextNode[]} nodes - The nodes to render.
   * @param {number} depth - Current depth in the inline HTML chain (0 = outermost).
   * @param {RTERenderContext} renderContext - The render context.
   * @returns {(HTMLElement | VNode)[]} Rendered nodes/elements at this depth.
   */
  renderGroupedNodesAtDepth(nodes, depth, renderContext) {
    var _a;
    const result = [];
    let i = 0;
    while (i < nodes.length) {
      const tag = nodes[i].getInlineHtmlTagAtDepth(depth);
      if (!(tag === null || tag === void 0 ? void 0 : tag.groupId)) {
        result.push(this.renderNodeFromDepth(nodes[i], depth, renderContext));
        i++;
        continue;
      }
      let groupEnd = i + 1;
      while (groupEnd < nodes.length &&
        ((_a = nodes[groupEnd].getInlineHtmlTagAtDepth(depth)) === null || _a === void 0 ? void 0 : _a.groupId) === tag.groupId) {
        groupEnd++;
      }
      if (groupEnd === i + 1) {
        // Single node in group — render normally from this depth.
        result.push(this.renderNodeFromDepth(nodes[i], depth, renderContext));
      }
      else {
        // Multiple nodes share a wrapper — emit the wrapper once and recurse.
        const attrs = tag.annotation.renderProps();
        const inner = this.renderGroupedNodesAtDepth(nodes.slice(i, groupEnd), depth + 1, renderContext);
        result.push(index.h(tag.htmlTag, attrs, inner));
      }
      i = groupEnd;
    }
    return result;
  }
  /**
   * Renders a single node starting from the given inline HTML depth.
   * At depth 0 the full annotation chain is rendered normally.
   * At depth > 0 the chain begins at that depth (the outer wrappers have
   * already been emitted by the grouping logic above).
   *
   * @param {RTETextNode} node - The node to render.
   * @param {number} depth - Depth in the inline HTML chain to start from.
   * @param {RTERenderContext} renderContext - The render context.
   * @returns {HTMLElement | VNode} The rendered node.
   */
  renderNodeFromDepth(node, depth, renderContext) {
    if (depth === 0) {
      const nodeRenderer = dtoRendererManager.RTEDTORendererManager.getRTERenderer(node.type);
      return nodeRenderer.render(node, renderContext, index.h);
    }
    return TextNodeRenderer.renderFromAnnotation(node, node.getInlineHtmlAnnotationAtDepth(depth));
  }
}

class RTETextBlockRenderer extends RTEBlockTextNodesRenderer {
  render(block, renderContext) {
    if (block.shouldRenderAsInternalWrapper()) {
      const outerTag = this.getOuterInlineTag(block.children);
      if (outerTag) {
        const OuterTag = outerTag.htmlTag;
        return (index.h(OuterTag, Object.assign({}, outerTag.annotation.renderProps(), { key: block.id, ref: (ref) => super.registerRef(ref, block) }), super.renderGroupedNodesAtDepth(block.children, 1, renderContext)));
      }
    }
    const BlockTag = block.getBlockTag();
    return (index.h(BlockTag, Object.assign({}, this.getCustomAttrs(block), { key: block.id, ref: (ref) => super.registerRef(ref, block), style: block.getStyles(), class: block.getClasses() }), super.renderNodes(block, renderContext)));
  }
  /**
   * Returns the promotable inline HTML tag when the block wraps exactly one
   * inline-HTML element (e.g. `<summary>`, `<section>`), or `null` otherwise.
   */
  getOuterInlineTag(children) {
    if (children.length !== 1)
      return null;
    return children[0].getInlineHtmlTagAtDepth(0);
  }
}
const RTETextBlockRenderer$1 = new RTETextBlockRenderer();

class RTEImageNodeRenderer extends RTENodeRenderer {
  constructor() {
    super(...arguments);
    this.handleChange = ({ detail }, node) => {
      switch (detail.action) {
        case 'edit': {
          const size = detail.payload.size;
          const alt = detail.payload.alt;
          node.apply(new imageAnnotationAction.ImageAnnotationAction(size, alt));
          break;
        }
        /*
         * The below method is e2e-test covered in
         * @see{module:vega-rich-text-editor-image-click-delete-button}
         */
        /* istanbul ignore next */
        case 'delete': {
          const event = new InputEvent('beforeinput', {
            inputType: 'deleteContentBackward',
            bubbles: true,
          });
          setTimeout(() => {
            codeBlock.stateEntityRenderingRegistry.getDOMByEntity(node).dispatchEvent(event);
          }, 50);
          break;
        }
      }
    };
  }
  render(node, renderContext) {
    const imageAnnotation = node.getAnnotationByType(codeBlock.NodeAnnotationTypeEnum.IMAGE) ||
      new contentState.ImageAnnotation('md', '');
    return renderContext.editable ? (index.h("vega-rich-text-image-editor", { key: node.id, class: this.getClassesForImageEditor(node), size: imageAnnotation.size, alt: imageAnnotation.alt, ref: (ref) => {
        domNodeSubjectObserverFactory.DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, vegaEventId.VegaChange, (e) => this.handleChange(e, node));
      } }, this.renderImage(imageAnnotation, node, renderContext))) : (this.renderImage(imageAnnotation, node, renderContext));
  }
  /**
   * The function will render an image.
   * In edit mode, it will be placed in the "vega-rich-text-image-editor" component as a slot.
   * In view mode, the img image will be displayed directly.
   *
   * @param {ImageAnnotation} imageAnnotation - the image annotation of the image node
   * @param {RTEImageNode} node  - the current image node
   * @returns {HTMLElement} return a image element
   */
  renderImage(imageAnnotation, node, renderContext) {
    var _a;
    return (index.h("img", Object.assign({}, (_a = node.getCustomAttributesAnnotation()) === null || _a === void 0 ? void 0 : _a.render({ filterAttributes: ['width', 'height'] }), { class: this.getClassesForImageNode(node, renderContext.editable), style: renderContext.editable
        ? Object.assign(Object.assign({}, node.getStyles()), { width: '100%' }) : Object.assign(Object.assign({}, node.getStyles()), imageAnnotation.renderStyle({ standalone: true })), alt: imageAnnotation.alt, "data-size": imageAnnotation.size, src: node.url, ref: (ref) => super.registerRef(ref, node), 
      // eslint-disable-next-line react/jsx-no-bind
      onError: (e) => {
        const img = e.target;
        img.style.width = '16px';
        img.style.height = '16px';
      } })));
  }
  /**
   * Get the custom class string of the current RTEImageNode.
   *
   * @returns {Nullable<string>} A string of classes.
   */
  getCommonClasses(node) {
    const customClassAnnotation = node.getAnnotationByType(codeBlock.CommonAnnotationTypeEnum.CUSTOM_CLASS);
    if (customClassAnnotation) {
      return customClassAnnotation.customClass
        .filter(typeGuard.isNonNullable)
        .reduce((pre, cur) => [pre, cur].join(' ').trim(), '');
    }
    return null;
  }
  /**
   * Get classes from annotations
   *
   * @param {RTERenderContext} [options={ standalone: false }] - Options to control style mode
   * @returns {string} - Annotation style
   */
  getClasses(node, options = { standalone: false }) {
    return Array.from(node.annotationMap.values())
      .filter((annotation) => annotation instanceof codeBlock.NodeAnnotation)
      .map((annotation) => annotation.renderClass(options))
      .filter(typeGuard.isNonNullable)
      .reduce((pre, cur) => [pre, cur].join(' ').trim(), '');
  }
  /**
   * Get the class string for the image node.
   *
   * @param {RTEImageNode} node - The image node
   * @param {boolean} editable - Whether the editor is in editable mode
   * @returns {string} - The class string for the image node
   */
  getClassesForImageNode(node, editable) {
    var _a;
    return editable
      ? `${codeBlock.RTEDecoratorNode.DECORATOR_NODE_CLASS} ${(_a = this.getCommonClasses(node)) !== null && _a !== void 0 ? _a : ''}`
      : node.getClasses();
  }
  /**
   * Get the class string for the image editor.
   *
   * @param {RTEImageNode} node - The image node
   * @returns {string} - The class string for the image editor
   */
  getClassesForImageEditor(node) {
    return `${codeBlock.RTEDecoratorNode.DECORATOR_CONTAINER_CLASS} ${this.getClasses(node)}`;
  }
}
const ImageNodeRenderer = new RTEImageNodeRenderer();

class RTEImageBlockRenderer extends RTEBlockRenderer {
  render(block, renderContext) {
    return (index.h("div", Object.assign({}, this.getCustomAttrs(block), { key: block.id, ref: (ref) => super.registerRef(ref, block), style: block.getStyles(), class: block.getClasses() }), block.children.map((node) => {
      return ImageNodeRenderer.render(node, renderContext);
    })));
  }
}
const RTEImageBlockRenderer$1 = new RTEImageBlockRenderer();

class RTEListItemBlockRenderer extends RTEBlockTextNodesRenderer {
  render(block, renderContext) {
    return (index.h("li", Object.assign({}, this.getCustomAttrs(block), { key: block.id, ref: (ref) => super.registerRef(ref, block), style: block.getStyles(), class: block.getClasses() }),
      super.renderNodes(block, renderContext),
      this.renderChildren(block.nestList, renderContext)));
  }
  renderChildren(children, renderContext) {
    return children === null || children === void 0 ? void 0 : children.map((block) => RTEListBlockRenderer$1.render(block, renderContext));
  }
}
const RTEListItemBlockRenderer$1 = new RTEListItemBlockRenderer();

class RTEListBlockRenderer extends RTEBlockRenderer {
  render(block, renderContext) {
    const BlockTag = block.getBlockTag();
    return (index.h(BlockTag, Object.assign({}, this.getCustomAttrs(block), { key: block.id, ref: (ref) => super.registerRef(ref, block), style: block.getStyles(), class: block.getClasses() }), block.children.map((listItemBlock) => RTEListItemBlockRenderer$1.render(listItemBlock, renderContext))));
  }
}
const RTEListBlockRenderer$1 = new RTEListBlockRenderer();

/**
 * Switch out from the code block and insert new paragraph after code block.
 *
 * @example codeBlock.apply(new SwitchOutFromCodeBlockAction(content, language))
 */
class SwitchOutFromCodeBlockAction extends codeBlock.ModifyContentAction {
  constructor(content, language) {
    super();
    this.isFlushable = true;
    this.type = codeBlock.ModifyContentActionType.SWITCH_OUT_FROM_CODE_BLOCK;
    this.content = content;
    this.language = language;
  }
}

/**
 * Remove the code block from the state.
 *
 * @example codeBlock.parentBlock.apply(new RemoveCodeBlockAction())
 */
class RemoveCodeBlockAction extends codeBlock.ModifyContentAction {
  constructor() {
    super(...arguments);
    this.isFlushable = true;
    this.type = codeBlock.ModifyContentActionType.DELETE_CODE_BLOCK;
  }
}

class RTECodeBlockNodeRenderer extends RTENodeRenderer {
  render(node, renderContext) {
    const { text: code, language } = node;
    return (index.h("vega-code-block", { key: node.id, value: { code, language }, readOnly: !renderContext.editable, "data-content": code, "data-language": language, ref: (ref) => {
        this.registerRef(ref, node);
        domNodeSubjectObserverFactory.DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, vegaEventId.VegaChange, (input) => this.handleCodeContentChange(input.detail, node));
        domNodeSubjectObserverFactory.DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, vegaEventId.VegaRemove, (input) => this.handleCodeBlockRemove(input, node));
        domNodeSubjectObserverFactory.DomNodeSubjectObserverFactory.addUniqueObserverToNode(ref, vegaInternalEventId.VegaInternalCodeBlockSelectionChange, (input) => this.handleSelectionChange(input.detail, node));
      } }));
  }
  /**
   * Sync the code block DTO language and content when the component change event emit.
   *
   * @param {VegaCodeBlockValue} codeBlockValue - The code block value.
   * @param {RTECodeBlockNode} node - The DTO class instance.
   */
  handleCodeContentChange(codeBlockValue, node) {
    const { code, language } = codeBlockValue;
    if (this.shouldSwitchOutOfCodeBlock(node.text, code)) {
      const switchAction = new SwitchOutFromCodeBlockAction(code, language);
      node.parent.apply(switchAction);
    }
    else {
      node.apply(new codeBlock.UpdateCodeBlockAction(code, language));
    }
  }
  /**
   * Remove the code block from RTE value when the component remove event emit.
   *
   * @param {ChangeManagerEventLike<unknown>} input - The internal event payload object.
   * @param {RTECodeBlockNode} node - The DTO class instance.
   */
  handleCodeBlockRemove(input, node) {
    input.preventDefault();
    node.parent.apply(new RemoveCodeBlockAction());
  }
  /**
   * The cursor should jump out of code block if enter three line breaks at the end.
   *
   * @param {string} oldCode - The old code content.
   * @param {string} newCode - The new code content.
   * @returns {boolean} - Boolean value.
   */
  shouldSwitchOutOfCodeBlock(oldCode, newCode) {
    const newCodes = newCode.split('\n');
    if (newCode.length > oldCode.length &&
      newCodes.length > 4 &&
      newCodes.slice(newCodes.length - 4).join('') === ``) {
      return true;
    }
    return false;
  }
  /**
   * Apply the selection action to code node or remove from the annotation map.
   *
   * @param {boolean} isSelected - The code block is focus or not.
   * @param {RTECodeBlockNode} node - The DTO class instance.
   */
  handleSelectionChange(isSelected, node) {
    if (isSelected) {
      node.apply(new codeBlock.SelectionChangeAction(null));
    }
    else {
      node.annotationMap.delete(codeBlock.InternalAnnotationTypeEnum.SELECTION_RANGE);
    }
  }
}
const RTECodeBlockNodeRenderer$1 = new RTECodeBlockNodeRenderer();

/**
 * The code block renderer.
 */
class RTECodeBlockRenderer extends RTEBlockRenderer {
  constructor() {
    super(...arguments);
    /**
     * Prevent the click event bubble, avoid the rich text content trigger focus event.
     *
     * @param {MouseEvent} e - The event object.
     */
    this.preventParentDoFocus = (e) => {
      e.stopPropagation();
      if (e.type === 'keydown') {
        this.dispatchMockKeydownEvent(e);
      }
    };
  }
  /**
   * Render the code block.
   *
   * @param {RTECodeBlock} block - The code block.
   * @param {RTERenderContext} renderContext - The render context.
   * @returns {HTMLElement} - The code block container element and code node elements.
   */
  render(block, renderContext) {
    const { id, children: nodes } = block;
    return (
    // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
    index.h("pre", { key: id, class: "code-block-container", ref: (node) => this.registerRef(node, block), onKeyDown: this.preventParentDoFocus, onClick: this.preventParentDoFocus, "data-language": nodes[0].language },
      this.renderPlaceholderElement('TOP'),
      RTECodeBlockNodeRenderer$1.render(nodes[0], renderContext),
      this.renderPlaceholderElement('BOTTOM')));
  }
  /**
   * The current element used to define the upper and lower bounds of a code block and to ensure that they are reflected in the range object when the code block is selected.
   *
   * @param {'TOP' | 'BOTTOM'} position - The element position.
   * @returns {HTMLElement} - The empty span element.
   */
  renderPlaceholderElement(position) {
    const marginTop = position === 'BOTTOM' ? '-1px' : '0px';
    const marginBottom = position === 'BOTTOM' ? '0px' : '-1px';
    return (index.h("span", { class: codeBlock.RTECodeBlock.CODE_BLOCK_PLACEHOLDER_CLASS_NAME, style: {
        display: 'block',
        height: '1px',
        overflow: 'hidden',
        zIndex: '1',
        marginTop,
        marginBottom,
      } }, codeBlock.ZERO_WIDTH_SPACE));
  }
  /**
   * If redo and undo in code block, here need a mock keydown event to make the helper class `KeyboardManager` could monitor the current keydown event.
   *
   * @param {KeyboardEvent} e - The keyboard event object.
   */
  dispatchMockKeydownEvent(e) {
    const safeDocument = tryGetDocument.tryGetDocument();
    if (safeDocument) {
      const { type, code, metaKey, ctrlKey, shiftKey } = e;
      const event = new Event(type, { bubbles: false, cancelable: true });
      event['code'] = code;
      event['metaKey'] = metaKey;
      event['ctrlKey'] = ctrlKey;
      event['shiftKey'] = shiftKey;
      safeDocument.dispatchEvent(event);
    }
  }
}
const RTECodeBlockRenderer$1 = new RTECodeBlockRenderer();

class RTEHTMLBlockRenderer extends RTEBlockRenderer {
  render(block, renderContext) {
    const BlockTag = block.htmlTag;
    return (index.h(BlockTag, Object.assign({}, this.getCustomAttrs(block), { key: block.id, ref: (ref) => super.registerRef(ref, block), style: block.getStyles(), class: block.getClasses() }), block.children.map((child) => {
      return dtoRendererManager.RTEDTORendererManager.getRTERenderer(child.type).render(child, renderContext, index.h);
    })));
  }
}
const RTEHTMLBlockRenderer$1 = new RTEHTMLBlockRenderer();

/**
 * RTEBlockRendererFactory is a factory class that provides methods to get the appropriate block renderer.
 * It registers various block renderers for different types of blocks and nodes.
 */
class RTEBlockRendererFactory {
  /**
   * Registers the default block renderers and node renderers.
   */
  constructor() {
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('title', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('subtitle', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('paragraph', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-1', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-2', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-3', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-4', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-5', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('heading-6', RTETextBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('bullet-list', RTEListBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('number-list', RTEListBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('list-item', RTEListItemBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('image', RTEImageBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('code-block', RTECodeBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('html-block', RTEHTMLBlockRenderer$1);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('TEXT', TextNodeRenderer);
    dtoRendererManager.RTEDTORendererManager.registerRTEDTORenderer('IMAGE', ImageNodeRenderer);
  }
  /**
   * getBlockRenderer retrieves the renderer for a given block type.
   *
   * @param {string} type - The type of the block for which the renderer is needed.
   * @returns {Nullable<BaseBlockRenderer>} - The renderer instance if found, otherwise null.
   */
  getBlockRenderer(type) {
    return dtoRendererManager.RTEDTORendererManager.getRTERenderer(type);
  }
}
const RTEBlockRendererFactory$1 = new RTEBlockRendererFactory();

var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
class VegaRichTextContentRenderer extends globalSlimmerRegistry.VegaSlimmer {
  constructor() {
    super();
    darkModeStyleController.VegaDarkModeStyleController.registerCustomDarkModeColor(imageAnnotationAction.TextColorToolbarButtonSlimmer.formatDarkModeColor());
  }
  componentWillLoad() {
    this.setRTEContent();
  }
  watchValueUpdate() {
    this.setRTEContent();
  }
  /**
   * Get the rich text content element
   *
   * @returns {Nullable<HTMLDivElement>} a div element
   */
  getRichTextContentRef() {
    return this.richTextContentRef;
  }
  render() {
    return (index.h(index.Host, null,
      this.extensionStyles ? (index.h("style", { nonce: vegaNonceManager.vegaNonceManager.nonce, class: "rte-extension-styles" }, this.extensionStyles)) : null,
      this.renderRichTextContent()));
  }
  setRTEContent() {
    if (this.content && !(this.content instanceof contentState.VegaRTEContent)) {
      this.content = contentState.VegaRTEContent.fromJSON(this.content);
    }
  }
  renderRichTextContent() {
    const showPlaceholder = this.shouldShowPlaceholder();
    return (index.h("div", { ref: (el) => (this.richTextContentRef = el), class: { 'showPlaceholder': showPlaceholder, 'rich-text-content': true }, "data-placeholder": this.placeholder, contenteditable: this.contentEditable }, this.renderContent()));
  }
  renderContent() {
    var _a;
    const renderContext = { editable: this.contentEditable };
    this.injectRTERefIntoContext(renderContext);
    return (_a = this.content) === null || _a === void 0 ? void 0 : _a.children.map((block) => {
      const blockRenderer = RTEBlockRendererFactory$1.getBlockRenderer(block.type);
      if (blockRenderer) {
        return blockRenderer.render(block, renderContext, index.h);
      }
    });
  }
  shouldShowPlaceholder() {
    var _a;
    const blocks = (_a = this.content) === null || _a === void 0 ? void 0 : _a.children;
    if (blocks) {
      if (blocks.length > 1) {
        return false;
      }
      for (const block of blocks) {
        if (block.isNotEmpty()) {
          return false;
        }
      }
    }
    return true;
  }
  /**
   * Inject the reference of rich text editor into render context for the usage of extensions.
   *
   * @param {RTERenderContext} renderContext - The render context which may contain the host reference.
   */
  injectRTERefIntoContext(renderContext) {
    const content = this.content;
    if (content) {
      const ref = codeBlock.stateEntityRenderingRegistry.getDOMByEntity(content);
      // The ref will be null if the content is not rendered by VegaRichTextEditor, in that case we will not inject the ref into context to avoid potential error on extensions which use the ref.
      ref && (renderContext.host = ref);
    }
  }
}
__decorate$3([
  globalSlimmerRegistry.MapToComponentField()
], VegaRichTextContentRenderer.prototype, "placeholder", void 0);
__decorate$3([
  globalSlimmerRegistry.MapToComponentField()
], VegaRichTextContentRenderer.prototype, "contentEditable", void 0);
__decorate$3([
  globalSlimmerRegistry.MapToComponentField({ writable: true })
], VegaRichTextContentRenderer.prototype, "content", void 0);
__decorate$3([
  globalSlimmerRegistry.MapToComponentField()
], VegaRichTextContentRenderer.prototype, "extensionStyles", void 0);
__decorate$3([
  globalSlimmerRegistry.MapToComponentMethod('componentWillLoad')
], VegaRichTextContentRenderer.prototype, "componentWillLoad", null);
__decorate$3([
  globalSlimmerRegistry.MapToComponentMethod('watchValueUpdate')
], VegaRichTextContentRenderer.prototype, "watchValueUpdate", null);

var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
 * Controller for the table row states
 */
class VegaRichTextContentStateController extends subStateObserverSlimmer.SubStateObserverSlimmer {
  // eslint-disable-next-line jsdoc/require-jsdoc
  constructor() {
    super({
      parent: 'vega-rich-text-editor',
      subStates: [
        {
          subStateName: 'placeholder',
          parentStateName: 'placeholder',
        },
        {
          subStateName: 'contentEditable',
          parentStateName: 'richTextContentEditable',
        },
      ],
    });
  }
}
__decorate$2([
  globalSlimmerRegistry.MapToComponentField()
], VegaRichTextContentStateController.prototype, "host", void 0);
__decorate$2([
  globalSlimmerRegistry.MapToComponentField({ writable: true })
], VegaRichTextContentStateController.prototype, "placeholder", void 0);
__decorate$2([
  globalSlimmerRegistry.MapToComponentField({ writable: true })
], VegaRichTextContentStateController.prototype, "contentEditable", void 0);

var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
 * attach the extension styles to the host.
 */
class RTEExtensionStylesController extends globalSlimmerRegistry.VegaSlimmer {
  /**
   * Attach extension styles to the host after load.
   */
  attachExtensionStyles() {
    this.attachStylesToHost();
  }
  /**
   * Update extension context when extensions property changes.
   *
   * @param {VegaRTEExtension[]} newValue - New extensions array.
   * @param {VegaRTEExtension[]} oldValue - Old extensions array.
   */
  handleExtensionsChange(newValue, oldValue) {
    if (!array.isArrayEqual(newValue, oldValue, false, (a, b) => a === b ? 0 : 1)) {
      this.attachStylesToHost();
    }
  }
  /**
   * Collects and attaches custom styles from all extensions to the host component.
   */
  attachStylesToHost() {
    if (this.extensions) {
      let customStyles = '';
      for (const extension of this.extensions) {
        const extensionStyles = extension.collectExtensionRendererStyles();
        if (extensionStyles) {
          customStyles += `${extensionStyles}\n`;
        }
      }
      this.extensionStyles = customStyles;
    }
  }
}
__decorate$1([
  globalSlimmerRegistry.MapToComponentField()
], RTEExtensionStylesController.prototype, "extensions", void 0);
__decorate$1([
  globalSlimmerRegistry.MapToComponentField()
], RTEExtensionStylesController.prototype, "host", void 0);
__decorate$1([
  globalSlimmerRegistry.MapToComponentField({ writable: true })
], RTEExtensionStylesController.prototype, "extensionStyles", void 0);
__decorate$1([
  globalSlimmerRegistry.MapToComponentMethod('componentWillLoad')
], RTEExtensionStylesController.prototype, "attachExtensionStyles", null);
__decorate$1([
  globalSlimmerRegistry.MapToComponentMethod('watchExtensions')
], RTEExtensionStylesController.prototype, "handleExtensionsChange", null);

const vegaRichTextContentCss = ":host{display:flex;flex-direction:column;width:100%}:host .rich-text-content{position:relative;height:100%;outline:2px solid transparent;outline-offset:2px;font-weight:500;color:var(--v-rich-text-editor-black, #111128);overflow-wrap:break-word;white-space:pre-wrap}:host .rich-text-content.showPlaceholder::before{position:absolute;content:attr(data-placeholder);font-family:\"Inter\", sans-serif;font-size:16px;font-weight:400;line-height:24px;letter-spacing:0px;color:rgba(var(--v-text-input-placeholder, 176, 180, 181, 1))}@media screen and (min-width: 768px) and (max-width: 1023px){:host .rich-text-content.showPlaceholder::before{font-family:\"Inter\", sans-serif;font-size:16px;font-weight:400;line-height:24px;letter-spacing:0px}}@media screen and (min-width: 1024px) and (max-width: 1439px){:host .rich-text-content.showPlaceholder::before{font-family:\"Inter\", sans-serif;font-size:16px;font-weight:400;line-height:24px;letter-spacing:0px}}@media screen and (min-width: 1440px) and (max-width: 9999px){:host .rich-text-content.showPlaceholder::before{font-family:\"Inter\", sans-serif;font-size:16px;font-weight:400;line-height:24px;letter-spacing:0px}}:host .rich-text-content a.v-rte--link{color:rgba(var(--v-text-link, 19, 98, 226, 1));outline:none}:host .rich-text-content a.v-rte--link:visited{color:rgba(var(--v-text-link-visited, 95, 56, 206, 1))}:host .rich-text-content a.v-rte--link:hover{color:rgba(var(--v-text-link-hover, 4, 112, 236, 1))}:host .rich-text-content a.v-rte--link:active{color:rgba(var(--v-text-link-active, 29, 65, 195, 1))}:host .rich-text-content a.v-rte--link:focus-visible{color:rgba(var(--v-text-link-focus, 4, 112, 236, 1));outline:2px solid rgba(var(--v-border-color-action, 19, 98, 226, 1));outline-offset:3px;border:1px solid rgba(var(--v-border-color-input-field-focus, 19, 98, 226, 1));border-radius:8px}:host .rich-text-content .v-rte--underline{text-decoration:underline}:host .rich-text-content .v-rte--strikethrough{text-decoration:line-through}:host .rich-text-content .v-rte--underline.v-rte--strikethrough{text-decoration:underline line-through}:host .rich-text-content .v-rte--horizontal-alignment-right{text-align:right}:host .rich-text-content .v-rte--horizontal-alignment-left{text-align:left}:host .rich-text-content .v-rte--horizontal-alignment-center{text-align:center}:host .rich-text-content .v-rte--horizontal-alignment-justify{text-align:justify}:host .rich-text-content .v-rte--code{font-family:\"Roboto Mono\";white-space:pre-wrap}:host .rich-text-content img{cursor:pointer}:host .rich-text-content ul.v-rte--list,:host .rich-text-content ol.v-rte--list{padding-left:8px;margin-left:16px}:host .rich-text-content .link-editor-wrapper{position:relative;outline:2px solid transparent;outline-offset:2px}:host .rich-text-content .link-editor-wrapper vega-rich-text-link-editor{position:absolute;bottom:0;left:0;right:0}:host .rich-text-content .code-block-container{margin-top:22px;margin-bottom:22px}:host .rich-text-content vega-code-block.focus{outline:none}:host .rich-text-content .v-rte--bold{font-weight:700}:host .rich-text-content .v-rte--italic{font-style:italic}:host .rich-text-content .v-rte--image-base img,:host .rich-text-content .v-rte--image-size-lg img,:host .rich-text-content .v-rte--image-size-md img,:host .rich-text-content .v-rte--image-size-sm img{vertical-align:bottom}:host .rich-text-content .v-rte--image-size-sm{width:25%}:host .rich-text-content .v-rte--image-size-md{width:50%}:host .rich-text-content .v-rte--image-size-lg{width:100%}:host .rich-text-content .v-rte--text-style-paragraph{font-family:\"Inter\";font-size:16px;line-height:22px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-title{font-family:\"Inter\";font-size:36px;line-height:40px;font-weight:500}:host .rich-text-content .v-rte--text-style-subtitle{font-family:\"Inter\";font-size:28px;line-height:32px;font-weight:500}:host .rich-text-content .v-rte--text-style-heading-1{font-family:\"Inter\";font-size:22px;line-height:24px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-heading-2{font-family:\"Inter\";font-size:20px;line-height:24px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-heading-3{font-family:\"Inter\";font-size:18px;line-height:22px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-heading-4{font-family:\"Inter\";font-size:16px;line-height:22px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-heading-5{font-family:\"Inter\";font-size:14px;line-height:22px;font-weight:500;margin:0}:host .rich-text-content .v-rte--text-style-heading-6{font-family:\"Inter\";font-size:12px;line-height:22px;font-weight:500;margin:0}";

var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1; i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
const VegaRichTextContent = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.globalSlimmers = {};
    this.vegaComponentUsageRuntimeMetricsSlimmer = new componentUsageRuntimeMetrics.VegaComponentUsageRuntimeMetricsSlimmer();
    this.vegaRichTextContentRenderer = new VegaRichTextContentRenderer();
    this.vegaRichTextContentStateController = new VegaRichTextContentStateController();
    this.vegaRichTextContentExtensionsStylesController = new RTEExtensionStylesController();
    this.darkModeStateControllerSlimmer = new darkModeStateControllerSlimmer.DarkModeStateControllerSlimmer();
    /**
     * Specifies whether the rich text content is editable.
     *
     * @vegaVersion 2.34.0
     */
    this.contentEditable = false;
    /**
     * Holds the custom styles generated by extensions.
     */
    this.extensionStyles = '';
    this.isInDarkMode = darkModeStyleController.VegaInternalThemeManager.isDarkMode();
    /**
     * Defines the configuration for rich text content extensions.
     * It enables support for custom nodes, ensuring that extended content is rendered correctly.
     *
     * @vegaVersion 2.62.0
     */
    this.extensions = [];
  }
  watchValueUpdate() {
  }
  watchExtensions(newValue, oldValue) {
  }
  /**
   * Invoke this method to focus on rich text content editable div
   *
   * @vegaVersion 2.34.0
   */
  async vegaFocus() {
    this.vegaRichTextContentRenderer.getRichTextContentRef().focus();
    const richTextEditorRef = ui.findParent(this.host, 'vega-rich-text-editor');
    if (richTextEditorRef) {
      await waitForComponentDidRender.waitForComponentDidRender(richTextEditorRef);
    }
  }
  render() {
    return component.sanitizeVegaComponent(this.vegaRichTextContentRenderer.render(), this.host);
  }
  get host() { return index.getElement(this); }
  static get watchers() { return {
    "content": ["watchValueUpdate"],
    "extensions": ["watchExtensions"]
  }; }
};
__decorate([
  componentUsageRuntimeMetrics.InjectVegaGlobalSlimmer()
], VegaRichTextContent.prototype, "globalSlimmers", void 0);
__decorate([
  globalSlimmerRegistry.InjectVegaSlimmer()
], VegaRichTextContent.prototype, "vegaComponentUsageRuntimeMetricsSlimmer", void 0);
__decorate([
  globalSlimmerRegistry.InjectVegaSlimmer()
], VegaRichTextContent.prototype, "vegaRichTextContentRenderer", void 0);
__decorate([
  globalSlimmerRegistry.InjectVegaSlimmer()
], VegaRichTextContent.prototype, "vegaRichTextContentStateController", void 0);
__decorate([
  globalSlimmerRegistry.InjectVegaSlimmer()
], VegaRichTextContent.prototype, "vegaRichTextContentExtensionsStylesController", void 0);
__decorate([
  globalSlimmerRegistry.InjectVegaSlimmer()
], VegaRichTextContent.prototype, "darkModeStateControllerSlimmer", void 0);
VegaRichTextContent.style = vegaRichTextContentCss;

exports.vega_rich_text_content = VegaRichTextContent;
