@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
@@ -0,0 +1,4 @@
1
+ "use strict";class f{constructor(t,e,o){this.doc=t,this.selection=e,this.schema=o}static create(t,e){const o=e||t.node("doc",{},[t.node("paragraph")]);return new f(o,{anchor:0,head:0},t)}apply(t,e){return new f(t,e||this.selection,this.schema)}}class w{constructor(t,e){this.nodes=new Map(Object.entries(t)),this.marks=new Map(Object.entries(e))}node(t,e,o){return{type:t,attrs:e,content:o}}text(t,e){return{type:"text",text:t,marks:e}}}class C{constructor(){this.plugins=[],this.pluginConfigs=new Map}register(t,e){if(this.plugins.push(t),e&&this.pluginConfigs.set(t.name,e),t.initialize){const o=this.pluginConfigs.get(t.name)||t.config;t.initialize(o)}}unregister(t){const e=this.plugins.findIndex(o=>o.name===t);if(e>-1){const o=this.plugins[e];o.destroy&&o.destroy(),this.plugins.splice(e,1),this.pluginConfigs.delete(t)}}getPlugin(t){return this.plugins.find(e=>e.name===t)}getPluginConfig(t){return this.pluginConfigs.get(t)}buildSchema(){const t={},e={};return this.plugins.forEach(o=>{o.nodes&&Object.assign(t,o.nodes),o.marks&&Object.assign(e,o.marks)}),new w(t,e)}getCommands(){const t={};return this.plugins.forEach(e=>{e.commands&&Object.assign(t,e.commands)}),t}getToolbarItems(){return this.plugins.flatMap(t=>t.toolbar||[])}async executePluginCommand(t,e,...o){const i=this.getPlugin(t);if(!i)throw new Error(`Plugin not found: ${t}`);const n=this.getPluginConfig(t)||i.config||{},a=n.mode||"local";try{switch(a){case"local":return i.executeLocal?i.executeLocal(e,...o):null;case"api":if(!i.executeAPI)throw new Error(`Plugin ${t} does not support API mode`);return await i.executeAPI(e,...o);case"hybrid":if(i.executeHybrid)return await i.executeHybrid(e,...o);try{if(i.executeAPI)return await i.executeAPI(e,...o)}catch(r){if(console.warn(`API execution failed for ${t}, falling back to local`,r),i.executeLocal&&n.fallbackToLocal!==!1)return i.executeLocal(e,...o);throw r}break;default:throw new Error(`Unknown plugin mode: ${a}`)}}catch(r){throw console.error(`Error executing command ${e} on plugin ${t}:`,r),r}}async destroyAll(){const t=this.plugins.filter(e=>e.destroy).map(e=>e.destroy());await Promise.all(t),this.plugins=[],this.pluginConfigs.clear()}}class E{constructor(t={}){this.commands=new Map,Object.entries(t).forEach(([e,o])=>{this.register(e,o)})}register(t,e){this.commands.has(t)&&console.warn(`Command ${t} is being overwritten`),this.commands.set(t,e)}unregister(t){this.commands.delete(t)}get(t){return this.commands.get(t)}has(t){return this.commands.has(t)}getCommandNames(){return Array.from(this.commands.keys())}clear(){this.commands.clear()}}class k{constructor(t={}){this.listeners=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));const e=this.pluginManager.buildSchema();this.state=f.create(e),this.commandRegistry=new E(this.pluginManager.getCommands())}execCommand(t,e){if(this.isReadonly)return console.warn("Cannot execute commands in readonly mode"),!1;if(this.isDestroyed)return console.warn("Cannot execute commands on destroyed editor"),!1;const o=this.commandRegistry.get(t);if(!o)return console.warn(`Command not found: ${t}`),!1;let i;return e!==void 0?i=o(this.state,e):i=o(this.state),i?(this.setState(i),this.emit("change",this.state),!0):!1}setState(t){this.isDestroyed||(this.state=t,this.emit("stateChange",t))}getState(){return this.state}setReadonly(t){this.isReadonly=t,this.emit("readonlyChange",t)}isReadOnly(){return this.isReadonly}on(t,e){return this.listeners.has(t)||this.listeners.set(t,[]),this.listeners.get(t).push(e),()=>{const o=this.listeners.get(t);if(o){const i=o.indexOf(e);i>-1&&o.splice(i,1)}}}emit(t,...e){const o=this.listeners.get(t);o&&o.forEach(i=>{try{i(...e)}catch(n){console.error(`Error in ${t} handler:`,n)}})}destroy(){this.isDestroyed||(this.isDestroyed=!0,this.listeners.clear(),this.emit("destroy"))}isEditorDestroyed(){return this.isDestroyed}}class v{constructor(t,e,o){this.config=t,this.plugins=e,this.pluginLoader=o}setCommandHandler(t){this.commandHandler=t}parseToolbarString(t){const e=[],o=t.split("|").map(r=>r.trim()),i=this.getAvailableToolbarItems(),n=new Map;i.forEach(r=>{r.command&&n.set(r.command,r),r.type==="group"&&r.label&&n.set(r.label,r)});const a={bold:"toggleBold",italic:"toggleItalic",underline:"toggleUnderline",strikethrough:"toggleStrikethrough",bullist:"toggleBulletList",numlist:"toggleOrderedList",checklist:"toggleChecklist",link:"openLinkDialog",image:"openImageDialog",table:"insertTable",anchor:"insertAnchor",code:"toggleSourceView",blockquote:"toggleBlockquote",undo:"undo",redo:"redo",textColor:"openTextColorPicker",backgroundColor:"openBackgroundColorPicker",fontSize:"fontSize",fontFamily:"setFontFamily",lineHeight:"setLineHeight",heading:"setBlockType",paragraph:"setParagraph",textAlignment:"setTextAlignment",direction:"setDirectionLTR",indent:"increaseIndent",outdent:"decreaseIndent",capitalization:"setCapitalization",math:"insertMath",specialCharacters:"insertSpecialCharacter",emojis:"openEmojiDialog",embedIframe:"openEmbedIframeDialog",fullscreen:"toggleFullscreen",preview:"togglePreview",print:"print",a11yChecker:"toggleA11yChecker",spellCheck:"toggleSpellCheck",comments:"addComment",showHideComments:"toggleComments",toggleComments:"toggleComments",footnote:"insertFootnote",mergeTags:"insertMergeTag",pageBreak:"insertPageBreak",template:"insertTemplate",importWord:"importWord",exportWord:"exportWord",exportPdf:"exportPdf",insertImage:"insertImage",insertVideo:"insertVideo",codeBlock:"insertCodeBlock"};return o.forEach(r=>{const s=[];r.split(/\s+/).filter(Boolean).forEach(u=>{if(u==="direction"){const c=n.get("setDirectionLTR"),h=n.get("setDirectionRTL");c&&s.push({id:"directionLTR",label:c.label,command:c.command,icon:c.icon,type:c.type||"button",options:c.options}),h&&s.push({id:"directionRTL",label:h.label,command:h.command,icon:h.icon,type:h.type||"button",options:h.options});return}if(u==="comments"){const c=n.get("addComment"),h=n.get("toggleComments");c&&s.push({id:"addComment",label:c.label,command:c.command,icon:c.icon,type:c.type||"button",options:c.options}),h&&s.push({id:"toggleComments",label:h.label,command:h.command,icon:h.icon,type:h.type||"button",options:h.options});return}const p=a[u]||u;let d=n.get(p);d||(d=n.get(u)),d&&s.push({id:u,label:d.label,command:d.command,icon:d.icon,type:d.type==="separator"?"separator":d.type||"button",options:d.options,items:d.items})}),s.length>0&&e.push(s)}),e}getAvailableToolbarItems(){return this.plugins.flatMap(e=>e.toolbar||[])}render(t){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}`);const e=this.config.items||this.getDefaultToolbarString(),o=this.parseToolbarString(e);o.forEach((i,n)=>{const a=document.createElement("div");if(a.className="editora-toolbar-group",i.forEach(r=>{this.appendToolbarButton(a,r)}),t.appendChild(a),n<o.length-1){const r=document.createElement("div");r.className="editora-toolbar-separator",t.appendChild(r)}})}appendToolbarButton(t,e){if(e.type==="separator"){const o=document.createElement("div");o.className="editora-toolbar-separator",t.appendChild(o)}else if(e.type==="dropdown"){const o=this.createDropdown(e);t.appendChild(o)}else if(e.type==="inline-menu"){const o=this.createInlineMenu(e);t.appendChild(o)}else if(e.type==="group"&&e.items&&e.items.length){const o=this.createGroupButton(e);t.appendChild(o)}else if(e.type==="input"){const o=this.createInput(e);t.appendChild(o)}else{const o=this.createButton(e);t.appendChild(o)}}createGroupButton(t){const e=document.createElement("div");if(e.className="editora-toolbar-group-button",e.title=t.label,t.icon)if(t.icon.startsWith("<svg")&&t.icon.endsWith("</svg>")){const o=document.createElement("span");o.className="editora-toolbar-icon",o.innerHTML=t.icon,e.appendChild(o)}else e.innerHTML=t.icon;if(t.items&&t.items.length){const o=document.createElement("div");o.className="editora-toolbar-group-items",t.items.forEach(i=>{this.appendToolbarButton(o,i)}),e.appendChild(o)}return e}createInput(t){const e=document.createElement("input");return e.className=`editora-toolbar-input ${t.label.toLowerCase().replace(/\s+/g,"-")}`,e.type="text",e.title=t.label,e.placeholder=t.placeholder||"",e.setAttribute("data-command",t.command),t.active&&e.classList.add("active"),t.disabled&&(e.disabled=!0),e.addEventListener("click",o=>{o.preventDefault(),this.commandHandler&&this.commandHandler(t.command)}),e}createButton(t){const e=document.createElement("button");if(e.className="editora-toolbar-button",e.type="button",e.title=t.label,e.setAttribute("data-command",t.command),t.icon)if(t.icon.startsWith("<svg")&&t.icon.endsWith("</svg>")){const o=document.createElement("span");o.className="editora-toolbar-icon",o.innerHTML=t.icon,e.appendChild(o)}else e.innerHTML=t.icon;else e.textContent=t.label;return t.active&&e.classList.add("active"),t.disabled&&(e.disabled=!0),e.addEventListener("click",o=>{o.preventDefault(),this.commandHandler&&this.commandHandler(t.command)}),e}createDropdown(t){const e=document.createElement("div");e.className="editora-toolbar-dropdown";const o=document.createElement("button");o.className="editora-toolbar-button editora-toolbar-dropdown-trigger",o.type="button",o.textContent=t.label;const i=document.createElement("div");i.className="editora-toolbar-dropdown-menu",i.style.display="none",t.options&&t.options.forEach(a=>{const r=document.createElement("button");r.className="editora-toolbar-dropdown-item",r.type="button",r.textContent=a.label,r.setAttribute("data-value",a.value),r.addEventListener("click",s=>{s.preventDefault(),this.commandHandler&&this.commandHandler(t.command,a.value),i.style.display="none"}),i.appendChild(r)}),o.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation();const r=i.style.display==="block";i.style.display=r?"none":"block"});const n=a=>{e.contains(a.target)||(i.style.display="none")};return document.addEventListener("click",n),e._cleanupDropdown=()=>{document.removeEventListener("click",n)},e.appendChild(o),e.appendChild(i),e}createInlineMenu(t){const e=document.createElement("div");e.className="editora-toolbar-dropdown editora-toolbar-inline-menu";const o=document.createElement("button");if(o.className="editora-toolbar-button",o.type="button",o.title=t.label,t.icon)if(t.icon.startsWith("<svg")&&t.icon.endsWith("</svg>")){const n=document.createElement("span");n.className="editora-toolbar-icon",n.innerHTML=t.icon,o.appendChild(n)}else o.innerHTML=t.icon;else o.textContent=t.label;const i=document.createElement("div");return i.className="editora-toolbar-dropdown-menu",i.style.display="none",t.options&&t.options.forEach(n=>{const a=document.createElement("button");a.className="editora-toolbar-dropdown-item",a.type="button",a.textContent=n.label,a.setAttribute("data-value",n.value),a.addEventListener("click",r=>{r.preventDefault(),r.stopPropagation(),this.commandHandler&&this.commandHandler(t.command,n.value),i.style.display="none"}),i.appendChild(a)}),o.addEventListener("click",n=>{var r;n.preventDefault(),n.stopPropagation();const a=(r=this.container)==null?void 0:r.querySelectorAll(".editora-toolbar-dropdown-menu");a==null||a.forEach(s=>{s!==i&&(s.style.display="none")}),i.style.display=i.style.display==="none"?"block":"none"}),document.addEventListener("click",n=>{e.contains(n.target)||(i.style.display="none")}),e.appendChild(o),e.appendChild(i),e}getDefaultToolbarString(){return this.getAvailableToolbarItems().map(e=>e.command).join(" ")}updateButtonState(t,e){if(!this.container)return;const o=this.container.querySelector(`[data-command="${t}"]`);o&&(e.active!==void 0&&o.classList.toggle("active",e.active),e.disabled!==void 0&&(o.disabled=e.disabled))}destroy(){this.container&&(this.container.querySelectorAll(".editora-toolbar-dropdown").forEach(e=>{const o=e._cleanupDropdown;o&&o()}),this.container.innerHTML=""),this.commandHandler=void 0}}class L{constructor(t){this.visible=!1,this.config=t}create(t){const e=document.createElement("div");return e.className="editora-floating-toolbar",e.style.display="none",e.style.position="absolute",e.style.zIndex="1000",this.container=e,t.appendChild(e),e}show(t,e){this.container&&(this.container.style.display="block",this.container.style.left=`${t}px`,this.container.style.top=`${e}px`,this.visible=!0)}hide(){this.container&&(this.container.style.display="none",this.visible=!1)}updatePosition(t,e){!this.container||!this.visible||(this.container.style.left=`${t}px`,this.container.style.top=`${e}px`)}isVisible(){return this.visible}destroy(){this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.container=void 0,this.visible=!1}}class T{constructor(t={}){this.statusInfo={},this.config=t}create(t){const e=document.createElement("div");return e.className="editora-statusbar",this.config.position&&e.classList.add(`editora-statusbar-${this.config.position}`),this.container=e,t.appendChild(e),e}update(t){this.statusInfo={...this.statusInfo,...t},this.render()}render(){if(!this.container)return;this.container.innerHTML="";const t=document.createElement("div");t.className="editora-statusbar-left";const e=document.createElement("div");e.className="editora-statusbar-right";const o=[];if(this.statusInfo.selectionInfo){const n=this.statusInfo.selectionInfo;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`))}else if(this.statusInfo.cursorPosition){const n=this.statusInfo.cursorPosition;o.push(`Ln ${n.line}, Col ${n.column}`)}this.statusInfo.language&&o.push(this.statusInfo.language);const i=[];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])=>{i.push(`${n}: ${a}`)}),o.forEach((n,a)=>{const r=document.createElement("span");if(r.className="editora-statusbar-item",r.textContent=n,t.appendChild(r),a<o.length-1){const s=document.createElement("span");s.className="editora-statusbar-separator",s.textContent="|",t.appendChild(s)}}),i.forEach((n,a)=>{const r=document.createElement("span");if(r.className="editora-statusbar-item",r.textContent=n,e.appendChild(r),a<i.length-1){const s=document.createElement("span");s.className="editora-statusbar-separator",s.textContent="|",e.appendChild(s)}}),this.container.appendChild(t),this.container.appendChild(e)}destroy(){this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.container=void 0}}function I(l,t){const e=l.textContent||"",o=P(l,t.startContainer,t.startOffset),n=e.substring(0,o).split(`
2
+ `),a=n.length,r=n[n.length-1].length+1;return{line:a,column:r}}function P(l,t,e){var a;let o=0;const i=document.createTreeWalker(l,NodeFilter.SHOW_TEXT,null);let n=i.firstChild();for(;n;){if(n===t){o+=e;break}else n.nodeType===Node.TEXT_NODE&&(o+=((a=n.textContent)==null?void 0:a.length)||0);n=i.nextNode()}return o}function S(l){var o,i;const t=l.querySelectorAll("div, p, br, h1, h2, h3, h4, h5, h6, blockquote, li, pre");let e=1;if(t.length>0){e=t.length;const n=t[t.length-1];(n.tagName==="BR"||((o=n.innerHTML)==null?void 0:o.trim())===""||((i=n.textContent)==null?void 0:i.trim())==="")&&e++}else{const a=(l.textContent||"").split(`
3
+ `).length;e=Math.max(1,a)}return e}function A(l){const t=l.trim()?l.trim().split(/\s+/).length:0,e=l.length;return{words:t,chars:e}}function N(l,t){const e=l.toString();return{startLine:t.line,startColumn:t.column,endLine:t.line,endColumn:t.column+e.length,selectedChars:e.length,selectedWords:e.trim().split(/\s+/).filter(Boolean).length}}const y=class y{static resolve(t){const e={};if(Object.assign(e,this.EDITOR_DEFAULTS),t.pluginDefaults&&Object.assign(e,t.pluginDefaults),t.attributes){const o=this.parseAttributes(t.attributes);Object.assign(e,o)}return t.jsConfig&&Object.assign(e,t.jsConfig),e}static parseAttributes(t){const e={};for(const[o,i]of Object.entries(t)){const n=this.kebabToCamel(o);e[n]=this.parseAttributeValue(i)}return e}static parseAttributeValue(t){if(t==="true")return!0;if(t==="false")return!1;if(/^\d+$/.test(t))return parseInt(t,10);if(/^\d+\.\d+$/.test(t))return parseFloat(t);if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){return t}return t}static kebabToCamel(t){return t.replace(/-([a-z])/g,(e,o)=>o.toUpperCase())}static validate(t){const e=[];return t.height!==void 0&&typeof t.height=="number"&&t.height<0&&e.push("height must be a positive number"),t.width!==void 0&&typeof t.width=="number"&&t.width<0&&e.push("width must be a positive number"),t.plugins!==void 0&&!Array.isArray(t.plugins)&&typeof t.plugins!="string"&&e.push("plugins must be an array or string"),t.theme!==void 0&&typeof t.theme!="string"&&e.push("theme must be a string"),{valid:e.length===0,errors:e}}static getDefaults(){return{...this.EDITOR_DEFAULTS}}static merge(...t){const e={};for(const o of t)for(const[i,n]of Object.entries(o))n!=null&&(typeof n=="object"&&!Array.isArray(n)&&e[i]?e[i]=this.merge(e[i],n):e[i]=n);return e}};y.EDITOR_DEFAULTS={height:400,width:"100%",readonly:!1,disabled:!1,menubar:!0,toolbar:!0,plugins:[],theme:"light",content:"",placeholder:"Start typing...",autofocus:!1,autosave:!1,spellcheck:!1,language:"en"};let b=y;class M{constructor(){this.loadedPlugins=new Map,this.pluginRegistry=new Map}register(t,e){this.pluginRegistry.set(t,e)}async load(t,e){if(this.loadedPlugins.has(t))return this.loadedPlugins.get(t);const o=this.pluginRegistry.get(t);if(!o)return console.warn(`Plugin not found: ${t}`),null;const i=await o();return e&&this.applyPluginConfig(i,e),this.loadedPlugins.set(t,i),i}async loadMultiple(t,e){return(await Promise.all(t.map(i=>this.load(i,e)))).filter(i=>i!==null)}async parsePluginString(t,e){const o=t.split(/\s+/).filter(Boolean);return this.loadMultiple(o,e)}applyPluginConfig(t,e){t.__pluginConfig=e}unload(t){this.loadedPlugins.delete(t)}clear(){this.loadedPlugins.clear()}getLoadedPlugins(){return Array.from(this.loadedPlugins.values())}getRegisteredPluginNames(){return Array.from(this.pluginRegistry.keys())}isLoaded(t){return this.loadedPlugins.has(t)}}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}}';let m;function z(){const l="editora-webcomponent-styles";if(!document.getElementById(l)){const t=document.createElement("style");t.id=l,t.textContent=H,document.head.appendChild(t)}}function B(){if(!m){const l=g.__globalPluginLoader;l?m=l:m=new M}return m}function D(l){const t=B();Object.entries(l).forEach(([e,o])=>{t.register(e,o)})}class g extends HTMLElement{constructor(){if(super(),this.config={},this.isInitialized=!1,z(),!this.hasAttribute("data-initial-content")){const t=this.innerHTML.trim();t&&this.setAttribute("data-initial-content",t)}}static get observedAttributes(){return["height","width","menubar","plugins","toolbar","toolbar-items","readonly","disabled","theme","placeholder","autofocus","language","spellcheck","statusbar"]}connectedCallback(){this.config=this.resolveConfig(),this.waitForPluginLoader().then(()=>{setTimeout(async()=>{await this.initialize()},0)})}async waitForPluginLoader(){if(g.__globalPluginLoader){this.pluginLoader=g.__globalPluginLoader;return}return new Promise(t=>{const e=()=>{g.__globalPluginLoader?(this.pluginLoader=g.__globalPluginLoader,t()):setTimeout(e,0)};e()})}disconnectedCallback(){this.destroy()}attributeChangedCallback(t,e,o){e!==o&&(this.config=this.resolveConfig(),this.handleAttributeChange(t,o))}async setConfig(t){this.jsConfig=t,this.config=this.resolveConfig(),this.isConnected&&(this.destroy(),await this.waitForPluginLoader(),await this.initialize())}async initialize(){if(this.querySelector(".editora-toolbar")||this.isInitialized)return;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}`);const t=await this.loadPlugins();t.forEach(o=>{if(o.init&&typeof o.init=="function")try{o.init({editorElement:this})}catch(i){console.error(`[RichTextEditor] Error initializing plugin ${o.name}:`,i)}});const e=this.getAttribute("data-initial-content")||"";this.engine=new k({content:e,plugins:t,readonly:this.config.readonly}),this.createUI(t,e),this.setupEventListeners(),this.isInitialized=!0,this.dispatchEvent(new CustomEvent("editor-ready",{detail:{api:this.getAPI()},bubbles:!0}))}getInitialContent(){if(this.config.content)return this.config.content;const t=this.querySelector("[slot]");return t?t.innerHTML:this.hasChildNodes()?Array.from(this.childNodes).map(o=>o.nodeType===Node.TEXT_NODE?o.textContent:o.nodeType===Node.ELEMENT_NODE?o.outerHTML:"").join("").trim():""}async loadPlugins(){this.pluginLoader||await this.waitForPluginLoader();const t=[];if(this.config.plugins&&(typeof this.config.plugins=="string"&&this.config.plugins.length>0||Array.isArray(this.config.plugins)&&this.config.plugins.length>0)){if(typeof this.config.plugins=="string"){const o=await this.pluginLoader.parsePluginString(this.config.plugins);t.push(...o)}else if(Array.isArray(this.config.plugins))for(const o of this.config.plugins)if(typeof o=="string"){const i=await this.pluginLoader.load(o);i&&t.push(i)}else t.push(o)}else{const o=this.pluginLoader.getRegisteredPluginNames(),i=await this.pluginLoader.loadMultiple(o);t.push(...i)}return t}createUI(t,e){const o=this.querySelector('[slot="toolbar"]'),i=this.querySelector('[slot="statusbar"]');if(this.innerHTML="",this.config.toolbar!==!1&&!o){this.toolbarElement=document.createElement("div"),this.toolbarElement.className="editora-toolbar-container",this.appendChild(this.toolbarElement);const n=this.config.toolbarItems||this.config.toolbar;this.toolbar=new v({items:typeof n=="string"?n:void 0,sticky:this.config.toolbar&&typeof this.config.toolbar=="object"?this.config.toolbar.sticky:!1,position:"top"},t,this.pluginLoader),this.toolbar.setCommandHandler((a,r)=>{var x,u;if(this.contentElement){this.contentElement.focus();const p=window.getSelection();if(!p||p.rangeCount===0||!this.contentElement.contains(p.anchorNode)){const d=document.createRange(),c=this.contentElement.lastChild||this.contentElement;c.nodeType===Node.TEXT_NODE?d.setStart(c,((x=c.textContent)==null?void 0:x.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)}}const s=t.find(p=>p.commands&&p.commands[a]);if(s&&s.commands){const p=s.commands[a];if(typeof p=="function")try{return p(a==="toggleFullscreen"?this:r)}catch(d){return console.error(`[RichTextEditor] Error executing native command ${a}:`,d),!1}}return((u=this.engine)==null?void 0:u.execCommand(a,r))||!1}),this.toolbar.render(this.toolbarElement)}else o&&this.appendChild(o);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);try{document.execCommand("defaultParagraphSeparator",!1,"p")}catch(n){console.warn("defaultParagraphSeparator not supported:",n)}if(e){const n=document.createElement("div");n.innerHTML=e.trim(),!Array.from(n.childNodes).some(r=>{if(r.nodeType===Node.ELEMENT_NODE){const s=r.tagName;return["P","DIV","H1","H2","H3","H4","H5","H6","UL","OL","BLOCKQUOTE","PRE"].includes(s)}return!1})&&e.trim()?this.contentElement.innerHTML=`<p>${e.trim()}</p>`:this.contentElement.innerHTML=e}else this.config.placeholder?this.contentElement.innerHTML="":this.contentElement.innerHTML="<p><br></p>";this.appendChild(this.contentElement),this.config.toolbar&&typeof this.config.toolbar=="object"&&this.config.toolbar.floating&&(this.floatingToolbar=new L({enabled:!0}),this.floatingToolbar.create(this)),i?this.appendChild(i):this.config.statusbar&&(this.statusBarElement=document.createElement("div"),this.statusBarElement.className="editora-statusbar-container",this.appendChild(this.statusBarElement),this.statusBar=new T({position:"bottom"}),this.statusBar.create(this.statusBarElement)),this.config.autofocus&&setTimeout(()=>{var n;return(n=this.contentElement)==null?void 0:n.focus()},0)}setupEventListeners(){if(!this.contentElement||!this.engine)return;this.contentElement.addEventListener("input",()=>{const e=this.contentElement.innerHTML;this.dispatchEvent(new CustomEvent("content-change",{detail:{html:e},bubbles:!0})),this.updateStatusBar()}),this.contentElement.addEventListener("focus",()=>{this.dispatchEvent(new Event("editor-focus",{bubbles:!0}))}),this.contentElement.addEventListener("blur",()=>{this.dispatchEvent(new Event("editor-blur",{bubbles:!0}))});const t=()=>{this.updateFloatingToolbar(),this.updateStatusBar()};document.addEventListener("selectionchange",t)}updateFloatingToolbar(){if(!this.floatingToolbar)return;const t=window.getSelection();if(!t||t.rangeCount===0){this.floatingToolbar.hide();return}const e=t.getRangeAt(0);if(e.collapsed){this.floatingToolbar.hide();return}const o=e.getBoundingClientRect();this.floatingToolbar.show(o.left,o.top-40)}updateStatusBar(){if(!this.statusBar||!this.contentElement)return;const t=this.contentElement.textContent||"",{words:e,chars:o}=A(t),i=S(this.contentElement),n=window.getSelection();let a,r;if(n&&n.rangeCount>0){const s=n.getRangeAt(0);a=I(this.contentElement,s),s.collapsed||(r=N(s,a),a=void 0)}this.statusBar.update({wordCount:e,charCount:o,lineCount:i,cursorPosition:a,selectionInfo:r})}handleAttributeChange(t,e){switch(t){case"readonly":this.contentElement&&(this.contentElement.contentEditable=e==="true"?"false":"true"),this.engine&&this.engine.setReadonly(e==="true");break;case"theme":this.classList.forEach(o=>{o.startsWith("editora-theme-")&&this.classList.remove(o)}),e&&this.classList.add(`editora-theme-${e}`);break;case"placeholder":this.contentElement&&this.contentElement.setAttribute("data-placeholder",e);break;case"toolbar":case"plugins":this.isConnected&&(this.destroy(),this.waitForPluginLoader().then(()=>{this.initialize().catch(o=>{console.error("[RichTextEditor] Error during attribute change re-initialization:",o)})}));break}}resolveConfig(){const t={};for(let e=0;e<this.attributes.length;e++){const o=this.attributes[e];t[o.name]=o.value}return b.resolve({jsConfig:this.jsConfig,attributes:t})}getAPI(){return{getContent:()=>{var t;return((t=this.contentElement)==null?void 0:t.innerHTML)||""},setContent:t=>{this.contentElement&&(this.contentElement.innerHTML=t)},execCommand:(t,e)=>{var o;return((o=this.engine)==null?void 0:o.execCommand(t,e))||!1},focus:()=>{var t;(t=this.contentElement)==null||t.focus()},blur:()=>{var t;(t=this.contentElement)==null||t.blur()},destroy:()=>{this.destroy()},on:(t,e)=>(this.addEventListener(t,e),()=>this.removeEventListener(t,e)),getConfig:()=>({...this.config}),setReadonly:t=>{this.setAttribute("readonly",t.toString())}}}destroy(){var t,e,o,i;(t=this.engine)==null||t.destroy(),(e=this.toolbar)==null||e.destroy(),(o=this.floatingToolbar)==null||o.destroy(),(i=this.statusBar)==null||i.destroy(),this.innerHTML="",this.isInitialized=!1,this.dispatchEvent(new Event("editor-destroy",{bubbles:!0}))}getContent(){var t;return((t=this.contentElement)==null?void 0:t.innerHTML)||""}setContent(t){this.contentElement&&(this.contentElement.innerHTML=t)}execCommand(t,e){var o;return((o=this.engine)==null?void 0:o.execCommand(t,e))||!1}focus(){var t;(t=this.contentElement)==null||t.focus()}blur(){var t;(t=this.contentElement)==null||t.blur()}}exports.CommandRegistry=E;exports.ConfigResolver=b;exports.EditorEngine=k;exports.EditorState=f;exports.FloatingToolbar=L;exports.PluginLoader=M;exports.PluginManager=C;exports.RichTextEditorElement=g;exports.Schema=w;exports.StatusBar=T;exports.ToolbarRenderer=v;exports.calculateTextStats=A;exports.countLines=S;exports.getCursorPosition=I;exports.getSelectionInfo=N;exports.getTextOffset=P;exports.initWebComponent=D;
4
+ //# sourceMappingURL=index-BF5RBhL9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BF5RBhL9.js","sources":["../src/EditorState.ts","../src/schema/Node.ts","../src/plugins/Plugin.ts","../src/core/CommandRegistry.ts","../src/core/EditorEngine.ts","../src/ui/ToolbarRenderer.ts","../src/ui/FloatingToolbar.ts","../src/ui/StatusBar.ts","../src/utils/statusBarUtils.ts","../src/config/ConfigResolver.ts","../src/config/PluginLoader.ts","../src/webcomponent/RichTextEditor.ts"],"sourcesContent":["import { Node, Schema } from './schema/Node';\n\nexport interface EditorSelection {\n anchor: number;\n head: number;\n}\n\nexport class EditorState {\n doc: Node;\n selection: EditorSelection;\n schema: Schema;\n\n constructor(doc: Node, selection: EditorSelection, schema: Schema) {\n this.doc = doc;\n this.selection = selection;\n this.schema = schema;\n }\n\n static create(schema: Schema, content?: Node): EditorState {\n const doc = content || schema.node('doc', {}, [schema.node('paragraph')]);\n return new EditorState(doc, { anchor: 0, head: 0 }, schema);\n }\n\n apply(doc: Node, selection?: EditorSelection): EditorState {\n return new EditorState(doc, selection || this.selection, this.schema);\n }\n}\n","export interface NodeSpec {\n content?: string;\n marks?: string;\n group?: string;\n inline?: boolean;\n attrs?: Record<string, any>;\n toDOM?: (node: Node) => [string, Record<string, any>?, ...any[]];\n parseDOM?: Array<{\n tag: string;\n getAttrs?: (dom: HTMLElement) => Record<string, any> | null;\n }>;\n}\n\nexport interface Node {\n type: string;\n content?: Node[];\n text?: string;\n marks?: string[];\n attrs?: Record<string, any>;\n}\n\nexport class Schema {\n nodes: Map<string, NodeSpec>;\n marks: Map<string, NodeSpec>;\n\n constructor(nodes: Record<string, NodeSpec>, marks: Record<string, NodeSpec>) {\n this.nodes = new Map(Object.entries(nodes));\n this.marks = new Map(Object.entries(marks));\n }\n\n node(type: string, attrs?: Record<string, any>, content?: Node[]): Node {\n return { type, attrs, content };\n }\n\n text(text: string, marks?: string[]): Node {\n return { type: 'text', text, marks };\n }\n}\n","import { Schema, NodeSpec } from '../schema/Node';\nimport { EditorState } from '../EditorState';\nimport React from 'react';\n\nexport interface ToolbarItem {\n id?: string;\n label: string;\n command?: string;\n icon?: string;\n type?:\n | \"button\"\n | \"dropdown\"\n | \"input\"\n | \"inline-menu\"\n | \"separator\"\n | \"group\";\n options?: Array<{ label: string; value: string }>;\n placeholder?: string;\n shortcut?: string;\n items?: ToolbarItem[]; // For groups and dropdowns\n}\n\nexport interface PluginContext {\n provider?: React.FC<{ children: React.ReactNode }>;\n initialize?: () => void;\n destroy?: () => void;\n onEditorReady?: (editor: any) => void;\n}\n\n/**\n * Plugin operation modes\n * - local: All operations happen client-side only\n * - api: All operations require API calls\n * - hybrid: Tries API first, falls back to local\n */\nexport type PluginMode = 'local' | 'api' | 'hybrid';\n\n/**\n * Plugin configuration\n */\nexport interface PluginConfig {\n mode?: PluginMode;\n apiUrl?: string;\n apiKey?: string;\n timeout?: number;\n fallbackToLocal?: boolean;\n retryAttempts?: number;\n offline?: {\n enabled?: boolean;\n cacheStrategy?: 'memory' | 'indexeddb' | 'localstorage';\n };\n [key: string]: any;\n}\n\nexport interface Plugin {\n name: string;\n nodes?: Record<string, NodeSpec>;\n marks?: Record<string, NodeSpec>;\n commands?: Record<string, (state: EditorState, ...args: any[]) => EditorState | null>;\n toolbar?: ToolbarItem[];\n context?: PluginContext;\n config?: PluginConfig;\n \n // Lifecycle hooks\n initialize?: (config?: PluginConfig) => void | Promise<void>;\n destroy?: () => void | Promise<void>;\n \n // Mode-specific operations\n executeLocal?: (command: string, ...args: any[]) => any;\n executeAPI?: (command: string, ...args: any[]) => Promise<any>;\n executeHybrid?: (command: string, ...args: any[]) => Promise<any>;\n}\n\nexport class PluginManager {\n plugins: Plugin[] = [];\n private pluginConfigs: Map<string, PluginConfig> = new Map();\n\n register(plugin: Plugin, config?: PluginConfig): void {\n this.plugins.push(plugin);\n \n if (config) {\n this.pluginConfigs.set(plugin.name, config);\n }\n \n // Initialize plugin if it has an initialize method\n if (plugin.initialize) {\n const pluginConfig = this.pluginConfigs.get(plugin.name) || plugin.config;\n plugin.initialize(pluginConfig);\n }\n }\n\n unregister(pluginName: string): void {\n const index = this.plugins.findIndex(p => p.name === pluginName);\n if (index > -1) {\n const plugin = this.plugins[index];\n \n // Destroy plugin if it has a destroy method\n if (plugin.destroy) {\n plugin.destroy();\n }\n \n this.plugins.splice(index, 1);\n this.pluginConfigs.delete(pluginName);\n }\n }\n\n getPlugin(name: string): Plugin | undefined {\n return this.plugins.find(p => p.name === name);\n }\n\n getPluginConfig(name: string): PluginConfig | undefined {\n return this.pluginConfigs.get(name);\n }\n\n buildSchema(): Schema {\n const nodes: Record<string, NodeSpec> = {};\n const marks: Record<string, NodeSpec> = {};\n\n this.plugins.forEach(plugin => {\n if (plugin.nodes) Object.assign(nodes, plugin.nodes);\n if (plugin.marks) Object.assign(marks, plugin.marks);\n });\n\n return new Schema(nodes, marks);\n }\n\n getCommands(): Record<string, (state: EditorState, ...args: any[]) => EditorState | null> {\n const commands: Record<string, (state: EditorState, ...args: any[]) => EditorState | null> = {};\n this.plugins.forEach(plugin => {\n if (plugin.commands) Object.assign(commands, plugin.commands);\n });\n return commands;\n }\n\n getToolbarItems(): ToolbarItem[] {\n return this.plugins.flatMap(p => p.toolbar || []);\n }\n\n /**\n * Execute plugin command with mode awareness\n */\n async executePluginCommand(\n pluginName: string,\n command: string,\n ...args: any[]\n ): Promise<any> {\n const plugin = this.getPlugin(pluginName);\n if (!plugin) {\n throw new Error(`Plugin not found: ${pluginName}`);\n }\n\n const config = this.getPluginConfig(pluginName) || plugin.config || {};\n const mode = config.mode || 'local';\n\n try {\n switch (mode) {\n case 'local':\n return plugin.executeLocal ? plugin.executeLocal(command, ...args) : null;\n\n case 'api':\n if (!plugin.executeAPI) {\n throw new Error(`Plugin ${pluginName} does not support API mode`);\n }\n return await plugin.executeAPI(command, ...args);\n\n case 'hybrid':\n if (plugin.executeHybrid) {\n return await plugin.executeHybrid(command, ...args);\n }\n \n // Default hybrid implementation: try API, fall back to local\n try {\n if (plugin.executeAPI) {\n return await plugin.executeAPI(command, ...args);\n }\n } catch (error) {\n console.warn(`API execution failed for ${pluginName}, falling back to local`, error);\n if (plugin.executeLocal && config.fallbackToLocal !== false) {\n return plugin.executeLocal(command, ...args);\n }\n throw error;\n }\n break;\n\n default:\n throw new Error(`Unknown plugin mode: ${mode}`);\n }\n } catch (error) {\n console.error(`Error executing command ${command} on plugin ${pluginName}:`, error);\n throw error;\n }\n }\n\n /**\n * Destroy all plugins\n */\n async destroyAll(): Promise<void> {\n const destroyPromises = this.plugins\n .filter(p => p.destroy)\n .map(p => p.destroy!());\n\n await Promise.all(destroyPromises);\n this.plugins = [];\n this.pluginConfigs.clear();\n }\n}\n","/**\n * CommandRegistry - Centralized command management\n */\n\nimport { EditorState } from '../EditorState';\n\nexport type CommandHandler = (state: EditorState, value?: any) => EditorState | null;\n\nexport class CommandRegistry {\n private commands: Map<string, CommandHandler> = new Map();\n\n constructor(initialCommands: Record<string, CommandHandler> = {}) {\n Object.entries(initialCommands).forEach(([name, handler]) => {\n this.register(name, handler);\n });\n }\n\n /**\n * Register a command\n */\n register(name: string, handler: CommandHandler): void {\n if (this.commands.has(name)) {\n console.warn(`Command ${name} is being overwritten`);\n }\n this.commands.set(name, handler);\n }\n\n /**\n * Unregister a command\n */\n unregister(name: string): void {\n this.commands.delete(name);\n }\n\n /**\n * Get a command handler\n */\n get(name: string): CommandHandler | undefined {\n return this.commands.get(name);\n }\n\n /**\n * Check if command exists\n */\n has(name: string): boolean {\n return this.commands.has(name);\n }\n\n /**\n * Get all command names\n */\n getCommandNames(): string[] {\n return Array.from(this.commands.keys());\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands.clear();\n }\n}\n","/**\n * EditorEngine - Core editor logic, framework-agnostic\n * Manages document model, selection, commands, and plugin registry\n */\n\nimport { EditorState } from '../EditorState';\nimport { PluginManager } from '../plugins/Plugin';\nimport { Schema } from '../schema/Node';\nimport { CommandRegistry } from './CommandRegistry';\n\nexport interface EditorEngineConfig {\n content?: string;\n plugins?: any[];\n readonly?: boolean;\n autofocus?: boolean;\n sanitize?: boolean;\n maxLength?: number;\n debounceDelay?: number;\n}\n\nexport class EditorEngine {\n state: EditorState;\n pluginManager: PluginManager;\n commandRegistry: CommandRegistry;\n private listeners: Map<string, Array<(...args: any[]) => void>> = new Map();\n private isReadonly: boolean = false;\n private isDestroyed: boolean = false;\n\n constructor(config: EditorEngineConfig = {}) {\n this.isReadonly = config.readonly || false;\n \n // Initialize plugin manager\n this.pluginManager = new PluginManager();\n if (config.plugins && Array.isArray(config.plugins)) {\n config.plugins.forEach(plugin => this.pluginManager.register(plugin));\n }\n \n // Build schema from plugins\n const schema = this.pluginManager.buildSchema();\n this.state = EditorState.create(schema);\n \n // Initialize command registry\n this.commandRegistry = new CommandRegistry(this.pluginManager.getCommands());\n }\n\n /**\n * Execute a command\n */\n execCommand(name: string, value?: any): boolean {\n if (this.isReadonly) {\n console.warn('Cannot execute commands in readonly mode');\n return false;\n }\n\n if (this.isDestroyed) {\n console.warn('Cannot execute commands on destroyed editor');\n return false;\n }\n\n const command = this.commandRegistry.get(name);\n if (!command) {\n console.warn(`Command not found: ${name}`);\n return false;\n }\n \n let newState: EditorState | null;\n \n if (value !== undefined) {\n newState = (command as any)(this.state, value);\n } else {\n newState = command(this.state);\n }\n \n if (newState) {\n this.setState(newState);\n this.emit('change', this.state);\n return true;\n }\n return false;\n }\n\n /**\n * Update editor state\n */\n setState(state: EditorState): void {\n if (this.isDestroyed) return;\n \n this.state = state;\n this.emit('stateChange', state);\n }\n\n /**\n * Get current state\n */\n getState(): EditorState {\n return this.state;\n }\n\n /**\n * Set readonly mode\n */\n setReadonly(readonly: boolean): void {\n this.isReadonly = readonly;\n this.emit('readonlyChange', readonly);\n }\n\n /**\n * Check if readonly\n */\n isReadOnly(): boolean {\n return this.isReadonly;\n }\n\n /**\n * Event emitter\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n \n this.listeners.get(event)!.push(handler);\n \n // Return unsubscribe function\n return () => {\n const handlers = this.listeners.get(event);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n }\n };\n }\n\n /**\n * Emit event\n */\n private emit(event: string, ...args: any[]): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n handlers.forEach(handler => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`Error in ${event} handler:`, error);\n }\n });\n }\n }\n\n /**\n * Destroy editor instance\n */\n destroy(): void {\n if (this.isDestroyed) return;\n \n this.isDestroyed = true;\n this.listeners.clear();\n this.emit('destroy');\n }\n\n /**\n * Check if destroyed\n */\n isEditorDestroyed(): boolean {\n return this.isDestroyed;\n }\n}\n","/**\n * ToolbarRenderer - Framework-agnostic toolbar rendering\n */\n\nimport { Plugin, ToolbarItem } from '../plugins/Plugin';\n\nexport interface ToolbarConfig {\n items?: string; // \"undo redo | bold italic | media table\"\n sticky?: boolean;\n position?: 'top' | 'bottom';\n floating?: boolean;\n}\n\nexport interface ToolbarButton {\n id: string;\n label: string;\n command?: string;\n icon?: string;\n type?: 'button' | 'dropdown' | 'input' | 'separator' | 'inline-menu' | 'group';\n options?: Array<{ label: string; value: string }>;\n active?: boolean;\n disabled?: boolean;\n items?: ToolbarButton[]; // For groups\n}\n\nexport class ToolbarRenderer {\n private config: ToolbarConfig;\n private plugins: Plugin[];\n private container?: HTMLElement;\n private commandHandler?: (command: string, value?: any) => void;\n private pluginLoader?: any; // PluginLoader instance to get all registered plugins\n\n constructor(config: ToolbarConfig, plugins: Plugin[], pluginLoader?: any) {\n this.config = config;\n this.plugins = plugins;\n this.pluginLoader = pluginLoader;\n }\n\n /**\n * Set command handler for toolbar buttons\n */\n setCommandHandler(handler: (command: string, value?: any) => void): void {\n this.commandHandler = handler;\n }\n\n /**\n * Parse toolbar string into button groups\n */\n private parseToolbarString(toolbarString: string): ToolbarButton[][] {\n const groups: ToolbarButton[][] = [];\n const sections = toolbarString.split(\"|\").map((s) => s.trim());\n\n const allToolbarItems = this.getAvailableToolbarItems();\n // Index items by command and by label (for group types with no command)\n const itemMap = new Map<string, ToolbarItem>();\n allToolbarItems.forEach((item) => {\n if (item.command) itemMap.set(item.command, item);\n if (item.type === \"group\" && item.label) itemMap.set(item.label, item);\n });\n\n // Common command aliases for backward compatibility\n const aliases: Record<string, string> = {\n bold: \"toggleBold\",\n italic: \"toggleItalic\",\n underline: \"toggleUnderline\",\n strikethrough: \"toggleStrikethrough\",\n bullist: \"toggleBulletList\",\n numlist: \"toggleOrderedList\",\n checklist: \"toggleChecklist\",\n link: \"openLinkDialog\",\n image: \"openImageDialog\",\n table: \"insertTable\",\n anchor: \"insertAnchor\",\n code: \"toggleSourceView\",\n blockquote: \"toggleBlockquote\",\n undo: \"undo\",\n redo: \"redo\",\n textColor: \"openTextColorPicker\",\n backgroundColor: \"openBackgroundColorPicker\",\n fontSize: \"fontSize\",\n fontFamily: \"setFontFamily\",\n lineHeight: \"setLineHeight\",\n heading: \"setBlockType\",\n paragraph: \"setParagraph\",\n textAlignment: \"setTextAlignment\",\n direction: \"setDirectionLTR\",\n indent: \"increaseIndent\",\n outdent: \"decreaseIndent\",\n capitalization: \"setCapitalization\",\n math: \"insertMath\",\n specialCharacters: \"insertSpecialCharacter\",\n emojis: \"openEmojiDialog\",\n embedIframe: \"openEmbedIframeDialog\",\n fullscreen: \"toggleFullscreen\",\n preview: \"togglePreview\",\n print: \"print\",\n a11yChecker: \"toggleA11yChecker\",\n spellCheck: \"toggleSpellCheck\",\n comments: \"addComment\",\n showHideComments: \"toggleComments\",\n toggleComments: \"toggleComments\",\n footnote: \"insertFootnote\",\n mergeTags: \"insertMergeTag\",\n pageBreak: \"insertPageBreak\",\n template: \"insertTemplate\",\n importWord: \"importWord\",\n exportWord: \"exportWord\",\n exportPdf: \"exportPdf\",\n insertImage: \"insertImage\",\n insertVideo: \"insertVideo\",\n codeBlock: \"insertCodeBlock\",\n };\n\n sections.forEach((section) => {\n const buttons: ToolbarButton[] = [];\n const commands = section.split(/\\s+/).filter(Boolean);\n\n commands.forEach((cmd) => {\n // Special handling for multi-button shortcuts\n if (cmd === \"direction\") {\n // Direction has two buttons: LTR and RTL\n const ltrItem = itemMap.get(\"setDirectionLTR\");\n const rtlItem = itemMap.get(\"setDirectionRTL\");\n if (ltrItem) {\n buttons.push({\n id: \"directionLTR\",\n label: ltrItem.label,\n command: ltrItem.command,\n icon: ltrItem.icon,\n type: ltrItem.type || \"button\",\n options: ltrItem.options,\n });\n }\n if (rtlItem) {\n buttons.push({\n id: \"directionRTL\",\n label: rtlItem.label,\n command: rtlItem.command,\n icon: rtlItem.icon,\n type: rtlItem.type || \"button\",\n options: rtlItem.options,\n });\n }\n return;\n }\n\n if (cmd === \"comments\") {\n // Comments has two buttons: Add Comment and Toggle Comments\n const addCommentItem = itemMap.get(\"addComment\");\n const toggleCommentsItem = itemMap.get(\"toggleComments\");\n if (addCommentItem) {\n buttons.push({\n id: \"addComment\",\n label: addCommentItem.label,\n command: addCommentItem.command,\n icon: addCommentItem.icon,\n type: addCommentItem.type || \"button\",\n options: addCommentItem.options,\n });\n }\n if (toggleCommentsItem) {\n buttons.push({\n id: \"toggleComments\",\n label: toggleCommentsItem.label,\n command: toggleCommentsItem.command,\n icon: toggleCommentsItem.icon,\n type: toggleCommentsItem.type || \"button\",\n options: toggleCommentsItem.options,\n });\n }\n return;\n }\n\n // Try direct command first, then alias\n const actualCommand = aliases[cmd] || cmd;\n let item = itemMap.get(actualCommand);\n // If not found by command, try by label (for group type)\n if (!item) item = itemMap.get(cmd);\n if (item) {\n buttons.push({\n id: cmd,\n label: item.label,\n command: item.command,\n icon: item.icon,\n type:\n item.type === \"separator\" ? \"separator\" : item.type || \"button\",\n options: item.options,\n items: item.items,\n });\n }\n });\n\n if (buttons.length > 0) {\n groups.push(buttons);\n }\n });\n\n return groups;\n }\n\n /**\n * Get all available toolbar items from plugins\n */\n private getAvailableToolbarItems(): ToolbarItem[] {\n // Use the plugins that were passed to the constructor - they should be loaded\n const items = this.plugins.flatMap((p) => p.toolbar || []);\n return items;\n }\n\n /**\n * Render toolbar to DOM element\n */\n render(container: HTMLElement): void {\n this.container = container;\n container.innerHTML = \"\";\n container.className = \"editora-toolbar\";\n\n if (this.config.sticky) {\n container.classList.add(\"editora-toolbar-sticky\");\n }\n\n if (this.config.position) {\n container.classList.add(`editora-toolbar-${this.config.position}`);\n }\n\n const toolbarString = this.config.items || this.getDefaultToolbarString();\n const buttonGroups = this.parseToolbarString(toolbarString);\n buttonGroups.forEach((group, groupIndex) => {\n const groupEl = document.createElement(\"div\");\n groupEl.className = \"editora-toolbar-group\";\n group.forEach((button) => {\n this.appendToolbarButton(groupEl, button);\n });\n container.appendChild(groupEl);\n // Add separator between groups (except last)\n if (groupIndex < buttonGroups.length - 1) {\n const separator = document.createElement(\"div\");\n separator.className = \"editora-toolbar-separator\";\n container.appendChild(separator);\n }\n });\n }\n\n /**\n * Append a toolbar button or group to a parent element\n */\n private appendToolbarButton(\n parent: HTMLElement,\n button: ToolbarButton,\n ): void {\n if (button.type === \"separator\") {\n const separator = document.createElement(\"div\");\n separator.className = \"editora-toolbar-separator\";\n parent.appendChild(separator);\n } else if (button.type === \"dropdown\") {\n const dropdownEl = this.createDropdown(button);\n parent.appendChild(dropdownEl);\n } else if (button.type === \"inline-menu\") {\n const inlineMenuEl = this.createInlineMenu(button);\n parent.appendChild(inlineMenuEl);\n } else if (button.type === \"group\" && button.items && button.items.length) {\n const groupButtonEl = this.createGroupButton(button);\n parent.appendChild(groupButtonEl);\n } else if (button.type === \"input\") {\n const inputEl = this.createInput(button);\n parent.appendChild(inputEl);\n } else {\n const buttonEl = this.createButton(button);\n parent.appendChild(buttonEl);\n }\n }\n\n /**\n * Create a toolbar button element\n */\n private createGroupButton(button: ToolbarButton): HTMLElement {\n const el = document.createElement(\"div\");\n el.className = \"editora-toolbar-group-button\";\n el.title = button.label;\n // Optionally add a label or icon for the group itself\n if (button.icon) {\n if (button.icon.startsWith(\"<svg\") && button.icon.endsWith(\"</svg>\")) {\n const iconWrapper = document.createElement(\"span\");\n iconWrapper.className = \"editora-toolbar-icon\";\n iconWrapper.innerHTML = button.icon;\n el.appendChild(iconWrapper);\n } else {\n el.innerHTML = button.icon;\n }\n }\n // Recursively render group items\n if (button.items && button.items.length) {\n const itemsContainer = document.createElement(\"div\");\n itemsContainer.className = \"editora-toolbar-group-items\";\n button.items.forEach((child) => {\n this.appendToolbarButton(itemsContainer, child);\n });\n el.appendChild(itemsContainer);\n }\n return el;\n }\n\n /**\n * Create a toolbar button element\n */\n private createInput(button: ToolbarButton): HTMLElement {\n const el = document.createElement(\"input\");\n el.className = `editora-toolbar-input ${button.label.toLowerCase().replace(/\\s+/g, \"-\")}`;\n el.type = \"text\";\n el.title = button.label;\n el.placeholder = button.placeholder || \"\";\n el.setAttribute(\"data-command\", button.command);\n\n if (button.active) {\n el.classList.add(\"active\");\n }\n\n if (button.disabled) {\n el.disabled = true;\n }\n\n el.addEventListener(\"click\", (e) => {\n e.preventDefault();\n if (this.commandHandler) {\n this.commandHandler(button.command);\n }\n });\n\n return el;\n }\n\n /**\n * Create a toolbar button element\n */\n private createButton(button: ToolbarButton): HTMLElement {\n const el = document.createElement(\"button\");\n el.className = \"editora-toolbar-button\";\n el.type = \"button\";\n el.title = button.label;\n el.setAttribute(\"data-command\", button.command);\n\n if (button.icon) {\n // Check if it's an SVG icon\n if (button.icon.startsWith(\"<svg\") && button.icon.endsWith(\"</svg>\")) {\n // Create a wrapper span for the SVG with proper styling\n const iconWrapper = document.createElement(\"span\");\n iconWrapper.className = \"editora-toolbar-icon\";\n iconWrapper.innerHTML = button.icon;\n el.appendChild(iconWrapper);\n } else {\n // Plain text icon or HTML\n el.innerHTML = button.icon;\n }\n } else {\n el.textContent = button.label;\n }\n\n if (button.active) {\n el.classList.add(\"active\");\n }\n\n if (button.disabled) {\n el.disabled = true;\n }\n\n el.addEventListener(\"click\", (e) => {\n e.preventDefault();\n if (this.commandHandler) {\n this.commandHandler(button.command);\n }\n });\n\n return el;\n }\n\n /**\n * Create a dropdown element\n */\n private createDropdown(button: ToolbarButton): HTMLElement {\n const container = document.createElement(\"div\");\n container.className = \"editora-toolbar-dropdown\";\n\n const trigger = document.createElement(\"button\");\n trigger.className =\n \"editora-toolbar-button editora-toolbar-dropdown-trigger\";\n trigger.type = \"button\";\n trigger.textContent = button.label;\n\n const menu = document.createElement(\"div\");\n menu.className = \"editora-toolbar-dropdown-menu\";\n menu.style.display = \"none\";\n\n if (button.options) {\n button.options.forEach((option) => {\n const item = document.createElement(\"button\");\n item.className = \"editora-toolbar-dropdown-item\";\n item.type = \"button\";\n item.textContent = option.label;\n item.setAttribute(\"data-value\", option.value);\n\n item.addEventListener(\"click\", (e) => {\n e.preventDefault();\n if (this.commandHandler) {\n this.commandHandler(button.command, option.value);\n }\n menu.style.display = \"none\";\n });\n\n menu.appendChild(item);\n });\n }\n\n trigger.addEventListener(\"click\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n const isOpen = menu.style.display === \"block\";\n menu.style.display = isOpen ? \"none\" : \"block\";\n });\n\n // Close dropdown when clicking outside\n const closeDropdown = (e: Event) => {\n if (!container.contains(e.target as Node)) {\n menu.style.display = \"none\";\n }\n };\n\n document.addEventListener(\"click\", closeDropdown);\n\n // Store the cleanup function for later removal\n (container as any)._cleanupDropdown = () => {\n document.removeEventListener(\"click\", closeDropdown);\n };\n\n container.appendChild(trigger);\n container.appendChild(menu);\n\n return container;\n }\n\n /**\n * Create an inline menu element (like dropdown but triggered by button click)\n */\n private createInlineMenu(button: ToolbarButton): HTMLElement {\n const container = document.createElement(\"div\");\n container.className =\n \"editora-toolbar-dropdown editora-toolbar-inline-menu\";\n\n const trigger = document.createElement(\"button\");\n trigger.className = \"editora-toolbar-button\";\n trigger.type = \"button\";\n trigger.title = button.label;\n\n // Add icon if available\n if (button.icon) {\n if (button.icon.startsWith(\"<svg\") && button.icon.endsWith(\"</svg>\")) {\n const iconWrapper = document.createElement(\"span\");\n iconWrapper.className = \"editora-toolbar-icon\";\n iconWrapper.innerHTML = button.icon;\n trigger.appendChild(iconWrapper);\n } else {\n trigger.innerHTML = button.icon;\n }\n } else {\n trigger.textContent = button.label;\n }\n\n const menu = document.createElement(\"div\");\n menu.className = \"editora-toolbar-dropdown-menu\";\n menu.style.display = \"none\";\n\n if (button.options) {\n button.options.forEach((option) => {\n const item = document.createElement(\"button\");\n item.className = \"editora-toolbar-dropdown-item\";\n item.type = \"button\";\n item.textContent = option.label;\n item.setAttribute(\"data-value\", option.value);\n\n item.addEventListener(\"click\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (this.commandHandler) {\n this.commandHandler(button.command, option.value);\n }\n menu.style.display = \"none\";\n });\n\n menu.appendChild(item);\n });\n }\n\n trigger.addEventListener(\"click\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n // Close all other menus\n const allMenus = this.container?.querySelectorAll(\n \".editora-toolbar-dropdown-menu\",\n );\n allMenus?.forEach((m) => {\n if (m !== menu) {\n (m as HTMLElement).style.display = \"none\";\n }\n });\n\n // Toggle this menu\n menu.style.display = menu.style.display === \"none\" ? \"block\" : \"none\";\n });\n\n // Close menu when clicking outside\n document.addEventListener(\"click\", (e) => {\n if (!container.contains(e.target as Node)) {\n menu.style.display = \"none\";\n }\n });\n\n container.appendChild(trigger);\n container.appendChild(menu);\n\n return container;\n }\n\n /**\n * Get default toolbar string if none provided\n */\n private getDefaultToolbarString(): string {\n const items = this.getAvailableToolbarItems();\n return items.map((item) => item.command).join(\" \");\n }\n\n /**\n * Update button state\n */\n updateButtonState(\n command: string,\n state: { active?: boolean; disabled?: boolean },\n ): void {\n if (!this.container) return;\n\n const button = this.container.querySelector(\n `[data-command=\"${command}\"]`,\n ) as HTMLButtonElement;\n if (button) {\n if (state.active !== undefined) {\n button.classList.toggle(\"active\", state.active);\n }\n if (state.disabled !== undefined) {\n button.disabled = state.disabled;\n }\n }\n }\n\n /**\n * Destroy toolbar\n */\n destroy(): void {\n if (this.container) {\n // Clean up dropdown event listeners\n const dropdowns = this.container.querySelectorAll('.editora-toolbar-dropdown');\n dropdowns.forEach(dropdown => {\n const cleanup = (dropdown as any)._cleanupDropdown;\n if (cleanup) {\n cleanup();\n }\n });\n this.container.innerHTML = \"\";\n }\n this.commandHandler = undefined;\n }\n}\n","/**\n * FloatingToolbar - Context-sensitive floating toolbar\n */\n\nexport interface FloatingToolbarConfig {\n enabled?: boolean;\n items?: string;\n anchorToSelection?: boolean;\n}\n\nexport class FloatingToolbar {\n private config: FloatingToolbarConfig;\n private container?: HTMLElement;\n private visible: boolean = false;\n\n constructor(config: FloatingToolbarConfig) {\n this.config = config;\n }\n\n /**\n * Create and mount floating toolbar\n */\n create(parentElement: HTMLElement): HTMLElement {\n const container = document.createElement('div');\n container.className = 'editora-floating-toolbar';\n container.style.display = 'none';\n container.style.position = 'absolute';\n container.style.zIndex = '1000';\n \n this.container = container;\n parentElement.appendChild(container);\n \n return container;\n }\n\n /**\n * Show toolbar at position\n */\n show(x: number, y: number): void {\n if (!this.container) return;\n \n this.container.style.display = 'block';\n this.container.style.left = `${x}px`;\n this.container.style.top = `${y}px`;\n this.visible = true;\n }\n\n /**\n * Hide toolbar\n */\n hide(): void {\n if (!this.container) return;\n \n this.container.style.display = 'none';\n this.visible = false;\n }\n\n /**\n * Update position\n */\n updatePosition(x: number, y: number): void {\n if (!this.container || !this.visible) return;\n \n this.container.style.left = `${x}px`;\n this.container.style.top = `${y}px`;\n }\n\n /**\n * Check if visible\n */\n isVisible(): boolean {\n return this.visible;\n }\n\n /**\n * Destroy floating toolbar\n */\n destroy(): void {\n if (this.container && this.container.parentNode) {\n this.container.parentNode.removeChild(this.container);\n }\n this.container = undefined;\n this.visible = false;\n }\n}\n","/**\n * StatusBar - Editor status information display\n */\n\nexport interface StatusBarConfig {\n enabled?: boolean;\n position?: 'top' | 'bottom';\n}\n\nexport interface StatusInfo {\n wordCount?: number;\n charCount?: number;\n lineCount?: number;\n language?: string;\n cursorPosition?: {\n line: number;\n column: number;\n };\n selectionInfo?: {\n startLine: number;\n startColumn: number;\n endLine: number;\n endColumn: number;\n selectedChars: number;\n selectedWords: number;\n };\n custom?: Record<string, string>;\n}\n\nexport class StatusBar {\n private config: StatusBarConfig;\n private container?: HTMLElement;\n private statusInfo: StatusInfo = {};\n\n constructor(config: StatusBarConfig = {}) {\n this.config = config;\n }\n\n /**\n * Create and mount status bar\n */\n create(parentElement: HTMLElement): HTMLElement {\n const container = document.createElement('div');\n container.className = 'editora-statusbar';\n \n if (this.config.position) {\n container.classList.add(`editora-statusbar-${this.config.position}`);\n }\n \n this.container = container;\n parentElement.appendChild(container);\n \n return container;\n }\n\n /**\n * Update status information\n */\n update(info: StatusInfo): void {\n this.statusInfo = { ...this.statusInfo, ...info };\n this.render();\n }\n\n /**\n * Render status bar content\n */\n private render(): void {\n if (!this.container) return;\n\n this.container.innerHTML = '';\n\n // Create left section\n const leftSection = document.createElement('div');\n leftSection.className = 'editora-statusbar-left';\n\n // Create right section\n const rightSection = document.createElement('div');\n rightSection.className = 'editora-statusbar-right';\n\n // Left section: Cursor position and selection info\n const leftItems: string[] = [];\n\n if (this.statusInfo.selectionInfo) {\n const sel = this.statusInfo.selectionInfo;\n if (sel.startLine === sel.endLine && sel.startColumn === sel.endColumn) {\n // Cursor position only\n leftItems.push(`Ln ${sel.startLine}, Col ${sel.startColumn}`);\n } else {\n // Selection info\n if (sel.startLine === sel.endLine) {\n leftItems.push(`Ln ${sel.startLine}, Col ${sel.startColumn}-${sel.endColumn}`);\n } else {\n leftItems.push(`Ln ${sel.startLine}:${sel.startColumn} - ${sel.endLine}:${sel.endColumn}`);\n }\n leftItems.push(`${sel.selectedChars} chars selected`);\n }\n } else if (this.statusInfo.cursorPosition) {\n const pos = this.statusInfo.cursorPosition;\n leftItems.push(`Ln ${pos.line}, Col ${pos.column}`);\n }\n\n if (this.statusInfo.language) {\n leftItems.push(this.statusInfo.language);\n }\n\n // Right section: Word count and character count\n const rightItems: string[] = [];\n\n if (this.statusInfo.wordCount !== undefined) {\n rightItems.push(`${this.statusInfo.wordCount} words`);\n }\n\n if (this.statusInfo.charCount !== undefined) {\n rightItems.push(`${this.statusInfo.charCount} chars`);\n }\n\n if (this.statusInfo.lineCount !== undefined) {\n rightItems.push(`${this.statusInfo.lineCount} lines`);\n }\n\n // Add custom items to right section\n if (this.statusInfo.custom) {\n Object.entries(this.statusInfo.custom).forEach(([key, value]) => {\n rightItems.push(`${key}: ${value}`);\n });\n }\n\n // Render left section\n leftItems.forEach((item, index) => {\n const span = document.createElement('span');\n span.className = 'editora-statusbar-item';\n span.textContent = item;\n leftSection.appendChild(span);\n\n if (index < leftItems.length - 1) {\n const separator = document.createElement('span');\n separator.className = 'editora-statusbar-separator';\n separator.textContent = '|';\n leftSection.appendChild(separator);\n }\n });\n\n // Render right section\n rightItems.forEach((item, index) => {\n const span = document.createElement('span');\n span.className = 'editora-statusbar-item';\n span.textContent = item;\n rightSection.appendChild(span);\n\n if (index < rightItems.length - 1) {\n const separator = document.createElement('span');\n separator.className = 'editora-statusbar-separator';\n separator.textContent = '|';\n rightSection.appendChild(separator);\n }\n });\n\n // Add sections to container\n this.container.appendChild(leftSection);\n this.container.appendChild(rightSection);\n }\n\n /**\n * Destroy status bar\n */\n destroy(): void {\n if (this.container && this.container.parentNode) {\n this.container.parentNode.removeChild(this.container);\n }\n this.container = undefined;\n }\n}\n","/**\n * Utility functions for status bar calculations\n */\n\n/**\n * Get cursor position (line and column) from a range within a content element\n */\nexport function getCursorPosition(contentElement: HTMLElement, range: Range): { line: number; column: number } {\n const text = contentElement.textContent || '';\n const startOffset = getTextOffset(contentElement, range.startContainer, range.startOffset);\n\n // Count lines up to the cursor position\n const textBeforeCursor = text.substring(0, startOffset);\n const lines = textBeforeCursor.split('\\n');\n const line = lines.length;\n const column = lines[lines.length - 1].length + 1;\n\n return { line, column };\n}\n\n/**\n * Get text offset from a DOM node and offset within a root element\n */\nexport function getTextOffset(rootElement: HTMLElement, node: Node, offset: number): number {\n let textOffset = 0;\n const walker = document.createTreeWalker(\n rootElement,\n NodeFilter.SHOW_TEXT,\n null\n );\n\n let currentNode = walker.firstChild();\n while (currentNode) {\n if (currentNode === node) {\n textOffset += offset;\n break;\n } else if (currentNode.nodeType === Node.TEXT_NODE) {\n textOffset += currentNode.textContent?.length || 0;\n }\n currentNode = walker.nextNode();\n }\n\n return textOffset;\n}\n\n/**\n * Count lines in a contentEditable element by analyzing block-level elements\n */\nexport function countLines(contentElement: HTMLElement): number {\n // Count block-level elements and br tags that represent line breaks\n const blocks = contentElement.querySelectorAll('div, p, br, h1, h2, h3, h4, h5, h6, blockquote, li, pre');\n let lineCount = 1; // At least 1 line\n\n // If there are block elements, count them as separate lines\n if (blocks.length > 0) {\n lineCount = blocks.length;\n // If the last element is empty or just a br, it might represent an additional empty line\n const lastBlock = blocks[blocks.length - 1];\n if (lastBlock.tagName === 'BR' ||\n (lastBlock as HTMLElement).innerHTML?.trim() === '' ||\n lastBlock.textContent?.trim() === '') {\n lineCount++;\n }\n } else {\n // No block elements, fall back to text-based line counting\n const text = contentElement.textContent || '';\n const textLines = text.split('\\n').length;\n lineCount = Math.max(1, textLines);\n }\n\n return lineCount;\n}\n\n/**\n * Calculate word and character counts from text\n */\nexport function calculateTextStats(text: string): { words: number; chars: number } {\n const words = text.trim() ? text.trim().split(/\\s+/).length : 0;\n const chars = text.length;\n return { words, chars };\n}\n\n/**\n * Get selection information from a range\n */\nexport function getSelectionInfo(range: Range, cursorPosition: { line: number; column: number }) {\n const selectedText = range.toString();\n return {\n startLine: cursorPosition.line,\n startColumn: cursorPosition.column,\n endLine: cursorPosition.line, // For now, assuming single line selections\n endColumn: cursorPosition.column + selectedText.length,\n selectedChars: selectedText.length,\n selectedWords: selectedText.trim().split(/\\s+/).filter(Boolean).length\n };\n}","/**\n * ConfigResolver - Configuration resolution with priority handling\n * Priority: Explicit JS config > Web Component attributes > Plugin defaults > Editor defaults\n */\n\nexport interface EditorConfigDefaults {\n height?: number | string;\n width?: number | string;\n readonly?: boolean;\n disabled?: boolean;\n menubar?: boolean;\n toolbar?: string | boolean;\n plugins?: string | string[];\n theme?: string;\n content?: string;\n placeholder?: string;\n autofocus?: boolean;\n autosave?: boolean | { interval?: number };\n spellcheck?: boolean | { mode?: 'local' | 'api' | 'hybrid'; apiUrl?: string };\n language?: string;\n [key: string]: any;\n}\n\nexport interface ConfigSource {\n jsConfig?: EditorConfigDefaults;\n attributes?: Record<string, string>;\n pluginDefaults?: EditorConfigDefaults;\n editorDefaults?: EditorConfigDefaults;\n}\n\nexport class ConfigResolver {\n private static readonly EDITOR_DEFAULTS: EditorConfigDefaults = {\n height: 400,\n width: '100%',\n readonly: false,\n disabled: false,\n menubar: true,\n toolbar: true,\n plugins: [],\n theme: 'light',\n content: '',\n placeholder: 'Start typing...',\n autofocus: false,\n autosave: false,\n spellcheck: false,\n language: 'en',\n };\n\n /**\n * Resolve configuration from multiple sources with priority\n */\n static resolve(sources: ConfigSource): EditorConfigDefaults {\n const config: EditorConfigDefaults = {};\n \n // Start with editor defaults\n Object.assign(config, this.EDITOR_DEFAULTS);\n \n // Apply plugin defaults\n if (sources.pluginDefaults) {\n Object.assign(config, sources.pluginDefaults);\n }\n \n // Apply web component attributes\n if (sources.attributes) {\n const parsedAttributes = this.parseAttributes(sources.attributes);\n Object.assign(config, parsedAttributes);\n }\n \n // Apply explicit JS config (highest priority)\n if (sources.jsConfig) {\n Object.assign(config, sources.jsConfig);\n }\n \n return config;\n }\n\n /**\n * Parse web component attributes\n */\n private static parseAttributes(attributes: Record<string, string>): EditorConfigDefaults {\n const config: EditorConfigDefaults = {};\n \n for (const [key, value] of Object.entries(attributes)) {\n const camelKey = this.kebabToCamel(key);\n config[camelKey] = this.parseAttributeValue(value);\n }\n \n return config;\n }\n\n /**\n * Parse attribute value to appropriate type\n */\n private static parseAttributeValue(value: string): any {\n // Boolean\n if (value === 'true') return true;\n if (value === 'false') return false;\n \n // Number\n if (/^\\d+$/.test(value)) return parseInt(value, 10);\n if (/^\\d+\\.\\d+$/.test(value)) return parseFloat(value);\n \n // JSON\n if (value.startsWith('{') || value.startsWith('[')) {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n \n // String\n return value;\n }\n\n /**\n * Convert kebab-case to camelCase\n */\n private static kebabToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n }\n\n /**\n * Validate configuration\n */\n static validate(config: EditorConfigDefaults): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n \n // Validate height\n if (config.height !== undefined) {\n if (typeof config.height === 'number' && config.height < 0) {\n errors.push('height must be a positive number');\n }\n }\n \n // Validate width\n if (config.width !== undefined) {\n if (typeof config.width === 'number' && config.width < 0) {\n errors.push('width must be a positive number');\n }\n }\n \n // Validate plugins\n if (config.plugins !== undefined) {\n if (!Array.isArray(config.plugins) && typeof config.plugins !== 'string') {\n errors.push('plugins must be an array or string');\n }\n }\n \n // Validate theme\n if (config.theme !== undefined) {\n if (typeof config.theme !== 'string') {\n errors.push('theme must be a string');\n }\n }\n \n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get default configuration\n */\n static getDefaults(): EditorConfigDefaults {\n return { ...this.EDITOR_DEFAULTS };\n }\n\n /**\n * Merge configurations (deep merge)\n */\n static merge(...configs: EditorConfigDefaults[]): EditorConfigDefaults {\n const result: EditorConfigDefaults = {};\n \n for (const config of configs) {\n for (const [key, value] of Object.entries(config)) {\n if (value !== undefined && value !== null) {\n if (typeof value === 'object' && !Array.isArray(value) && result[key]) {\n // Deep merge objects\n result[key] = this.merge(result[key], value);\n } else {\n result[key] = value;\n }\n }\n }\n }\n \n return result;\n }\n}\n","/**\n * PluginLoader - Dynamic plugin loading and resolution\n */\n\nimport { Plugin } from '../plugins/Plugin';\n\nexport interface PluginLoadConfig {\n mode?: 'local' | 'api' | 'hybrid';\n apiUrl?: string;\n fallbackToLocal?: boolean;\n}\n\nexport class PluginLoader {\n private loadedPlugins: Map<string, Plugin> = new Map();\n private pluginRegistry: Map<string, () => Plugin | Promise<Plugin>> = new Map();\n\n /**\n * Register a plugin factory (sync or async)\n */\n register(name: string, factory: () => Plugin | Promise<Plugin>): void {\n this.pluginRegistry.set(name, factory);\n }\n\n /**\n * Load a plugin by name (async)\n */\n async load(name: string, config?: PluginLoadConfig): Promise<Plugin | null> {\n // Check if already loaded\n if (this.loadedPlugins.has(name)) {\n return this.loadedPlugins.get(name)!;\n }\n \n // Check if registered\n const factory = this.pluginRegistry.get(name);\n if (!factory) {\n console.warn(`Plugin not found: ${name}`);\n return null;\n }\n \n // Create plugin instance (may be async)\n const plugin = await factory();\n \n // Apply config if provided\n if (config) {\n this.applyPluginConfig(plugin, config);\n }\n \n this.loadedPlugins.set(name, plugin);\n return plugin;\n }\n\n /**\n * Load multiple plugins\n */\n async loadMultiple(names: string[], config?: PluginLoadConfig): Promise<Plugin[]> {\n const plugins = await Promise.all(\n names.map(name => this.load(name, config))\n );\n return plugins.filter((p): p is Plugin => p !== null);\n }\n\n /**\n * Parse plugin string \"lists link image media\"\n */\n async parsePluginString(pluginString: string, config?: PluginLoadConfig): Promise<Plugin[]> {\n const names = pluginString.split(/\\s+/).filter(Boolean);\n return this.loadMultiple(names, config);\n }\n\n /**\n * Apply configuration to plugin\n */\n private applyPluginConfig(plugin: Plugin, config: PluginLoadConfig): void {\n // Store config on plugin instance for runtime use\n (plugin as any).__pluginConfig = config;\n }\n\n /**\n * Unload a plugin\n */\n unload(name: string): void {\n this.loadedPlugins.delete(name);\n }\n\n /**\n * Clear all loaded plugins\n */\n clear(): void {\n this.loadedPlugins.clear();\n }\n\n /**\n * Get all loaded plugins\n */\n getLoadedPlugins(): Plugin[] {\n return Array.from(this.loadedPlugins.values());\n }\n\n /**\n * Get all registered plugin names (available for loading)\n */\n getRegisteredPluginNames(): string[] {\n return Array.from(this.pluginRegistry.keys());\n }\n\n /**\n * Check if plugin is loaded\n */\n isLoaded(name: string): boolean {\n return this.loadedPlugins.has(name);\n }\n}\n","/**\n * RichTextEditor Web Component\n * TinyMCE-style declarative API for framework-agnostic usage\n */\n\nimport { EditorEngine } from '../core/EditorEngine';\nimport { ToolbarRenderer } from '../ui/ToolbarRenderer';\nimport { FloatingToolbar } from '../ui/FloatingToolbar';\nimport { StatusBar } from '../ui/StatusBar';\nimport { getCursorPosition, countLines, calculateTextStats, getSelectionInfo } from '../utils/statusBarUtils';\nimport { ConfigResolver, EditorConfigDefaults } from '../config/ConfigResolver';\nimport { PluginLoader } from '../config/PluginLoader';\nimport { Plugin } from '../plugins/Plugin';\n\n// Import styles\nimport styles from './styles.css?inline';\n\n// Global plugin registry for the web component\n// Will be set by standalone.ts before custom element definition\nlet globalPluginRegistry: PluginLoader;\n\n/**\n * Inject styles into document head if not already present\n */\nfunction injectStyles(): void {\n const styleId = 'editora-webcomponent-styles';\n if (!document.getElementById(styleId)) {\n const styleElement = document.createElement('style');\n styleElement.id = styleId;\n styleElement.textContent = styles;\n document.head.appendChild(styleElement);\n }\n}\n\n/**\n * Get or create the global plugin registry\n */\nfunction getGlobalRegistry(): PluginLoader {\n if (!globalPluginRegistry) {\n // Check if it was set externally (by standalone.ts)\n const externalRegistry = (RichTextEditorElement as any).__globalPluginLoader;\n if (externalRegistry) {\n globalPluginRegistry = externalRegistry;\n } else {\n // Fallback: create new registry\n globalPluginRegistry = new PluginLoader();\n }\n }\n return globalPluginRegistry;\n}\n\n/**\n * Initialize web component with plugin factories\n * This should be called once to register all available plugins\n */\nexport function initWebComponent(plugins: Record<string, () => Plugin>): void {\n const registry = getGlobalRegistry();\n Object.entries(plugins).forEach(([name, factory]) => {\n registry.register(name, factory);\n });\n}\n\nexport class RichTextEditorElement extends HTMLElement {\n private engine?: EditorEngine;\n private toolbar?: ToolbarRenderer;\n private floatingToolbar?: FloatingToolbar;\n private statusBar?: StatusBar;\n private pluginLoader: PluginLoader;\n private config: EditorConfigDefaults = {};\n private contentElement?: HTMLElement;\n private toolbarElement?: HTMLElement;\n private statusBarElement?: HTMLElement;\n private jsConfig?: EditorConfigDefaults;\n private isInitialized = false;\n\n // Observed attributes for reactive updates\n static get observedAttributes(): string[] {\n return [\n 'height',\n 'width',\n 'menubar',\n 'plugins',\n 'toolbar',\n 'toolbar-items',\n 'readonly',\n 'disabled',\n 'theme',\n 'placeholder',\n 'autofocus',\n 'language',\n 'spellcheck',\n 'statusbar',\n ];\n }\n\n constructor() {\n super();\n \n // Inject styles into document head\n injectStyles();\n\n // Capture initial content before any processing\n if (!this.hasAttribute('data-initial-content')) {\n const content = this.innerHTML.trim();\n if (content) {\n this.setAttribute('data-initial-content', content);\n }\n }\n }\n\n /**\n * Called when element is added to DOM\n */\n connectedCallback(): void {\n // Resolve configuration\n this.config = this.resolveConfig();\n \n // Wait for plugin loader to be available, then initialize\n this.waitForPluginLoader().then(() => {\n // Defer initialization to ensure DOM is fully ready\n setTimeout(async () => {\n await this.initialize();\n }, 0);\n });\n }\n\n /**\n * Wait for the global plugin loader to be available\n */\n private async waitForPluginLoader(): Promise<void> {\n // If already available, return immediately\n if ((RichTextEditorElement as any).__globalPluginLoader) {\n this.pluginLoader = (RichTextEditorElement as any).__globalPluginLoader;\n return;\n }\n \n // Wait for it to become available\n return new Promise((resolve) => {\n const checkLoader = () => {\n if ((RichTextEditorElement as any).__globalPluginLoader) {\n this.pluginLoader = (RichTextEditorElement as any).__globalPluginLoader;\n resolve();\n } else {\n // Check again in next tick\n setTimeout(checkLoader, 0);\n }\n };\n checkLoader();\n });\n }\n\n /**\n * Called when element is removed from DOM\n */\n disconnectedCallback(): void {\n this.destroy();\n }\n\n /**\n * Called when an observed attribute changes\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string): void {\n if (oldValue === newValue) return;\n \n // Update config and reinitialize affected parts\n this.config = this.resolveConfig();\n this.handleAttributeChange(name, newValue);\n }\n\n /**\n * Set configuration via JavaScript API\n */\n async setConfig(config: EditorConfigDefaults): Promise<void> {\n this.jsConfig = config;\n this.config = this.resolveConfig();\n \n // Reinitialize if already connected\n if (this.isConnected) {\n this.destroy();\n await this.waitForPluginLoader();\n await this.initialize();\n }\n }\n\n /**\n * Initialize the editor\n */\n private async initialize(): Promise<void> {\n // Prevent re-initialization if already has toolbar\n if (this.querySelector('.editora-toolbar')) {\n return;\n }\n \n // Prevent re-initialization\n if (this.isInitialized) return;\n \n // Mark this element as an editor container for multi-instance support\n this.setAttribute('data-editora-editor', 'true');\n \n // Config is already resolved in connectedCallback\n \n // Apply dimensions\n if (this.config.height) {\n this.style.height = typeof this.config.height === 'number'\n ? `${this.config.height}px`\n : this.config.height;\n }\n \n if (this.config.width) {\n this.style.width = typeof this.config.width === 'number'\n ? `${this.config.width}px`\n : this.config.width;\n }\n \n // Add base class\n this.classList.add('editora-editor');\n \n if (this.config.theme) {\n this.classList.add(`editora-theme-${this.config.theme}`);\n }\n \n // Load plugins\n const plugins = await this.loadPlugins();\n \n // Initialize plugins (call init hooks)\n plugins.forEach(plugin => {\n if (plugin.init && typeof plugin.init === 'function') {\n try {\n // Pass the web component element as context for plugins that need it\n plugin.init({ editorElement: this });\n } catch (error) {\n console.error(`[RichTextEditor] Error initializing plugin ${plugin.name}:`, error);\n }\n }\n });\n \n // Get initial content before clearing innerHTML\n const initialContent = this.getAttribute('data-initial-content') || '';\n \n // Create editor engine\n this.engine = new EditorEngine({\n content: initialContent,\n plugins,\n readonly: this.config.readonly,\n });\n \n // Create UI elements\n this.createUI(plugins, initialContent);\n \n // Setup event listeners\n this.setupEventListeners();\n \n // Mark as initialized\n this.isInitialized = true;\n \n // Emit ready event\n this.dispatchEvent(new CustomEvent('editor-ready', {\n detail: { api: this.getAPI() },\n bubbles: true,\n }));\n }\n\n /**\n * Get initial content from slot or attribute\n */\n private getInitialContent(): string {\n // Check for content attribute first\n if (this.config.content) {\n return this.config.content;\n }\n \n // Check for slot\n const slot = this.querySelector('[slot]');\n if (slot) {\n return slot.innerHTML;\n }\n \n // Check for direct child content\n if (this.hasChildNodes()) {\n const content = Array.from(this.childNodes).map(n => {\n if (n.nodeType === Node.TEXT_NODE) {\n return n.textContent;\n } else if (n.nodeType === Node.ELEMENT_NODE) {\n return (n as Element).outerHTML;\n }\n return '';\n }).join('');\n return content.trim();\n }\n \n return '';\n }\n\n /**\n * Load plugins based on configuration\n */\n private async loadPlugins(): Promise<Plugin[]> {\n // Ensure plugin loader is available\n if (!this.pluginLoader) {\n await this.waitForPluginLoader();\n }\n \n const plugins: Plugin[] = [];\n \n // Check if plugins are explicitly configured (non-empty array or string)\n const hasPluginConfig = this.config.plugins && (\n (typeof this.config.plugins === 'string' && this.config.plugins.length > 0) ||\n (Array.isArray(this.config.plugins) && this.config.plugins.length > 0)\n );\n \n if (hasPluginConfig) {\n if (typeof this.config.plugins === 'string') {\n // Parse plugin string\n const loadedPlugins = await this.pluginLoader.parsePluginString(this.config.plugins);\n plugins.push(...loadedPlugins);\n } else if (Array.isArray(this.config.plugins)) {\n // Already plugin instances or names\n for (const p of this.config.plugins) {\n if (typeof p === 'string') {\n const plugin = await this.pluginLoader.load(p);\n if (plugin) plugins.push(plugin);\n } else {\n plugins.push(p as Plugin);\n }\n }\n }\n } else {\n // No plugins specified - load all registered plugins\n const registeredNames = this.pluginLoader.getRegisteredPluginNames();\n const loadedPlugins = await this.pluginLoader.loadMultiple(registeredNames);\n plugins.push(...loadedPlugins);\n }\n return plugins;\n }\n\n /**\n * Create UI elements\n */\n private createUI(plugins: Plugin[], initialContent: string): void {\n // Preserve slot elements and initial content before clearing\n const toolbarSlot = this.querySelector('[slot=\"toolbar\"]');\n const statusBarSlot = this.querySelector('[slot=\"statusbar\"]');\n \n // Clear existing content\n this.innerHTML = '';\n \n // Restore or create toolbar\n if (this.config.toolbar !== false && !toolbarSlot) {\n // Create default toolbar\n this.toolbarElement = document.createElement('div');\n this.toolbarElement.className = 'editora-toolbar-container';\n this.appendChild(this.toolbarElement);\n \n // Support both toolbar and toolbarItems attributes\n const toolbarItems = (this.config as any).toolbarItems || this.config.toolbar;\n \n this.toolbar = new ToolbarRenderer(\n {\n items: typeof toolbarItems === 'string' ? toolbarItems : undefined,\n sticky: this.config.toolbar && typeof this.config.toolbar === 'object'\n ? (this.config.toolbar as any).sticky\n : false,\n position: 'top',\n },\n plugins,\n this.pluginLoader // Pass plugin loader to get all registered plugins\n );\n \n this.toolbar.setCommandHandler((command, value) => {\n // Ensure editor has focus and a valid selection for multi-instance support\n if (this.contentElement) {\n // Focus the editor\n this.contentElement.focus();\n \n // Ensure there's a selection in this editor instance\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0 || !this.contentElement.contains(selection.anchorNode)) {\n // Create a selection at the end of the content\n const range = document.createRange();\n const lastChild = this.contentElement.lastChild || this.contentElement;\n \n if (lastChild.nodeType === Node.TEXT_NODE) {\n range.setStart(lastChild, lastChild.textContent?.length || 0);\n } else if (lastChild.nodeType === Node.ELEMENT_NODE) {\n range.selectNodeContents(lastChild);\n range.collapse(false); // Collapse to end\n } else {\n range.setStart(this.contentElement, 0);\n }\n \n range.collapse(true);\n selection?.removeAllRanges();\n selection?.addRange(range);\n }\n }\n \n // Try to find the command in loaded plugins first (for native commands)\n \n const plugin = plugins.find(p => p.commands && p.commands[command]);\n if (plugin && plugin.commands) {\n const commandFn = plugin.commands[command];\n if (typeof commandFn === 'function') {\n // Call native command directly\n try {\n // Pass editor element for fullscreen command\n if (command === 'toggleFullscreen') {\n const result = commandFn(this);\n return result;\n } else {\n const result = commandFn(value);\n return result;\n }\n } catch (error) {\n console.error(`[RichTextEditor] Error executing native command ${command}:`, error);\n return false;\n }\n }\n }\n // Fallback to engine command (ProseMirror-style)\n return this.engine?.execCommand(command, value) || false;\n });\n \n this.toolbar.render(this.toolbarElement);\n } else if (toolbarSlot) {\n // Use custom toolbar from slot\n this.appendChild(toolbarSlot);\n }\n \n // Create content area\n this.contentElement = document.createElement('div');\n this.contentElement.className = 'editora-content rte-content'; // Add rte-content class for plugin helpers\n this.contentElement.contentEditable = this.config.readonly ? 'false' : 'true';\n this.contentElement.setAttribute('role', 'textbox');\n this.contentElement.setAttribute('aria-multiline', 'true');\n \n if (this.config.placeholder) {\n this.contentElement.setAttribute('data-placeholder', this.config.placeholder);\n }\n \n // Set default paragraph separator to <p> for consistency with React\n try {\n document.execCommand('defaultParagraphSeparator', false, 'p');\n } catch (e) {\n // Fallback: some browsers may not support this\n console.warn('defaultParagraphSeparator not supported:', e);\n }\n \n // Set initial content and ensure it's wrapped in <p> tags\n if (initialContent) {\n // Check if content is already wrapped in block elements\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = initialContent.trim();\n \n // If content has no block-level elements, wrap it in a <p> tag\n const hasBlockElements = Array.from(tempDiv.childNodes).some(node => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const tagName = (node as Element).tagName;\n return ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'BLOCKQUOTE', 'PRE'].includes(tagName);\n }\n return false;\n });\n \n if (!hasBlockElements && initialContent.trim()) {\n this.contentElement.innerHTML = `<p>${initialContent.trim()}</p>`;\n } else {\n this.contentElement.innerHTML = initialContent;\n }\n } else {\n // Initialize with an empty paragraph for proper structure, unless we have a placeholder\n if (this.config.placeholder) {\n // Leave empty so placeholder shows\n this.contentElement.innerHTML = '';\n } else {\n this.contentElement.innerHTML = '<p><br></p>';\n }\n }\n \n this.appendChild(this.contentElement);\n \n // Floating toolbar\n if (this.config.toolbar && typeof this.config.toolbar === 'object' && (this.config.toolbar as any).floating) {\n this.floatingToolbar = new FloatingToolbar({ enabled: true });\n this.floatingToolbar.create(this);\n }\n \n // Status bar - restore custom slot if exists\n if (statusBarSlot) {\n this.appendChild(statusBarSlot);\n } else {\n // Create default status bar if configured\n if (this.config.statusbar) {\n this.statusBarElement = document.createElement('div');\n this.statusBarElement.className = 'editora-statusbar-container';\n this.appendChild(this.statusBarElement);\n \n this.statusBar = new StatusBar({ position: 'bottom' });\n this.statusBar.create(this.statusBarElement);\n }\n }\n \n // Auto-focus if configured\n if (this.config.autofocus) {\n setTimeout(() => this.contentElement?.focus(), 0);\n }\n }\n\n /**\n * Setup event listeners\n */\n private setupEventListeners(): void {\n if (!this.contentElement || !this.engine) return;\n \n // Content change\n this.contentElement.addEventListener('input', () => {\n const html = this.contentElement!.innerHTML;\n \n this.dispatchEvent(new CustomEvent('content-change', {\n detail: { html },\n bubbles: true,\n }));\n \n // Update status bar\n this.updateStatusBar();\n });\n \n // Focus/blur\n this.contentElement.addEventListener('focus', () => {\n this.dispatchEvent(new Event('editor-focus', { bubbles: true }));\n });\n \n this.contentElement.addEventListener('blur', () => {\n this.dispatchEvent(new Event('editor-blur', { bubbles: true }));\n });\n \n // Selection change for floating toolbar and status bar\n const updateSelectionInfo = () => {\n this.updateFloatingToolbar();\n this.updateStatusBar();\n };\n\n document.addEventListener('selectionchange', updateSelectionInfo);\n }\n\n /**\n * Update floating toolbar position\n */\n private updateFloatingToolbar(): void {\n if (!this.floatingToolbar) return;\n \n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n this.floatingToolbar.hide();\n return;\n }\n \n const range = selection.getRangeAt(0);\n if (range.collapsed) {\n this.floatingToolbar.hide();\n return;\n }\n \n const rect = range.getBoundingClientRect();\n this.floatingToolbar.show(rect.left, rect.top - 40);\n }\n\n /**\n * Update status bar with selection and cursor information\n */\n /**\n * Update status bar with current content and cursor information\n */\n private updateStatusBar(): void {\n if (!this.statusBar || !this.contentElement) return;\n\n const text = this.contentElement.textContent || '';\n const { words, chars } = calculateTextStats(text);\n const lineCount = countLines(this.contentElement);\n\n const selection = window.getSelection();\n let cursorPosition, selectionInfo;\n\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n cursorPosition = getCursorPosition(this.contentElement, range);\n\n if (!range.collapsed) {\n selectionInfo = getSelectionInfo(range, cursorPosition);\n cursorPosition = undefined; // Don't show cursor position when text is selected\n }\n }\n\n this.statusBar.update({\n wordCount: words,\n charCount: chars,\n lineCount,\n cursorPosition,\n selectionInfo\n });\n }\n\n /**\n * Handle attribute changes\n */\n private handleAttributeChange(name: string, value: string): void {\n switch (name) {\n case 'readonly':\n if (this.contentElement) {\n this.contentElement.contentEditable = value === 'true' ? 'false' : 'true';\n }\n if (this.engine) {\n this.engine.setReadonly(value === 'true');\n }\n break;\n \n case 'theme':\n // Remove old theme classes\n this.classList.forEach(cls => {\n if (cls.startsWith('editora-theme-')) {\n this.classList.remove(cls);\n }\n });\n // Add new theme class\n if (value) {\n this.classList.add(`editora-theme-${value}`);\n }\n break;\n \n case 'placeholder':\n if (this.contentElement) {\n this.contentElement.setAttribute('data-placeholder', value);\n }\n break;\n \n case 'toolbar':\n case 'plugins':\n // These require re-initialization\n if (this.isConnected) {\n this.destroy();\n this.waitForPluginLoader().then(() => {\n this.initialize().catch(error => {\n console.error('[RichTextEditor] Error during attribute change re-initialization:', error);\n });\n });\n }\n break;\n }\n }\n\n /**\n * Resolve configuration from all sources\n */\n private resolveConfig(): EditorConfigDefaults {\n const attributes: Record<string, string> = {};\n \n // Collect all attributes\n for (let i = 0; i < this.attributes.length; i++) {\n const attr = this.attributes[i];\n attributes[attr.name] = attr.value;\n }\n \n return ConfigResolver.resolve({\n jsConfig: this.jsConfig,\n attributes,\n });\n }\n\n /**\n * Get public API\n */\n getAPI(): EditorAPI {\n return {\n getContent: () => {\n return this.contentElement?.innerHTML || '';\n },\n \n setContent: (html: string) => {\n if (this.contentElement) {\n this.contentElement.innerHTML = html;\n }\n },\n \n execCommand: (name: string, value?: any) => {\n return this.engine?.execCommand(name, value) || false;\n },\n \n focus: () => {\n this.contentElement?.focus();\n },\n \n blur: () => {\n this.contentElement?.blur();\n },\n \n destroy: () => {\n this.destroy();\n },\n \n on: (event: string, handler: (...args: any[]) => void) => {\n this.addEventListener(event, handler as EventListener);\n return () => this.removeEventListener(event, handler as EventListener);\n },\n \n getConfig: () => {\n return { ...this.config };\n },\n \n setReadonly: (readonly: boolean) => {\n this.setAttribute('readonly', readonly.toString());\n },\n };\n }\n\n /**\n * Destroy the editor\n */\n private destroy(): void {\n this.engine?.destroy();\n this.toolbar?.destroy();\n this.floatingToolbar?.destroy();\n this.statusBar?.destroy();\n \n this.innerHTML = '';\n this.isInitialized = false;\n \n this.dispatchEvent(new Event('editor-destroy', { bubbles: true }));\n }\n\n // Public API methods\n \n public getContent(): string {\n return this.contentElement?.innerHTML || '';\n }\n\n public setContent(html: string): void {\n if (this.contentElement) {\n this.contentElement.innerHTML = html;\n }\n }\n\n public execCommand(name: string, value?: any): boolean {\n return this.engine?.execCommand(name, value) || false;\n }\n\n public focus(): void {\n this.contentElement?.focus();\n }\n\n public blur(): void {\n this.contentElement?.blur();\n }\n}\n\n/**\n * Editor API interface\n */\nexport interface EditorAPI {\n getContent(): string;\n setContent(html: string): void;\n execCommand(name: string, value?: any): boolean;\n focus(): void;\n blur(): void;\n destroy(): void;\n on(event: string, handler: (...args: any[]) => void): () => void;\n getConfig(): EditorConfigDefaults;\n setReadonly(readonly: boolean): void;\n}\n\n// Note: Custom element registration moved to standalone.ts\n// to ensure plugins are registered before element instances are created\n"],"names":["EditorState","doc","selection","schema","content","Schema","nodes","marks","type","attrs","text","PluginManager","plugin","config","pluginConfig","pluginName","index","p","name","commands","command","args","mode","error","destroyPromises","CommandRegistry","initialCommands","handler","EditorEngine","value","newState","state","readonly","event","handlers","ToolbarRenderer","plugins","pluginLoader","toolbarString","groups","sections","s","allToolbarItems","itemMap","item","aliases","section","buttons","cmd","ltrItem","rtlItem","addCommentItem","toggleCommentsItem","actualCommand","container","buttonGroups","group","groupIndex","groupEl","button","separator","parent","dropdownEl","inlineMenuEl","groupButtonEl","inputEl","buttonEl","el","iconWrapper","itemsContainer","child","e","trigger","menu","option","isOpen","closeDropdown","allMenus","_a","m","dropdown","cleanup","FloatingToolbar","parentElement","x","y","StatusBar","info","leftSection","rightSection","leftItems","sel","pos","rightItems","key","span","getCursorPosition","contentElement","range","startOffset","getTextOffset","lines","line","column","rootElement","node","offset","textOffset","walker","currentNode","countLines","blocks","lineCount","lastBlock","_b","textLines","calculateTextStats","words","chars","getSelectionInfo","cursorPosition","selectedText","_ConfigResolver","sources","parsedAttributes","attributes","camelKey","str","_","letter","errors","configs","result","ConfigResolver","PluginLoader","factory","names","pluginString","globalPluginRegistry","injectStyles","styleId","styleElement","styles","getGlobalRegistry","externalRegistry","RichTextEditorElement","initWebComponent","registry","resolve","checkLoader","oldValue","newValue","initialContent","slot","n","loadedPlugins","registeredNames","toolbarSlot","statusBarSlot","toolbarItems","lastChild","commandFn","tempDiv","tagName","html","updateSelectionInfo","rect","selectionInfo","cls","i","attr","_c","_d"],"mappings":"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"}