@editora/core 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +9 -0
  2. package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs +475 -0
  3. package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs.map +1 -0
  4. package/dist/AnchorPlugin.native-7es9PVZ9.mjs +340 -0
  5. package/dist/AnchorPlugin.native-7es9PVZ9.mjs.map +1 -0
  6. package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs +449 -0
  7. package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs.map +1 -0
  8. package/dist/BlockquotePlugin.native-JFmOLsxN.mjs +48 -0
  9. package/dist/BlockquotePlugin.native-JFmOLsxN.mjs.map +1 -0
  10. package/dist/BoldPlugin.native-BAzzoqU5.mjs +45 -0
  11. package/dist/BoldPlugin.native-BAzzoqU5.mjs.map +1 -0
  12. package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs +79 -0
  13. package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs.map +1 -0
  14. package/dist/ChecklistPlugin.native-Dccs3nLe.mjs +153 -0
  15. package/dist/ChecklistPlugin.native-Dccs3nLe.mjs.map +1 -0
  16. package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs +27 -0
  17. package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs.map +1 -0
  18. package/dist/CodePlugin.native-DD9xFIid.mjs +1679 -0
  19. package/dist/CodePlugin.native-DD9xFIid.mjs.map +1 -0
  20. package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs +326 -0
  21. package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs.map +1 -0
  22. package/dist/CommentsPlugin.native-2zQV8Ia4.mjs +473 -0
  23. package/dist/CommentsPlugin.native-2zQV8Ia4.mjs.map +1 -0
  24. package/dist/DirectionPlugin.native-Be7wCzkI.mjs +59 -0
  25. package/dist/DirectionPlugin.native-Be7wCzkI.mjs.map +1 -0
  26. package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs +116 -0
  27. package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs.map +1 -0
  28. package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs +461 -0
  29. package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs.map +1 -0
  30. package/dist/EmojisPlugin.native-D6mJSnSR.mjs +1033 -0
  31. package/dist/EmojisPlugin.native-D6mJSnSR.mjs.map +1 -0
  32. package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs +106 -0
  33. package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs.map +1 -0
  34. package/dist/FontSizePlugin.native-DkLMLPue.mjs +186 -0
  35. package/dist/FontSizePlugin.native-DkLMLPue.mjs.map +1 -0
  36. package/dist/FootnotePlugin.native-BciVc9W6.mjs +128 -0
  37. package/dist/FootnotePlugin.native-BciVc9W6.mjs.map +1 -0
  38. package/dist/FullscreenPlugin.native-ChXyxeNw.mjs +77 -0
  39. package/dist/FullscreenPlugin.native-ChXyxeNw.mjs.map +1 -0
  40. package/dist/HeadingPlugin.native-DrLYwQnQ.mjs +64 -0
  41. package/dist/HeadingPlugin.native-DrLYwQnQ.mjs.map +1 -0
  42. package/dist/HistoryPlugin.native-DoDRifCf.mjs +89 -0
  43. package/dist/HistoryPlugin.native-DoDRifCf.mjs.map +1 -0
  44. package/dist/IndentPlugin.native-CbFugPoi.mjs +133 -0
  45. package/dist/IndentPlugin.native-CbFugPoi.mjs.map +1 -0
  46. package/dist/ItalicPlugin.native-CQjjDyUL.mjs +43 -0
  47. package/dist/ItalicPlugin.native-CQjjDyUL.mjs.map +1 -0
  48. package/dist/LineHeightPlugin.native-CWQT2FIa.mjs +73 -0
  49. package/dist/LineHeightPlugin.native-CWQT2FIa.mjs.map +1 -0
  50. package/dist/LinkPlugin.native-BdAOV-iu.mjs +206 -0
  51. package/dist/LinkPlugin.native-BdAOV-iu.mjs.map +1 -0
  52. package/dist/ListPlugin.native-CLFU5AUQ.mjs +59 -0
  53. package/dist/ListPlugin.native-CLFU5AUQ.mjs.map +1 -0
  54. package/dist/MathPlugin.native-DE_ii-LA.mjs +182 -0
  55. package/dist/MathPlugin.native-DE_ii-LA.mjs.map +1 -0
  56. package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs +533 -0
  57. package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs.map +1 -0
  58. package/dist/MergeTagPlugin.native-CrxyThyn.mjs +178 -0
  59. package/dist/MergeTagPlugin.native-CrxyThyn.mjs.map +1 -0
  60. package/dist/PageBreakPlugin.native-DDjcDyRW.mjs +172 -0
  61. package/dist/PageBreakPlugin.native-DDjcDyRW.mjs.map +1 -0
  62. package/dist/PreviewPlugin.native-DBvfpmIv.mjs +322 -0
  63. package/dist/PreviewPlugin.native-DBvfpmIv.mjs.map +1 -0
  64. package/dist/PrintPlugin.native-BUpm52VJ.mjs +311 -0
  65. package/dist/PrintPlugin.native-BUpm52VJ.mjs.map +1 -0
  66. package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs +731 -0
  67. package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs.map +1 -0
  68. package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs +465 -0
  69. package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs.map +1 -0
  70. package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs +43 -0
  71. package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs.map +1 -0
  72. package/dist/TablePlugin.native-EEWXn1-s.mjs +491 -0
  73. package/dist/TablePlugin.native-EEWXn1-s.mjs.map +1 -0
  74. package/dist/TemplatePlugin.native-BlSn1c9h.mjs +564 -0
  75. package/dist/TemplatePlugin.native-BlSn1c9h.mjs.map +1 -0
  76. package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs +97 -0
  77. package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs.map +1 -0
  78. package/dist/TextColorPlugin.native-D6SmTglm.mjs +432 -0
  79. package/dist/TextColorPlugin.native-D6SmTglm.mjs.map +1 -0
  80. package/dist/UnderlinePlugin.native-QpIcK4L2.mjs +35 -0
  81. package/dist/UnderlinePlugin.native-QpIcK4L2.mjs.map +1 -0
  82. package/dist/documentManager-irzj9n3V.mjs +37627 -0
  83. package/dist/documentManager-irzj9n3V.mjs.map +1 -0
  84. package/dist/editorContainerHelpers-C7kdWnS0.mjs +27 -0
  85. package/dist/editorContainerHelpers-C7kdWnS0.mjs.map +1 -0
  86. package/dist/editora.min.js +14 -12
  87. package/dist/editora.min.js.map +1 -1
  88. package/dist/editora.umd.js +14 -12
  89. package/dist/editora.umd.js.map +1 -1
  90. package/dist/index-BF5RBhL9.js +4 -0
  91. package/dist/index-BF5RBhL9.js.map +1 -0
  92. package/dist/{index-BS4zT-KN.mjs → index-BPsf460l.mjs} +286 -162
  93. package/dist/index-BPsf460l.mjs.map +1 -0
  94. package/dist/index.cjs.js +3 -3
  95. package/dist/index.cjs.js.map +1 -1
  96. package/dist/index.es-CuicffkQ.mjs +6665 -0
  97. package/dist/index.es-CuicffkQ.mjs.map +1 -0
  98. package/dist/index.esm.js +117 -112
  99. package/dist/index.esm.js.map +1 -1
  100. package/dist/plugin-loader.js +55 -0
  101. package/dist/plugin-loader.js.map +1 -0
  102. package/dist/purify.es-CKpwg8Tk.mjs +471 -0
  103. package/dist/purify.es-CKpwg8Tk.mjs.map +1 -0
  104. package/dist/webcomponent-core.js +1243 -0
  105. package/dist/webcomponent-core.js.map +1 -0
  106. package/dist/webcomponent-core.min.css +1 -0
  107. package/dist/webcomponent-core.min.js +597 -0
  108. package/dist/webcomponent-core.min.js.map +1 -0
  109. package/dist/webcomponent.cjs.js +1 -1
  110. package/dist/webcomponent.esm.js +3 -3
  111. package/dist/webcomponent.js +1286 -0
  112. package/dist/webcomponent.js.map +1 -0
  113. package/dist/webcomponent.min.css +1 -0
  114. package/dist/webcomponent.min.js +337 -334
  115. package/dist/webcomponent.min.js.map +1 -1
  116. package/package.json +16 -4
  117. package/dist/index-BK2lHfHK.js +0 -2
  118. package/dist/index-BK2lHfHK.js.map +0 -1
  119. package/dist/index-BS4zT-KN.mjs.map +0 -1
  120. package/dist/webcomponent.umd.js +0 -4073
  121. package/dist/webcomponent.umd.js.map +0 -1
