@editora/core 1.0.0 → 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 (119) 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/core.css +1 -0
  83. package/dist/documentManager-irzj9n3V.mjs +37627 -0
  84. package/dist/documentManager-irzj9n3V.mjs.map +1 -0
  85. package/dist/editorContainerHelpers-C7kdWnS0.mjs +27 -0
  86. package/dist/editorContainerHelpers-C7kdWnS0.mjs.map +1 -0
  87. package/dist/editora.min.js +519 -4
  88. package/dist/editora.min.js.map +1 -0
  89. package/dist/editora.umd.js +519 -4
  90. package/dist/editora.umd.js.map +1 -0
  91. package/dist/index-BF5RBhL9.js +4 -0
  92. package/dist/index-BF5RBhL9.js.map +1 -0
  93. package/dist/index-BPsf460l.mjs +1243 -0
  94. package/dist/index-BPsf460l.mjs.map +1 -0
  95. package/dist/index.cjs.js +517 -4
  96. package/dist/index.cjs.js.map +1 -0
  97. package/dist/index.es-CuicffkQ.mjs +6665 -0
  98. package/dist/index.es-CuicffkQ.mjs.map +1 -0
  99. package/dist/index.esm.js +1403 -122
  100. package/dist/index.esm.js.map +1 -0
  101. package/dist/plugin-loader.js +55 -0
  102. package/dist/plugin-loader.js.map +1 -0
  103. package/dist/purify.es-CKpwg8Tk.mjs +471 -0
  104. package/dist/purify.es-CKpwg8Tk.mjs.map +1 -0
  105. package/dist/webcomponent-core.js +1243 -0
  106. package/dist/webcomponent-core.js.map +1 -0
  107. package/dist/webcomponent-core.min.css +1 -0
  108. package/dist/webcomponent-core.min.js +597 -0
  109. package/dist/webcomponent-core.min.js.map +1 -0
  110. package/dist/webcomponent.cjs.js +2 -0
  111. package/dist/webcomponent.cjs.js.map +1 -0
  112. package/dist/webcomponent.esm.js +6 -0
  113. package/dist/webcomponent.esm.js.map +1 -0
  114. package/dist/webcomponent.js +1286 -0
  115. package/dist/webcomponent.js.map +1 -0
  116. package/dist/webcomponent.min.css +1 -0
  117. package/dist/webcomponent.min.js +4076 -0
  118. package/dist/webcomponent.min.js.map +1 -0
  119. package/package.json +64 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmojisPlugin.native-D6mJSnSR.mjs","sources":["../../plugins/emojis/src/Constants.ts","../../plugins/emojis/src/EmojisPlugin.native.ts"],"sourcesContent":["type EmojiCategory =\n | \"all\"\n | \"symbols\"\n | \"people\"\n | \"animals-nature\"\n | \"food-drink\"\n | \"activity\"\n | \"travel-places\"\n | \"objects\"\n | \"flags\";\n\nconst emojisSets: Record<EmojiCategory, { name: string; emojis: string[] }> = {\n all: {\n name: \"All\",\n emojis: [\n /* Symbols */\n \"❤️\",\n \"💔\",\n \"💙\",\n \"💚\",\n \"💛\",\n \"🖤\",\n \"🤍\",\n \"🤎\",\n \"✔️\",\n \"❌\",\n \"☑️\",\n \"❗\",\n \"❓\",\n \"⚠️\",\n \"💯\",\n \"➕\",\n \"➖\",\n \"✖️\",\n \"➗\",\n \"♻️\",\n \"⚡\",\n \"🔥\",\n \"✨\",\n \"⭐\",\n \"⭕\",\n \"🚫\",\n\n /* People */\n \"😀\",\n \"😃\",\n \"😄\",\n \"😁\",\n \"😆\",\n \"😅\",\n \"😂\",\n \"🤣\",\n \"😊\",\n \"😇\",\n \"🙂\",\n \"🙃\",\n \"😉\",\n \"😍\",\n \"😘\",\n \"😎\",\n \"🤓\",\n \"😐\",\n \"😑\",\n \"😬\",\n \"🙄\",\n \"😏\",\n \"😌\",\n \"🤩\",\n \"🥳\",\n \"🤔\",\n \"😴\",\n \"😭\",\n \"😢\",\n \"😡\",\n \"🤯\",\n \"👍\",\n \"👎\",\n \"👌\",\n \"✌️\",\n \"🤞\",\n \"🙏\",\n \"👏\",\n \"🙌\",\n \"💪\",\n\n /* Animals & Nature */\n \"🐶\",\n \"🐱\",\n \"🐭\",\n \"🐹\",\n \"🐰\",\n \"🦊\",\n \"🐻\",\n \"🐼\",\n \"🐨\",\n \"🐯\",\n \"🦁\",\n \"🐮\",\n \"🐷\",\n \"🐸\",\n \"🐵\",\n \"🐔\",\n \"🐧\",\n \"🐦\",\n \"🦆\",\n \"🦅\",\n \"🦄\",\n \"🐝\",\n \"🦋\",\n \"🌲\",\n \"🌳\",\n \"🌴\",\n \"🌵\",\n \"🌸\",\n \"🌼\",\n \"🌻\",\n \"☀️\",\n \"🌙\",\n \"⭐\",\n \"🌈\",\n \"🌧️\",\n \"❄️\",\n \"🌊\",\n\n /* Food & Drink */\n \"🍎\",\n \"🍌\",\n \"🍉\",\n \"🍇\",\n \"🍓\",\n \"🍒\",\n \"🍍\",\n \"🥭\",\n \"🍐\",\n \"🍊\",\n \"🍋\",\n \"🍑\",\n \"🥝\",\n \"🥑\",\n \"🍔\",\n \"🍟\",\n \"🍕\",\n \"🌭\",\n \"🥪\",\n \"🌮\",\n \"🌯\",\n \"🍣\",\n \"🍜\",\n \"🍰\",\n \"🧁\",\n \"🍩\",\n \"🍪\",\n \"🍫\",\n \"☕\",\n \"🍵\",\n \"🥤\",\n \"🍺\",\n \"🍷\",\n \"🍸\",\n \"🍹\",\n \"🥂\",\n\n /* Activity */\n \"⚽\",\n \"🏀\",\n \"🏈\",\n \"⚾\",\n \"🎾\",\n \"🏐\",\n \"🏉\",\n \"🎮\",\n \"🎯\",\n \"🎳\",\n \"🎲\",\n \"♟️\",\n \"🏃\",\n \"🚴\",\n \"🏊\",\n \"🏋️\",\n \"🧘\",\n \"🎸\",\n \"🎹\",\n \"🥁\",\n \"🎺\",\n \"🎤\",\n \"🏆\",\n \"🥇\",\n\n /* Travel & Places */\n \"🚗\",\n \"🚕\",\n \"🚌\",\n \"🚎\",\n \"🚓\",\n \"🚑\",\n \"🚒\",\n \"✈️\",\n \"🚀\",\n \"🚁\",\n \"🚤\",\n \"🛳️\",\n \"🚢\",\n \"🏠\",\n \"🏢\",\n \"🏬\",\n \"🏫\",\n \"🏥\",\n \"🏰\",\n \"🗼\",\n \"🗽\",\n \"⛩️\",\n \"🕌\",\n \"🌍\",\n \"🌎\",\n \"🌏\",\n \"🏖️\",\n \"🏝️\",\n\n /* Objects */\n \"📱\",\n \"💻\",\n \"🖥️\",\n \"⌨️\",\n \"🖱️\",\n \"📷\",\n \"📸\",\n \"🎥\",\n \"📹\",\n \"📚\",\n \"📖\",\n \"📝\",\n \"📄\",\n \"📂\",\n \"🔒\",\n \"🔑\",\n \"🗝️\",\n \"💡\",\n \"🔦\",\n \"🕯️\",\n \"🧰\",\n \"🛠️\",\n \"🔧\",\n \"⚙️\",\n \"📦\",\n \"💳\",\n \"💰\",\n \"🔋\",\n \"🔌\",\n\n /* Flags */\n \"🇮🇳\",\n \"🇺🇸\",\n \"🇬🇧\",\n \"🇨🇦\",\n \"🇦🇺\",\n \"🇩🇪\",\n \"🇫🇷\",\n \"🇪🇸\",\n \"🇮🇹\",\n \"🇯🇵\",\n \"🇰🇷\",\n \"🇨🇳\",\n \"🇧🇷\",\n \"🇲🇽\",\n \"🇷🇺\",\n \"🇿🇦\",\n \"🇳🇿\",\n ],\n },\n\n symbols: {\n name: \"Symbols\",\n emojis: [\n \"❤️\",\n \"💔\",\n \"💙\",\n \"💚\",\n \"💛\",\n \"🖤\",\n \"🤍\",\n \"🤎\",\n \"✔️\",\n \"❌\",\n \"☑️\",\n \"❗\",\n \"❓\",\n \"⚠️\",\n \"💯\",\n \"➕\",\n \"➖\",\n \"✖️\",\n \"➗\",\n \"♻️\",\n \"⚡\",\n \"🔥\",\n \"✨\",\n \"⭐\",\n \"⭕\",\n \"🚫\",\n \"⬆️\",\n \"⬇️\",\n \"⬅️\",\n \"➡️\",\n \"🔄\",\n \"🔁\",\n \"🔀\",\n \"🔔\",\n \"🔕\",\n \"⏰\",\n \"⌛\",\n \"⏳\",\n ],\n },\n\n people: {\n name: \"People\",\n emojis: [\n \"😀\",\n \"😃\",\n \"😄\",\n \"😁\",\n \"😆\",\n \"😅\",\n \"😂\",\n \"🤣\",\n \"😊\",\n \"😇\",\n \"🙂\",\n \"🙃\",\n \"😉\",\n \"😍\",\n \"😘\",\n \"😎\",\n \"🤓\",\n \"😐\",\n \"😑\",\n \"😬\",\n \"🙄\",\n \"😏\",\n \"😌\",\n \"🤩\",\n \"🥳\",\n \"🤔\",\n \"😴\",\n \"😭\",\n \"😢\",\n \"😡\",\n \"🤯\",\n \"👍\",\n \"👎\",\n \"👌\",\n \"✌️\",\n \"🤞\",\n \"🙏\",\n \"👏\",\n \"🙌\",\n \"💪\",\n ],\n },\n\n \"animals-nature\": {\n name: \"Animals & Nature\",\n emojis: [\n \"🐶\",\n \"🐱\",\n \"🐭\",\n \"🐹\",\n \"🐰\",\n \"🦊\",\n \"🐻\",\n \"🐼\",\n \"🐨\",\n \"🐯\",\n \"🦁\",\n \"🐮\",\n \"🐷\",\n \"🐸\",\n \"🐵\",\n \"🐔\",\n \"🐧\",\n \"🐦\",\n \"🦆\",\n \"🦅\",\n \"🦄\",\n \"🐝\",\n \"🦋\",\n \"🌲\",\n \"🌳\",\n \"🌴\",\n \"🌵\",\n \"🌸\",\n \"🌼\",\n \"🌻\",\n \"☀️\",\n \"🌙\",\n \"⭐\",\n \"🌈\",\n \"🌧️\",\n \"❄️\",\n \"🌊\",\n ],\n },\n\n \"food-drink\": {\n name: \"Food & Drink\",\n emojis: [\n \"🍎\",\n \"🍌\",\n \"🍉\",\n \"🍇\",\n \"🍓\",\n \"🍒\",\n \"🍍\",\n \"🥭\",\n \"🍐\",\n \"🍊\",\n \"🍋\",\n \"🍑\",\n \"🥝\",\n \"🥑\",\n \"🍔\",\n \"🍟\",\n \"🍕\",\n \"🌭\",\n \"🥪\",\n \"🌮\",\n \"🌯\",\n \"🍣\",\n \"🍜\",\n \"🍰\",\n \"🧁\",\n \"🍩\",\n \"🍪\",\n \"🍫\",\n \"☕\",\n \"🍵\",\n \"🥤\",\n \"🍺\",\n \"🍷\",\n \"🍸\",\n \"🍹\",\n \"🥂\",\n ],\n },\n\n activity: {\n name: \"Activity\",\n emojis: [\n \"⚽\",\n \"🏀\",\n \"🏈\",\n \"⚾\",\n \"🎾\",\n \"🏐\",\n \"🏉\",\n \"🎮\",\n \"🎯\",\n \"🎳\",\n \"🎲\",\n \"♟️\",\n \"🏃\",\n \"🚴\",\n \"🏊\",\n \"🏋️\",\n \"🧘\",\n \"🎸\",\n \"🎹\",\n \"🥁\",\n \"🎺\",\n \"🎤\",\n \"🏆\",\n \"🥇\",\n \"🥈\",\n \"🥉\",\n ],\n },\n\n \"travel-places\": {\n name: \"Travel & Places\",\n emojis: [\n \"🚗\",\n \"🚕\",\n \"🚌\",\n \"🚎\",\n \"🚓\",\n \"🚑\",\n \"🚒\",\n \"✈️\",\n \"🚀\",\n \"🚁\",\n \"🚤\",\n \"🛳️\",\n \"🚢\",\n \"🏠\",\n \"🏢\",\n \"🏬\",\n \"🏫\",\n \"🏥\",\n \"🏰\",\n \"🗼\",\n \"🗽\",\n \"⛩️\",\n \"🕌\",\n \"🌍\",\n \"🌎\",\n \"🌏\",\n \"🏖️\",\n \"🏝️\",\n ],\n },\n\n objects: {\n name: \"Objects\",\n emojis: [\n \"📱\",\n \"💻\",\n \"🖥️\",\n \"⌨️\",\n \"🖱️\",\n \"📷\",\n \"📸\",\n \"🎥\",\n \"📹\",\n \"📚\",\n \"📖\",\n \"📝\",\n \"📄\",\n \"📂\",\n \"🔒\",\n \"🔑\",\n \"🗝️\",\n \"💡\",\n \"🔦\",\n \"🕯️\",\n \"🧰\",\n \"🛠️\",\n \"🔧\",\n \"⚙️\",\n \"📦\",\n \"💳\",\n \"💰\",\n \"🔋\",\n \"🔌\",\n ],\n },\n\n flags: {\n name: \"Flags\",\n emojis: [\n \"🇮🇳\",\n \"🇺🇸\",\n \"🇬🇧\",\n \"🇨🇦\",\n \"🇦🇺\",\n \"🇩🇪\",\n \"🇫🇷\",\n \"🇪🇸\",\n \"🇮🇹\",\n \"🇯🇵\",\n \"🇰🇷\",\n \"🇨🇳\",\n \"🇧🇷\",\n \"🇲🇽\",\n \"🇷🇺\",\n \"🇿🇦\",\n \"🇳🇿\",\n ],\n },\n};\n\nconst descriptions: Record<string, string> = {\n \"💙\": \"blue heart\",\n \"💚\": \"green heart\",\n \"💛\": \"yellow heart\",\n \"🖤\": \"black heart\",\n \"🤍\": \"white heart\",\n \"🤎\": \"brown heart\",\n \"☑️\": \"check box with check\",\n \"🔴\": \"red circle\",\n \"🟢\": \"green circle\",\n \"🟡\": \"yellow circle\",\n \"🔵\": \"blue circle\",\n \"⬆️\": \"up arrow\",\n \"⬇️\": \"down arrow\",\n \"⬅️\": \"left arrow\",\n \"➡️\": \"right arrow\",\n \"🔄\": \"counterclockwise arrows\",\n \"🔁\": \"repeat button\",\n \"🔀\": \"shuffle tracks\",\n \"🔔\": \"bell\",\n \"🔕\": \"muted bell\",\n \"⏰\": \"alarm clock\",\n \"⏳\": \"hourglass not done\",\n \"⌛\": \"hourglass done\",\n \"♠️\": \"spade suit\",\n \"♥️\": \"heart suit\",\n \"♦️\": \"diamond suit\",\n \"♣️\": \"club suit\",\n \"🚫\": \"prohibited\",\n \"⭕\": \"hollow red circle\",\n \"❎\": \"cross mark button\",\n\n \"😐\": \"neutral face\",\n \"😑\": \"expressionless face\",\n \"😬\": \"grimacing face\",\n \"🙄\": \"face with rolling eyes\",\n \"😏\": \"smirking face\",\n \"😌\": \"relieved face\",\n \"🤩\": \"star struck\",\n \"😜\": \"winking face with tongue\",\n \"😝\": \"squinting face with tongue\",\n \"🤪\": \"zany face\",\n \"😢\": \"crying face\",\n \"😥\": \"sad but relieved face\",\n \"😓\": \"downcast face with sweat\",\n \"😱\": \"face screaming in fear\",\n \"😨\": \"fearful face\",\n \"🤗\": \"hugging face\",\n \"🤭\": \"face with hand over mouth\",\n \"🤫\": \"shushing face\",\n \"🤥\": \"lying face\",\n \"👌\": \"ok hand\",\n \"✌️\": \"victory hand\",\n \"🤞\": \"crossed fingers\",\n \"🙌\": \"raising hands\",\n \"💪\": \"flexed biceps\",\n\n \"🐔\": \"chicken\",\n \"🐧\": \"penguin\",\n \"🐦\": \"bird\",\n \"🐤\": \"baby chick\",\n \"🦆\": \"duck\",\n \"🦅\": \"eagle\",\n \"🐺\": \"wolf\",\n \"🦄\": \"unicorn\",\n \"🐝\": \"honeybee\",\n \"🐞\": \"lady beetle\",\n \"🦋\": \"butterfly\",\n \"🐢\": \"turtle\",\n \"🐍\": \"snake\",\n \"🦖\": \"t-rex\",\n \"🌿\": \"herb\",\n \"🍀\": \"four leaf clover\",\n \"🍁\": \"maple leaf\",\n \"🍂\": \"fallen leaf\",\n \"🌊\": \"water wave\",\n \"❄️\": \"snowflake\",\n \"☁️\": \"cloud\",\n \"⛈️\": \"cloud with lightning and rain\",\n \"🌪️\": \"tornado\",\n\n \"🍐\": \"pear\",\n \"🍊\": \"tangerine\",\n \"🍋\": \"lemon\",\n \"🍑\": \"peach\",\n \"🥝\": \"kiwi fruit\",\n \"🥑\": \"avocado\",\n \"🍆\": \"eggplant\",\n \"🌽\": \"ear of corn\",\n \"🥕\": \"carrot\",\n \"🥔\": \"potato\",\n \"🍞\": \"bread\",\n \"🥐\": \"croissant\",\n \"🥖\": \"baguette bread\",\n \"🧀\": \"cheese wedge\",\n \"🍖\": \"meat on bone\",\n \"🍗\": \"poultry leg\",\n \"🥩\": \"cut of meat\",\n \"🍦\": \"soft ice cream\",\n \"🍨\": \"ice cream\",\n \"🍫\": \"chocolate bar\",\n \"🍬\": \"candy\",\n \"🥛\": \"glass of milk\",\n \"🧃\": \"beverage box\",\n \"🍹\": \"tropical drink\",\n \"🥂\": \"clinking glasses\",\n\n \"🏓\": \"ping pong\",\n \"🥊\": \"boxing glove\",\n \"🥋\": \"martial arts uniform\",\n \"⛳\": \"flag in hole\",\n \"🏹\": \"bow and arrow\",\n \"🎿\": \"skis\",\n \"⛷️\": \"skier\",\n \"🏂\": \"snowboarder\",\n \"🎤\": \"microphone\",\n \"🎬\": \"clapper board\",\n \"🎨\": \"artist palette\",\n \"🧩\": \"puzzle piece\",\n \"🪀\": \"yo-yo\",\n\n \"🚇\": \"metro\",\n \"🚉\": \"station\",\n \"🚊\": \"tram\",\n \"🚝\": \"monorail\",\n \"🛻\": \"pickup truck\",\n \"🚐\": \"minibus\",\n \"🗺️\": \"world map\",\n \"🧭\": \"compass\",\n \"⛰️\": \"mountain\",\n \"🏔️\": \"snow capped mountain\",\n \"🌋\": \"volcano\",\n \"🏜️\": \"desert\",\n \"🏕️\": \"camping\",\n \"🏙️\": \"cityscape\",\n \"🌆\": \"city at dusk\",\n \"🌃\": \"night with stars\",\n\n \"📦\": \"package\",\n \"📫\": \"closed mailbox with raised flag\",\n \"📬\": \"open mailbox with raised flag\",\n \"📭\": \"open mailbox with lowered flag\",\n \"🧾\": \"receipt\",\n \"💳\": \"credit card\",\n \"💰\": \"money bag\",\n \"🪙\": \"coin\",\n \"🔋\": \"battery\",\n \"🔌\": \"electric plug\",\n \"🧯\": \"fire extinguisher\",\n \"🪜\": \"ladder\",\n \"🪞\": \"mirror\",\n \"🧹\": \"broom\",\n \"🧸\": \"teddy bear\",\n};\n\nexport { emojisSets, type EmojiCategory, descriptions };\n","import type { Plugin } from '@editora/core';\nimport { emojisSets, descriptions, type EmojiCategory } from './Constants';\n\n/**\n * EmojisPlugin - Native implementation for emoji insertion\n * \n * Features:\n * - Full-featured emoji picker dialog\n * - Categorized emojis (All, Symbols, People, Animals & Nature, Food & Drink, Activity, Travel & Places, Objects, Flags)\n * - Search/filter emojis by name or description\n * - Click to insert\n * - Responsive design\n * - Keyboard shortcut (Mod-Shift-j)\n * \n * Commands:\n * - openEmojiDialog: Opens the emoji picker dialog\n * - insertEmoji: Inserts a specific emoji\n * \n * UI/UX Features:\n * - Vertical tabs for categories (or horizontal on mobile)\n * - Search input with real-time filtering\n * - Grid layout with hover effects\n * - No results message when search returns empty\n * - Professional styling matching React design system\n */\n\nlet dialogElement: HTMLElement | null = null;\nlet activeTab: EmojiCategory = 'all';\nlet searchQuery = '';\n// Store the selection range before opening the dialog\nlet savedSelectionRange: Range | null = null;\n\nexport const EmojisPlugin = (): Plugin => {\n return {\n name: \"emojis\",\n\n toolbar: [\n {\n label: \"Insert Emoji\",\n command: \"openEmojiDialog\",\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M9 11c.6 0 1-.4 1-1s-.4-1-1-1a1 1 0 0 0-1 1c0 .6.4 1 1 1Zm6 0c.6 0 1-.4 1-1s-.4-1-1-1a1 1 0 0 0-1 1c0 .6.4 1 1 1Zm-3 5.5c2.1 0 4-1.5 4.4-3.5H7.6c.5 2 2.3 3.5 4.4 3.5ZM12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Zm0 14.5a6.5 6.5 0 1 1 0-13 6.5 6.5 0 0 1 0 13Z\" fill-rule=\"nonzero\"></path></svg>',\n shortcut: \"Mod-Shift-j\",\n type: \"button\",\n },\n ],\n\n commands: {\n openEmojiDialog: (_args, context) => {\n // Try to get the correct editor content element from context\n const editorContent = context?.contentElement || getActiveEditorContent();\n if (editorContent) {\n createEmojiDialog(editorContent);\n return true;\n }\n return false;\n },\n\n insertEmoji: (emoji?: string, context?) => {\n if (!emoji) return false;\n const editorContent = context?.contentElement || getActiveEditorContent();\n if (!editorContent) return false;\n try {\n insertEmoji(emoji, editorContent);\n return true;\n } catch (error) {\n // No console log in production\n return false;\n }\n },\n },\n\n keymap: {\n \"Mod-Shift-j\": \"openEmojiDialog\",\n },\n };\n};\n\nfunction createEmojiDialog(editorContent: HTMLElement): void {\n activeTab = 'all';\n searchQuery = '';\n\n // Save the current selection range before opening the dialog\n const selection = window.getSelection();\n savedSelectionRange = null;\n if (selection && selection.rangeCount > 0 && editorContent.contains(selection.anchorNode)) {\n savedSelectionRange = selection.getRangeAt(0).cloneRange();\n }\n\n const overlay = document.createElement('div');\n overlay.className = 'emojis-overlay';\n overlay.onclick = closeDialog;\n\n const dialog = document.createElement('div');\n dialog.className = 'emojis-dialog';\n dialog.onclick = (e) => e.stopPropagation();\n\n const categories = Object.keys(emojisSets) as EmojiCategory[];\n\n dialog.innerHTML = `\n <div class=\"rte-dialog-header emojis-header\">\n <h3>Insert Emojis</h3>\n <button class=\"rte-dialog-close emojis-close\">×</button>\n </div>\n <div class=\"rte-dialog-body emojis-content\">\n <div class=\"emojis-tabs\">\n ${categories.map(category => `\n <button class=\"emojis-tab ${category === activeTab ? 'active' : ''}\" data-category=\"${category}\">\n ${emojisSets[category].name}\n </button>\n `).join('')}\n </div>\n <div class=\"emojis-main-content\">\n <div class=\"emojis-search\">\n <svg class=\"emojis-search-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/>\n <path d=\"m21 21-4.35-4.35\"/>\n </svg>\n <input \n type=\"text\" \n placeholder=\"Search emojis...\" \n class=\"emojis-search-input\"\n id=\"emoji-search-input\"\n />\n </div>\n <div class=\"emojis-grid\" id=\"emojis-grid\">\n ${renderEmojiGrid(activeTab, searchQuery)}\n </div>\n </div>\n </div>\n `;\n\n overlay.appendChild(dialog);\n document.body.appendChild(overlay);\n dialogElement = overlay;\n\n // Add event listeners\n setupEmojiDialogEventListeners(dialog, editorContent);\n\n injectEmojiDialogStyles();\n\n setTimeout(() => {\n (dialog.querySelector('#emoji-search-input') as HTMLInputElement)?.focus();\n }, 100);\n}\n\nfunction setupEmojiDialogEventListeners(dialog: HTMLElement, editorContent: HTMLElement): void {\n dialog.querySelector('.emojis-close')?.addEventListener('click', closeDialog);\n\n dialog.querySelectorAll('.emojis-tab').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n const category = (e.target as HTMLElement).getAttribute('data-category') as EmojiCategory;\n if (category) switchEmojiTab(dialog, category, editorContent);\n });\n });\n\n const searchInput = dialog.querySelector('#emoji-search-input') as HTMLInputElement;\n searchInput?.addEventListener('input', (e) => {\n searchQuery = (e.target as HTMLInputElement).value;\n updateEmojiGrid(dialog, editorContent);\n });\n\n // Initial emoji click handlers\n updateEmojiGrid(dialog, editorContent);\n}\n\nfunction switchEmojiTab(dialog: HTMLElement, category: EmojiCategory, editorContent: HTMLElement): void {\n activeTab = category;\n dialog.querySelectorAll('.emojis-tab').forEach((btn) => {\n btn.classList.toggle('active', btn.getAttribute('data-category') === category);\n });\n updateEmojiGrid(dialog, editorContent);\n}\n\nfunction updateEmojiGrid(dialog: HTMLElement, editorContent: HTMLElement): void {\n const grid = dialog.querySelector('#emojis-grid');\n if (grid) {\n grid.innerHTML = renderEmojiGrid(activeTab, searchQuery);\n grid.querySelectorAll('.emojis-item').forEach((item) => {\n item.addEventListener('click', () => {\n const emoji = item.textContent?.trim() || '';\n if (emoji) {\n insertEmoji(emoji, editorContent);\n closeDialog();\n }\n });\n });\n }\n}\n\nfunction renderEmojiGrid(category: EmojiCategory, search: string): string {\n let emojis = emojisSets[category].emojis;\n\n // Filter by search query\n if (search.trim()) {\n emojis = emojis.filter(emoji => {\n // Search by emoji itself\n if (emoji.toLowerCase().includes(search.toLowerCase())) {\n return true;\n }\n\n // Search by Unicode name/description\n const description = descriptions[emoji] || '';\n return description.toLowerCase().includes(search.toLowerCase());\n });\n }\n\n if (emojis.length === 0 && search.trim()) {\n return `<div class=\"emojis-no-results\">No emojis found for \"${search}\"</div>`;\n }\n\n return emojis.map((emoji, index) => `\n <button \n class=\"emojis-item\" \n title=\"Insert ${emoji}\"\n data-emoji=\"${emoji}\"\n >\n ${emoji}\n </button>\n `).join('');\n}\n\nfunction closeDialog(): void {\n if (dialogElement) {\n document.body.removeChild(dialogElement);\n dialogElement = null;\n }\n}\n\n// Helper function to insert emoji at cursor\nfunction insertEmoji(emoji: string, editorContent: HTMLElement): void {\n editorContent.focus();\n let selection = window.getSelection();\n // Restore the saved selection range if available\n if (savedSelectionRange) {\n selection?.removeAllRanges();\n selection?.addRange(savedSelectionRange);\n savedSelectionRange = null;\n }\n selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n range.deleteContents();\n const textNode = document.createTextNode(emoji);\n range.insertNode(textNode);\n range.setStartAfter(textNode);\n range.setEndAfter(textNode);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n}\n// Helper to get the currently focused editor content element (fallback)\nfunction getActiveEditorContent(): HTMLElement | null {\n // Try to find the focused .editora-content or .rte-content\n const active = document.activeElement as HTMLElement | null;\n if (active && (active.classList.contains('editora-content') || active.classList.contains('rte-content'))) {\n return active;\n }\n // Fallback: first editor content in DOM\n return document.querySelector('.editora-content, .rte-content') as HTMLElement | null;\n}\n\nfunction injectEmojiDialogStyles(): void {\n if (document.getElementById('emojis-dialog-styles')) return;\n\n const style = document.createElement('style');\n style.id = 'emojis-dialog-styles';\n style.textContent = `\n /* Emojis Dialog Styles */\n .emojis-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n }\n\n .emojis-dialog {\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n max-width: 800px;\n width: 90%;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n }\n\n .emojis-header h3 {\n color: #1a202c;\n }\n\n .emojis-content {\n display: flex;\n flex: 1;\n overflow: hidden;\n padding: 0;\n }\n\n .emojis-main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .emojis-search {\n padding: 16px 16px 0 16px;\n position: relative;\n }\n\n .emojis-search-icon {\n position: absolute;\n left: 28px;\n top: 27px;\n color: #a0aec0;\n pointer-events: none;\n z-index: 1;\n }\n\n .emojis-search-input {\n width: calc(100% - 24px);\n padding: 10px 12px 10px 40px;\n border: 1px solid #e1e5e9;\n border-radius: 6px;\n font-size: 14px;\n color: #2d3748;\n background-color: #ffffff;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n }\n\n .emojis-search-input:focus {\n outline: none;\n border-color: #4299e1;\n box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);\n }\n\n .emojis-search-input:focus + .emojis-search-icon {\n color: #4299e1;\n }\n\n .emojis-search-input::placeholder {\n color: #a0aec0;\n }\n\n .emojis-tabs {\n display: flex;\n flex-direction: column;\n width: 180px;\n border-right: 1px solid #e1e5e9;\n background-color: #f8fafc;\n }\n\n .emojis-tab {\n padding: 12px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: #4a5568;\n border-bottom: 1px solid #e1e5e9;\n transition: all 0.2s ease;\n }\n\n .emojis-tab:hover {\n background-color: #edf2f7;\n color: #2d3748;\n }\n\n .emojis-tab.active {\n background-color: #4299e1;\n color: white;\n font-weight: 500;\n }\n\n .emojis-tab.active:hover {\n background-color: #3182ce;\n }\n\n .emojis-grid {\n padding: 16px;\n overflow-y: auto;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));\n gap: 8px;\n }\n\n .emojis-item {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid #e1e5e9;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n font-size: 18px;\n transition: all 0.2s ease;\n color: #2d3748;\n }\n\n .emojis-item:hover {\n background-color: #4299e1;\n border-color: #4299e1;\n color: white;\n transform: scale(1.05);\n }\n\n .emojis-item:active {\n transform: scale(0.95);\n }\n\n .emojis-no-results {\n grid-column: 1 / -1;\n text-align: center;\n color: #718096;\n font-size: 14px;\n padding: 40px 20px;\n background-color: #f8fafc;\n border-radius: 6px;\n border: 1px solid #e1e5e9;\n }\n\n /* Responsive design */\n @media (max-width: 768px) {\n .emojis-dialog {\n width: 95%;\n max-height: 90vh;\n }\n\n .emojis-content {\n flex-direction: column;\n }\n\n .emojis-tabs {\n width: 100%;\n border-right: none;\n border-bottom: 1px solid #e1e5e9;\n flex-direction: row;\n overflow-x: auto;\n }\n\n .emojis-tab {\n border-bottom: none;\n border-right: 1px solid #e1e5e9;\n white-space: nowrap;\n min-width: 80px;\n }\n\n .emojis-grid {\n grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));\n gap: 6px;\n }\n\n .emojis-item {\n width: 36px;\n height: 36px;\n font-size: 16px;\n }\n }\n `;\n \n document.head.appendChild(style);\n}\n"],"names":["emojisSets","descriptions","dialogElement","activeTab","searchQuery","savedSelectionRange","EmojisPlugin","_args","context","editorContent","getActiveEditorContent","createEmojiDialog","emoji","insertEmoji","error","selection","overlay","closeDialog","dialog","e","categories","category","renderEmojiGrid","setupEmojiDialogEventListeners","injectEmojiDialogStyles","_a","btn","switchEmojiTab","searchInput","updateEmojiGrid","grid","item","search","emojis","index","range","textNode","active","style"],"mappings":"AAWA,MAAMA,IAAwE;AAAA,EAC5E,KAAK;AAAA,IACH,MAAM;AAAA,IACN,QAAQ;AAAA;AAAA,MAEN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MA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,EAEL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EAEN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EAEP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EAEN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA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"}
