import { P as g, E as y, a as b, T as f, R as v } from "./index-YZ5TROdg.mjs";
import { C as G, h as O, F as V, K, i as B, S as W, b as X, e as _, d as Y, g as J, f as Q, c as Z } from "./index-YZ5TROdg.mjs";
class L {
  constructor(e) {
    if (this.listeners = [], e instanceof g)
      this.pluginManager = e;
    else {
      const i = e;
      this.pluginManager = new g(), i.plugins && Array.isArray(i.plugins) && i.plugins.forEach((n) => {
        this.pluginManager.register(n);
      }), i.element && (this.domElement = i.element, this.setupDOMElement(i));
    }
    const t = this.pluginManager.buildSchema();
    this.state = y.create(t), this.commands = this.pluginManager.getCommands();
  }
  setupDOMElement(e) {
    this.domElement && (e.enableToolbar !== !1 && e.toolbarElement ? this.toolbarElement = e.toolbarElement : e.enableToolbar !== !1 && (this.toolbarElement = document.createElement("div"), this.toolbarElement.className = "editora-toolbar-container", this.domElement.appendChild(this.toolbarElement)), this.contentElement = document.createElement("div"), this.contentElement.contentEditable = "true", this.contentElement.className = "editora-content", this.contentElement.style.minHeight = "200px", this.contentElement.style.outline = "none", this.contentElement.style.padding = "12px", e.content && (this.contentElement.innerHTML = e.content), this.domElement.appendChild(this.contentElement), this.contentElement.addEventListener("input", () => {
      this.listeners.forEach((t) => t(this.state));
    }));
  }
  setupKeyboardShortcuts(e) {
    const t = {};
    e.forEach((i) => {
      i.shortcut && (t[i.shortcut.toLowerCase()] = i.command);
    }), document.addEventListener("keydown", (i) => {
      if (this.contentElement !== document.activeElement && !(document.activeElement instanceof HTMLElement && document.activeElement.contentEditable === "true"))
        return;
      const n = [];
      (i.ctrlKey || i.metaKey) && n.push("ctrl"), i.shiftKey && n.push("shift"), i.altKey && n.push("alt");
      const o = i.key.toLowerCase(), s = n.length > 0 ? `${n.join("+")}+${o}` : o, a = t[s];
      a && (i.preventDefault(), this.execCommand(a));
    });
  }
  handleToolbarCommand(e, t) {
    const n = this.pluginManager.getToolbarItems().find((o) => o.id && o.id === e || o.command === e);
    n != null && n.command && (t !== void 0 ? this.execCommand(n.command, t) : this.execCommand(n.command));
  }
  setState(e) {
    this.state = e, this.listeners.forEach((t) => t(e));
  }
  onChange(e) {
    return this.listeners.push(e), () => {
      this.listeners = this.listeners.filter((t) => t !== e);
    };
  }
  // Alias for onChange to support both patterns
  on(e, t) {
    return e === "change" || e === "input" ? this.onChange(t) : () => {
    };
  }
  getElement() {
    return this.contentElement || this.domElement || null;
  }
  execCommand(e, t) {
    const i = this.commands[e];
    if (!i)
      return console.warn(`Command not found: ${e}`), !1;
    let n;
    return t !== void 0 ? n = i(this.state, t) : n = i(this.state), n instanceof Promise ? (n.then((o) => {
      o && typeof o == "object" && "doc" in o && "selection" in o && this.setState(o);
    }).catch((o) => {
      console.error(`Async command failed: ${e}`, o);
    }), !0) : n && typeof n == "object" && "doc" in n && "selection" in n ? (this.setState(n), !0) : n !== !1 && n != null;
  }
  setContent(e) {
    typeof e == "string" ? this.contentElement && (this.contentElement.innerHTML = e) : this.setState(this.state.apply(e));
  }
  getContent() {
    return this.contentElement ? this.contentElement.innerHTML : this.state.doc;
  }
  destroy() {
    this.listeners = [], this.contentElement && this.contentElement.removeEventListener("input", () => {
    });
  }
}
class E {
  constructor(e) {
    this.initialized = !1, this.plugin = e;
  }
  /**
   * Safe initialization
   */
  initialize(e) {
    var t, i;
    if (this.initialized)
      return console.warn(`Plugin "${this.plugin.name}" already initialized`), !1;
    try {
      return this.context = e, (t = this.plugin.context) != null && t.initialize && this.plugin.context.initialize(), (i = this.plugin.context) != null && i.onEditorReady && e.provider && this.plugin.context.onEditorReady(e), this.initialized = !0, !0;
    } catch (n) {
      return console.error(`Failed to initialize plugin "${this.plugin.name}":`, n), !1;
    }
  }
  /**
   * Safe destruction
   */
  destroy() {
    var e;
    if (!this.initialized)
      return !1;
    try {
      return (e = this.plugin.context) != null && e.destroy && this.plugin.context.destroy(), this.initialized = !1, this.context = void 0, !0;
    } catch (t) {
      return console.error(`Failed to destroy plugin "${this.plugin.name}":`, t), !1;
    }
  }
  /**
   * Safe command execution
   */
  executeCommand(e, ...t) {
    var i;
    if (!this.initialized)
      return console.warn(`Plugin "${this.plugin.name}" not initialized, cannot execute command "${e}"`), null;
    try {
      const n = (i = this.plugin.commands) == null ? void 0 : i[e];
      return n ? n(...t) : (console.warn(`Command "${e}" not found in plugin "${this.plugin.name}"`), null);
    } catch (n) {
      return console.error(`Error executing command "${e}" in plugin "${this.plugin.name}":`, n), null;
    }
  }
  /**
   * Get plugin name
   */
  getName() {
    return this.plugin.name;
  }
  /**
   * Check if initialized
   */
  isInitialized() {
    return this.initialized;
  }
  /**
   * Get underlying plugin
   */
  getPlugin() {
    return this.plugin;
  }
  /**
   * Get context
   */
  getContext() {
    return this.context;
  }
}
function k(l) {
  return new E(l);
}
function T(l = {}) {
  const {
    enabled: e = !1,
    provider: t = "browser",
    apiUrl: i = "",
    apiHeaders: n = {},
    language: o = "en",
    customDictionary: s = [],
    ignoreAllCaps: a = !0,
    ignoreNumbers: r = !0
  } = l;
  return {
    name: "spellcheck",
    context: {
      initialize: () => {
        if (e)
          switch (console.log("[Spellcheck Plugin] Initialized", {
            provider: t,
            language: o
          }), t) {
            case "browser":
              console.log("[Spellcheck] Using browser spellcheck");
              break;
            case "local":
              console.log("[Spellcheck] Using local dictionary (not implemented)");
              break;
            case "api":
              i ? console.log("[Spellcheck] Using API:", i) : console.warn("[Spellcheck] API provider selected but no apiUrl provided");
              break;
          }
      },
      destroy: () => {
        console.log("[Spellcheck Plugin] Destroyed");
      },
      onEditorReady: (d) => {
        console.log("[Spellcheck Plugin] Editor ready");
      }
    },
    commands: {
      toggleSpellcheck: () => (console.log("[Spellcheck] Toggle command (not implemented)"), null),
      addToDictionary: (d) => (console.log("[Spellcheck] Add to dictionary:", d), null),
      checkSpelling: async () => (console.log("[Spellcheck] Check spelling (not implemented)"), null)
    },
    toolbar: e ? [
      {
        label: "Spellcheck",
        command: "toggleSpellcheck",
        icon: "Aa",
        type: "button"
      }
    ] : []
  };
}
function I(l = {}) {
  const {
    uploadUrl: e = "",
    libraryUrl: t = "",
    maxFileSize: i = 10 * 1024 * 1024,
    // 10MB
    allowedTypes: n = ["image/jpeg", "image/png", "image/gif", "image/webp"],
    headers: o = {},
    withCredentials: s = !1,
    chunkSize: a = 1024 * 1024,
    // 1MB chunks
    enableChunking: r = !0,
    onProgress: d,
    onError: h,
    onSuccess: C
  } = l;
  return {
    name: "media",
    context: {
      initialize: () => {
        console.log("[Media Plugin] Initialized", {
          uploadUrl: e,
          libraryUrl: t,
          maxFileSize: i,
          allowedTypes: n
        }), e || console.warn("[Media] No uploadUrl provided - upload will not work");
      },
      destroy: () => {
        console.log("[Media Plugin] Destroyed");
      },
      onEditorReady: (c) => {
        console.log("[Media Plugin] Editor ready");
      }
    },
    commands: {
      insertImage: async (c) => {
        if (console.log("[Media] Insert image command (not implemented)", c), !c)
          return console.log("[Media] No file provided - should open picker"), null;
        if (!n.includes(c.type)) {
          const p = new Error(`File type ${c.type} not allowed`);
          return h == null || h(p), null;
        }
        if (c.size > i) {
          const p = new Error(`File size ${c.size} exceeds max ${i}`);
          return h == null || h(p), null;
        }
        return null;
      },
      openMediaLibrary: () => (console.log("[Media] Open media library (not implemented)"), t || console.warn("[Media] No libraryUrl provided"), null),
      uploadMedia: async (c) => (console.log("[Media] Upload media (not implemented)", {
        name: c.name,
        size: c.size,
        type: c.type
      }), null)
    },
    toolbar: [
      {
        label: "Image",
        command: "insertImage",
        icon: "🖼️",
        type: "button"
      },
      {
        label: "Media Library",
        command: "openMediaLibrary",
        icon: "📁",
        type: "button"
      }
    ]
  };
}
class m {
  constructor(e, t = { anchor: 0, head: 0 }) {
    this.doc = e, this.selection = t;
  }
  getDocument() {
    return this.doc;
  }
  setDocument(e) {
    return new m(e, this.selection);
  }
  getSelection() {
    return { ...this.selection };
  }
  setSelection(e) {
    return new m(this.doc, e);
  }
  /**
   * Create a new model with updated document and selection
   */
  update(e, t) {
    return new m(
      e || this.doc,
      t || this.selection
    );
  }
  /**
   * Get text content
   */
  getTextContent() {
    return "";
  }
  /**
   * Check if selection is empty
   */
  isSelectionEmpty() {
    return this.selection.anchor === this.selection.head;
  }
}
class u {
  constructor(e) {
    this.config = {
      closeOnEscape: !0,
      closeOnBackdrop: !0,
      ...e
    }, this.element = this.createElement(), this.attachEventListeners();
  }
  createElement() {
    const e = document.createElement("dialog");
    e.className = "editora-dialog", this.config.width && (e.style.width = this.config.width), this.config.height && (e.style.height = this.config.height);
    const t = this.config.buttons && this.config.buttons.length > 0 ? this.config.buttons.map((i, n) => `<button type="button" class="editora-btn ${i.type === "danger" ? "editora-btn-danger" : i.type === "primary" || i.primary ? "editora-btn-primary" : "editora-btn-cancel"}" data-dialog-button="${n}">${i.label}</button>`).join("") : `
          <button type="button" class="editora-btn editora-btn-cancel" data-dialog-default="cancel">Cancel</button>
          <button type="button" class="editora-btn editora-btn-primary" data-dialog-default="ok">OK</button>
        `;
    if (e.innerHTML = `
      <div class="editora-dialog-container">
        <div class="editora-dialog-header">
          <h3>${this.config.title}</h3>
          <button class="editora-dialog-close" aria-label="Close">&times;</button>
        </div>
        <div class="editora-dialog-body">
          ${typeof this.config.content == "string" ? this.config.content : ""}
        </div>
        <div class="editora-dialog-footer">
          ${t}
        </div>
      </div>
    `, typeof this.config.content != "string") {
      const i = e.querySelector(".editora-dialog-body");
      i && (i.innerHTML = "", i.appendChild(this.config.content));
    }
    return e;
  }
  attachEventListeners() {
    const e = this.element.querySelector(".editora-dialog-close");
    if (e == null || e.addEventListener("click", () => this.close()), this.config.buttons && this.config.buttons.length > 0)
      this.element.querySelectorAll("[data-dialog-button]").forEach((i) => {
        i.addEventListener("click", () => {
          var s, a;
          const n = Number(i.getAttribute("data-dialog-button")), o = (s = this.config.buttons) == null ? void 0 : s[n];
          (a = o == null ? void 0 : o.onClick) == null || a.call(o);
        });
      });
    else {
      const t = this.element.querySelector('[data-dialog-default="cancel"]');
      t == null || t.addEventListener("click", () => {
        var n, o;
        (o = (n = this.config).onCancel) == null || o.call(n), this.close();
      });
      const i = this.element.querySelector('[data-dialog-default="ok"]');
      i == null || i.addEventListener("click", () => this.handleSubmit());
    }
    this.config.closeOnEscape && this.element.addEventListener("cancel", (t) => {
      t.preventDefault(), this.close();
    }), this.config.closeOnBackdrop && this.element.addEventListener("click", (t) => {
      const i = this.element.getBoundingClientRect();
      (t.clientX < i.left || t.clientX > i.right || t.clientY < i.top || t.clientY > i.bottom) && this.close();
    });
  }
  handleSubmit() {
    var t, i, n, o;
    const e = this.element.querySelector("form");
    if (e) {
      const s = new FormData(e);
      (i = (t = this.config).onSubmit) == null || i.call(t, s);
    } else {
      const s = this.element.querySelectorAll("input, select, textarea"), a = new FormData();
      s.forEach((r) => {
        r.name && a.append(r.name, r.value);
      }), (o = (n = this.config).onSubmit) == null || o.call(n, a);
    }
    this.close();
  }
  show() {
    document.body.appendChild(this.element), this.element.showModal();
  }
  close() {
    this.element.close(), this.element.remove();
  }
  destroy() {
    this.close();
  }
}
class F {
  constructor(e) {
    this.isOpen = !1, this.config = e, this.selectedValue = e.value, this.element = this.createElement(), this.attachEventListeners();
  }
  createElement() {
    const e = document.createElement("div");
    e.className = "editora-dropdown", this.config.width && (e.style.width = this.config.width);
    const t = this.config.options.find((n) => n.value === this.selectedValue), i = (t == null ? void 0 : t.label) || this.config.placeholder || "Select...";
    return e.innerHTML = `
      <button class="editora-dropdown-toggle" type="button">
        <span class="editora-dropdown-label">${i}</span>
        <span class="editora-dropdown-arrow">▼</span>
      </button>
      <div class="editora-dropdown-menu" style="display: none;">
        ${this.config.options.map((n) => `
          <div class="editora-dropdown-item" data-value="${n.value}">
            ${n.icon ? `<span class="editora-dropdown-icon">${n.icon}</span>` : ""}
            <span>${n.label}</span>
          </div>
        `).join("")}
      </div>
    `, e;
  }
  attachEventListeners() {
    const e = this.element.querySelector(".editora-dropdown-toggle"), t = this.element.querySelector(".editora-dropdown-menu");
    e.addEventListener("click", (n) => {
      n.stopPropagation(), this.isOpen = !this.isOpen, t.style.display = this.isOpen ? "block" : "none";
    }), this.element.querySelectorAll(".editora-dropdown-item").forEach((n) => {
      n.addEventListener("click", () => {
        var s, a;
        const o = n.getAttribute("data-value");
        o && (this.setValue(o), (a = (s = this.config).onChange) == null || a.call(s, o), this.close());
      });
    }), document.addEventListener("click", (n) => {
      this.element.contains(n.target) || this.close();
    });
  }
  setValue(e) {
    this.selectedValue = e;
    const t = this.config.options.find((n) => n.value === e), i = this.element.querySelector(".editora-dropdown-label");
    i && t && (i.textContent = t.label);
  }
  getValue() {
    return this.selectedValue;
  }
  close() {
    this.isOpen = !1;
    const e = this.element.querySelector(".editora-dropdown-menu");
    e && (e.style.display = "none");
  }
  getElement() {
    return this.element;
  }
  destroy() {
    this.element.remove();
  }
}
class M {
  constructor(e) {
    this.defaultPresets = [
      "#000000",
      "#434343",
      "#666666",
      "#999999",
      "#B7B7B7",
      "#CCCCCC",
      "#D9D9D9",
      "#EFEFEF",
      "#F3F3F3",
      "#FFFFFF",
      "#980000",
      "#FF0000",
      "#FF9900",
      "#FFFF00",
      "#00FF00",
      "#00FFFF",
      "#4A86E8",
      "#0000FF",
      "#9900FF",
      "#FF00FF",
      "#E6B8AF",
      "#F4CCCC",
      "#FCE5CD",
      "#FFF2CC",
      "#D9EAD3",
      "#D0E0E3",
      "#C9DAF8",
      "#CFE2F3",
      "#D9D2E9",
      "#EAD1DC"
    ], this.config = {
      presetColors: this.defaultPresets,
      ...e
    }, this.selectedColor = e.value, this.element = this.createElement(), this.attachEventListeners();
  }
  createElement() {
    var t;
    const e = document.createElement("div");
    return e.className = "editora-color-picker", e.innerHTML = `
      <div class="editora-color-picker-input">
        <input type="color" value="${this.selectedColor || "#000000"}" />
        <input type="text" value="${this.selectedColor || "#000000"}" placeholder="#000000" />
      </div>
      <div class="editora-color-picker-presets">
        ${(t = this.config.presetColors) == null ? void 0 : t.map((i) => `
          <button 
            class="editora-color-preset" 
            style="background-color: ${i};" 
            data-color="${i}"
            title="${i}"
          ></button>
        `).join("")}
      </div>
    `, e;
  }
  attachEventListeners() {
    const e = this.element.querySelector('input[type="color"]'), t = this.element.querySelector('input[type="text"]');
    e.addEventListener("input", (n) => {
      var s, a;
      const o = n.target.value;
      t.value = o, this.selectedColor = o, (a = (s = this.config).onChange) == null || a.call(s, o);
    }), t.addEventListener("input", (n) => {
      var s, a;
      const o = n.target.value;
      /^#[0-9A-Fa-f]{6}$/.test(o) && (e.value = o, this.selectedColor = o, (a = (s = this.config).onChange) == null || a.call(s, o));
    }), this.element.querySelectorAll(".editora-color-preset").forEach((n) => {
      n.addEventListener("click", () => {
        var s, a;
        const o = n.getAttribute("data-color");
        o && (e.value = o, t.value = o, this.selectedColor = o, (a = (s = this.config).onChange) == null || a.call(s, o));
      });
    });
  }
  getValue() {
    return this.selectedColor;
  }
  setValue(e) {
    this.selectedColor = e;
    const t = this.element.querySelector('input[type="color"]'), i = this.element.querySelector('input[type="text"]');
    t && (t.value = e), i && (i.value = e);
  }
  getElement() {
    return this.element;
  }
  destroy() {
    this.element.remove();
  }
}
class q {
  constructor(e) {
    const { initialUrl: t = "", initialText: i = "", onSubmit: n, onCancel: o } = e;
    this.dialog = new u({
      title: "Insert/Edit Link",
      content: this.createFormHTML(t, i),
      onSubmit: (s) => {
        const a = (s.get("url") || "").trim(), r = (s.get("text") || "").trim(), d = s.get("openInNewTab") === "on";
        if (!a) {
          alert("Please enter a URL");
          return;
        }
        n({ url: a, text: r, openInNewTab: d }), this.dialog.close();
      },
      onCancel: () => {
        o == null || o(), this.dialog.close();
      },
      width: "500px"
    });
  }
  createFormHTML(e, t) {
    return `
      <form class="link-dialog-form">
        <div class="form-group">
          <label for="link-url">URL</label>
          <input 
            type="url" 
            id="link-url"
            name="url" 
            placeholder="https://example.com"
            value="${this.escapeHtml(e)}"
            required 
            autofocus
          />
          <small>Enter the web address (URL) for the link</small>
        </div>

        <div class="form-group">
          <label for="link-text">Link Text</label>
          <input 
            type="text" 
            id="link-text"
            name="text" 
            placeholder="Click here"
            value="${this.escapeHtml(t)}"
          />
          <small>Text to display for the link (leave empty to use URL)</small>
        </div>

        <div class="form-group">
          <label class="checkbox-label">
            <input 
              type="checkbox" 
              name="openInNewTab"
              id="link-new-tab"
            />
            <span>Open link in new tab</span>
          </label>
        </div>

        <div class="form-actions">
          <button type="button" class="btn btn-secondary" data-action="cancel">
            Cancel
          </button>
          <button type="submit" class="btn btn-primary">
            Insert Link
          </button>
        </div>
      </form>
    `;
  }
  escapeHtml(e) {
    const t = document.createElement("div");
    return t.textContent = e, t.innerHTML;
  }
  show() {
    this.dialog.show();
  }
  close() {
    this.dialog.close();
  }
}
class j {
  constructor(e) {
    const { onSubmit: t, onCancel: i } = e;
    this.dialog = new u({
      title: "Insert Table",
      content: this.createFormHTML(),
      onSubmit: (n) => {
        const o = parseInt(n.get("rows"), 10), s = parseInt(n.get("cols"), 10), a = n.get("headerRow") === "on";
        if (o < 1 || o > 100) {
          alert("Please enter a valid number of rows (1-100)");
          return;
        }
        if (s < 1 || s > 20) {
          alert("Please enter a valid number of columns (1-20)");
          return;
        }
        t({ rows: o, cols: s, headerRow: a }), this.dialog.close();
      },
      onCancel: () => {
        i == null || i(), this.dialog.close();
      },
      width: "400px"
    });
  }
  createFormHTML() {
    return `
      <form class="table-dialog-form">
        <div class="form-group">
          <label for="table-rows">Rows</label>
          <input 
            type="number" 
            id="table-rows"
            name="rows" 
            min="1" 
            max="100" 
            value="3"
            required 
            autofocus
          />
          <small>Number of rows (1-100)</small>
        </div>

        <div class="form-group">
          <label for="table-cols">Columns</label>
          <input 
            type="number" 
            id="table-cols"
            name="cols" 
            min="1" 
            max="20" 
            value="3"
            required
          />
          <small>Number of columns (1-20)</small>
        </div>

        <div class="form-group">
          <label class="checkbox-label">
            <input 
              type="checkbox" 
              name="headerRow"
              id="table-header"
              checked
            />
            <span>Include header row</span>
          </label>
        </div>

        <div class="table-preview">
          <strong>Preview:</strong>
          <div id="table-preview-content" style="margin-top: 8px; font-size: 12px; color: #666;">
            3 rows × 3 columns with header
          </div>
        </div>

        <div class="form-actions">
          <button type="button" class="btn btn-secondary" data-action="cancel">
            Cancel
          </button>
          <button type="submit" class="btn btn-primary">
            Insert Table
          </button>
        </div>
      </form>
    `;
  }
  show() {
    this.dialog.show(), this.attachPreviewListeners();
  }
  close() {
    this.dialog.close();
  }
  attachPreviewListeners() {
    const e = document.querySelector(".table-dialog-form");
    if (!e) return;
    const t = e.querySelector("#table-rows"), i = e.querySelector("#table-cols"), n = e.querySelector("#table-header"), o = e.querySelector("#table-preview-content"), s = () => {
      const a = parseInt((t == null ? void 0 : t.value) || "3", 10), r = parseInt((i == null ? void 0 : i.value) || "3", 10), d = n == null ? void 0 : n.checked;
      o && (o.textContent = `${a} rows × ${r} columns${d ? " with header" : ""}`);
    };
    t == null || t.addEventListener("input", s), i == null || i.addEventListener("input", s), n == null || n.addEventListener("change", s);
  }
}
class $ {
  constructor(e) {
    this.config = e;
    const { onSubmit: t, onCancel: i } = e;
    this.dialog = new u({
      title: "Insert Image",
      content: this.createFormHTML(),
      onSubmit: (n) => {
        const o = (n.get("src") || "").trim(), s = (n.get("alt") || "").trim(), a = (n.get("width") || "").trim(), r = (n.get("height") || "").trim();
        if (!o) {
          alert("Please enter an image URL or upload an image");
          return;
        }
        t({
          src: o,
          alt: s,
          width: a || void 0,
          height: r || void 0
        }), this.dialog.close();
      },
      onCancel: () => {
        i == null || i(), this.dialog.close();
      },
      width: "500px"
    });
  }
  createFormHTML() {
    return `
      <form class="image-dialog-form">
        ${this.config.allowUpload ? `
      <div class="form-group">
        <label for="image-upload">Upload Image</label>
        <input 
          type="file" 
          id="image-upload"
          accept="image/*"
        />
        <small>Or upload an image from your computer</small>
      </div>
      <div class="form-divider">OR</div>
    ` : ""}

        <div class="form-group">
          <label for="image-src">Image URL</label>
          <input 
            type="url" 
            id="image-src"
            name="src" 
            placeholder="https://example.com/image.jpg"
            ${this.config.allowUpload ? "" : "required autofocus"}
          />
          <small>Enter the web address (URL) of the image</small>
        </div>

        <div class="form-group">
          <label for="image-alt">Alt Text</label>
          <input 
            type="text" 
            id="image-alt"
            name="alt" 
            placeholder="Description of the image"
          />
          <small>Alternative text for accessibility (recommended)</small>
        </div>

        <div class="form-row">
          <div class="form-group">
            <label for="image-width">Width</label>
            <input 
              type="text" 
              id="image-width"
              name="width" 
              placeholder="auto"
            />
          </div>

          <div class="form-group">
            <label for="image-height">Height</label>
            <input 
              type="text" 
              id="image-height"
              name="height" 
              placeholder="auto"
            />
          </div>
        </div>

        <div class="image-preview" id="image-preview" style="display: none;">
          <strong>Preview:</strong>
          <img id="preview-img" style="max-width: 100%; max-height: 200px; margin-top: 8px;" />
        </div>

        <div class="form-actions">
          <button type="button" class="btn btn-secondary" data-action="cancel">
            Cancel
          </button>
          <button type="submit" class="btn btn-primary">
            Insert Image
          </button>
        </div>
      </form>
    `;
  }
  show() {
    this.dialog.show(), this.attachImagePreview(), this.attachFileUpload();
  }
  close() {
    this.dialog.close();
  }
  attachImagePreview() {
    const e = document.querySelector(".image-dialog-form");
    if (!e) return;
    const t = e.querySelector("#image-src"), i = e.querySelector("#image-preview"), n = e.querySelector("#preview-img");
    t == null || t.addEventListener("input", () => {
      const o = t.value.trim();
      o && this.isValidImageUrl(o) ? (n.src = o, i.style.display = "block", n.onerror = () => {
        i.style.display = "none";
      }) : i.style.display = "none";
    });
  }
  attachFileUpload() {
    if (!this.config.allowUpload) return;
    const e = document.querySelector(".image-dialog-form");
    if (!e) return;
    const t = e.querySelector("#image-upload"), i = e.querySelector("#image-src");
    t == null || t.addEventListener("change", async (n) => {
      var a;
      const o = (a = n.target.files) == null ? void 0 : a[0];
      if (!o) return;
      const s = new FileReader();
      s.onload = (r) => {
        var h;
        const d = (h = r.target) == null ? void 0 : h.result;
        i.value = d, i.dispatchEvent(new Event("input"));
      }, s.readAsDataURL(o);
    });
  }
  isValidImageUrl(e) {
    try {
      return new URL(e), /\.(jpg|jpeg|png|gif|svg|webp|bmp)$/i.test(e) || e.startsWith("data:image/");
    } catch (t) {
      return !1;
    }
  }
}
class P {
  constructor(e) {
    this.onSubmit = e.onSubmit;
    const t = this.createContent();
    this.dialog = new u({
      title: "Insert Math Equation",
      content: t,
      buttons: [
        {
          label: "Cancel",
          onClick: () => this.dialog.close()
        },
        {
          label: "Insert",
          onClick: () => this.handleSubmit(),
          primary: !0
        }
      ]
    }), this.latexInput = t.querySelector("#math-latex"), this.previewDiv = t.querySelector("#math-preview"), this.displayTypeSelect = t.querySelector("#math-display-type"), this.latexInput.addEventListener("input", () => this.updatePreview());
  }
  createContent() {
    const e = document.createElement("div");
    return e.className = "math-dialog-content", e.style.minWidth = "500px", e.innerHTML = `
      <style>
        .math-dialog-content {
          display: flex;
          flex-direction: column;
          gap: 1rem;
        }
        .math-form-group {
          display: flex;
          flex-direction: column;
          gap: 0.5rem;
        }
        .math-form-group label {
          font-weight: 500;
          color: #333;
        }
        .math-latex-input {
          width: 100%;
          min-height: 80px;
          padding: 0.5rem;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-family: 'Courier New', monospace;
          font-size: 14px;
          resize: vertical;
        }
        .math-preview {
          padding: 1rem;
          background: #f9f9f9;
          border: 1px solid #ddd;
          border-radius: 4px;
          min-height: 60px;
          font-size: 18px;
          text-align: center;
        }
        .math-preview:empty::before {
          content: 'Preview will appear here...';
          color: #999;
          font-style: italic;
        }
        .math-symbols {
          display: grid;
          grid-template-columns: repeat(8, 1fr);
          gap: 0.5rem;
          padding: 0.5rem;
          background: #f5f5f5;
          border-radius: 4px;
        }
        .math-symbol-btn {
          padding: 0.5rem;
          border: 1px solid #ddd;
          background: white;
          border-radius: 4px;
          cursor: pointer;
          font-size: 18px;
          transition: all 0.2s;
        }
        .math-symbol-btn:hover {
          background: #e3f2fd;
          border-color: #2196f3;
        }
        .math-display-select {
          padding: 0.5rem;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-size: 14px;
        }
      </style>

      <div class="math-form-group">
        <label for="math-latex">LaTeX Expression:</label>
        <textarea 
          id="math-latex" 
          class="math-latex-input"
          placeholder="Enter LaTeX (e.g., x^2 + y^2 = r^2)"
        ></textarea>
      </div>

      <div class="math-form-group">
        <label>Common Symbols:</label>
        <div class="math-symbols">
          <button class="math-symbol-btn" data-symbol="\\frac{a}{b}" title="Fraction">a/b</button>
          <button class="math-symbol-btn" data-symbol="x^{2}" title="Superscript">x²</button>
          <button class="math-symbol-btn" data-symbol="x_{i}" title="Subscript">xᵢ</button>
          <button class="math-symbol-btn" data-symbol="\\sqrt{x}" title="Square root">√x</button>
          <button class="math-symbol-btn" data-symbol="\\sum" title="Sum">∑</button>
          <button class="math-symbol-btn" data-symbol="\\int" title="Integral">∫</button>
          <button class="math-symbol-btn" data-symbol="\\pi" title="Pi">π</button>
          <button class="math-symbol-btn" data-symbol="\\alpha" title="Alpha">α</button>
          <button class="math-symbol-btn" data-symbol="\\beta" title="Beta">β</button>
          <button class="math-symbol-btn" data-symbol="\\gamma" title="Gamma">γ</button>
          <button class="math-symbol-btn" data-symbol="\\theta" title="Theta">θ</button>
          <button class="math-symbol-btn" data-symbol="\\lambda" title="Lambda">λ</button>
          <button class="math-symbol-btn" data-symbol="\\infty" title="Infinity">∞</button>
          <button class="math-symbol-btn" data-symbol="\\leq" title="Less or equal">≤</button>
          <button class="math-symbol-btn" data-symbol="\\geq" title="Greater or equal">≥</button>
          <button class="math-symbol-btn" data-symbol="\\neq" title="Not equal">≠</button>
        </div>
      </div>

      <div class="math-form-group">
        <label for="math-preview">Preview:</label>
        <div id="math-preview" class="math-preview"></div>
      </div>

      <div class="math-form-group">
        <label for="math-display-type">Display Type:</label>
        <select id="math-display-type" class="math-display-select">
          <option value="inline">Inline (within text)</option>
          <option value="block">Block (centered, new line)</option>
        </select>
      </div>
    `, e.querySelectorAll(".math-symbol-btn").forEach((i) => {
      i.addEventListener("click", (n) => {
        n.preventDefault();
        const o = i.getAttribute("data-symbol");
        if (o && this.latexInput) {
          const s = this.latexInput.selectionStart, a = this.latexInput.selectionEnd, r = this.latexInput.value;
          this.latexInput.value = r.substring(0, s) + o + r.substring(a), this.latexInput.focus(), this.latexInput.selectionStart = this.latexInput.selectionEnd = s + o.length, this.updatePreview();
        }
      });
    }), e;
  }
  updatePreview() {
    const e = this.latexInput.value.trim();
    if (!e) {
      this.previewDiv.textContent = "";
      return;
    }
    let t = e.replace(/\\frac\{([^}]+)\}\{([^}]+)\}/g, "($1)/($2)").replace(/\^\{([^}]+)\}/g, "^$1").replace(/\_\{([^}]+)\}/g, "_$1").replace(/\\sqrt\{([^}]+)\}/g, "√($1)").replace(/\\sum/g, "∑").replace(/\\int/g, "∫").replace(/\\pi/g, "π").replace(/\\alpha/g, "α").replace(/\\beta/g, "β").replace(/\\gamma/g, "γ").replace(/\\theta/g, "θ").replace(/\\lambda/g, "λ").replace(/\\infty/g, "∞").replace(/\\leq/g, "≤").replace(/\\geq/g, "≥").replace(/\\neq/g, "≠");
    this.previewDiv.textContent = t;
  }
  handleSubmit() {
    const e = this.latexInput.value.trim();
    if (!e) {
      alert("Please enter a LaTeX expression.");
      return;
    }
    const t = this.displayTypeSelect.value;
    this.onSubmit({ latex: e, display: t }), this.dialog.close();
  }
  show() {
    this.dialog.show(), this.latexInput.value = "", this.previewDiv.textContent = "", this.displayTypeSelect.value = "inline", setTimeout(() => this.latexInput.focus(), 100);
  }
  close() {
    this.dialog.close();
  }
}
class H {
  constructor(e) {
    this.characters = {
      common: ["©", "®", "™", "§", "¶", "†", "‡", "•", "‣", "⁃", "◦", "▪", "▫", "◊", "○", "●", "□", "■", "△", "▲", "▽", "▼", "◇", "◆", "★", "☆"],
      arrows: ["←", "→", "↑", "↓", "↔", "↕", "⇐", "⇒", "⇑", "⇓", "⇔", "⇕", "⟵", "⟶", "⟷", "↖", "↗", "↘", "↙", "⇖", "⇗", "⇘", "⇙"],
      currency: ["$", "€", "£", "¥", "₹", "₽", "₩", "₪", "₦", "฿", "₴", "₡", "₵", "₸", "₫", "₱", "₲", "₳", "₭"],
      math: ["±", "×", "÷", "=", "≠", "≈", "≡", "≤", "≥", "<", ">", "∞", "∑", "∏", "∫", "∂", "√", "∛", "∜", "°", "′", "″", "∠", "∟", "⊥", "∥"],
      greek: ["α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "Α", "Β", "Γ", "Δ", "Ε", "Ζ", "Η", "Θ"],
      punctuation: ["‚", "„", "“", "”", "‘", "’", "«", "»", "‹", "›", "—", "–", "…", "·", "¡", "¿", "‰", "′", "″", "‴"],
      superscript: ["⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", "⁺", "⁻", "⁼", "⁽", "⁾", "ⁿ", "ⁱ"],
      subscript: ["₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", "₊", "₋", "₌", "₍", "₎"]
    }, this.onSelect = e.onSelect;
    const t = this.createContent();
    this.dialog = new u({
      title: "Insert Special Character",
      content: t,
      buttons: [
        {
          label: "Close",
          onClick: () => this.dialog.close()
        }
      ]
    }), this.searchInput = t.querySelector("#char-search"), this.categorySelect = t.querySelector("#char-category"), this.charactersGrid = t.querySelector("#char-grid"), this.searchInput.addEventListener("input", () => this.filterCharacters()), this.categorySelect.addEventListener("change", () => this.updateGrid()), this.updateGrid();
  }
  createContent() {
    const e = document.createElement("div");
    return e.className = "character-dialog-content", e.style.minWidth = "500px", e.innerHTML = `
      <style>
        .character-dialog-content {
          display: flex;
          flex-direction: column;
          gap: 1rem;
        }
        .char-controls {
          display: flex;
          gap: 0.5rem;
        }
        .char-search, .char-category {
          padding: 0.5rem;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-size: 14px;
        }
        .char-search {
          flex: 1;
        }
        .char-category {
          min-width: 150px;
        }
        .char-grid {
          display: grid;
          grid-template-columns: repeat(10, 1fr);
          gap: 0.5rem;
          max-height: 300px;
          overflow-y: auto;
          padding: 1rem;
          background: #f9f9f9;
          border: 1px solid #ddd;
          border-radius: 4px;
        }
        .char-button {
          aspect-ratio: 1;
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 0.5rem;
          border: 1px solid #ddd;
          background: white;
          border-radius: 4px;
          cursor: pointer;
          font-size: 20px;
          transition: all 0.2s;
        }
        .char-button:hover {
          background: #e3f2fd;
          border-color: #2196f3;
          transform: scale(1.1);
        }
        .char-info {
          padding: 0.5rem;
          background: #f5f5f5;
          border-radius: 4px;
          font-size: 12px;
          color: #666;
          text-align: center;
        }
      </style>

      <div class="char-controls">
        <input 
          type="text" 
          id="char-search" 
          class="char-search" 
          placeholder="Search characters..."
        />
        <select id="char-category" class="char-category">
          <option value="all">All Categories</option>
          <option value="common">Common Symbols</option>
          <option value="arrows">Arrows</option>
          <option value="currency">Currency</option>
          <option value="math">Mathematics</option>
          <option value="greek">Greek Letters</option>
          <option value="punctuation">Punctuation</option>
          <option value="superscript">Superscript</option>
          <option value="subscript">Subscript</option>
        </select>
      </div>

      <div id="char-grid" class="char-grid"></div>

      <div class="char-info">
        Click any character to insert it into your document.
      </div>
    `, e;
  }
  updateGrid() {
    const e = this.categorySelect.value;
    this.charactersGrid.innerHTML = "";
    let t = [];
    e === "all" ? t = Object.values(this.characters).flat() : t = this.characters[e] || [], t.forEach((i) => {
      const n = document.createElement("button");
      n.className = "char-button", n.textContent = i, n.title = `Insert ${i} (U+${i.charCodeAt(0).toString(16).toUpperCase()})`, n.addEventListener("click", (o) => {
        o.preventDefault(), this.handleSelect(i);
      }), this.charactersGrid.appendChild(n);
    });
  }
  filterCharacters() {
    const e = this.searchInput.value.toLowerCase();
    this.charactersGrid.querySelectorAll(".char-button").forEach((i) => {
      const n = i.textContent || "", o = `u+${n.charCodeAt(0).toString(16)}`, s = !e || n.includes(e) || o.includes(e);
      i.style.display = s ? "flex" : "none";
    });
  }
  handleSelect(e) {
    this.onSelect(e), this.dialog.close();
  }
  show() {
    this.dialog.show(), this.searchInput.value = "", this.categorySelect.value = "all", this.updateGrid(), setTimeout(() => this.searchInput.focus(), 100);
  }
  close() {
    this.dialog.close();
  }
}
class A {
  constructor(e) {
    this.emojis = {
      popular: ["😀", "😃", "😄", "😁", "😊", "😍", "🤩", "😘", "😗", "😚", "😙", "🙂", "🤗", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "👍", "👎", "👌", "✌️", "🤞", "🤝", "👏", "🙌", "👋", "🤚", "✋", "🖐️", "🖖", "👊", "✊", "🤛", "🤜", "💪"],
      smileys: ["😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "🙃", "😉", "😊", "😇", "🥰", "😍", "🤩", "😘", "😗", "😚", "😙", "😋", "😛", "😜", "🤪", "😝", "🤑", "🤗", "🤭", "🤫", "🤔"],
      emotions: ["😳", "😞", "😟", "😠", "😡", "🤬", "😔", "😕", "🙁", "😬", "🥺", "😣", "😖", "😫", "😩", "🥱", "😤", "😮", "😱", "😨", "😰", "😥", "😢", "😭", "😪", "😓", "🤤", "😴", "😷", "🤒"],
      gestures: ["👍", "👎", "👌", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "👇", "☝️", "👋", "🤚", "✋", "🖐️", "🖖", "👏", "🙌", "👐", "🤲", "🤝", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦿"],
      people: ["👶", "👧", "🧒", "👦", "👩", "🧑", "👨", "👵", "🧓", "👴", "👲", "👳", "🧕", "👮", "👷", "💂", "🕵️", "👩‍⚕️", "👨‍⚕️", "👩‍🎓", "👨‍🎓", "👩‍🏫", "👨‍🏫", "👩‍⚖️", "👨‍⚖️", "👩‍🌾", "👨‍🌾", "👩‍🍳", "👨‍🍳", "👩‍🔧"],
      animals: ["🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯", "🦁", "🐮", "🐷", "🐸", "🐵", "🙈", "🙉", "🙊", "🐔", "🐧", "🐦", "🐤", "🐣", "🐥", "🦆", "🦅", "🦉", "🦇", "🐺", "🐗"],
      nature: ["🌵", "🎄", "🌲", "🌳", "🌴", "🌱", "🌿", "☘️", "🍀", "🎍", "🎋", "🍃", "🍂", "🍁", "🍄", "🌾", "💐", "🌷", "🌹", "🥀", "🌺", "🌸", "🌼", "🌻", "🌞", "🌝", "🌛", "🌜", "⭐", "🌟"],
      food: ["🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", "🍑", "🥭", "🍍", "🥥", "🥝", "🍅", "🍆", "🥑", "🥦", "🥬", "🥒", "🌶️", "🌽", "🥕", "🧄", "🧅", "🥔", "🍠", "🥐"],
      objects: ["⌚", "📱", "💻", "⌨️", "🖥️", "🖨️", "🖱️", "🕹️", "💾", "💿", "📀", "📷", "📹", "🎥", "📞", "☎️", "📟", "📠", "📺", "📻", "🎙️", "🎚️", "🎛️", "🧭", "⏱️", "⏰", "📡", "🔋", "🔌", "💡"],
      symbols: ["❤️", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "🤎", "💔", "❣️", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "✨", "💫", "⭐", "🌟", "✔️", "✅", "❌", "❎", "➕", "➖", "✖️", "➗"],
      activities: ["⚽", "🏀", "🏈", "⚾", "🥎", "🎾", "🏐", "🏉", "🥏", "🎱", "🪀", "🏓", "🏸", "🏒", "🏑", "🥍", "🏏", "🪃", "🥅", "⛳", "🪁", "🏹", "🎣", "🤿", "🥊", "🥋", "🎽", "🛹", "🛼", "🛷"]
    }, this.onSelect = e.onSelect;
    const t = this.createContent();
    this.dialog = new u({
      title: "Insert Emoji",
      content: t,
      buttons: [
        {
          label: "Close",
          onClick: () => this.dialog.close()
        }
      ]
    }), this.searchInput = t.querySelector("#emoji-search"), this.categorySelect = t.querySelector("#emoji-category"), this.emojisGrid = t.querySelector("#emoji-grid"), this.searchInput.addEventListener("input", () => this.filterEmojis()), this.categorySelect.addEventListener("change", () => this.updateGrid()), this.updateGrid();
  }
  createContent() {
    const e = document.createElement("div");
    return e.className = "emoji-dialog-content", e.style.minWidth = "500px", e.innerHTML = `
      <style>
        .emoji-dialog-content {
          display: flex;
          flex-direction: column;
          gap: 1rem;
        }
        .emoji-controls {
          display: flex;
          gap: 0.5rem;
        }
        .emoji-search, .emoji-category {
          padding: 0.5rem;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-size: 14px;
        }
        .emoji-search {
          flex: 1;
        }
        .emoji-category {
          min-width: 150px;
        }
        .emoji-grid {
          display: grid;
          grid-template-columns: repeat(10, 1fr);
          gap: 0.5rem;
          max-height: 350px;
          overflow-y: auto;
          padding: 1rem;
          background: #f9f9f9;
          border: 1px solid #ddd;
          border-radius: 4px;
        }
        .emoji-button {
          aspect-ratio: 1;
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 0.5rem;
          border: 1px solid #ddd;
          background: white;
          border-radius: 4px;
          cursor: pointer;
          font-size: 24px;
          transition: all 0.2s;
        }
        .emoji-button:hover {
          background: #fff3e0;
          border-color: #ff9800;
          transform: scale(1.15);
        }
        .emoji-info {
          padding: 0.5rem;
          background: #f5f5f5;
          border-radius: 4px;
          font-size: 12px;
          color: #666;
          text-align: center;
        }
      </style>

      <div class="emoji-controls">
        <input 
          type="text" 
          id="emoji-search" 
          class="emoji-search" 
          placeholder="Search emojis..."
        />
        <select id="emoji-category" class="emoji-category">
          <option value="all">All Emojis</option>
          <option value="popular">Popular</option>
          <option value="smileys">Smileys & Faces</option>
          <option value="emotions">Emotions</option>
          <option value="gestures">Gestures & Hands</option>
          <option value="people">People</option>
          <option value="animals">Animals</option>
          <option value="nature">Nature</option>
          <option value="food">Food & Drink</option>
          <option value="objects">Objects</option>
          <option value="symbols">Symbols</option>
          <option value="activities">Activities & Sports</option>
        </select>
      </div>

      <div id="emoji-grid" class="emoji-grid"></div>

      <div class="emoji-info">
        Click any emoji to insert it into your document.
      </div>
    `, e;
  }
  updateGrid() {
    const e = this.categorySelect.value;
    this.emojisGrid.innerHTML = "";
    let t = [];
    e === "all" ? t = Object.values(this.emojis).flat() : t = this.emojis[e] || [], t.forEach((i) => {
      const n = document.createElement("button");
      n.className = "emoji-button", n.textContent = i, n.title = `Insert ${i}`, n.addEventListener("click", (o) => {
        o.preventDefault(), this.handleSelect(i);
      }), this.emojisGrid.appendChild(n);
    });
  }
  filterEmojis() {
    const e = this.searchInput.value.toLowerCase();
    this.emojisGrid.querySelectorAll(".emoji-button").forEach((i) => {
      const n = i.textContent || "", o = !e || n.includes(e);
      i.style.display = o ? "flex" : "none";
    });
  }
  handleSelect(e) {
    this.onSelect(e), this.dialog.close();
  }
  show() {
    this.dialog.show(), this.searchInput.value = "", this.categorySelect.value = "popular", this.updateGrid(), setTimeout(() => this.searchInput.focus(), 100);
  }
  close() {
    this.dialog.close();
  }
}
class x {
  constructor(e = {}) {
    this.changeListeners = [], this.options = e, this.engine = new b({
      content: e.content,
      plugins: e.plugins || [],
      readonly: e.readonly
    }), e.onChange && this.onChange(e.onChange), this.engine.on("change", () => {
      const t = this.getHTML();
      this.changeListeners.forEach((i) => i(t));
    });
  }
  /**
   * Mount editor to DOM elements
   */
  mount(e, t) {
    this.contentElement = e, this.toolbarElement = t, this.contentElement.contentEditable = this.options.readonly ? "false" : "true", this.contentElement.className = "rte-content", this.options.content && (this.contentElement.innerHTML = this.options.content), this.options.toolbar !== !1 && this.toolbarElement && (this.toolbar = new f(
      {
        items: typeof this.options.toolbar == "string" ? this.options.toolbar : void 0
      },
      this.options.plugins || []
    ), this.toolbar.setCommandHandler((i, n) => {
      this.execCommand(i, n);
    }), this.toolbar.render(this.toolbarElement)), this.contentElement.addEventListener("input", () => {
      const i = this.getHTML();
      this.changeListeners.forEach((n) => n(i));
    }), this.options.onInit && this.options.onInit(this.getAPI());
  }
  /**
   * Get HTML content
   */
  getHTML() {
    var e;
    return ((e = this.contentElement) == null ? void 0 : e.innerHTML) || "";
  }
  /**
   * Set HTML content
   */
  setHTML(e) {
    this.contentElement && (this.contentElement.innerHTML = e);
  }
  /**
   * Execute command
   */
  execCommand(e, t) {
    const i = this.engine.execCommand(e, t);
    return this.toolbar, i;
  }
  /**
   * Focus editor
   */
  focus() {
    var e;
    (e = this.contentElement) == null || e.focus();
  }
  /**
   * Blur editor
   */
  blur() {
    var e;
    (e = this.contentElement) == null || e.blur();
  }
  /**
   * Register change listener
   */
  onChange(e) {
    return this.changeListeners.push(e), () => {
      const t = this.changeListeners.indexOf(e);
      t > -1 && this.changeListeners.splice(t, 1);
    };
  }
  /**
   * Register command
   */
  registerCommand(e, t) {
    if (typeof window != "undefined") {
      const i = window.__editorCommands || /* @__PURE__ */ new Map();
      i.set(e, t), window.__editorCommands = i;
    }
  }
  /**
   * Get state
   */
  getState() {
    return {
      plugins: this.options.plugins,
      config: this.options,
      engine: this.engine.getState()
    };
  }
  /**
   * Get public API
   */
  getAPI() {
    var e;
    return {
      getHTML: () => this.getHTML(),
      setHTML: (t) => this.setHTML(t),
      execCommand: (t, i) => this.execCommand(t, i),
      focus: () => this.focus(),
      blur: () => this.blur(),
      destroy: () => this.destroy(),
      registerCommand: (t, i) => this.registerCommand(t, i),
      onChange: (t) => this.onChange(t),
      getState: () => this.getState(),
      toolbar: {
        items: ((e = this.options.plugins) == null ? void 0 : e.flatMap((t) => t.toolbar || [])) || []
      }
    };
  }
  /**
   * Destroy editor
   */
  destroy() {
    var e;
    this.engine.destroy(), (e = this.toolbar) == null || e.destroy(), this.changeListeners = [], this.options.onDestroy && this.options.onDestroy();
  }
}
function D(l) {
  return new x(l);
}
class w {
  constructor(e) {
    this.options = e, this.containerElement = e.element;
    const t = this.resolvePlugins(e.plugins);
    this.engine = new b({
      content: e.content,
      plugins: t,
      readonly: e.readonly
    }), this.initializeDOM();
  }
  /**
   * Resolve plugins from string or array
   */
  resolvePlugins(e) {
    return e ? typeof e == "string" ? (console.warn("String-based plugin loading not yet implemented for VanillaAdapter"), []) : e : [];
  }
  /**
   * Initialize DOM elements
   */
  initializeDOM() {
    this.containerElement.innerHTML = "", this.containerElement.classList.add("editora-editor"), this.options.enableToolbar !== !1 && this.options.toolbar !== !1 && (this.toolbarElement = document.createElement("div"), this.toolbarElement.className = "editora-toolbar-container", this.containerElement.appendChild(this.toolbarElement), this.toolbar = new f(
      {
        items: typeof this.options.toolbar == "string" ? this.options.toolbar : void 0
      },
      this.options.plugins || []
    ), this.toolbar.setCommandHandler((e, t) => {
      this.execCommand(e, t);
    }), this.toolbar.render(this.toolbarElement)), this.contentElement = document.createElement("div"), this.contentElement.className = "editora-content", this.contentElement.contentEditable = this.options.readonly ? "false" : "true", this.contentElement.style.minHeight = "200px", this.contentElement.style.outline = "none", this.contentElement.style.padding = "12px", this.options.content && (this.contentElement.innerHTML = this.options.content), this.containerElement.appendChild(this.contentElement), this.contentElement.addEventListener("input", () => {
      this.containerElement.dispatchEvent(new CustomEvent("change", {
        detail: { html: this.getContent() }
      }));
    });
  }
  /**
   * Get content
   */
  getContent() {
    var e;
    return ((e = this.contentElement) == null ? void 0 : e.innerHTML) || "";
  }
  /**
   * Set content
   */
  setContent(e) {
    this.contentElement && (this.contentElement.innerHTML = e);
  }
  /**
   * Execute command
   */
  execCommand(e, t) {
    return this.engine.execCommand(e, t);
  }
  /**
   * Focus editor
   */
  focus() {
    var e;
    (e = this.contentElement) == null || e.focus();
  }
  /**
   * Add event listener
   */
  on(e, t) {
    const i = (n) => {
      t(n.detail);
    };
    return this.containerElement.addEventListener(e, i), () => {
      this.containerElement.removeEventListener(e, i);
    };
  }
  /**
   * Destroy editor
   */
  destroy() {
    var e;
    this.engine.destroy(), (e = this.toolbar) == null || e.destroy(), this.containerElement.innerHTML = "";
  }
}
function z(l) {
  return new w(l);
}
function U() {
  typeof window != "undefined" && !customElements.get("editora-editor") && customElements.define("editora-editor", v);
}
export {
  H as CharacterDialog,
  M as ColorPicker,
  G as CommandRegistry,
  O as ConfigResolver,
  u as Dialog,
  m as DocumentModel,
  F as Dropdown,
  L as Editor,
  b as EditorEngine,
  y as EditorState,
  A as EmojiDialog,
  V as FloatingToolbar,
  $ as ImageDialog,
  K as KeyboardShortcutManager,
  q as LinkDialog,
  P as MathDialog,
  I as MediaPlugin,
  B as PluginLoader,
  g as PluginManager,
  E as PluginRuntime,
  x as ReactAdapter,
  v as RichTextEditorElement,
  W as Schema,
  T as SpellcheckPlugin,
  X as StatusBar,
  j as TableDialog,
  f as ToolbarRenderer,
  w as VanillaAdapter,
  _ as calculateTextStats,
  Y as countLines,
  z as createEditor,
  k as createPluginRuntime,
  D as createReactAdapter,
  J as getCursorPosition,
  Q as getSelectionInfo,
  Z as getTextOffset,
  U as initWebComponent
};
//# sourceMappingURL=index.esm.js.map