@@ -10,7 +10,7 @@ class m {
10
10
  return new m(t, e || this.selection, this.schema);
11
11
  }
12
12
  }
13
- class E {
13
+ class w {
14
14
  constructor(t, e) {
15
15
  this.nodes = new Map(Object.entries(t)), this.marks = new Map(Object.entries(e));
16
16
  }
@@ -48,7 +48,7 @@ class C {
48
48
  const t = {}, e = {};
49
49
  return this.plugins.forEach((o) => {
50
50
  o.nodes && Object.assign(t, o.nodes), o.marks && Object.assign(e, o.marks);
51
- }), new E(t, e);
51
+ }), new w(t, e);
52
52
  }
53
53
  getCommands() {
54
54
  const t = {};
@@ -66,9 +66,9 @@ class C {
66
66
  const i = this.getPlugin(t);
67
67
  if (!i)
68
68
  throw new Error(`Plugin not found: ${t}`);
69
- const n = this.getPluginConfig(t) || i.config || {}, s = n.mode || "local";
69
+ const n = this.getPluginConfig(t) || i.config || {}, a = n.mode || "local";
70
70
  try {
71
- switch (s) {
71
+ switch (a) {
72
72
  case "local":
73
73
  return i.executeLocal ? i.executeLocal(e, ...o) : null;
74
74
  case "api":
@@ -88,7 +88,7 @@ class C {
88
88
  }
89
89
  break;
90
90
  default:
91
- throw new Error(`Unknown plugin mode: ${s}`);
91
+ throw new Error(`Unknown plugin mode: ${a}`);
92
92
  }
93
93
  } catch (r) {
94
94
  throw console.error(`Error executing command ${e} on plugin ${t}:`, r), r;
@@ -102,7 +102,7 @@ class C {
102
102
  await Promise.all(t), this.plugins = [], this.pluginConfigs.clear();
103
103
  }
104
104
  }
105
- class w {
105
+ class E {
106
106
  constructor(t = {}) {
107
107
  this.commands = /* @__PURE__ */ new Map(), Object.entries(t).forEach(([e, o]) => {
108
108
  this.register(e, o);
@@ -149,7 +149,7 @@ class k {
149
149
  constructor(t = {}) {
150
150
  this.listeners = /* @__PURE__ */ new Map(), this.isReadonly = !1, this.isDestroyed = !1, this.isReadonly = t.readonly || !1, this.pluginManager = new C(), t.plugins && Array.isArray(t.plugins) && t.plugins.forEach((o) => this.pluginManager.register(o));
151
151
  const e = this.pluginManager.buildSchema();
152
- this.state = m.create(e), this.commandRegistry = new w(this.pluginManager.getCommands());
152
+ this.state = m.create(e), this.commandRegistry = new E(this.pluginManager.getCommands());
153
153
  }
154
154
  /**
155
155
  * Execute a command
@@ -246,7 +246,7 @@ class v {
246
246
  i.forEach((r) => {
247
247
  r.command && n.set(r.command, r), r.type === "group" && r.label && n.set(r.label, r);
248
248
  });
249
- const s = {
249
+ const a = {
250
250
  bold: "toggleBold",
251
251
  italic: "toggleItalic",
252
252
  underline: "toggleUnderline",
@@ -298,66 +298,65 @@ class v {
298
298
  codeBlock: "insertCodeBlock"
299
299
  };
300
300
  return o.forEach((r) => {
301
- const d = [];
302
- r.split(/\s+/).filter(Boolean).forEach((p) => {
303
- if (p === "direction") {
304
- const l = n.get("setDirectionLTR"), u = n.get("setDirectionRTL");
305
- l && d.push({
301
+ const s = [];
302
+ r.split(/\s+/).filter(Boolean).forEach((u) => {
303
+ if (u === "direction") {
304
+ const c = n.get("setDirectionLTR"), h = n.get("setDirectionRTL");
305
+ c && s.push({
306
306
  id: "directionLTR",
307
- label: l.label,
308
- command: l.command,
309
- icon: l.icon,
310
- type: l.type || "button",
311
- options: l.options
312
- }), u && d.push({
307
+ label: c.label,
308
+ command: c.command,
309
+ icon: c.icon,
310
+ type: c.type || "button",
311
+ options: c.options
312
+ }), h && s.push({
313
313
  id: "directionRTL",
314
- label: u.label,
315
- command: u.command,
316
- icon: u.icon,
317
- type: u.type || "button",
318
- options: u.options
314
+ label: h.label,
315
+ command: h.command,
316
+ icon: h.icon,
317
+ type: h.type || "button",
318
+ options: h.options
319
319
  });
320
320
  return;
321
321
  }
322
- if (p === "comments") {
323
- const l = n.get("addComment"), u = n.get("toggleComments");
324
- l && d.push({
322
+ if (u === "comments") {
323
+ const c = n.get("addComment"), h = n.get("toggleComments");
324
+ c && s.push({
325
325
  id: "addComment",
326
- label: l.label,
327
- command: l.command,
328
- icon: l.icon,
329
- type: l.type || "button",
330
- options: l.options
331
- }), u && d.push({
326
+ label: c.label,
327
+ command: c.command,
328
+ icon: c.icon,
329
+ type: c.type || "button",
330
+ options: c.options
331
+ }), h && s.push({
332
332
  id: "toggleComments",
333
- label: u.label,
334
- command: u.command,
335
- icon: u.icon,
336
- type: u.type || "button",
337
- options: u.options
333
+ label: h.label,
334
+ command: h.command,
335
+ icon: h.icon,
336
+ type: h.type || "button",
337
+ options: h.options
338
338
  });
339
339
  return;
340
340
  }
341
- const c = s[p] || p;
342
- let a = n.get(c);
343
- a || (a = n.get(p)), a && d.push({
344
- id: p,
345
- label: a.label,
346
- command: a.command,
347
- icon: a.icon,
348
- type: a.type === "separator" ? "separator" : a.type || "button",
349
- options: a.options,
350
- items: a.items
341
+ const p = a[u] || u;
342
+ let d = n.get(p);
343
+ d || (d = n.get(u)), d && s.push({
344
+ id: u,
345
+ label: d.label,
346
+ command: d.command,
347
+ icon: d.icon,
348
+ type: d.type === "separator" ? "separator" : d.type || "button",
349
+ options: d.options,
350
+ items: d.items
351
351
  });
352
- }), d.length > 0 && e.push(d);
352
+ }), s.length > 0 && e.push(s);
353
353
  }), e;
354
354
  }
355
355
  /**
356
356
  * Get all available toolbar items from plugins
357
357
  */
358
358
  getAvailableToolbarItems() {
359
- let t = this.plugins;
360
- return this.pluginLoader && (t = this.pluginLoader.getRegisteredPluginNames().map((n) => this.pluginLoader.load(n)).filter((n) => n !== null)), t.flatMap((o) => o.toolbar || []);
359
+ return this.plugins.flatMap((e) => e.toolbar || []);
361
360
  }
362
361
  /**
363
362
  * Render toolbar to DOM element
@@ -366,10 +365,10 @@ class v {
366
365
  this.container = t, t.innerHTML = "", t.className = "editora-toolbar", this.config.sticky && t.classList.add("editora-toolbar-sticky"), this.config.position && t.classList.add(`editora-toolbar-${this.config.position}`);
367
366
  const e = this.config.items || this.getDefaultToolbarString(), o = this.parseToolbarString(e);
368
367
  o.forEach((i, n) => {
369
- const s = document.createElement("div");
370
- if (s.className = "editora-toolbar-group", i.forEach((r) => {
371
- this.appendToolbarButton(s, r);
372
- }), t.appendChild(s), n < o.length - 1) {
368
+ const a = document.createElement("div");
369
+ if (a.className = "editora-toolbar-group", i.forEach((r) => {
370
+ this.appendToolbarButton(a, r);
371
+ }), t.appendChild(a), n < o.length - 1) {
373
372
  const r = document.createElement("div");
374
373
  r.className = "editora-toolbar-separator", t.appendChild(r);
375
374
  }
@@ -453,18 +452,18 @@ class v {
453
452
  const o = document.createElement("button");
454
453
  o.className = "editora-toolbar-button editora-toolbar-dropdown-trigger", o.type = "button", o.textContent = t.label;
455
454
  const i = document.createElement("div");
456
- i.className = "editora-toolbar-dropdown-menu", i.style.display = "none", t.options && t.options.forEach((s) => {
455
+ i.className = "editora-toolbar-dropdown-menu", i.style.display = "none", t.options && t.options.forEach((a) => {
457
456
  const r = document.createElement("button");
458
- r.className = "editora-toolbar-dropdown-item", r.type = "button", r.textContent = s.label, r.setAttribute("data-value", s.value), r.addEventListener("click", (d) => {
459
- d.preventDefault(), this.commandHandler && this.commandHandler(t.command, s.value), i.style.display = "none";
457
+ r.className = "editora-toolbar-dropdown-item", r.type = "button", r.textContent = a.label, r.setAttribute("data-value", a.value), r.addEventListener("click", (s) => {
458
+ s.preventDefault(), this.commandHandler && this.commandHandler(t.command, a.value), i.style.display = "none";
460
459
  }), i.appendChild(r);
461
- }), o.addEventListener("click", (s) => {
462
- s.preventDefault(), s.stopPropagation();
460
+ }), o.addEventListener("click", (a) => {
461
+ a.preventDefault(), a.stopPropagation();
463
462
  const r = i.style.display === "block";
464
463
  i.style.display = r ? "none" : "block";
465
464
  });
466
- const n = (s) => {
467
- e.contains(s.target) || (i.style.display = "none");
465
+ const n = (a) => {
466
+ e.contains(a.target) || (i.style.display = "none");
468
467
  };
469
468
  return document.addEventListener("click", n), e._cleanupDropdown = () => {
470
469
  document.removeEventListener("click", n);
@@ -487,18 +486,18 @@ class v {
487
486
  o.textContent = t.label;
488
487
  const i = document.createElement("div");
489
488
  return i.className = "editora-toolbar-dropdown-menu", i.style.display = "none", t.options && t.options.forEach((n) => {
490
- const s = document.createElement("button");
491
- s.className = "editora-toolbar-dropdown-item", s.type = "button", s.textContent = n.label, s.setAttribute("data-value", n.value), s.addEventListener("click", (r) => {
489
+ const a = document.createElement("button");
490
+ a.className = "editora-toolbar-dropdown-item", a.type = "button", a.textContent = n.label, a.setAttribute("data-value", n.value), a.addEventListener("click", (r) => {
492
491
  r.preventDefault(), r.stopPropagation(), this.commandHandler && this.commandHandler(t.command, n.value), i.style.display = "none";
493
- }), i.appendChild(s);
492
+ }), i.appendChild(a);
494
493
  }), o.addEventListener("click", (n) => {
495
494
  var r;
496
495
  n.preventDefault(), n.stopPropagation();
497
- const s = (r = this.container) == null ? void 0 : r.querySelectorAll(
496
+ const a = (r = this.container) == null ? void 0 : r.querySelectorAll(
498
497
  ".editora-toolbar-dropdown-menu"
499
498
  );
500
- s == null || s.forEach((d) => {
501
- d !== i && (d.style.display = "none");
499
+ a == null || a.forEach((s) => {
500
+ s !== i && (s.style.display = "none");
502
501
  }), i.style.display = i.style.display === "none" ? "block" : "none";
503
502
  }), document.addEventListener("click", (n) => {
504
503
  e.contains(n.target) || (i.style.display = "none");
@@ -595,16 +594,35 @@ class T {
595
594
  render() {
596
595
  if (!this.container) return;
597
596
  this.container.innerHTML = "";
598
- const t = [];
599
- this.statusInfo.wordCount !== void 0 && t.push(`Words: ${this.statusInfo.wordCount}`), this.statusInfo.charCount !== void 0 && t.push(`Characters: ${this.statusInfo.charCount}`), this.statusInfo.lineCount !== void 0 && t.push(`Lines: ${this.statusInfo.lineCount}`), this.statusInfo.language && t.push(`Language: ${this.statusInfo.language}`), this.statusInfo.custom && Object.entries(this.statusInfo.custom).forEach(([e, o]) => {
600
- t.push(`${e}: ${o}`);
601
- }), t.forEach((e, o) => {
602
- const i = document.createElement("span");
603
- if (i.className = "editora-statusbar-item", i.textContent = e, this.container.appendChild(i), o < t.length - 1) {
604
- const n = document.createElement("span");
605
- n.className = "editora-statusbar-separator", n.textContent = "|", this.container.appendChild(n);
597
+ const t = document.createElement("div");
598
+ t.className = "editora-statusbar-left";
599
+ const e = document.createElement("div");
600
+ e.className = "editora-statusbar-right";
601
+ const o = [];
602
+ if (this.statusInfo.selectionInfo) {
603
+ const n = this.statusInfo.selectionInfo;
604
+ n.startLine === n.endLine && n.startColumn === n.endColumn ? o.push(`Ln ${n.startLine}, Col ${n.startColumn}`) : (n.startLine === n.endLine ? o.push(`Ln ${n.startLine}, Col ${n.startColumn}-${n.endColumn}`) : o.push(`Ln ${n.startLine}:${n.startColumn} - ${n.endLine}:${n.endColumn}`), o.push(`${n.selectedChars} chars selected`));
605
+ } else if (this.statusInfo.cursorPosition) {
606
+ const n = this.statusInfo.cursorPosition;
607
+ o.push(`Ln ${n.line}, Col ${n.column}`);
608
+ }
609
+ this.statusInfo.language && o.push(this.statusInfo.language);
610
+ const i = [];
611
+ this.statusInfo.wordCount !== void 0 && i.push(`${this.statusInfo.wordCount} words`), this.statusInfo.charCount !== void 0 && i.push(`${this.statusInfo.charCount} chars`), this.statusInfo.lineCount !== void 0 && i.push(`${this.statusInfo.lineCount} lines`), this.statusInfo.custom && Object.entries(this.statusInfo.custom).forEach(([n, a]) => {
612
+ i.push(`${n}: ${a}`);
613
+ }), o.forEach((n, a) => {
614
+ const r = document.createElement("span");
615
+ if (r.className = "editora-statusbar-item", r.textContent = n, t.appendChild(r), a < o.length - 1) {
616
+ const s = document.createElement("span");
617
+ s.className = "editora-statusbar-separator", s.textContent = "|", t.appendChild(s);
606
618
  }
607
- });
619
+ }), i.forEach((n, a) => {
620
+ const r = document.createElement("span");
621
+ if (r.className = "editora-statusbar-item", r.textContent = n, e.appendChild(r), a < i.length - 1) {
622
+ const s = document.createElement("span");
623
+ s.className = "editora-statusbar-separator", s.textContent = "|", e.appendChild(s);
624
+ }
625
+ }), this.container.appendChild(t), this.container.appendChild(e);
608
626
  }
609
627
  /**
610
628
  * Destroy status bar
@@ -613,6 +631,60 @@ class T {
613
631
  this.container && this.container.parentNode && this.container.parentNode.removeChild(this.container), this.container = void 0;
614
632
  }
615
633
  }
634
+ function I(l, t) {
635
+ const e = l.textContent || "", o = P(l, t.startContainer, t.startOffset), n = e.substring(0, o).split(`
636
+ `), a = n.length, r = n[n.length - 1].length + 1;
637
+ return { line: a, column: r };
638
+ }
639
+ function P(l, t, e) {
640
+ var a;
641
+ let o = 0;
642
+ const i = document.createTreeWalker(
643
+ l,
644
+ NodeFilter.SHOW_TEXT,
645
+ null
646
+ );
647
+ let n = i.firstChild();
648
+ for (; n; ) {
649
+ if (n === t) {
650
+ o += e;
651
+ break;
652
+ } else n.nodeType === Node.TEXT_NODE && (o += ((a = n.textContent) == null ? void 0 : a.length) || 0);
653
+ n = i.nextNode();
654
+ }
655
+ return o;
656
+ }
657
+ function A(l) {
658
+ var o, i;
659
+ const t = l.querySelectorAll("div, p, br, h1, h2, h3, h4, h5, h6, blockquote, li, pre");
660
+ let e = 1;
661
+ if (t.length > 0) {
662
+ e = t.length;
663
+ const n = t[t.length - 1];
664
+ (n.tagName === "BR" || ((o = n.innerHTML) == null ? void 0 : o.trim()) === "" || ((i = n.textContent) == null ? void 0 : i.trim()) === "") && e++;
665
+ } else {
666
+ const a = (l.textContent || "").split(`
667
+ `).length;
668
+ e = Math.max(1, a);
669
+ }
670
+ return e;
671
+ }
672
+ function N(l) {
673
+ const t = l.trim() ? l.trim().split(/\s+/).length : 0, e = l.length;
674
+ return { words: t, chars: e };
675
+ }
676
+ function S(l, t) {
677
+ const e = l.toString();
678
+ return {
679
+ startLine: t.line,
680
+ startColumn: t.column,
681
+ endLine: t.line,
682
+ // For now, assuming single line selections
683
+ endColumn: t.column + e.length,
684
+ selectedChars: e.length,
685
+ selectedWords: e.trim().split(/\s+/).filter(Boolean).length
686
+ };
687
+ }
616
688
  const y = class y {
617
689
  /**
618
690
  * Resolve configuration from multiple sources with priority
@@ -701,39 +773,41 @@ y.EDITOR_DEFAULTS = {
701
773
  spellcheck: !1,
702
774
  language: "en"
703
775
  };
704
- let b = y;
705
- class P {
776
+ let x = y;
777
+ class M {
706
778
  constructor() {
707
779
  this.loadedPlugins = /* @__PURE__ */ new Map(), this.pluginRegistry = /* @__PURE__ */ new Map();
708
780
  }
709
781
  /**
710
- * Register a plugin factory
782
+ * Register a plugin factory (sync or async)
711
783
  */
712
784
  register(t, e) {
713
785
  this.pluginRegistry.set(t, e);
714
786
  }
715
787
  /**
716
- * Load a plugin by name
788
+ * Load a plugin by name (async)
717
789
  */
718
- load(t, e) {
790
+ async load(t, e) {
719
791
  if (this.loadedPlugins.has(t))
720
792
  return this.loadedPlugins.get(t);
721
793
  const o = this.pluginRegistry.get(t);
722
794
  if (!o)
723
795
  return console.warn(`Plugin not found: ${t}`), null;
724
- const i = o();
796
+ const i = await o();
725
797
  return e && this.applyPluginConfig(i, e), this.loadedPlugins.set(t, i), i;
726
798
  }
727
799
  /**
728
800
  * Load multiple plugins
729
801
  */
730
- loadMultiple(t, e) {
731
- return t.map((o) => this.load(o, e)).filter((o) => o !== null);
802
+ async loadMultiple(t, e) {
803
+ return (await Promise.all(
804
+ t.map((i) => this.load(i, e))
805
+ )).filter((i) => i !== null);
732
806
  }
733
807
  /**
734
808
  * Parse plugin string "lists link image media"
735
809
  */
736
- parsePluginString(t, e) {
810
+ async parsePluginString(t, e) {
737
811
  const o = t.split(/\s+/).filter(Boolean);
738
812
  return this.loadMultiple(o, e);
739
813
  }
@@ -756,10 +830,10 @@ class P {
756
830
  this.loadedPlugins.clear();
757
831
  }
758
832
  /**
759
- * Get all loaded plugin names
833
+ * Get all loaded plugins
760
834
  */
761
- getLoadedPluginNames() {
762
- return Array.from(this.loadedPlugins.keys());
835
+ getLoadedPlugins() {
836
+ return Array.from(this.loadedPlugins.values());
763
837
  }
764
838
  /**
765
839
  * Get all registered plugin names (available for loading)
@@ -774,31 +848,31 @@ class P {
774
848
  return this.loadedPlugins.has(t);
775
849
  }
776
850
  }
777
- const I = '.editora-editor{display:flex;flex-direction:column;border:1px solid #ddd;border-radius:4px;background:#fff;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;font-size:14px;overflow:hidden}.editora-editor *{box-sizing:border-box}.editora-theme-light{background:#fff;color:#333}.editora-theme-dark{background:#1e1e1e;color:#d4d4d4;border-color:#3c3c3c}.editora-toolbar{display:flex;align-items:center;gap:4px;padding:8px;background:#f5f5f5;border-bottom:1px solid #ddd;flex-wrap:wrap}.editora-theme-dark .editora-toolbar{background:#252526;border-bottom-color:#3c3c3c}.editora-toolbar-sticky{position:sticky;top:0;z-index:100}.editora-toolbar-group{display:flex;align-items:center;gap:2px}.editora-toolbar-button{padding:6px 12px;border:1px solid #ccc;background:#fff;cursor:pointer;border-radius:3px;font-weight:600;font-size:14px;height:30px;display:flex;align-items:center;white-space:nowrap}.editora-toolbar-input.font-size{width:40px;padding:.25rem;text-align:center;font-size:14px;background:#fff;border:1px solid var(--rte-color-border-light);border-radius:var(--rte-radius-sm)}.editora-toolbar-group-items{display:flex;align-items:center;border:1px solid #ccc;.editora-toolbar-button{border:none;border-radius:0;&:first-child{border-right:1px solid #ccc;border-top-left-radius:3px;border-bottom-left-radius:3px}&:last-child{border-left:1px solid #ccc;border-top-right-radius:3px;border-bottom-right-radius:3px}}}.editora-theme-dark .editora-toolbar-button{color:#d4d4d4}.editora-toolbar-button:hover{background:#e0e0e0;border-color:#ccc}.editora-theme-dark .editora-toolbar-button:hover{background:#37373d;border-color:#555}.editora-toolbar-button:active,.editora-toolbar-button.active{background:#d0d0d0;border-color:#999}.editora-theme-dark .editora-toolbar-button:active,.editora-theme-dark .editora-toolbar-button.active{background:#2a2d2e;border-color:#666}.editora-toolbar-button:disabled{opacity:.5;cursor:not-allowed}.editora-toolbar-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;line-height:1}.editora-toolbar-button svg,.editora-toolbar-icon svg{width:24px;height:24px;display:block}.editora-toolbar-separator{width:1px;height:24px;background:#ddd;margin:0 4px}.editora-theme-dark .editora-toolbar-separator{background:#3c3c3c}.editora-toolbar-dropdown{position:relative}.editora-toolbar-dropdown-menu{position:absolute;top:100%;left:0;min-width:150px;margin-top:4px;padding:4px 0;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 2px 8px #00000026;z-index:1000}.editora-theme-dark .editora-toolbar-dropdown-menu{background:#252526;border-color:#3c3c3c;box-shadow:0 2px 8px #00000080}.editora-toolbar-dropdown-item{display:block;width:100%;padding:8px 12px;border:none;background:transparent;color:#333;text-align:left;cursor:pointer;font-size:13px;transition:background .15s ease}.editora-theme-dark .editora-toolbar-dropdown-item{color:#d4d4d4}.editora-toolbar-dropdown-item:hover{background:#f5f5f5}.editora-theme-dark .editora-toolbar-dropdown-item:hover{background:#37373d}.editora-content{flex:1;min-height:200px;padding:16px;outline:none;overflow-y:auto;line-height:1.6}.editora-content:empty:before{content:attr(data-placeholder);color:#999;pointer-events:none}.editora-theme-dark .editora-content:empty:before{color:#6a6a6a}.editora-content h1{font-size:2em;margin:.67em 0;font-weight:600}.editora-content h2{font-size:1.5em;margin:.75em 0;font-weight:600}.editora-content h3{font-size:1.17em;margin:.83em 0;font-weight:600}.editora-content p{margin:1em 0}.editora-content ul,.editora-content ol{margin:1em 0;padding-left:2em}.editora-content a{color:#06c;text-decoration:underline}.editora-theme-dark .editora-content a{color:#4db8ff}.editora-content code{padding:2px 4px;background:#f5f5f5;border-radius:3px;font-family:Monaco,Menlo,Consolas,monospace;font-size:.9em}.editora-theme-dark .editora-content code{background:#1e1e1e}.editora-content pre{padding:12px;background:#f5f5f5;border-radius:4px;overflow-x:auto;margin:1em 0}.editora-theme-dark .editora-content pre{background:#1e1e1e}.editora-content blockquote{margin:1em 0;padding-left:1em;border-left:4px solid #ddd;color:#666}.editora-theme-dark .editora-content blockquote{border-left-color:#3c3c3c;color:#9a9a9a}.editora-floating-toolbar{position:absolute;padding:4px;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 2px 8px #00000026;z-index:1000}.editora-theme-dark .editora-floating-toolbar{background:#252526;border-color:#3c3c3c;box-shadow:0 2px 8px #00000080}.editora-statusbar{display:flex;align-items:center;gap:12px;padding:6px 12px;background:#f5f5f5;border-top:1px solid #ddd;font-size:12px;color:#666}.editora-theme-dark .editora-statusbar{background:#252526;border-top-color:#3c3c3c;color:#9a9a9a}.editora-statusbar-item{white-space:nowrap}.editora-statusbar-separator{color:#ddd}.editora-theme-dark .editora-statusbar-separator{color:#3c3c3c}.editora-editor[readonly] .editora-content{background:#fafafa;cursor:not-allowed}.editora-theme-dark.editora-editor[readonly] .editora-content{background:#1a1a1a}.editora-editor:focus-within{border-color:#06c;box-shadow:0 0 0 3px #0066cc1a}.editora-theme-dark.editora-editor:focus-within{border-color:#4db8ff;box-shadow:0 0 0 3px #4db8ff1a}.editora-editor[disabled]{opacity:.6;pointer-events:none}@media(max-width:768px){.editora-toolbar{padding:4px}.editora-toolbar-button{min-width:28px;min-height:28px;padding:4px 8px;font-size:12px}.editora-content{padding:12px}}.editora-content ::selection{background:#06c3}.editora-theme-dark .editora-content ::selection{background:#4db8ff33}.editora-content table{border-collapse:collapse;width:100%;margin:1em 0}.editora-content th,.editora-content td{border:1px solid #ddd;padding:8px 12px;text-align:left}.editora-theme-dark .editora-content th,.editora-theme-dark .editora-content td{border-color:#3c3c3c}.editora-content th{background:#f5f5f5;font-weight:600}.editora-theme-dark .editora-content th{background:#252526}.editora-content img{max-width:100%;height:auto;border-radius:4px}.editora-editor.loading{opacity:.7;pointer-events:none}.editora-editor.loading:after{content:"";position:absolute;top:50%;left:50%;width:24px;height:24px;margin:-12px 0 0 -12px;border:3px solid #ddd;border-top-color:#06c;border-radius:50%;animation:editora-spin .8s linear infinite}@keyframes editora-spin{to{transform:rotate(360deg)}}';
778
- let g;
779
- function A() {
780
- const h = "editora-webcomponent-styles";
781
- if (!document.getElementById(h)) {
851
+ const H = '.editora-editor{display:flex;flex-direction:column;border:1px solid #ddd;border-radius:4px;background:#fff;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;font-size:14px;overflow:hidden}.editora-editor *{box-sizing:border-box}.editora-theme-light{background:#fff;color:#333}.editora-theme-dark{background:#1e1e1e;color:#d4d4d4;border-color:#3c3c3c}.editora-toolbar{display:flex;align-items:center;gap:4px;padding:8px;background:#f5f5f5;border-bottom:1px solid #ddd;flex-wrap:wrap}.editora-theme-dark .editora-toolbar{background:#252526;border-bottom-color:#3c3c3c}.editora-toolbar-sticky{position:sticky;top:0;z-index:100;position:-webkit-sticky}.editora-toolbar-group{display:flex;align-items:center;gap:2px}.editora-toolbar-button{padding:6px 12px;border:1px solid #ccc;background:#fff;cursor:pointer;border-radius:3px;font-weight:600;font-size:14px;height:30px;display:flex;align-items:center;white-space:nowrap}.editora-toolbar-input.font-size{width:40px;padding:.25rem;text-align:center;font-size:14px;background:#fff;border:1px solid var(--rte-color-border-light);border-radius:var(--rte-radius-sm)}.editora-toolbar-group-items{display:flex;align-items:center;border:1px solid #ccc;.editora-toolbar-button{border:none;border-radius:0;&:first-child{border-right:1px solid #ccc;border-top-left-radius:3px;border-bottom-left-radius:3px}&:last-child{border-left:1px solid #ccc;border-top-right-radius:3px;border-bottom-right-radius:3px}}}.editora-theme-dark .editora-toolbar-button{color:#d4d4d4}.editora-toolbar-button:hover{background:#e0e0e0;border-color:#ccc}.editora-theme-dark .editora-toolbar-button:hover{background:#37373d;border-color:#555}.editora-toolbar-button:active,.editora-toolbar-button.active{background:#d0d0d0;border-color:#999}.editora-theme-dark .editora-toolbar-button:active,.editora-theme-dark .editora-toolbar-button.active{background:#2a2d2e;border-color:#666}.editora-toolbar-button:disabled{opacity:.5;cursor:not-allowed}.editora-toolbar-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;line-height:1}.editora-toolbar-button svg,.editora-toolbar-icon svg{width:24px;height:24px;display:block}.editora-toolbar-separator{width:1px;height:24px;background:#ddd;margin:0 4px}.editora-theme-dark .editora-toolbar-separator{background:#3c3c3c}.editora-toolbar-dropdown{position:relative}.editora-toolbar-dropdown-menu{position:absolute;top:100%;left:0;min-width:150px;margin-top:4px;padding:4px 0;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 2px 8px #00000026;z-index:1000}.editora-theme-dark .editora-toolbar-dropdown-menu{background:#252526;border-color:#3c3c3c;box-shadow:0 2px 8px #00000080}.editora-toolbar-dropdown-item{display:block;width:100%;padding:8px 12px;border:none;background:transparent;color:#333;text-align:left;cursor:pointer;font-size:13px;transition:background .15s ease}.editora-theme-dark .editora-toolbar-dropdown-item{color:#d4d4d4}.editora-toolbar-dropdown-item:hover{background:#f5f5f5}.editora-theme-dark .editora-toolbar-dropdown-item:hover{background:#37373d}.editora-content{flex:1;min-height:200px;padding:16px;outline:none;overflow-y:auto;line-height:1.6}.editora-content:empty:before{content:attr(data-placeholder);color:#999;pointer-events:none}.editora-theme-dark .editora-content:empty:before{color:#6a6a6a}.editora-content h1{font-size:2em;margin:.67em 0;font-weight:600}.editora-content h2{font-size:1.5em;margin:.75em 0;font-weight:600}.editora-content h3{font-size:1.17em;margin:.83em 0;font-weight:600}.editora-content p{margin:1em 0}.editora-content ul,.editora-content ol{margin:1em 0;padding-left:2em}.editora-content a{color:#06c;text-decoration:underline}.editora-theme-dark .editora-content a{color:#4db8ff}.editora-content code{padding:2px 4px;background:#f5f5f5;border-radius:3px;font-family:Monaco,Menlo,Consolas,monospace;font-size:.9em}.editora-theme-dark .editora-content code{background:#1e1e1e}.editora-content pre{padding:12px;background:#f5f5f5;border-radius:4px;overflow-x:auto;margin:1em 0}.editora-theme-dark .editora-content pre{background:#1e1e1e}.editora-content blockquote{margin:1em 0;padding-left:1em;border-left:4px solid #ddd;color:#666}.editora-theme-dark .editora-content blockquote{border-left-color:#3c3c3c;color:#9a9a9a}.editora-floating-toolbar{position:absolute;padding:4px;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 2px 8px #00000026;z-index:1000}.editora-theme-dark .editora-floating-toolbar{background:#252526;border-color:#3c3c3c;box-shadow:0 2px 8px #00000080}.editora-statusbar-container{display:flex;flex-direction:column}.editora-statusbar-left{display:flex;align-items:center;gap:8px}.editora-statusbar-right{display:flex;align-items:center;gap:8px;margin-left:auto}.editora-statusbar{display:flex;align-items:center;gap:12px;padding:6px 12px;background:#f5f5f5;border-top:1px solid #ddd;font-size:12px;color:#666}.editora-theme-dark .editora-statusbar{background:#252526;border-top-color:#3c3c3c;color:#9a9a9a}.editora-statusbar-item{white-space:nowrap}.editora-statusbar-separator{color:#ddd}.editora-theme-dark .editora-statusbar-separator{color:#3c3c3c}.editora-editor[readonly] .editora-content{background:#fafafa;cursor:not-allowed}.editora-theme-dark.editora-editor[readonly] .editora-content{background:#1a1a1a}.editora-editor:focus-within{border-color:#06c;box-shadow:0 0 0 3px #0066cc1a}.editora-theme-dark.editora-editor:focus-within{border-color:#4db8ff;box-shadow:0 0 0 3px #4db8ff1a}.editora-editor[disabled]{opacity:.6;pointer-events:none}@media(max-width:768px){.editora-toolbar{padding:4px}.editora-toolbar-button{min-width:28px;min-height:28px;padding:4px 8px;font-size:12px}.editora-content{padding:12px}}.editora-content ::selection{background:#06c3}.editora-theme-dark .editora-content ::selection{background:#4db8ff33}.editora-content table{border-collapse:collapse;width:100%;margin:1em 0}.editora-content th,.editora-content td{border:1px solid #ddd;padding:8px 12px;text-align:left}.editora-theme-dark .editora-content th,.editora-theme-dark .editora-content td{border-color:#3c3c3c}.editora-content th{background:#f5f5f5;font-weight:600}.editora-theme-dark .editora-content th{background:#252526}.editora-content img{max-width:100%;height:auto;border-radius:4px;display:block}.editora-content video{max-width:100%;height:auto;border-radius:4px;display:block}.editora-editor.loading{opacity:.7;pointer-events:none}.editora-editor.loading:after{content:"";position:absolute;top:50%;left:50%;width:24px;height:24px;margin:-12px 0 0 -12px;border:3px solid #ddd;border-top-color:#06c;border-radius:50%;animation:editora-spin .8s linear infinite}@keyframes editora-spin{to{transform:rotate(360deg)}}.toolbar-container-wrapper{display:flex;align-items:center;background:#fff;border-bottom:1px solid #e0e0e0;padding:0;margin:0;width:100%;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:1.5;position:relative}.toolbar-container-wrapper[data-toolbar-sticky=true]{position:sticky;top:0;z-index:999;box-shadow:0 2px 4px #0000001a}.toolbar-container-wrapper[data-toolbar-floating=true]{position:fixed;top:0;left:0;right:0;z-index:1000;box-shadow:0 4px 12px #00000026}.toolbar-container-wrapper[data-toolbar-position=bottom]{border-bottom:none;border-top:1px solid #e0e0e0}.toolbar-container-wrapper .toolbar-wrapper{display:flex;width:100%;padding:8px;gap:4px;flex-wrap:wrap;align-items:center}.toolbar-container-wrapper .toolbar{display:flex;width:100%;gap:4px;flex-wrap:wrap;align-items:center}.toolbar-container-wrapper .toolbar-container{display:flex;gap:4px;flex-wrap:wrap;align-items:center;flex:1;position:relative}.toolbar-container-wrapper .toolbar-item{display:flex;align-items:center;gap:2px}.toolbar-container-wrapper .toolbar-button{padding:6px 10px;border:1px solid #d1d5db;background:#fff;border-radius:4px;cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;gap:4px;transition:all .15s ease;min-height:32px;white-space:nowrap}.toolbar-container-wrapper .toolbar-button:hover{background-color:#f3f4f6;border-color:#9ca3af}.toolbar-container-wrapper .toolbar-button:active,.toolbar-container-wrapper .toolbar-button[data-active=true]{background-color:#06c;color:#fff;border-color:#0052a3;box-shadow:inset 0 1px 3px #0000001a}.toolbar-container-wrapper .toolbar-button:disabled{opacity:.5;cursor:not-allowed;background-color:#f9fafb}.toolbar-container-wrapper .toolbar-more-button{padding:6px 8px;font-size:16px;font-weight:500;line-height:1}.toolbar-container-wrapper .toolbar-separator{width:1px;height:24px;background-color:#d1d5db;margin:0 4px}.toolbar-container-wrapper .toolbar-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex-shrink:0}.toolbar-container-wrapper .toolbar-icon svg{width:100%;height:100%}.toolbar-container-wrapper .toolbar-dropdown{position:relative;display:flex;align-items:center}.toolbar-container-wrapper .toolbar-dropdown-arrow{font-size:10px;margin-left:2px;line-height:1}.toolbar-container-wrapper .toolbar-dropdown-menu{position:absolute;top:100%;left:0;background:#fff;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 4px 12px #00000026;z-index:1000;min-width:160px;padding:4px 0;margin-top:4px;display:none}.toolbar-container-wrapper .toolbar-dropdown-menu.show{display:block}.toolbar-container-wrapper .toolbar-dropdown-item{display:block;width:100%;padding:8px 12px;border:none;background:transparent;text-align:left;cursor:pointer;font-size:13px;color:#1f2937;transition:background-color .15s ease;font-family:inherit}.toolbar-container-wrapper .toolbar-dropdown-item:hover{background-color:#f3f4f6}.toolbar-container-wrapper .toolbar-dropdown-item:active{background-color:#e5e7eb}.toolbar-container-wrapper .toolbar-input{padding:6px 8px;border:1px solid #d1d5db;border-radius:4px;font-size:13px;font-family:inherit;background-color:#fff;color:#1f2937;transition:all .15s ease}.toolbar-container-wrapper .toolbar-input:focus{outline:none;border-color:#06c;box-shadow:0 0 0 3px #0066cc1a;background-color:#fff}.toolbar-container-wrapper .toolbar-input::placeholder{color:#9ca3af}.toolbar-overflow-menu{animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.toolbar-overflow-item{transition:background-color .15s ease}.floating-toolbar{user-select:none;-webkit-user-select:none;font-family:system-ui,-apple-system,sans-serif;font-size:14px;animation:fadeInUp .15s ease-out}@keyframes fadeInUp{0%{opacity:0;transform:translate(-50%) translateY(10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.floating-toolbar-btn{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:4px;color:#495057;cursor:pointer;font-size:14px;font-weight:500;transition:all .15s ease;outline:none}.floating-toolbar-btn:hover{background:#f8f9fa;color:#212529}.floating-toolbar-btn:active{background:#e9ecef;transform:scale(.95)}.floating-toolbar-btn.floating-toolbar-toggle{color:#dc3545;font-weight:700}.floating-toolbar-btn.floating-toolbar-toggle:hover{background:#f8d7da;color:#721c24}.floating-toolbar-separator{width:1px;height:20px;background:#e1e5e9;margin:0 2px}@media(max-width:768px){.toolbar-container-wrapper .toolbar-button{padding:5px 8px;font-size:12px;min-height:28px}.toolbar-container-wrapper .toolbar-icon{width:16px;height:16px}.toolbar-container-wrapper .toolbar-dropdown-menu{min-width:140px}.toolbar-container-wrapper .toolbar-dropdown-item{padding:6px 10px;font-size:12px}.floating-toolbar{padding:4px;gap:2px}.floating-toolbar-btn{width:28px;height:28px;font-size:12px}}@media(max-width:480px){.toolbar-container-wrapper{padding:4px}.toolbar-container-wrapper .toolbar-wrapper{padding:4px;gap:2px}.toolbar-container-wrapper .toolbar-button{padding:4px 6px;font-size:11px;min-height:24px}.toolbar-container-wrapper .toolbar-icon{width:14px;height:14px}}.floating-toolbar{pointer-events:auto}.floating-toolbar{max-width:calc(100vw - 20px);overflow-x:auto}@media(prefers-color-scheme:dark){.floating-toolbar{background:#2d3748;border-color:#4a5568;color:#e2e8f0}.floating-toolbar-btn:hover{background:#4a5568;color:#f7fafc}.floating-toolbar-btn:active{background:#718096}.floating-toolbar-separator{background:#4a5568}}';
852
+ let f;
853
+ function z() {
854
+ const l = "editora-webcomponent-styles";
855
+ if (!document.getElementById(l)) {
782
856
  const t = document.createElement("style");
783
- t.id = h, t.textContent = I, document.head.appendChild(t);
857
+ t.id = l, t.textContent = H, document.head.appendChild(t);
784
858
  }
785
859
  }
786
- function x() {
787
- if (!g) {
788
- const h = M.__globalPluginLoader;
789
- h ? g = h : g = new P();
860
+ function B() {
861
+ if (!f) {
862
+ const l = g.__globalPluginLoader;
863
+ l ? f = l : f = new M();
790
864
  }
791
- return g;
865
+ return f;
792
866
  }
793
- function N(h) {
794
- const t = x();
795
- Object.entries(h).forEach(([e, o]) => {
867
+ function D(l) {
868
+ const t = B();
869
+ Object.entries(l).forEach(([e, o]) => {
796
870
  t.register(e, o);
797
871
  });
798
872
  }
799
- class M extends HTMLElement {
873
+ class g extends HTMLElement {
800
874
  constructor() {
801
- if (super(), this.config = {}, this.isInitialized = !1, this.pluginLoader = x(), A(), !this.hasAttribute("data-initial-content")) {
875
+ if (super(), this.config = {}, this.isInitialized = !1, z(), !this.hasAttribute("data-initial-content")) {
802
876
  const t = this.innerHTML.trim();
803
877
  t && this.setAttribute("data-initial-content", t);
804
878
  }
@@ -818,16 +892,34 @@ class M extends HTMLElement {
818
892
  "placeholder",
819
893
  "autofocus",
820
894
  "language",
821
- "spellcheck"
895
+ "spellcheck",
896
+ "statusbar"
822
897
  ];
823
898
  }
824
899
  /**
825
900
  * Called when element is added to DOM
826
901
  */
827
902
  connectedCallback() {
828
- this.config = this.resolveConfig(), setTimeout(() => {
829
- this.initialize();
830
- }, 0);
903
+ this.config = this.resolveConfig(), this.waitForPluginLoader().then(() => {
904
+ setTimeout(async () => {
905
+ await this.initialize();
906
+ }, 0);
907
+ });
908
+ }
909
+ /**
910
+ * Wait for the global plugin loader to be available
911
+ */
912
+ async waitForPluginLoader() {
913
+ if (g.__globalPluginLoader) {
914
+ this.pluginLoader = g.__globalPluginLoader;
915
+ return;
916
+ }
917
+ return new Promise((t) => {
918
+ const e = () => {
919
+ g.__globalPluginLoader ? (this.pluginLoader = g.__globalPluginLoader, t()) : setTimeout(e, 0);
920
+ };
921
+ e();
922
+ });
831
923
  }
832
924
  /**
833
925
  * Called when element is removed from DOM
@@ -844,20 +936,20 @@ class M extends HTMLElement {
844
936
  /**
845
937
  * Set configuration via JavaScript API
846
938
  */
847
- setConfig(t) {
848
- this.jsConfig = t, this.config = this.resolveConfig(), this.isConnected && (this.destroy(), this.initialize());
939
+ async setConfig(t) {
940
+ this.jsConfig = t, this.config = this.resolveConfig(), this.isConnected && (this.destroy(), await this.waitForPluginLoader(), await this.initialize());
849
941
  }
850
942
  /**
851
943
  * Initialize the editor
852
944
  */
853
- initialize() {
945
+ async initialize() {
854
946
  if (this.querySelector(".editora-toolbar") || this.isInitialized) return;
855
947
  this.setAttribute("data-editora-editor", "true"), this.config.height && (this.style.height = typeof this.config.height == "number" ? `${this.config.height}px` : this.config.height), this.config.width && (this.style.width = typeof this.config.width == "number" ? `${this.config.width}px` : this.config.width), this.classList.add("editora-editor"), this.config.theme && this.classList.add(`editora-theme-${this.config.theme}`);
856
- const t = this.loadPlugins();
948
+ const t = await this.loadPlugins();
857
949
  t.forEach((o) => {
858
950
  if (o.init && typeof o.init == "function")
859
951
  try {
860
- o.init();
952
+ o.init({ editorElement: this });
861
953
  } catch (i) {
862
954
  console.error(`[RichTextEditor] Error initializing plugin ${o.name}:`, i);
863
955
  }
@@ -884,21 +976,22 @@ class M extends HTMLElement {
884
976
  /**
885
977
  * Load plugins based on configuration
886
978
  */
887
- loadPlugins() {
979
+ async loadPlugins() {
980
+ this.pluginLoader || await this.waitForPluginLoader();
888
981
  const t = [];
889
- if (this.config.plugins && (typeof this.config.plugins == "string" && this.config.plugins.length > 0 || Array.isArray(this.config.plugins) && this.config.plugins.length > 0))
982
+ if (this.config.plugins && (typeof this.config.plugins == "string" && this.config.plugins.length > 0 || Array.isArray(this.config.plugins) && this.config.plugins.length > 0)) {
890
983
  if (typeof this.config.plugins == "string") {
891
- const o = this.pluginLoader.parsePluginString(this.config.plugins);
984
+ const o = await this.pluginLoader.parsePluginString(this.config.plugins);
892
985
  t.push(...o);
893
- } else Array.isArray(this.config.plugins) && this.config.plugins.forEach((o) => {
894
- if (typeof o == "string") {
895
- const i = this.pluginLoader.load(o);
896
- i && t.push(i);
897
- } else
898
- t.push(o);
899
- });
900
- else {
901
- const o = this.pluginLoader.getRegisteredPluginNames(), i = this.pluginLoader.loadMultiple(o);
986
+ } else if (Array.isArray(this.config.plugins))
987
+ for (const o of this.config.plugins)
988
+ if (typeof o == "string") {
989
+ const i = await this.pluginLoader.load(o);
990
+ i && t.push(i);
991
+ } else
992
+ t.push(o);
993
+ } else {
994
+ const o = this.pluginLoader.getRegisteredPluginNames(), i = await this.pluginLoader.loadMultiple(o);
902
995
  t.push(...i);
903
996
  }
904
997
  return t;
@@ -920,27 +1013,27 @@ class M extends HTMLElement {
920
1013
  t,
921
1014
  this.pluginLoader
922
1015
  // Pass plugin loader to get all registered plugins
923
- ), this.toolbar.setCommandHandler((s, r) => {
924
- var f, p;
1016
+ ), this.toolbar.setCommandHandler((a, r) => {
1017
+ var b, u;
925
1018
  if (this.contentElement) {
926
1019
  this.contentElement.focus();
927
- const c = window.getSelection();
928
- if (!c || c.rangeCount === 0 || !this.contentElement.contains(c.anchorNode)) {
929
- const a = document.createRange(), l = this.contentElement.lastChild || this.contentElement;
930
- l.nodeType === Node.TEXT_NODE ? a.setStart(l, ((f = l.textContent) == null ? void 0 : f.length) || 0) : l.nodeType === Node.ELEMENT_NODE ? (a.selectNodeContents(l), a.collapse(!1)) : a.setStart(this.contentElement, 0), a.collapse(!0), c == null || c.removeAllRanges(), c == null || c.addRange(a);
1020
+ const p = window.getSelection();
1021
+ if (!p || p.rangeCount === 0 || !this.contentElement.contains(p.anchorNode)) {
1022
+ const d = document.createRange(), c = this.contentElement.lastChild || this.contentElement;
1023
+ c.nodeType === Node.TEXT_NODE ? d.setStart(c, ((b = c.textContent) == null ? void 0 : b.length) || 0) : c.nodeType === Node.ELEMENT_NODE ? (d.selectNodeContents(c), d.collapse(!1)) : d.setStart(this.contentElement, 0), d.collapse(!0), p == null || p.removeAllRanges(), p == null || p.addRange(d);
931
1024
  }
932
1025
  }
933
- const d = t.find((c) => c.commands && c.commands[s]);
934
- if (d && d.commands) {
935
- const c = d.commands[s];
936
- if (typeof c == "function")
1026
+ const s = t.find((p) => p.commands && p.commands[a]);
1027
+ if (s && s.commands) {
1028
+ const p = s.commands[a];
1029
+ if (typeof p == "function")
937
1030
  try {
938
- return c(s === "toggleFullscreen" ? this : r);
939
- } catch (a) {
940
- return console.error(`[RichTextEditor] Error executing native command ${s}:`, a), !1;
1031
+ return p(a === "toggleFullscreen" ? this : r);
1032
+ } catch (d) {
1033
+ return console.error(`[RichTextEditor] Error executing native command ${a}:`, d), !1;
941
1034
  }
942
1035
  }
943
- return ((p = this.engine) == null ? void 0 : p.execCommand(s, r)) || !1;
1036
+ return ((u = this.engine) == null ? void 0 : u.execCommand(a, r)) || !1;
944
1037
  }), this.toolbar.render(this.toolbarElement);
945
1038
  } else o && this.appendChild(o);
946
1039
  this.contentElement = document.createElement("div"), this.contentElement.className = "editora-content rte-content", this.contentElement.contentEditable = this.config.readonly ? "false" : "true", this.contentElement.setAttribute("role", "textbox"), this.contentElement.setAttribute("aria-multiline", "true"), this.config.placeholder && this.contentElement.setAttribute("data-placeholder", this.config.placeholder);
@@ -953,8 +1046,8 @@ class M extends HTMLElement {
953
1046
  const n = document.createElement("div");
954
1047
  n.innerHTML = e.trim(), !Array.from(n.childNodes).some((r) => {
955
1048
  if (r.nodeType === Node.ELEMENT_NODE) {
956
- const d = r.tagName;
957
- return ["P", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "UL", "OL", "BLOCKQUOTE", "PRE"].includes(d);
1049
+ const s = r.tagName;
1050
+ return ["P", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "UL", "OL", "BLOCKQUOTE", "PRE"].includes(s);
958
1051
  }
959
1052
  return !1;
960
1053
  }) && e.trim() ? this.contentElement.innerHTML = `<p>${e.trim()}</p>` : this.contentElement.innerHTML = e;
@@ -969,22 +1062,22 @@ class M extends HTMLElement {
969
1062
  * Setup event listeners
970
1063
  */
971
1064
  setupEventListeners() {
972
- !this.contentElement || !this.engine || (this.contentElement.addEventListener("input", () => {
973
- const t = this.contentElement.innerHTML;
974
- if (this.dispatchEvent(new CustomEvent("content-change", {
975
- detail: { html: t },
1065
+ if (!this.contentElement || !this.engine) return;
1066
+ this.contentElement.addEventListener("input", () => {
1067
+ const e = this.contentElement.innerHTML;
1068
+ this.dispatchEvent(new CustomEvent("content-change", {
1069
+ detail: { html: e },
976
1070
  bubbles: !0
977
- })), this.statusBar) {
978
- const e = this.contentElement.textContent || "", o = e.trim().split(/\s+/).filter(Boolean).length, i = e.length;
979
- this.statusBar.update({ wordCount: o, charCount: i });
980
- }
1071
+ })), this.updateStatusBar();
981
1072
  }), this.contentElement.addEventListener("focus", () => {
982
1073
  this.dispatchEvent(new Event("editor-focus", { bubbles: !0 }));
983
1074
  }), this.contentElement.addEventListener("blur", () => {
984
1075
  this.dispatchEvent(new Event("editor-blur", { bubbles: !0 }));
985
- }), this.floatingToolbar && document.addEventListener("selectionchange", () => {
986
- this.updateFloatingToolbar();
987
- }));
1076
+ });
1077
+ const t = () => {
1078
+ this.updateFloatingToolbar(), this.updateStatusBar();
1079
+ };
1080
+ document.addEventListener("selectionchange", t);
988
1081
  }
989
1082
  /**
990
1083
  * Update floating toolbar position
@@ -1004,6 +1097,28 @@ class M extends HTMLElement {
1004
1097
  const o = e.getBoundingClientRect();
1005
1098
  this.floatingToolbar.show(o.left, o.top - 40);
1006
1099
  }
1100
+ /**
1101
+ * Update status bar with selection and cursor information
1102
+ */
1103
+ /**
1104
+ * Update status bar with current content and cursor information
1105
+ */
1106
+ updateStatusBar() {
1107
+ if (!this.statusBar || !this.contentElement) return;
1108
+ const t = this.contentElement.textContent || "", { words: e, chars: o } = N(t), i = A(this.contentElement), n = window.getSelection();
1109
+ let a, r;
1110
+ if (n && n.rangeCount > 0) {
1111
+ const s = n.getRangeAt(0);
1112
+ a = I(this.contentElement, s), s.collapsed || (r = S(s, a), a = void 0);
1113
+ }
1114
+ this.statusBar.update({
1115
+ wordCount: e,
1116
+ charCount: o,
1117
+ lineCount: i,
1118
+ cursorPosition: a,
1119
+ selectionInfo: r
1120
+ });
1121
+ }
1007
1122
  /**
1008
1123
  * Handle attribute changes
1009
1124
  */
@@ -1022,7 +1137,11 @@ class M extends HTMLElement {
1022
1137
  break;
1023
1138
  case "toolbar":
1024
1139
  case "plugins":
1025
- this.isConnected && (this.destroy(), this.initialize());
1140
+ this.isConnected && (this.destroy(), this.waitForPluginLoader().then(() => {
1141
+ this.initialize().catch((o) => {
1142
+ console.error("[RichTextEditor] Error during attribute change re-initialization:", o);
1143
+ });
1144
+ }));
1026
1145
  break;
1027
1146
  }
1028
1147
  }
@@ -1035,7 +1154,7 @@ class M extends HTMLElement {
1035
1154
  const o = this.attributes[e];
1036
1155
  t[o.name] = o.value;
1037
1156
  }
1038
- return b.resolve({
1157
+ return x.resolve({
1039
1158
  jsConfig: this.jsConfig,
1040
1159
  attributes: t
1041
1160
  });
@@ -1103,17 +1222,22 @@ class M extends HTMLElement {
1103
1222
  }
1104
1223
  }
1105
1224
  export {
1106
- w as C,
1225
+ E as C,
1107
1226
  m as E,
1108
1227
  L as F,
1109
1228
  C as P,
1110
- M as R,
1111
- E as S,
1229
+ g as R,
1230
+ w as S,
1112
1231
  v as T,
1113
1232
  k as a,
1114
1233
  T as b,
1115
- b as c,
1116
- P as d,
1117
- N as i
1234
+ P as c,
1235
+ A as d,
1236
+ N as e,
1237
+ S as f,
1238
+ I as g,
1239
+ x as h,
1240
+ M as i,
1241
+ D as j
1118
1242
  };
1119
- //# sourceMappingURL=index-BS4zT-KN.mjs.map
1243
+ //# sourceMappingURL=index-BPsf460l.mjs.map