@@ -0,0 +1,106 @@
1
+ const f = () => ({
2
+ name: "fontFamily",
3
+ marks: {
4
+ fontFamily: {
5
+ attrs: {
6
+ family: { default: null }
7
+ },
8
+ parseDOM: [
9
+ {
10
+ tag: 'span[style*="font-family"]',
11
+ getAttrs: (n) => {
12
+ const t = n.style.fontFamily;
13
+ return t ? { family: t } : !1;
14
+ }
15
+ },
16
+ {
17
+ tag: "font[face]",
18
+ getAttrs: (n) => {
19
+ const t = n.getAttribute("face");
20
+ return t ? { family: t } : !1;
21
+ }
22
+ }
23
+ ],
24
+ toDOM: (n) => ["span", { style: `font-family: ${n.attrs.family}` }, 0]
25
+ }
26
+ },
27
+ toolbar: [
28
+ {
29
+ label: "Font Family",
30
+ command: "setFontFamily",
31
+ type: "inline-menu",
32
+ options: [
33
+ { label: "Arial", value: "Arial, sans-serif" },
34
+ { label: "Times New Roman", value: "Times New Roman, serif" },
35
+ { label: "Courier New", value: "Courier New, monospace" },
36
+ { label: "Georgia", value: "Georgia, serif" },
37
+ { label: "Verdana", value: "Verdana, sans-serif" },
38
+ { label: "Helvetica", value: "Helvetica, Arial, sans-serif" },
39
+ { label: "Trebuchet MS", value: "Trebuchet MS, sans-serif" },
40
+ { label: "Impact", value: "Impact, sans-serif" }
41
+ ],
42
+ icon: '<svg fill="#000000" width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M15 4h7v2h-7zm1 4h6v2h-6zm2 4h4v2h-4zM9.307 4l-6 16h2.137l1.875-5h6.363l1.875 5h2.137l-6-16H9.307zm-1.239 9L10.5 6.515 12.932 13H8.068z"></path></g></svg>'
43
+ }
44
+ ],
45
+ commands: {
46
+ setFontFamily: (n) => {
47
+ if (!n) return !1;
48
+ try {
49
+ return m(n), !0;
50
+ } catch (e) {
51
+ return console.error("Failed to set font family:", e), !1;
52
+ }
53
+ }
54
+ },
55
+ keymap: {
56
+ "Mod-Shift-f": "setFontFamily"
57
+ }
58
+ });
59
+ function m(n) {
60
+ const e = window.getSelection();
61
+ if (!e || e.rangeCount === 0) return;
62
+ const t = e.getRangeAt(0);
63
+ if (t.collapsed)
64
+ return;
65
+ const l = t.commonAncestorContainer, o = u(l);
66
+ if (o && d(t, o)) {
67
+ o.style.fontFamily = n;
68
+ const a = document.createRange();
69
+ a.selectNodeContents(o), e.removeAllRanges(), e.addRange(a);
70
+ const r = o.closest('[contenteditable="true"]');
71
+ r && r.dispatchEvent(new Event("input", { bubbles: !0 }));
72
+ } else {
73
+ const a = document.createElement("span");
74
+ a.style.fontFamily = n, a.className = "rte-font-family";
75
+ try {
76
+ t.cloneRange().surroundContents(a), t.selectNodeContents(a), e.removeAllRanges(), e.addRange(t);
77
+ } catch (i) {
78
+ const c = t.extractContents();
79
+ a.appendChild(c), t.insertNode(a);
80
+ const s = document.createRange();
81
+ s.selectNodeContents(a), e.removeAllRanges(), e.addRange(s);
82
+ }
83
+ const r = a.closest('[contenteditable="true"]');
84
+ r && r.dispatchEvent(new Event("input", { bubbles: !0 }));
85
+ }
86
+ }
87
+ function u(n) {
88
+ let e = n;
89
+ for (; e; ) {
90
+ if (e.nodeType === Node.ELEMENT_NODE) {
91
+ const t = e;
92
+ if (t.tagName === "SPAN" && t.style.fontFamily)
93
+ return t;
94
+ }
95
+ e = e.parentNode;
96
+ }
97
+ return null;
98
+ }
99
+ function d(n, e) {
100
+ const t = n.startContainer, l = n.endContainer, o = e.contains(t) || t.nodeType === Node.TEXT_NODE && t.parentElement === e, a = e.contains(l) || l.nodeType === Node.TEXT_NODE && l.parentElement === e;
101
+ return o && a;
102
+ }
103
+ export {
104
+ f as FontFamilyPlugin
105
+ };
106
+ //# sourceMappingURL=FontFamilyPlugin.native-BzS_9qbM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FontFamilyPlugin.native-BzS_9qbM.mjs","sources":["../../plugins/font-family/src/FontFamilyPlugin.native.ts"],"sourcesContent":["import type { Plugin } from '@editora/core';\n\n/**\n * FontFamilyPlugin - Native implementation for font family formatting\n * \n * Features:\n * - Inline menu with predefined web-safe font families\n * - Applies font family to selected text using span elements\n * - Supports proper font family stacking with fallbacks\n * \n * Commands:\n * - setFontFamily: Sets the font family to specified value\n * \n * UI/UX Features:\n * - Inline dropdown menu with font previews\n * - 8 carefully curated web-safe fonts\n * - Professional \"A\" glyph icon matching React version\n * - Keyboard shortcut (Mod-Shift-f)\n */\nexport const FontFamilyPlugin = (): Plugin => {\n return {\n name: 'fontFamily',\n \n marks: {\n fontFamily: {\n attrs: {\n family: { default: null }\n },\n parseDOM: [\n {\n tag: 'span[style*=\"font-family\"]',\n getAttrs: (dom) => {\n const element = dom as HTMLElement;\n const family = element.style.fontFamily;\n return family ? { family } : false;\n }\n },\n {\n tag: 'font[face]',\n getAttrs: (dom) => {\n const element = dom as HTMLElement;\n const family = element.getAttribute('face');\n return family ? { family } : false;\n }\n }\n ],\n toDOM: (mark) => {\n return ['span', { style: `font-family: ${mark.attrs.family}` }, 0];\n }\n }\n },\n\n toolbar: [\n {\n label: 'Font Family',\n command: 'setFontFamily',\n type: 'inline-menu',\n options: [\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Times New Roman', value: 'Times New Roman, serif' },\n { label: 'Courier New', value: 'Courier New, monospace' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Helvetica', value: 'Helvetica, Arial, sans-serif' },\n { label: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' },\n { label: 'Impact', value: 'Impact, sans-serif' },\n ],\n icon: '<svg fill=\"#000000\" width=\"24px\" height=\"24px\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g><g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g><g id=\"SVGRepo_iconCarrier\"><path d=\"M15 4h7v2h-7zm1 4h6v2h-6zm2 4h4v2h-4zM9.307 4l-6 16h2.137l1.875-5h6.363l1.875 5h2.137l-6-16H9.307zm-1.239 9L10.5 6.515 12.932 13H8.068z\"></path></g></svg>'\n }\n ],\n\n commands: {\n setFontFamily: (family?: string) => {\n if (!family) return false;\n \n try {\n applyFontFamilyToSelection(family);\n return true;\n } catch (error) {\n console.error('Failed to set font family:', error);\n return false;\n }\n }\n },\n\n keymap: {\n 'Mod-Shift-f': 'setFontFamily'\n }\n };\n};\n\n/**\n * Helper function to apply font family to current selection\n * Uses DOM manipulation for reliable font family application\n */\nfunction applyFontFamilyToSelection(fontFamily: string) {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n\n // If there's no actual selection (just cursor), return\n if (range.collapsed) {\n return;\n }\n\n // Check if the entire selection is within a single font-family span\n const commonAncestor = range.commonAncestorContainer;\n const fontFamilySpan = findFontFamilySpanAncestor(commonAncestor);\n\n if (fontFamilySpan && isSelectionEntirelyWithinSpan(range, fontFamilySpan)) {\n // Update existing span's font-family\n fontFamilySpan.style.fontFamily = fontFamily;\n\n // Restore selection\n const newRange = document.createRange();\n newRange.selectNodeContents(fontFamilySpan);\n selection.removeAllRanges();\n selection.addRange(newRange);\n \n // Trigger input event to update editor state\n const contentElement = fontFamilySpan.closest('[contenteditable=\"true\"]');\n if (contentElement) {\n contentElement.dispatchEvent(new Event('input', { bubbles: true }));\n }\n } else {\n // Create new span wrapper\n const span = document.createElement('span');\n span.style.fontFamily = fontFamily;\n span.className = 'rte-font-family';\n\n // Wrap the selected content\n try {\n // Clone range to avoid modifying original\n const clonedRange = range.cloneRange();\n clonedRange.surroundContents(span);\n \n // Update original range to select the span content\n range.selectNodeContents(span);\n selection.removeAllRanges();\n selection.addRange(range);\n } catch (e) {\n // surroundContents fails if the range spans multiple elements\n // Use extractContents and insertNode instead\n const contents = range.extractContents();\n span.appendChild(contents);\n range.insertNode(span);\n \n // Select the span content\n const newRange = document.createRange();\n newRange.selectNodeContents(span);\n selection.removeAllRanges();\n selection.addRange(newRange);\n }\n \n // Trigger input event to update editor state\n const contentElement = span.closest('[contenteditable=\"true\"]');\n if (contentElement) {\n contentElement.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n}\n\n/**\n * Helper function to find if there's a font-family span ancestor\n */\nfunction findFontFamilySpanAncestor(node: Node): HTMLElement | null {\n let current: Node | null = node;\n\n while (current) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n if (element.tagName === 'SPAN' && element.style.fontFamily) {\n return element;\n }\n }\n current = current.parentNode;\n }\n\n return null;\n}\n\n/**\n * Helper function to check if selection is entirely within a span\n */\nfunction isSelectionEntirelyWithinSpan(range: Range, span: HTMLElement): boolean {\n const startContainer = range.startContainer;\n const endContainer = range.endContainer;\n\n // Check if both start and end are within the span\n const startInSpan = span.contains(startContainer) ||\n (startContainer.nodeType === Node.TEXT_NODE &&\n startContainer.parentElement === span);\n\n const endInSpan = span.contains(endContainer) ||\n (endContainer.nodeType === Node.TEXT_NODE &&\n endContainer.parentElement === span);\n\n return startInSpan && endInSpan;\n}\n"],"names":["FontFamilyPlugin","dom","family","mark","applyFontFamilyToSelection","error","fontFamily","selection","range","commonAncestor","fontFamilySpan","findFontFamilySpanAncestor","isSelectionEntirelyWithinSpan","newRange","contentElement","span","e","contents","node","current","element","startContainer","endContainer","startInSpan","endInSpan"],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ const y = () => ({
2
+ name: "fontSize",
3
+ marks: {
4
+ fontSize: {
5
+ attrs: {
6
+ size: { default: null }
7
+ },
8
+ parseDOM: [
9
+ {
10
+ tag: 'span[style*="font-size"]',
11
+ getAttrs: (t) => {
12
+ const e = t.style.fontSize;
13
+ return e ? { size: e } : !1;
14
+ }
15
+ },
16
+ {
17
+ tag: "font[size]",
18
+ getAttrs: (t) => {
19
+ const e = t.getAttribute("size");
20
+ return e ? { size: e } : !1;
21
+ }
22
+ }
23
+ ],
24
+ toDOM: (t) => ["span", { style: `font-size: ${t.attrs.size}` }, 0]
25
+ }
26
+ },
27
+ toolbar: [
28
+ {
29
+ label: "Font Size",
30
+ command: "fontSize",
31
+ type: "group",
32
+ items: [
33
+ {
34
+ label: "Decrease Font Size",
35
+ command: "decreaseFontSize",
36
+ icon: "−",
37
+ type: "button"
38
+ },
39
+ {
40
+ label: "Font Size",
41
+ command: "setFontSize",
42
+ type: "input",
43
+ placeholder: "14"
44
+ },
45
+ {
46
+ label: "Increase Font Size",
47
+ command: "increaseFontSize",
48
+ icon: "+",
49
+ type: "button"
50
+ }
51
+ ]
52
+ }
53
+ ],
54
+ commands: {
55
+ decreaseFontSize: () => {
56
+ try {
57
+ return u(-2), m(), !0;
58
+ } catch (t) {
59
+ return console.error("Failed to decrease font size:", t), !1;
60
+ }
61
+ },
62
+ increaseFontSize: () => {
63
+ try {
64
+ return u(2), m(), !0;
65
+ } catch (t) {
66
+ return console.error("Failed to increase font size:", t), !1;
67
+ }
68
+ },
69
+ setFontSize: (t) => {
70
+ var o;
71
+ if (!t) return !1;
72
+ try {
73
+ const n = t.trim().match(/^(\d+(?:\.\d+)?)(px|em|rem)?$/i);
74
+ if (!n) return !1;
75
+ const r = parseFloat(n[1]), i = ((o = n[2]) == null ? void 0 : o.toLowerCase()) || "px";
76
+ return i === "px" && (r < 8 || r > 72) || (i === "em" || i === "rem") && (r < 0.5 || r > 5) ? !1 : (d(r, i), !0);
77
+ } catch (e) {
78
+ return console.error("Failed to set font size:", e), !1;
79
+ }
80
+ }
81
+ },
82
+ keymap: {}
83
+ });
84
+ function u(t) {
85
+ const o = window.getSelection();
86
+ if (!o || o.rangeCount === 0) return;
87
+ const { value: e, unit: n } = f();
88
+ let r = t;
89
+ (n === "em" || n === "rem") && (r = t * 0.125);
90
+ let i;
91
+ n === "px" ? i = t < 0 ? Math.max(8, e + t) : Math.min(72, e + t) : i = t < 0 ? Math.max(0.5, e + r) : Math.min(5, e + r), d(i, n);
92
+ }
93
+ function f() {
94
+ var r;
95
+ const t = window.getSelection();
96
+ if (!t || t.rangeCount === 0)
97
+ return { value: 14, unit: "px" };
98
+ const e = t.getRangeAt(0).startContainer, n = e.nodeType === Node.TEXT_NODE ? e.parentElement : e;
99
+ if (n) {
100
+ const i = (r = n.style) == null ? void 0 : r.fontSize;
101
+ if (i) {
102
+ const l = i.match(/^(\d+(?:\.\d+)?)(px|em|rem)$/i);
103
+ if (l)
104
+ return {
105
+ value: parseFloat(l[1]),
106
+ unit: l[2].toLowerCase()
107
+ };
108
+ }
109
+ const s = window.getComputedStyle(n).fontSize.match(/^(\d+(?:\.\d+)?)(px|em|rem)$/i);
110
+ if (s)
111
+ return {
112
+ value: parseFloat(s[1]),
113
+ unit: s[2].toLowerCase()
114
+ };
115
+ }
116
+ return { value: 14, unit: "px" };
117
+ }
118
+ function d(t, o = "px") {
119
+ const e = window.getSelection();
120
+ if (!e || e.rangeCount === 0) return;
121
+ const n = e.getRangeAt(0);
122
+ if (n.collapsed)
123
+ return;
124
+ const r = `${t}${o}`, i = n.commonAncestorContainer, c = S(i);
125
+ if (c && z(n, c)) {
126
+ c.style.fontSize = r;
127
+ const a = document.createRange();
128
+ a.selectNodeContents(c), e.removeAllRanges(), e.addRange(a);
129
+ } else {
130
+ const a = document.createElement("span");
131
+ a.style.fontSize = r;
132
+ try {
133
+ n.surroundContents(a);
134
+ } catch (l) {
135
+ const p = n.extractContents();
136
+ a.appendChild(p), n.insertNode(a);
137
+ }
138
+ const s = document.createRange();
139
+ s.selectNodeContents(a), e.removeAllRanges(), e.addRange(s);
140
+ }
141
+ }
142
+ function S(t) {
143
+ let o = t;
144
+ for (; o && o !== document.body; ) {
145
+ if (o.nodeType === Node.ELEMENT_NODE) {
146
+ const e = o;
147
+ if (e.tagName === "SPAN" && e.style.fontSize)
148
+ return e;
149
+ }
150
+ o = o.parentNode;
151
+ }
152
+ return null;
153
+ }
154
+ function z(t, o) {
155
+ const e = t.startContainer, n = t.endContainer;
156
+ return o.contains(e) && o.contains(n);
157
+ }
158
+ function m() {
159
+ setTimeout(() => {
160
+ const { value: t, unit: o } = f();
161
+ let e = null;
162
+ if (e = document.querySelector(
163
+ 'input[placeholder="14"]'
164
+ ), e || (e = document.querySelector(
165
+ '.rte-toolbar-input[type="text"]'
166
+ )), !e) {
167
+ const n = Array.from(document.querySelectorAll("button")).find(
168
+ (r) => {
169
+ var i;
170
+ return ((i = r.textContent) == null ? void 0 : i.trim()) === "−";
171
+ }
172
+ );
173
+ n && n.parentElement && (e = n.parentElement.querySelector(
174
+ 'input[type="text"]'
175
+ ));
176
+ }
177
+ if (e) {
178
+ const n = t % 1 === 0 ? t.toString() : t.toFixed(2).replace(/\.?0+$/, "");
179
+ e.value = `${n}${o}`;
180
+ }
181
+ }, 10);
182
+ }
183
+ export {
184
+ y as FontSizePlugin
185
+ };
186
+ //# sourceMappingURL=FontSizePlugin.native-DkLMLPue.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FontSizePlugin.native-DkLMLPue.mjs","sources":["../../plugins/font-size/src/FontSizePlugin.native.ts"],"sourcesContent":["import type { Plugin } from \"@editora/core\";\n\n/**\n * FontSizePlugin - Native implementation for font size formatting\n *\n * Features:\n * - Decrease/Increase font size buttons (−/+)\n * - Manual font size input field with CSS unit support (px, em, rem)\n * - Range: 8-72px or 0.5-5em/rem\n * - Updates input to show current size with unit\n *\n * Commands:\n * - decreaseFontSize: Decrease font size by 2px (or 0.125em/rem)\n * - increaseFontSize: Increase font size by 2px (or 0.125em/rem)\n * - setFontSize: Set specific font size from input (supports px, em, rem)\n *\n * UI/UX Features:\n * - Three toolbar items: decrease button, input, increase button\n * - Input shows current font size from selection with unit\n * - Simple +/− text icons matching React version\n * - Unit preservation (if user sets em, stays in em)\n */\nexport const FontSizePlugin = (): Plugin => {\n return {\n name: \"fontSize\",\n\n marks: {\n fontSize: {\n attrs: {\n size: { default: null },\n },\n parseDOM: [\n {\n tag: 'span[style*=\"font-size\"]',\n getAttrs: (dom) => {\n const element = dom as HTMLElement;\n const size = element.style.fontSize;\n return size ? { size } : false;\n },\n },\n {\n tag: \"font[size]\",\n getAttrs: (dom) => {\n const element = dom as HTMLElement;\n const size = element.getAttribute(\"size\");\n return size ? { size } : false;\n },\n },\n ],\n toDOM: (mark) => {\n return [\"span\", { style: `font-size: ${mark.attrs.size}` }, 0];\n },\n },\n },\n\n toolbar: [\n {\n label: \"Font Size\",\n command: \"fontSize\",\n type: \"group\",\n items: [\n {\n label: \"Decrease Font Size\",\n command: \"decreaseFontSize\",\n icon: \"−\",\n type: \"button\",\n },\n {\n label: \"Font Size\",\n command: \"setFontSize\",\n type: \"input\",\n placeholder: \"14\",\n },\n {\n label: \"Increase Font Size\",\n command: \"increaseFontSize\",\n icon: \"+\",\n type: \"button\",\n },\n ],\n },\n ],\n\n commands: {\n decreaseFontSize: () => {\n try {\n applyFontSizeChange(-2);\n updateFontSizeInput();\n return true;\n } catch (error) {\n console.error(\"Failed to decrease font size:\", error);\n return false;\n }\n },\n\n increaseFontSize: () => {\n try {\n applyFontSizeChange(2);\n updateFontSizeInput();\n return true;\n } catch (error) {\n console.error(\"Failed to increase font size:\", error);\n return false;\n }\n },\n\n setFontSize: (size?: string) => {\n if (!size) return false;\n\n try {\n // Parse size with unit support (px, em, rem)\n const trimmedSize = size.trim();\n const match = trimmedSize.match(/^(\\d+(?:\\.\\d+)?)(px|em|rem)?$/i);\n\n if (!match) return false;\n\n const value = parseFloat(match[1]);\n const unit = match[2]?.toLowerCase() || \"px\"; // Default to px if no unit\n\n // Unit-specific validation\n if (unit === \"px\" && (value < 8 || value > 72)) return false;\n if ((unit === \"em\" || unit === \"rem\") && (value < 0.5 || value > 5))\n return false;\n\n applyFontSizeToSelection(value, unit);\n return true;\n } catch (error) {\n console.error(\"Failed to set font size:\", error);\n return false;\n }\n },\n },\n\n keymap: {},\n };\n};\n\n/**\n * Helper function to apply relative font size change\n */\nfunction applyFontSizeChange(delta: number) {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n // Get current font size from selection with unit\n const { value, unit } = getCurrentFontSizeFromSelection();\n\n // Calculate delta based on unit\n let adjustedDelta = delta;\n if (unit === \"em\" || unit === \"rem\") {\n // For em/rem, use smaller increments (0.125 = 2px at 16px base)\n adjustedDelta = delta * 0.125;\n }\n\n // Calculate new size with bounds based on unit\n let newSize: number;\n if (unit === \"px\") {\n newSize =\n delta < 0 ? Math.max(8, value + delta) : Math.min(72, value + delta);\n } else {\n newSize =\n delta < 0\n ? Math.max(0.5, value + adjustedDelta)\n : Math.min(5, value + adjustedDelta);\n }\n\n applyFontSizeToSelection(newSize, unit);\n}\n\n/**\n * Helper function to get current font size from selection with unit\n */\nfunction getCurrentFontSizeFromSelection(): { value: number; unit: string } {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return { value: 14, unit: \"px\" };\n }\n\n const range = selection.getRangeAt(0);\n const startContainer = range.startContainer;\n const element =\n startContainer.nodeType === Node.TEXT_NODE\n ? startContainer.parentElement\n : (startContainer as Element);\n\n if (element) {\n // First check if there's an inline style with font-size (preserves user's unit choice)\n const inlineStyle = (element as HTMLElement).style?.fontSize;\n if (inlineStyle) {\n const match = inlineStyle.match(/^(\\d+(?:\\.\\d+)?)(px|em|rem)$/i);\n if (match) {\n return {\n value: parseFloat(match[1]),\n unit: match[2].toLowerCase(),\n };\n }\n }\n\n // Fall back to computed style (usually returns px)\n const computedStyle = window.getComputedStyle(element);\n const fontSize = computedStyle.fontSize;\n const match = fontSize.match(/^(\\d+(?:\\.\\d+)?)(px|em|rem)$/i);\n if (match) {\n return {\n value: parseFloat(match[1]),\n unit: match[2].toLowerCase(),\n };\n }\n }\n\n return { value: 14, unit: \"px\" };\n}\n\n/**\n * Helper function to apply font size to the current selection\n */\nfunction applyFontSizeToSelection(size: number, unit: string = \"px\") {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n\n // If there's no actual selection (just cursor), return\n if (range.collapsed) {\n return;\n }\n\n const fontSizeValue = `${size}${unit}`;\n\n // Check if the entire selection is within a single font-size span\n const commonAncestor = range.commonAncestorContainer;\n const fontSizeSpan = findFontSizeSpanAncestor(commonAncestor);\n\n if (fontSizeSpan && isSelectionEntirelyWithinSpan(range, fontSizeSpan)) {\n // Update existing span's font-size\n fontSizeSpan.style.fontSize = fontSizeValue;\n\n // Restore selection\n const newRange = document.createRange();\n newRange.selectNodeContents(fontSizeSpan);\n selection.removeAllRanges();\n selection.addRange(newRange);\n } else {\n // Create new span wrapper\n const span = document.createElement(\"span\");\n span.style.fontSize = fontSizeValue;\n\n // Wrap the selected content\n try {\n range.surroundContents(span);\n } catch (e) {\n // surroundContents fails if the range spans multiple elements\n const contents = range.extractContents();\n span.appendChild(contents);\n range.insertNode(span);\n }\n\n // Restore selection to the inserted span\n const newRange = document.createRange();\n newRange.selectNodeContents(span);\n selection.removeAllRanges();\n selection.addRange(newRange);\n }\n}\n\n/**\n * Helper function to find if there's a font-size span ancestor\n */\nfunction findFontSizeSpanAncestor(node: Node): HTMLElement | null {\n let current: Node | null = node;\n\n while (current && current !== document.body) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n if (element.tagName === \"SPAN\" && element.style.fontSize) {\n return element;\n }\n }\n current = current.parentNode;\n }\n\n return null;\n}\n\n/**\n * Helper function to check if selection is entirely within a span\n */\nfunction isSelectionEntirelyWithinSpan(\n range: Range,\n span: HTMLElement,\n): boolean {\n const startContainer = range.startContainer;\n const endContainer = range.endContainer;\n\n // Check if both start and end are within the span\n return span.contains(startContainer) && span.contains(endContainer);\n}\n\n/**\n * Update font size input field to reflect current selection\n */\nfunction updateFontSizeInput() {\n // Small delay to ensure DOM has updated\n setTimeout(() => {\n const { value, unit } = getCurrentFontSizeFromSelection();\n\n // Try multiple selectors to find the font size input\n let input: HTMLInputElement | null = null;\n\n // Try finding by placeholder\n input = document.querySelector(\n 'input[placeholder=\"14\"]',\n ) as HTMLInputElement;\n\n // Try finding by class if available\n if (!input) {\n input = document.querySelector(\n '.rte-toolbar-input[type=\"text\"]',\n ) as HTMLInputElement;\n }\n\n // Try finding any input near the increase/decrease buttons\n if (!input) {\n const decreaseBtn = Array.from(document.querySelectorAll(\"button\")).find(\n (btn) => btn.textContent?.trim() === \"−\",\n );\n if (decreaseBtn && decreaseBtn.parentElement) {\n input = decreaseBtn.parentElement.querySelector(\n 'input[type=\"text\"]',\n ) as HTMLInputElement;\n }\n }\n\n if (input) {\n // Format value: remove trailing zeros and show unit\n const formattedValue =\n value % 1 === 0\n ? value.toString()\n : value.toFixed(2).replace(/\\.?0+$/, \"\");\n input.value = `${formattedValue}${unit}`;\n }\n }, 10);\n}\n"],"names":["FontSizePlugin","dom","size","mark","applyFontSizeChange","updateFontSizeInput","error","_a","match","value","unit","applyFontSizeToSelection","delta","selection","getCurrentFontSizeFromSelection","adjustedDelta","newSize","startContainer","element","inlineStyle","range","fontSizeValue","commonAncestor","fontSizeSpan","findFontSizeSpanAncestor","isSelectionEntirelyWithinSpan","newRange","span","e","contents","node","current","endContainer","input","decreaseBtn","btn","formattedValue"],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ const C = () => ({
2
+ name: "footnote",
3
+ toolbar: [
4
+ {
5
+ label: "Footnote",
6
+ command: "insertFootnote",
7
+ icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><rect x="3" y="4" width="14" height="2" rx="1" /><rect x="3" y="8" width="18" height="2" rx="1" /><rect x="3" y="12" width="16" height="2" rx="1" /><rect x="3" y="16" width="10" height="1.5" rx="0.75" /><text x="19" y="11" font-size="9" font-weight="600" fill="currentColor" font-family="system-ui, sans-serif">1</text></svg>',
8
+ type: "button"
9
+ }
10
+ ],
11
+ commands: {
12
+ insertFootnote: () => (y(), null)
13
+ },
14
+ keymap: {}
15
+ }), m = /* @__PURE__ */ new Map();
16
+ function l() {
17
+ const e = window.getSelection();
18
+ if (e && e.rangeCount > 0) {
19
+ let o = e.getRangeAt(0).startContainer;
20
+ for (; o && o !== document.body; ) {
21
+ if (o.nodeType === Node.ELEMENT_NODE) {
22
+ const n = o;
23
+ if (n.getAttribute("contenteditable") === "true")
24
+ return n;
25
+ }
26
+ o = o.parentNode;
27
+ }
28
+ }
29
+ const t = document.activeElement;
30
+ if (t) {
31
+ if (t.getAttribute("contenteditable") === "true")
32
+ return t;
33
+ const o = t.closest('[contenteditable="true"]');
34
+ if (o) return o;
35
+ }
36
+ return document.querySelector('[contenteditable="true"]');
37
+ }
38
+ function g() {
39
+ const e = l();
40
+ if (!e)
41
+ throw new Error("Contenteditable element not found");
42
+ let t = e.querySelector(".rte-footnotes");
43
+ if (!t) {
44
+ t = document.createElement("section"), t.className = "rte-footnotes", t.setAttribute("data-type", "footnotes"), t.setAttribute("contenteditable", "true");
45
+ const o = document.createElement("ol");
46
+ t.appendChild(o), e.appendChild(t);
47
+ }
48
+ return t;
49
+ }
50
+ const y = (e = "") => {
51
+ const t = window.getSelection();
52
+ if (!t || t.rangeCount === 0) return;
53
+ const o = t.getRangeAt(0), n = `fn-${Date.now()}`, r = h(), i = document.createElement("sup");
54
+ i.className = "rte-footnote-ref", i.setAttribute("data-footnote-id", n), i.setAttribute("data-number", r.toString()), i.textContent = r.toString(), i.style.cursor = "pointer";
55
+ try {
56
+ o.insertNode(i), o.setStartAfter(i), o.collapse(!0), t.removeAllRanges(), t.addRange(o);
57
+ } catch (b) {
58
+ console.error("Error inserting footnote reference:", b);
59
+ return;
60
+ }
61
+ const s = g().querySelector("ol"), c = document.createElement("li");
62
+ c.id = n, c.className = "rte-footnote-item", c.setAttribute("data-type", "footnote"), c.setAttribute("data-number", r.toString());
63
+ const f = document.createElement("div");
64
+ f.className = "rte-footnote-content", f.setAttribute("contenteditable", "true"), f.textContent = e || `Footnote ${r}`, c.appendChild(f);
65
+ const a = document.createElement("a");
66
+ a.className = "rte-footnote-backref", a.href = `#ref-${n}`, a.setAttribute("aria-label", `Back to reference ${r}`), a.textContent = "↩", c.appendChild(a), s == null || s.appendChild(c), m.set(n, {
67
+ id: n,
68
+ number: r,
69
+ content: e
70
+ }), u();
71
+ };
72
+ function h() {
73
+ const e = l(), t = e == null ? void 0 : e.querySelector(".rte-footnotes");
74
+ return t ? t.querySelectorAll('li[data-type="footnote"]').length + 1 : 1;
75
+ }
76
+ const p = () => {
77
+ const e = l(), t = e == null ? void 0 : e.querySelector(".rte-footnotes");
78
+ if (!t) return;
79
+ const o = t.querySelectorAll('li[data-type="footnote"]');
80
+ let n = 1;
81
+ o.forEach((r) => {
82
+ const i = r.id;
83
+ r.setAttribute("data-number", n.toString());
84
+ const d = e == null ? void 0 : e.querySelector(`.rte-footnote-ref[data-footnote-id="${i}"]`);
85
+ d && (d.setAttribute("data-number", n.toString()), d.textContent = n.toString());
86
+ const s = m.get(i);
87
+ s && (s.number = n), n++;
88
+ });
89
+ }, A = (e) => {
90
+ const t = l(), o = t == null ? void 0 : t.querySelector(`.rte-footnote-ref[data-footnote-id="${e}"]`), n = document.getElementById(e);
91
+ o && o.remove(), n && n.remove(), m.delete(e), p();
92
+ };
93
+ function u() {
94
+ const e = l();
95
+ e && (e.addEventListener("click", (t) => {
96
+ const o = t.target;
97
+ if (o.classList.contains("rte-footnote-ref")) {
98
+ const n = o.getAttribute("data-footnote-id");
99
+ if (n) {
100
+ const r = document.getElementById(n);
101
+ r && (r.scrollIntoView({ behavior: "smooth", block: "center" }), r.style.backgroundColor = "#fff3cd", setTimeout(() => {
102
+ r.style.backgroundColor = "";
103
+ }, 1500));
104
+ }
105
+ }
106
+ }), e.addEventListener("click", (t) => {
107
+ var n;
108
+ const o = t.target;
109
+ if (o.classList.contains("rte-footnote-backref")) {
110
+ t.preventDefault();
111
+ const r = (n = o.closest("li")) == null ? void 0 : n.id;
112
+ if (r) {
113
+ const i = e.querySelector(`.rte-footnote-ref[data-footnote-id="${r}"]`);
114
+ i && (i.scrollIntoView({ behavior: "smooth", block: "center" }), i.style.backgroundColor = "#fff3cd", setTimeout(() => {
115
+ i.style.backgroundColor = "";
116
+ }, 1500));
117
+ }
118
+ }
119
+ }));
120
+ }
121
+ typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", u) : u());
122
+ export {
123
+ C as FootnotePlugin,
124
+ A as deleteFootnote,
125
+ y as insertFootnoteCommand,
126
+ p as renumberAllFootnotes
127
+ };
128
+ //# sourceMappingURL=FootnotePlugin.native-BciVc9W6.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FootnotePlugin.native-BciVc9W6.mjs","sources":["../../plugins/footnote/src/FootnotePlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Footnote Plugin - Native Implementation\n * \n * Features:\n * - Auto-numbering and renumbering\n * - Bidirectional links (reference ↔ footnote)\n * - Editable footnote content\n * - Semantic HTML structure\n * - Print support\n * \n * Structure:\n * - References: <sup class=\"rte-footnote-ref\" data-footnote-id=\"fn-xxx\">[1]</sup>\n * - Container: <section class=\"rte-footnotes\"><ol><li id=\"fn-xxx\">...</li></ol></section>\n * \n * Icon: Document lines with superscript \"1\" indicating footnote reference\n */\nexport const FootnotePlugin = (): Plugin => ({\n name: 'footnote',\n \n toolbar: [\n {\n label: 'Footnote',\n command: 'insertFootnote',\n icon: '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><rect x=\"3\" y=\"4\" width=\"14\" height=\"2\" rx=\"1\" /><rect x=\"3\" y=\"8\" width=\"18\" height=\"2\" rx=\"1\" /><rect x=\"3\" y=\"12\" width=\"16\" height=\"2\" rx=\"1\" /><rect x=\"3\" y=\"16\" width=\"10\" height=\"1.5\" rx=\"0.75\" /><text x=\"19\" y=\"11\" font-size=\"9\" font-weight=\"600\" fill=\"currentColor\" font-family=\"system-ui, sans-serif\">1</text></svg>',\n type: 'button'\n }\n ],\n \n commands: {\n insertFootnote: () => {\n insertFootnoteCommand();\n return null;\n }\n },\n \n keymap: {}\n});\n\n/**\n * Footnote registry to track footnotes\n */\ninterface FootnoteData {\n id: string;\n number: number;\n content: string;\n}\n\nconst footnoteRegistry = new Map<string, FootnoteData>();\n\n/**\n * Find the active editor based on current selection or focus\n */\nfunction findActiveEditor(): HTMLElement | null {\n // Try to find editor from current selection\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n let node: Node | null = selection.getRangeAt(0).startContainer;\n while (node && node !== document.body) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n if (element.getAttribute('contenteditable') === 'true') {\n return element;\n }\n }\n node = node.parentNode;\n }\n }\n \n // Try to find focused editor\n const activeElement = document.activeElement;\n if (activeElement) {\n if (activeElement.getAttribute('contenteditable') === 'true') {\n return activeElement as HTMLElement;\n }\n const editor = activeElement.closest('[contenteditable=\"true\"]');\n if (editor) return editor as HTMLElement;\n }\n \n // Fallback to first editor\n return document.querySelector('[contenteditable=\"true\"]');\n}\n\n/**\n * Get or create footnote container\n * Always at the end of the content area\n */\nfunction getFootnoteContainer(): HTMLElement {\n const contentElement = findActiveEditor();\n if (!contentElement) {\n throw new Error('Contenteditable element not found');\n }\n \n let container = contentElement.querySelector('.rte-footnotes') as HTMLElement;\n \n if (!container) {\n container = document.createElement('section');\n container.className = 'rte-footnotes';\n container.setAttribute('data-type', 'footnotes');\n container.setAttribute('contenteditable', 'true');\n \n const ol = document.createElement('ol');\n container.appendChild(ol);\n \n contentElement.appendChild(container);\n }\n \n return container;\n}\n\n/**\n * Insert Footnote Command\n */\nexport const insertFootnoteCommand = (content: string = '') => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n\n // Generate unique footnote ID\n const footnoteId = `fn-${Date.now()}`;\n const nextNumber = getNextFootnoteNumber();\n\n // Create reference element\n const reference = document.createElement('sup');\n reference.className = 'rte-footnote-ref';\n reference.setAttribute('data-footnote-id', footnoteId);\n reference.setAttribute('data-number', nextNumber.toString());\n reference.textContent = nextNumber.toString();\n \n // Style the reference inline (will be enhanced by CSS)\n reference.style.cursor = 'pointer';\n\n // Insert reference at cursor and collapse selection after it\n try {\n range.insertNode(reference);\n range.setStartAfter(reference);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n } catch (e) {\n console.error('Error inserting footnote reference:', e);\n return;\n }\n\n // Get or create footnote container\n const container = getFootnoteContainer();\n const ol = container.querySelector('ol');\n\n // Create footnote item\n const li = document.createElement('li');\n li.id = footnoteId;\n li.className = 'rte-footnote-item';\n li.setAttribute('data-type', 'footnote');\n li.setAttribute('data-number', nextNumber.toString());\n\n // Add content\n const contentDiv = document.createElement('div');\n contentDiv.className = 'rte-footnote-content';\n contentDiv.setAttribute('contenteditable', 'true');\n contentDiv.textContent = content || `Footnote ${nextNumber}`;\n li.appendChild(contentDiv);\n\n // Add back reference\n const backRef = document.createElement('a');\n backRef.className = 'rte-footnote-backref';\n backRef.href = `#ref-${footnoteId}`;\n backRef.setAttribute('aria-label', `Back to reference ${nextNumber}`);\n backRef.textContent = '↩';\n li.appendChild(backRef);\n\n // Append to footnote list\n ol?.appendChild(li);\n\n // Register footnote\n footnoteRegistry.set(footnoteId, {\n id: footnoteId,\n number: nextNumber,\n content\n });\n\n // Setup click handlers\n setupFootnoteInteractions();\n};\n\n/**\n * Get next footnote number\n */\nfunction getNextFootnoteNumber(): number {\n const contentElement = findActiveEditor();\n const container = contentElement?.querySelector('.rte-footnotes');\n if (!container) return 1;\n\n const items = container.querySelectorAll('li[data-type=\"footnote\"]');\n return items.length + 1;\n}\n\n/**\n * Renumber all footnotes\n * Called when a footnote is deleted or reordered\n */\nexport const renumberAllFootnotes = () => {\n const contentElement = findActiveEditor();\n const container = contentElement?.querySelector('.rte-footnotes');\n if (!container) return;\n\n const items = container.querySelectorAll('li[data-type=\"footnote\"]');\n let number = 1;\n\n items.forEach(item => {\n const footnoteId = item.id;\n \n // Update footnote item\n item.setAttribute('data-number', number.toString());\n \n // Update reference\n const ref = contentElement?.querySelector(`.rte-footnote-ref[data-footnote-id=\"${footnoteId}\"]`);\n if (ref) {\n ref.setAttribute('data-number', number.toString());\n ref.textContent = number.toString();\n }\n\n // Update registry\n const footnoteData = footnoteRegistry.get(footnoteId);\n if (footnoteData) {\n footnoteData.number = number;\n }\n\n number++;\n });\n};\n\n/**\n * Delete footnote and its reference\n */\nexport const deleteFootnote = (footnoteId: string) => {\n const contentElement = findActiveEditor();\n const reference = contentElement?.querySelector(`.rte-footnote-ref[data-footnote-id=\"${footnoteId}\"]`);\n const footnoteItem = document.getElementById(footnoteId);\n\n if (reference) reference.remove();\n if (footnoteItem) footnoteItem.remove();\n\n footnoteRegistry.delete(footnoteId);\n renumberAllFootnotes();\n};\n\n/**\n * Setup interactions (scrolling between references and footnotes)\n */\nfunction setupFootnoteInteractions() {\n const contentElement = findActiveEditor();\n if (!contentElement) return;\n\n // Click on reference -> scroll to footnote\n contentElement.addEventListener('click', (e) => {\n const target = e.target as HTMLElement;\n if (target.classList.contains('rte-footnote-ref')) {\n const footnoteId = target.getAttribute('data-footnote-id');\n if (footnoteId) {\n const footnote = document.getElementById(footnoteId);\n if (footnote) {\n footnote.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // Highlight the footnote briefly\n footnote.style.backgroundColor = '#fff3cd';\n setTimeout(() => {\n footnote.style.backgroundColor = '';\n }, 1500);\n }\n }\n }\n });\n\n // Click on back reference -> scroll to reference\n contentElement.addEventListener('click', (e) => {\n const target = e.target as HTMLElement;\n if (target.classList.contains('rte-footnote-backref')) {\n e.preventDefault();\n const footnoteId = target.closest('li')?.id;\n if (footnoteId) {\n const reference = contentElement.querySelector(`.rte-footnote-ref[data-footnote-id=\"${footnoteId}\"]`);\n if (reference) {\n reference.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // Highlight the reference briefly\n (reference as HTMLElement).style.backgroundColor = '#fff3cd';\n setTimeout(() => {\n (reference as HTMLElement).style.backgroundColor = '';\n }, 1500);\n }\n }\n }\n });\n}\n\n// Initialize interactions on load\nif (typeof window !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', setupFootnoteInteractions);\n } else {\n setupFootnoteInteractions();\n }\n}\n"],"names":["FootnotePlugin","insertFootnoteCommand","footnoteRegistry","findActiveEditor","selection","node","element","activeElement","editor","getFootnoteContainer","contentElement","container","ol","content","range","footnoteId","nextNumber","getNextFootnoteNumber","reference","e","li","contentDiv","backRef","setupFootnoteInteractions","renumberAllFootnotes","items","number","item","ref","footnoteData","deleteFootnote","footnoteItem","target","footnote","_a"],"mappings":"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"}