@prolibu-suite/cobalt-core 0.2.0 → 0.4.0

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 (678) hide show
  1. package/custom-elements.json +19263 -11548
  2. package/dist/cjs/co-accordion.cjs.entry.js +3 -3
  3. package/dist/cjs/co-app-shell.cjs.entry.js +4 -4
  4. package/dist/cjs/co-autocomplete.cjs.entry.js +10 -7
  5. package/dist/cjs/co-avatar-group.cjs.entry.js +77 -0
  6. package/dist/cjs/co-avatar.cjs.entry.js +12 -5
  7. package/dist/cjs/co-badge.cjs.entry.js +2 -2
  8. package/dist/cjs/co-bottom-sheet.cjs.entry.js +325 -0
  9. package/dist/cjs/co-breadcrumb-item.cjs.entry.js +37 -0
  10. package/dist/cjs/co-breadcrumb.cjs.entry.js +55 -0
  11. package/dist/cjs/co-button-group.cjs.entry.js +3 -3
  12. package/dist/cjs/co-button.cjs.entry.js +12 -6
  13. package/dist/cjs/co-calendar-month.cjs.entry.js +381 -0
  14. package/dist/cjs/co-calendar_3.cjs.entry.js +41 -11
  15. package/dist/cjs/co-card.cjs.entry.js +3 -3
  16. package/dist/cjs/co-checkbox-group.cjs.entry.js +5 -5
  17. package/dist/cjs/co-checkbox.cjs.entry.js +18 -6
  18. package/dist/cjs/co-chip.cjs.entry.js +19 -11
  19. package/dist/cjs/co-color-picker.cjs.entry.js +7 -5
  20. package/dist/cjs/co-column-picker.cjs.entry.js +3 -3
  21. package/dist/cjs/co-combobox.cjs.entry.js +7 -7
  22. package/dist/cjs/co-command-search.cjs.entry.js +151 -12
  23. package/dist/cjs/co-data-table-pagination.cjs.entry.js +5 -5
  24. package/dist/cjs/co-data-table.cjs.entry.js +44 -23
  25. package/dist/cjs/co-date-picker.cjs.entry.js +2 -2
  26. package/dist/cjs/co-date-range-picker.cjs.entry.js +3 -3
  27. package/dist/cjs/co-date-range.cjs.entry.js +2 -2
  28. package/dist/cjs/co-drive-card.cjs.entry.js +81 -0
  29. package/dist/cjs/co-drop-zone.cjs.entry.js +63 -0
  30. package/dist/cjs/co-empty-state.cjs.entry.js +13 -3
  31. package/dist/cjs/co-event-calendar.cjs.entry.js +318 -0
  32. package/dist/cjs/co-fab.cjs.entry.js +3 -3
  33. package/dist/cjs/co-file-field.cjs.entry.js +8 -8
  34. package/dist/cjs/co-file-type-tile.cjs.entry.js +78 -0
  35. package/dist/cjs/co-helper-text.cjs.entry.js +3 -3
  36. package/dist/cjs/co-icon-button.cjs.entry.js +24 -8
  37. package/dist/cjs/co-icon.cjs.entry.js +33 -25
  38. package/dist/cjs/co-input.cjs.entry.js +36 -7
  39. package/dist/cjs/co-json-field.cjs.entry.js +10 -6
  40. package/dist/cjs/co-lightbox.cjs.entry.js +5 -5
  41. package/dist/cjs/co-list-footer.cjs.entry.js +25 -0
  42. package/dist/cjs/co-list-item.cjs.entry.js +60 -4
  43. package/dist/cjs/co-loader.cjs.entry.js +2 -2
  44. package/dist/cjs/co-media-thumb.cjs.entry.js +36 -0
  45. package/dist/cjs/co-menu-divider.cjs.entry.js +2 -2
  46. package/dist/cjs/co-menu-item.cjs.entry.js +26 -11
  47. package/dist/cjs/co-menu.cjs.entry.js +3 -3
  48. package/dist/cjs/co-modal.cjs.entry.js +41 -5
  49. package/dist/cjs/co-navbar.cjs.entry.js +3 -3
  50. package/dist/cjs/co-number-field.cjs.entry.js +18 -6
  51. package/dist/cjs/co-option-list.cjs.entry.js +379 -0
  52. package/dist/cjs/co-overlay.cjs.entry.js +243 -3
  53. package/dist/cjs/co-page-header.cjs.entry.js +2 -2
  54. package/dist/cjs/co-phone-field.cjs.entry.js +6 -4
  55. package/dist/cjs/co-popover.cjs.entry.js +45 -14
  56. package/dist/cjs/co-progress-bar.cjs.entry.js +8 -4
  57. package/dist/cjs/co-progress-circle.cjs.entry.js +3 -3
  58. package/dist/cjs/co-radio-group.cjs.entry.js +4 -4
  59. package/dist/cjs/co-radio.cjs.entry.js +4 -4
  60. package/dist/cjs/co-rating.cjs.entry.js +4 -4
  61. package/dist/cjs/co-ref-field.cjs.entry.js +36 -13
  62. package/dist/cjs/co-rich-text-editor.cjs.entry.js +1879 -33
  63. package/dist/cjs/co-rich-text-toolbar.cjs.entry.js +995 -71
  64. package/dist/cjs/co-rich-text-viewer.cjs.entry.js +55 -19
  65. package/dist/cjs/co-row.cjs.entry.js +3 -3
  66. package/dist/cjs/co-segmented-bar.cjs.entry.js +58 -0
  67. package/dist/cjs/co-select.cjs.entry.js +8 -8
  68. package/dist/cjs/co-separator.cjs.entry.js +2 -2
  69. package/dist/cjs/co-sidebar-nav.cjs.entry.js +29 -9
  70. package/dist/cjs/co-sidebar.cjs.entry.js +3 -3
  71. package/dist/cjs/co-skeleton.cjs.entry.js +26 -0
  72. package/dist/cjs/co-slider.cjs.entry.js +3 -3
  73. package/dist/cjs/co-switch.cjs.entry.js +6 -6
  74. package/dist/cjs/co-tab-group.cjs.entry.js +15 -3
  75. package/dist/cjs/co-tab.cjs.entry.js +8 -5
  76. package/dist/cjs/co-tags-field.cjs.entry.js +19 -13
  77. package/dist/cjs/co-textarea.cjs.entry.js +11 -7
  78. package/dist/cjs/co-toast.cjs.entry.js +10 -4
  79. package/dist/cjs/co-toggle-button-group.cjs.entry.js +16 -4
  80. package/dist/cjs/co-toggle-button.cjs.entry.js +9 -5
  81. package/dist/cjs/co-tooltip.cjs.entry.js +51 -16
  82. package/dist/cjs/co-transfer-list.cjs.entry.js +3 -3
  83. package/dist/cjs/co-video.cjs.entry.js +839 -0
  84. package/dist/cjs/cobalt.cjs.js +2 -2
  85. package/dist/cjs/fieldChip-DtYUP0VZ.js +7 -0
  86. package/dist/{esm/index-BjAqSidM.js → cjs/index-4y1Dm145.js} +14436 -6178
  87. package/dist/cjs/{index-DoFnrUVH.js → index-NNvye1ul.js} +105 -21
  88. package/dist/cjs/loader.cjs.js +2 -2
  89. package/dist/cjs/overlayAfterClose-BdeXrhVY.js +12 -0
  90. package/dist/{esm/sanitizer-DcK0GGZC.js → cjs/purify.es-DX41ZWS2.js} +3 -107
  91. package/dist/cjs/{requiredMark-DA6y-4rp.js → requiredMark-DyjZzUCd.js} +1 -1
  92. package/dist/cjs/richTextI18n-B7ktXg3M.js +382 -0
  93. package/dist/cjs/toolbar-config-3PlT-3zm.js +216 -0
  94. package/dist/cjs/tz-Dgom0W69.js +127 -0
  95. package/dist/cobalt/cobalt.css +1 -1
  96. package/dist/cobalt/cobalt.esm.js +1 -1
  97. package/dist/cobalt/p-06c27cc5.entry.js +1 -0
  98. package/dist/cobalt/{p-136bdbd2.entry.js → p-075f6ca4.entry.js} +1 -1
  99. package/dist/cobalt/p-0810ee1e.entry.js +1 -0
  100. package/dist/cobalt/p-08519a7c.entry.js +1 -0
  101. package/dist/cobalt/p-0b41e76e.entry.js +1 -0
  102. package/dist/cobalt/p-0be124d5.entry.js +1 -0
  103. package/dist/cobalt/{p-e8b58332.entry.js → p-0e1afdea.entry.js} +1 -1
  104. package/dist/cobalt/p-1388eac6.entry.js +1 -0
  105. package/dist/cobalt/{p-7f818368.entry.js → p-19f7ee64.entry.js} +1 -1
  106. package/dist/cobalt/p-1af6ef83.entry.js +1 -0
  107. package/dist/cobalt/{p-f2c5cb74.entry.js → p-1cecb9e1.entry.js} +1 -1
  108. package/dist/cobalt/{p-273afd93.entry.js → p-20c68308.entry.js} +1 -1
  109. package/dist/cobalt/p-21916f82.entry.js +1 -0
  110. package/dist/cobalt/p-23c9208a.entry.js +1 -0
  111. package/dist/cobalt/p-2d4e1ca8.entry.js +1 -0
  112. package/dist/cobalt/{p-def448e4.entry.js → p-304c3be1.entry.js} +1 -1
  113. package/dist/cobalt/p-311118cb.entry.js +1 -0
  114. package/dist/cobalt/{p-2b4d8535.entry.js → p-328f0470.entry.js} +1 -1
  115. package/dist/cobalt/p-35c63fdc.entry.js +1 -0
  116. package/dist/cobalt/{p-f97ad9ad.entry.js → p-363a5262.entry.js} +1 -1
  117. package/dist/cobalt/p-376c43b8.entry.js +1 -0
  118. package/dist/cobalt/p-39a29bbb.entry.js +1 -0
  119. package/dist/cobalt/p-3d07e4a9.entry.js +1 -0
  120. package/dist/cobalt/{p-1e0282b8.entry.js → p-3dd6b57b.entry.js} +1 -1
  121. package/dist/cobalt/{p-7ef766c6.entry.js → p-48c5f311.entry.js} +1 -1
  122. package/dist/cobalt/{p-fe9e85b6.entry.js → p-4aeefe3f.entry.js} +1 -1
  123. package/dist/cobalt/p-523cfd98.entry.js +1 -0
  124. package/dist/cobalt/{p-c87285b6.entry.js → p-58aed8d6.entry.js} +1 -1
  125. package/dist/cobalt/p-593fd213.entry.js +1 -0
  126. package/dist/cobalt/p-5eecea26.entry.js +1 -0
  127. package/dist/cobalt/p-64a0b656.entry.js +1 -0
  128. package/dist/cobalt/p-69289e82.entry.js +1 -0
  129. package/dist/cobalt/p-6a3ed174.entry.js +1 -0
  130. package/dist/cobalt/p-6f12e721.entry.js +1 -0
  131. package/dist/cobalt/{p-3f9b3fcb.entry.js → p-7040e4c5.entry.js} +1 -1
  132. package/dist/cobalt/p-755ecee1.entry.js +1 -0
  133. package/dist/cobalt/p-76b46336.entry.js +1 -0
  134. package/dist/cobalt/p-79e49749.entry.js +1 -0
  135. package/dist/cobalt/p-7b5dec05.entry.js +1 -0
  136. package/dist/cobalt/p-7d9f2021.entry.js +1 -0
  137. package/dist/cobalt/p-804d025f.entry.js +1 -0
  138. package/dist/cobalt/p-860a685f.entry.js +1 -0
  139. package/dist/cobalt/p-87289d32.entry.js +1 -0
  140. package/dist/cobalt/{p-b758c2e6.entry.js → p-8ae5da0c.entry.js} +1 -1
  141. package/dist/cobalt/{p-ff2690e5.entry.js → p-8fdf2163.entry.js} +1 -1
  142. package/dist/cobalt/p-9310739f.entry.js +1 -0
  143. package/dist/cobalt/{p-522fcdb7.entry.js → p-96baec0e.entry.js} +1 -1
  144. package/dist/cobalt/p-B-ckjCUA.js +1 -0
  145. package/dist/cobalt/p-B2QLgWrz.js +2 -0
  146. package/dist/cobalt/p-B6JZk8fL.js +1 -0
  147. package/dist/cobalt/p-BUgUTjOB.js +1 -0
  148. package/dist/cobalt/p-Bgxofdfb.js +1 -0
  149. package/dist/cobalt/p-BxzuCRMr.js +1 -0
  150. package/dist/cobalt/p-Ch1jfwZ2.js +1 -0
  151. package/dist/cobalt/p-ChibIpZv.js +1 -0
  152. package/dist/cobalt/p-Es9IUmmt.js +2 -0
  153. package/dist/cobalt/p-a0749d7b.entry.js +1 -0
  154. package/dist/cobalt/p-a71fd4f1.entry.js +1 -0
  155. package/dist/cobalt/p-aa1ad9fa.entry.js +1 -0
  156. package/dist/cobalt/p-af0495d8.entry.js +1 -0
  157. package/dist/cobalt/p-b045d680.entry.js +1 -0
  158. package/dist/cobalt/p-b3c8fc9a.entry.js +1 -0
  159. package/dist/cobalt/p-b4dcc260.entry.js +1 -0
  160. package/dist/cobalt/p-b8200f7f.entry.js +1 -0
  161. package/dist/cobalt/p-b8f36f12.entry.js +1 -0
  162. package/dist/cobalt/p-ba6f0f90.entry.js +1 -0
  163. package/dist/cobalt/p-bae82095.entry.js +1 -0
  164. package/dist/cobalt/p-be3e61f4.entry.js +1 -0
  165. package/dist/cobalt/p-c1abc74b.entry.js +1 -0
  166. package/dist/cobalt/{p-bb07da22.entry.js → p-c23a2ff6.entry.js} +1 -1
  167. package/dist/cobalt/p-c682453a.entry.js +1 -0
  168. package/dist/cobalt/{p-97c20011.entry.js → p-c857b9ff.entry.js} +1 -1
  169. package/dist/cobalt/{p-54f26e95.entry.js → p-c85a6a9e.entry.js} +1 -1
  170. package/dist/cobalt/p-ca108c6d.entry.js +1 -0
  171. package/dist/cobalt/p-cf239452.entry.js +1 -0
  172. package/dist/cobalt/p-d2507f04.entry.js +1 -0
  173. package/dist/cobalt/p-d403d9c4.entry.js +1 -0
  174. package/dist/cobalt/{p-aa63812a.entry.js → p-d4086c34.entry.js} +1 -1
  175. package/dist/cobalt/p-d55652f2.entry.js +1 -0
  176. package/dist/cobalt/p-d7c9cf93.entry.js +1 -0
  177. package/dist/cobalt/p-d7cbb4c7.entry.js +1 -0
  178. package/dist/cobalt/p-da211abf.entry.js +1 -0
  179. package/dist/cobalt/p-dcc7fc95.entry.js +1 -0
  180. package/dist/cobalt/p-dd03c00b.entry.js +1 -0
  181. package/dist/cobalt/p-e55fb916.entry.js +1 -0
  182. package/dist/cobalt/p-e8e752f9.entry.js +1 -0
  183. package/dist/cobalt/p-e93644cb.entry.js +1 -0
  184. package/dist/cobalt/{p-f0e8fa7d.entry.js → p-f6b93f17.entry.js} +1 -1
  185. package/dist/cobalt/p-f72f0e38.entry.js +1 -0
  186. package/dist/cobalt/{p-beb9c11d.entry.js → p-fb86cdb9.entry.js} +1 -1
  187. package/dist/cobalt/p-ff6be242.entry.js +1 -0
  188. package/dist/cobalt/{p-CyYF8IJE.js → p-tPYikBRJ.js} +1 -1
  189. package/dist/collection/collection-manifest.json +18 -3
  190. package/dist/collection/components/co-accordion/co-accordion.js +2 -2
  191. package/dist/collection/components/co-app-shell/co-app-shell.css +79 -6
  192. package/dist/collection/components/co-app-shell/co-app-shell.js +2 -2
  193. package/dist/collection/components/co-autocomplete/co-autocomplete.css +28 -1
  194. package/dist/collection/components/co-autocomplete/co-autocomplete.js +27 -4
  195. package/dist/collection/components/co-avatar/co-avatar.css +38 -1
  196. package/dist/collection/components/co-avatar/co-avatar.js +48 -3
  197. package/dist/collection/components/co-avatar-group/co-avatar-group.css +86 -0
  198. package/dist/collection/components/co-avatar-group/co-avatar-group.js +224 -0
  199. package/dist/collection/components/co-badge/co-badge.js +1 -1
  200. package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.css +136 -0
  201. package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.js +507 -0
  202. package/dist/collection/components/co-breadcrumb/co-breadcrumb.css +6 -0
  203. package/dist/collection/components/co-breadcrumb/co-breadcrumb.js +111 -0
  204. package/dist/collection/components/co-breadcrumb-item/co-breadcrumb-item.css +66 -0
  205. package/dist/collection/components/co-breadcrumb-item/co-breadcrumb-item.js +169 -0
  206. package/dist/collection/components/co-button/co-button.css +63 -7
  207. package/dist/collection/components/co-button/co-button.js +72 -7
  208. package/dist/collection/components/co-button-group/co-button-group.js +2 -2
  209. package/dist/collection/components/co-calendar/co-calendar.js +1 -1
  210. package/dist/collection/components/co-calendar-month/co-calendar-month.css +231 -0
  211. package/dist/collection/components/co-calendar-month/co-calendar-month.js +594 -0
  212. package/dist/collection/components/co-card/co-card.js +2 -2
  213. package/dist/collection/components/co-checkbox/co-checkbox.css +70 -1
  214. package/dist/collection/components/co-checkbox/co-checkbox.js +58 -7
  215. package/dist/collection/components/co-checkbox-group/co-checkbox-group.css +7 -1
  216. package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +3 -3
  217. package/dist/collection/components/co-chip/co-chip.css +82 -7
  218. package/dist/collection/components/co-chip/co-chip.js +102 -17
  219. package/dist/collection/components/co-color-picker/co-color-picker.css +35 -1
  220. package/dist/collection/components/co-color-picker/co-color-picker.js +24 -2
  221. package/dist/collection/components/co-column-picker/co-column-picker.js +2 -2
  222. package/dist/collection/components/co-combobox/co-combobox.css +7 -47
  223. package/dist/collection/components/co-combobox/co-combobox.js +4 -4
  224. package/dist/collection/components/co-command-search/co-command-search.css +163 -1
  225. package/dist/collection/components/co-command-search/co-command-search.js +355 -14
  226. package/dist/collection/components/co-command-search/commandSearchGroup.js +17 -0
  227. package/dist/collection/components/co-command-search/commandSearchLogic.js +27 -0
  228. package/dist/collection/components/co-data-table/co-data-table.css +42 -2
  229. package/dist/collection/components/co-data-table/co-data-table.js +116 -23
  230. package/dist/collection/components/co-data-table-pagination/co-data-table-pagination.js +4 -4
  231. package/dist/collection/components/co-date-field/co-date-field.css +7 -1
  232. package/dist/collection/components/co-date-field/co-date-field.js +4 -4
  233. package/dist/collection/components/co-date-range/co-date-range.js +1 -1
  234. package/dist/collection/components/co-date-range-picker/co-date-range-picker.css +7 -1
  235. package/dist/collection/components/co-drawer/co-drawer.css +21 -3
  236. package/dist/collection/components/co-drawer/co-drawer.js +52 -2
  237. package/dist/collection/components/co-drive-card/co-drive-card.css +285 -0
  238. package/dist/collection/components/co-drive-card/co-drive-card.js +329 -0
  239. package/dist/collection/components/co-drop-zone/co-drop-zone.css +49 -0
  240. package/dist/collection/components/co-drop-zone/co-drop-zone.js +197 -0
  241. package/dist/collection/components/co-empty-state/co-empty-state.css +38 -0
  242. package/dist/collection/components/co-empty-state/co-empty-state.js +72 -1
  243. package/dist/collection/components/co-event-calendar/co-event-calendar.css +146 -0
  244. package/dist/collection/components/co-event-calendar/co-event-calendar.js +620 -0
  245. package/dist/collection/components/co-fab/co-fab.js +2 -2
  246. package/dist/collection/components/co-file-field/co-file-field.css +7 -1
  247. package/dist/collection/components/co-file-field/co-file-field.js +5 -5
  248. package/dist/collection/components/co-file-type-tile/co-file-type-tile.css +14 -0
  249. package/dist/collection/components/co-file-type-tile/co-file-type-tile.js +164 -0
  250. package/dist/collection/components/co-helper-text/co-helper-text.js +2 -2
  251. package/dist/collection/components/co-icon/co-icon.js +7 -37
  252. package/dist/collection/components/co-icon/iconLoader.js +39 -0
  253. package/dist/collection/components/co-icon-button/co-icon-button.css +26 -8
  254. package/dist/collection/components/co-icon-button/co-icon-button.js +82 -8
  255. package/dist/collection/components/co-input/co-input.css +65 -1
  256. package/dist/collection/components/co-input/co-input.js +54 -5
  257. package/dist/collection/components/co-json-field/co-json-field.css +25 -1
  258. package/dist/collection/components/co-json-field/co-json-field.js +27 -3
  259. package/dist/collection/components/co-lightbox/co-lightbox.js +4 -4
  260. package/dist/collection/components/co-list-footer/co-list-footer.css +50 -0
  261. package/dist/collection/components/co-list-footer/co-list-footer.js +149 -0
  262. package/dist/collection/components/co-list-item/co-list-item.css +7 -0
  263. package/dist/collection/components/co-list-item/co-list-item.js +65 -2
  264. package/dist/collection/components/co-loader/co-loader.css +9 -0
  265. package/dist/collection/components/co-media-thumb/co-media-thumb.css +43 -0
  266. package/dist/collection/components/co-media-thumb/co-media-thumb.js +148 -0
  267. package/dist/collection/components/co-menu/co-menu.css +6 -4
  268. package/dist/collection/components/co-menu/co-menu.js +20 -1
  269. package/dist/collection/components/co-menu-divider/co-menu-divider.js +1 -1
  270. package/dist/collection/components/co-menu-item/co-menu-item.css +44 -8
  271. package/dist/collection/components/co-menu-item/co-menu-item.js +84 -10
  272. package/dist/collection/components/co-modal/co-modal.css +59 -2
  273. package/dist/collection/components/co-modal/co-modal.js +99 -6
  274. package/dist/collection/components/co-navbar/co-navbar.js +2 -2
  275. package/dist/collection/components/co-number-field/co-number-field.css +19 -1
  276. package/dist/collection/components/co-number-field/co-number-field.js +34 -3
  277. package/dist/collection/components/co-option-list/co-option-list.css +228 -0
  278. package/dist/collection/components/co-option-list/co-option-list.js +860 -0
  279. package/dist/collection/components/co-option-list/optionListLogic.js +100 -0
  280. package/dist/collection/components/co-overlay/co-overlay.css +15 -1
  281. package/dist/collection/components/co-overlay/co-overlay.js +266 -1
  282. package/dist/collection/components/co-overlay/focusTrap.js +53 -0
  283. package/dist/collection/components/co-overlay/overlayAfterClose.js +8 -0
  284. package/dist/collection/components/co-page-header/co-page-header.js +1 -1
  285. package/dist/collection/components/co-phone-field/co-phone-field.css +30 -2
  286. package/dist/collection/components/co-phone-field/co-phone-field.js +23 -1
  287. package/dist/collection/components/co-popover/co-popover.css +9 -0
  288. package/dist/collection/components/co-popover/co-popover.js +43 -12
  289. package/dist/collection/components/co-progress-bar/co-progress-bar.css +22 -0
  290. package/dist/collection/components/co-progress-bar/co-progress-bar.js +26 -2
  291. package/dist/collection/components/co-progress-circle/co-progress-circle.js +2 -2
  292. package/dist/collection/components/co-radio/co-radio.js +3 -3
  293. package/dist/collection/components/co-radio-group/co-radio-group.js +3 -3
  294. package/dist/collection/components/co-rating/co-rating.js +3 -3
  295. package/dist/collection/components/co-ref-field/co-ref-field.css +64 -6
  296. package/dist/collection/components/co-ref-field/co-ref-field.js +0 -0
  297. package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.css +1125 -41
  298. package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.js +2008 -53
  299. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.css +791 -9
  300. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.js +1071 -71
  301. package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.css +78 -0
  302. package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.js +46 -41
  303. package/dist/collection/components/co-row/co-row.js +2 -2
  304. package/dist/collection/components/co-segmented-bar/co-segmented-bar.css +36 -0
  305. package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +176 -0
  306. package/dist/collection/components/co-select/co-select.css +7 -1
  307. package/dist/collection/components/co-select/co-select.js +5 -5
  308. package/dist/collection/components/co-separator/co-separator.js +1 -1
  309. package/dist/collection/components/co-sidebar/co-sidebar.js +2 -2
  310. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.css +99 -12
  311. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +28 -8
  312. package/dist/collection/components/co-skeleton/co-skeleton.css +28 -0
  313. package/dist/collection/components/co-skeleton/co-skeleton.js +97 -0
  314. package/dist/collection/components/co-slider/co-slider.js +2 -2
  315. package/dist/collection/components/co-switch/co-switch.css +9 -1
  316. package/dist/collection/components/co-switch/co-switch.js +3 -3
  317. package/dist/collection/components/co-tab/co-tab.css +54 -3
  318. package/dist/collection/components/co-tab/co-tab.js +45 -3
  319. package/dist/collection/components/co-tab-group/co-tab-group.css +8 -0
  320. package/dist/collection/components/co-tab-group/co-tab-group.js +35 -1
  321. package/dist/collection/components/co-tags-field/co-tags-field.css +39 -1
  322. package/dist/collection/components/co-tags-field/co-tags-field.js +36 -10
  323. package/dist/collection/components/co-textarea/co-textarea.css +26 -1
  324. package/dist/collection/components/co-textarea/co-textarea.js +28 -4
  325. package/dist/collection/components/co-toast/co-toast.css +56 -2
  326. package/dist/collection/components/co-toast/co-toast.js +27 -2
  327. package/dist/collection/components/co-toggle-button/co-toggle-button.css +64 -4
  328. package/dist/collection/components/co-toggle-button/co-toggle-button.js +47 -4
  329. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.css +32 -12
  330. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.js +34 -2
  331. package/dist/collection/components/co-tooltip/co-tooltip.css +8 -0
  332. package/dist/collection/components/co-tooltip/co-tooltip.js +69 -14
  333. package/dist/collection/components/co-transfer-list/co-transfer-list.js +2 -2
  334. package/dist/collection/components/co-video/co-video.css +497 -0
  335. package/dist/collection/components/co-video/co-video.js +1772 -0
  336. package/dist/collection/utils/fieldChip.js +2 -0
  337. package/dist/collection/utils/icon-config.js +12 -0
  338. package/dist/collection/utils/richTextI18n.js +378 -0
  339. package/dist/collection/utils/sheetGesture.js +53 -0
  340. package/dist/components/co-accordion.js +1 -1
  341. package/dist/components/co-app-shell.js +1 -1
  342. package/dist/components/co-autocomplete.js +1 -1
  343. package/dist/components/co-avatar-group.d.ts +11 -0
  344. package/dist/components/co-avatar-group.js +1 -0
  345. package/dist/components/co-avatar.js +1 -1
  346. package/dist/components/co-badge.js +1 -1
  347. package/dist/components/co-bottom-sheet.d.ts +11 -0
  348. package/dist/components/co-bottom-sheet.js +1 -0
  349. package/dist/components/co-breadcrumb-item.d.ts +11 -0
  350. package/dist/components/co-breadcrumb-item.js +1 -0
  351. package/dist/components/co-breadcrumb.d.ts +11 -0
  352. package/dist/components/co-breadcrumb.js +1 -0
  353. package/dist/components/co-button-group.js +1 -1
  354. package/dist/components/co-button.js +1 -1
  355. package/dist/components/co-calendar-month.d.ts +11 -0
  356. package/dist/components/co-calendar-month.js +1 -0
  357. package/dist/components/co-calendar.js +1 -1
  358. package/dist/components/co-card.js +1 -1
  359. package/dist/components/co-checkbox-group.js +1 -1
  360. package/dist/components/co-checkbox.js +1 -1
  361. package/dist/components/co-chip.js +1 -1
  362. package/dist/components/co-color-picker.js +1 -1
  363. package/dist/components/co-column-picker.js +1 -1
  364. package/dist/components/co-combobox.js +1 -1
  365. package/dist/components/co-command-search.js +1 -1
  366. package/dist/components/co-data-table-pagination.js +1 -1
  367. package/dist/components/co-data-table.js +1 -1
  368. package/dist/components/co-date-field.js +1 -1
  369. package/dist/components/co-date-picker.js +1 -1
  370. package/dist/components/co-date-range-picker.js +1 -1
  371. package/dist/components/co-date-range.js +1 -1
  372. package/dist/components/co-drawer.js +1 -1
  373. package/dist/components/co-drive-card.d.ts +11 -0
  374. package/dist/components/co-drive-card.js +1 -0
  375. package/dist/components/co-drop-zone.d.ts +11 -0
  376. package/dist/components/co-drop-zone.js +1 -0
  377. package/dist/components/co-empty-state.js +1 -1
  378. package/dist/components/co-event-calendar.d.ts +11 -0
  379. package/dist/components/co-event-calendar.js +1 -0
  380. package/dist/components/co-fab.js +1 -1
  381. package/dist/components/co-file-field.js +1 -1
  382. package/dist/components/co-file-type-tile.d.ts +11 -0
  383. package/dist/components/co-file-type-tile.js +1 -0
  384. package/dist/components/co-helper-text.js +1 -1
  385. package/dist/components/co-icon-button.js +1 -1
  386. package/dist/components/co-icon.js +1 -1
  387. package/dist/components/co-input.js +1 -1
  388. package/dist/components/co-json-field.js +1 -1
  389. package/dist/components/co-lightbox.js +1 -1
  390. package/dist/components/co-list-footer.d.ts +11 -0
  391. package/dist/components/co-list-footer.js +1 -0
  392. package/dist/components/co-list-item.js +1 -1
  393. package/dist/components/co-loader.js +1 -1
  394. package/dist/components/co-media-thumb.d.ts +11 -0
  395. package/dist/components/co-media-thumb.js +1 -0
  396. package/dist/components/co-menu-divider.js +1 -1
  397. package/dist/components/co-menu-item.js +1 -1
  398. package/dist/components/co-menu.js +1 -1
  399. package/dist/components/co-modal.js +1 -1
  400. package/dist/components/co-navbar.js +1 -1
  401. package/dist/components/co-number-field.js +1 -1
  402. package/dist/components/co-option-list.d.ts +11 -0
  403. package/dist/components/co-option-list.js +1 -0
  404. package/dist/components/co-overlay.js +1 -1
  405. package/dist/components/co-page-header.js +1 -1
  406. package/dist/components/co-phone-field.js +1 -1
  407. package/dist/components/co-popover.js +1 -1
  408. package/dist/components/co-progress-bar.js +1 -1
  409. package/dist/components/co-progress-circle.js +1 -1
  410. package/dist/components/co-radio-group.js +1 -1
  411. package/dist/components/co-radio.js +1 -1
  412. package/dist/components/co-rating.js +1 -1
  413. package/dist/components/co-ref-field.js +1 -1
  414. package/dist/components/co-rich-text-editor.js +1 -1
  415. package/dist/components/co-rich-text-toolbar.js +1 -1
  416. package/dist/components/co-rich-text-viewer.js +1 -1
  417. package/dist/components/co-row.js +1 -1
  418. package/dist/components/co-segmented-bar.d.ts +11 -0
  419. package/dist/components/co-segmented-bar.js +1 -0
  420. package/dist/components/co-select.js +1 -1
  421. package/dist/components/co-separator.js +1 -1
  422. package/dist/components/co-sidebar-nav.js +1 -1
  423. package/dist/components/co-sidebar.js +1 -1
  424. package/dist/components/co-skeleton.d.ts +11 -0
  425. package/dist/components/co-skeleton.js +1 -0
  426. package/dist/components/co-slider.js +1 -1
  427. package/dist/components/co-switch.js +1 -1
  428. package/dist/components/co-tab-group.js +1 -1
  429. package/dist/components/co-tab.js +1 -1
  430. package/dist/components/co-tags-field.js +1 -1
  431. package/dist/components/co-textarea.js +1 -1
  432. package/dist/components/co-toast.js +1 -1
  433. package/dist/components/co-toggle-button-group.js +1 -1
  434. package/dist/components/co-toggle-button.js +1 -1
  435. package/dist/components/co-tooltip.js +1 -1
  436. package/dist/components/co-transfer-list.js +1 -1
  437. package/dist/components/co-video.d.ts +11 -0
  438. package/dist/components/co-video.js +1 -0
  439. package/dist/components/index.js +1 -1
  440. package/dist/components/p-B0buzt_E.js +1 -0
  441. package/dist/components/p-B2QLgWrz.js +2 -0
  442. package/dist/components/p-B3igDRut.js +1 -0
  443. package/dist/components/p-Bgxofdfb.js +1 -0
  444. package/dist/components/p-BhSJcOUS.js +1 -0
  445. package/dist/components/{p-DObrQi5F.js → p-BnTTeIFH.js} +1 -1
  446. package/dist/components/{p-C9tHLXKS.js → p-Bx1OwdIV.js} +1 -1
  447. package/dist/components/p-BxiKVtk4.js +1 -0
  448. package/dist/components/p-C7tPadNy.js +1 -0
  449. package/dist/components/p-CBzpUqwG.js +1 -0
  450. package/dist/components/p-CUvAZhuM.js +1 -0
  451. package/dist/components/p-CZKHHCdL.js +1 -0
  452. package/dist/components/p-ChibIpZv.js +1 -0
  453. package/dist/components/p-CybHxq25.js +1 -0
  454. package/dist/components/p-CzkeIavk.js +1 -0
  455. package/dist/components/p-D7dk2gM7.js +1 -0
  456. package/dist/components/p-DTS-dgEe.js +1 -0
  457. package/dist/components/p-DvhR3H61.js +1 -0
  458. package/dist/components/{p-OGpfa9Yd.js → p-DzoNGEDU.js} +1 -1
  459. package/dist/components/{p-BeWXpX8I.js → p-HXlAaApx.js} +1 -1
  460. package/dist/components/p-K6LC1Hz4.js +1 -0
  461. package/dist/components/p-LAxCvyJl.js +1 -0
  462. package/dist/components/p-vLFwJ77w.js +1 -0
  463. package/dist/esm/co-accordion.entry.js +3 -3
  464. package/dist/esm/co-app-shell.entry.js +4 -4
  465. package/dist/esm/co-autocomplete.entry.js +10 -7
  466. package/dist/esm/co-avatar-group.entry.js +75 -0
  467. package/dist/esm/co-avatar.entry.js +12 -5
  468. package/dist/esm/co-badge.entry.js +2 -2
  469. package/dist/esm/co-bottom-sheet.entry.js +323 -0
  470. package/dist/esm/co-breadcrumb-item.entry.js +35 -0
  471. package/dist/esm/co-breadcrumb.entry.js +53 -0
  472. package/dist/esm/co-button-group.entry.js +3 -3
  473. package/dist/esm/co-button.entry.js +12 -6
  474. package/dist/esm/co-calendar-month.entry.js +379 -0
  475. package/dist/esm/co-calendar_3.entry.js +42 -12
  476. package/dist/esm/co-card.entry.js +3 -3
  477. package/dist/esm/co-checkbox-group.entry.js +5 -5
  478. package/dist/esm/co-checkbox.entry.js +18 -6
  479. package/dist/esm/co-chip.entry.js +19 -11
  480. package/dist/esm/co-color-picker.entry.js +7 -5
  481. package/dist/esm/co-column-picker.entry.js +3 -3
  482. package/dist/esm/co-combobox.entry.js +7 -7
  483. package/dist/esm/co-command-search.entry.js +151 -12
  484. package/dist/esm/co-data-table-pagination.entry.js +5 -5
  485. package/dist/esm/co-data-table.entry.js +44 -23
  486. package/dist/esm/co-date-picker.entry.js +2 -2
  487. package/dist/esm/co-date-range-picker.entry.js +4 -4
  488. package/dist/esm/co-date-range.entry.js +2 -2
  489. package/dist/esm/co-drive-card.entry.js +79 -0
  490. package/dist/esm/co-drop-zone.entry.js +61 -0
  491. package/dist/esm/co-empty-state.entry.js +13 -3
  492. package/dist/esm/co-event-calendar.entry.js +316 -0
  493. package/dist/esm/co-fab.entry.js +3 -3
  494. package/dist/esm/co-file-field.entry.js +8 -8
  495. package/dist/esm/co-file-type-tile.entry.js +76 -0
  496. package/dist/esm/co-helper-text.entry.js +3 -3
  497. package/dist/esm/co-icon-button.entry.js +24 -8
  498. package/dist/esm/co-icon.entry.js +33 -25
  499. package/dist/esm/co-input.entry.js +36 -7
  500. package/dist/esm/co-json-field.entry.js +10 -6
  501. package/dist/esm/co-lightbox.entry.js +5 -5
  502. package/dist/esm/co-list-footer.entry.js +23 -0
  503. package/dist/esm/co-list-item.entry.js +60 -4
  504. package/dist/esm/co-loader.entry.js +2 -2
  505. package/dist/esm/co-media-thumb.entry.js +34 -0
  506. package/dist/esm/co-menu-divider.entry.js +2 -2
  507. package/dist/esm/co-menu-item.entry.js +26 -11
  508. package/dist/esm/co-menu.entry.js +3 -3
  509. package/dist/esm/co-modal.entry.js +41 -5
  510. package/dist/esm/co-navbar.entry.js +3 -3
  511. package/dist/esm/co-number-field.entry.js +18 -6
  512. package/dist/esm/co-option-list.entry.js +377 -0
  513. package/dist/esm/co-overlay.entry.js +243 -3
  514. package/dist/esm/co-page-header.entry.js +2 -2
  515. package/dist/esm/co-phone-field.entry.js +6 -4
  516. package/dist/esm/co-popover.entry.js +45 -14
  517. package/dist/esm/co-progress-bar.entry.js +8 -4
  518. package/dist/esm/co-progress-circle.entry.js +3 -3
  519. package/dist/esm/co-radio-group.entry.js +4 -4
  520. package/dist/esm/co-radio.entry.js +4 -4
  521. package/dist/esm/co-rating.entry.js +4 -4
  522. package/dist/esm/co-ref-field.entry.js +36 -13
  523. package/dist/esm/co-rich-text-editor.entry.js +1879 -33
  524. package/dist/esm/co-rich-text-toolbar.entry.js +995 -71
  525. package/dist/esm/co-rich-text-viewer.entry.js +55 -19
  526. package/dist/esm/co-row.entry.js +3 -3
  527. package/dist/esm/co-segmented-bar.entry.js +56 -0
  528. package/dist/esm/co-select.entry.js +8 -8
  529. package/dist/esm/co-separator.entry.js +2 -2
  530. package/dist/esm/co-sidebar-nav.entry.js +29 -9
  531. package/dist/esm/co-sidebar.entry.js +3 -3
  532. package/dist/esm/co-skeleton.entry.js +24 -0
  533. package/dist/esm/co-slider.entry.js +3 -3
  534. package/dist/esm/co-switch.entry.js +6 -6
  535. package/dist/esm/co-tab-group.entry.js +15 -3
  536. package/dist/esm/co-tab.entry.js +8 -5
  537. package/dist/esm/co-tags-field.entry.js +19 -13
  538. package/dist/esm/co-textarea.entry.js +11 -7
  539. package/dist/esm/co-toast.entry.js +10 -4
  540. package/dist/esm/co-toggle-button-group.entry.js +16 -4
  541. package/dist/esm/co-toggle-button.entry.js +9 -5
  542. package/dist/esm/co-tooltip.entry.js +51 -16
  543. package/dist/esm/co-transfer-list.entry.js +3 -3
  544. package/dist/esm/co-video.entry.js +837 -0
  545. package/dist/esm/cobalt.js +3 -3
  546. package/dist/esm/{dates-CyYF8IJE.js → dates-tPYikBRJ.js} +1 -1
  547. package/dist/esm/fieldChip-BBu4ukje.js +5 -0
  548. package/dist/{cjs/index-CaEJnpZe.js → esm/index-Cyrxk8Qq.js} +14437 -6194
  549. package/dist/esm/{index-BKmfyPZK.js → index-Es9IUmmt.js} +105 -21
  550. package/dist/esm/loader.js +3 -3
  551. package/dist/esm/overlayAfterClose-Ch1jfwZ2.js +10 -0
  552. package/dist/{cjs/sanitizer-CjHZAkOm.js → esm/purify.es-B2QLgWrz.js} +1 -110
  553. package/dist/esm/{requiredMark-DFvtYtkE.js → requiredMark-Bg25QWFn.js} +1 -1
  554. package/dist/esm/richTextI18n-B-ckjCUA.js +380 -0
  555. package/dist/esm/toolbar-config-ChibIpZv.js +212 -0
  556. package/dist/esm/tz-B6JZk8fL.js +119 -0
  557. package/dist/types/components/co-autocomplete/co-autocomplete.d.ts +2 -0
  558. package/dist/types/components/co-avatar/co-avatar.d.ts +4 -0
  559. package/dist/types/components/co-avatar-group/co-avatar-group.d.ts +33 -0
  560. package/dist/types/components/co-bottom-sheet/co-bottom-sheet.d.ts +81 -0
  561. package/dist/types/components/co-breadcrumb/co-breadcrumb.d.ts +27 -0
  562. package/dist/types/components/co-breadcrumb-item/co-breadcrumb-item.d.ts +33 -0
  563. package/dist/types/components/co-button/co-button.d.ts +7 -1
  564. package/dist/types/components/co-calendar-month/co-calendar-month.d.ts +83 -0
  565. package/dist/types/components/co-checkbox/co-checkbox.d.ts +10 -2
  566. package/dist/types/components/co-chip/co-chip.d.ts +22 -5
  567. package/dist/types/components/co-color-picker/co-color-picker.d.ts +2 -0
  568. package/dist/types/components/co-command-search/co-command-search.d.ts +39 -6
  569. package/dist/types/components/co-command-search/commandSearchGroup.d.ts +20 -0
  570. package/dist/types/components/co-command-search/commandSearchLogic.d.ts +17 -0
  571. package/dist/types/components/co-data-table/co-data-table.d.ts +15 -2
  572. package/dist/types/components/co-drawer/co-drawer.d.ts +12 -0
  573. package/dist/types/components/co-drive-card/co-drive-card.d.ts +52 -0
  574. package/dist/types/components/co-drop-zone/co-drop-zone.d.ts +38 -0
  575. package/dist/types/components/co-empty-state/co-empty-state.d.ts +6 -0
  576. package/dist/types/components/co-event-calendar/co-event-calendar.d.ts +110 -0
  577. package/dist/types/components/co-file-type-tile/co-file-type-tile.d.ts +11 -0
  578. package/dist/types/components/co-icon/co-icon.d.ts +1 -1
  579. package/dist/types/components/co-icon/iconLoader.d.ts +6 -0
  580. package/dist/types/components/co-icon-button/co-icon-button.d.ts +18 -1
  581. package/dist/types/components/co-input/co-input.d.ts +13 -1
  582. package/dist/types/components/co-json-field/co-json-field.d.ts +3 -0
  583. package/dist/types/components/co-list-footer/co-list-footer.d.ts +26 -0
  584. package/dist/types/components/co-list-item/co-list-item.d.ts +11 -0
  585. package/dist/types/components/co-media-thumb/co-media-thumb.d.ts +21 -0
  586. package/dist/types/components/co-menu/co-menu.d.ts +4 -0
  587. package/dist/types/components/co-menu-item/co-menu-item.d.ts +10 -1
  588. package/dist/types/components/co-modal/co-modal.d.ts +26 -2
  589. package/dist/types/components/co-number-field/co-number-field.d.ts +13 -0
  590. package/dist/types/components/co-option-list/co-option-list.d.ts +101 -0
  591. package/dist/types/components/co-option-list/optionListLogic.d.ts +69 -0
  592. package/dist/types/components/co-overlay/co-overlay.d.ts +45 -0
  593. package/dist/types/components/co-overlay/focusTrap.d.ts +20 -0
  594. package/dist/types/components/co-overlay/overlayAfterClose.d.ts +5 -0
  595. package/dist/types/components/co-phone-field/co-phone-field.d.ts +2 -0
  596. package/dist/types/components/co-popover/co-popover.d.ts +9 -0
  597. package/dist/types/components/co-progress-bar/co-progress-bar.d.ts +2 -0
  598. package/dist/types/components/co-ref-field/co-ref-field.d.ts +17 -2
  599. package/dist/types/components/co-rich-text-editor/co-rich-text-editor.d.ts +161 -9
  600. package/dist/types/components/co-rich-text-toolbar/co-rich-text-toolbar.d.ts +119 -13
  601. package/dist/types/components/co-rich-text-viewer/co-rich-text-viewer.d.ts +1 -14
  602. package/dist/types/components/co-segmented-bar/co-segmented-bar.d.ts +32 -0
  603. package/dist/types/components/co-skeleton/co-skeleton.d.ts +13 -0
  604. package/dist/types/components/co-tab/co-tab.d.ts +4 -0
  605. package/dist/types/components/co-tab-group/co-tab-group.d.ts +3 -0
  606. package/dist/types/components/co-tags-field/co-tags-field.d.ts +2 -0
  607. package/dist/types/components/co-textarea/co-textarea.d.ts +3 -0
  608. package/dist/types/components/co-toast/co-toast.d.ts +7 -0
  609. package/dist/types/components/co-toggle-button/co-toggle-button.d.ts +6 -0
  610. package/dist/types/components/co-toggle-button-group/co-toggle-button-group.d.ts +5 -0
  611. package/dist/types/components/co-tooltip/co-tooltip.d.ts +12 -0
  612. package/dist/types/components/co-video/co-video.d.ts +203 -0
  613. package/dist/types/components.d.ts +3184 -221
  614. package/dist/types/utils/fieldChip.d.ts +37 -0
  615. package/dist/types/utils/icon-config.d.ts +11 -0
  616. package/dist/types/utils/richTextI18n.d.ts +130 -0
  617. package/dist/types/utils/sheetGesture.d.ts +31 -0
  618. package/package.json +5 -4
  619. package/dist/cobalt/p-01fc77c4.entry.js +0 -1
  620. package/dist/cobalt/p-0a6d8061.entry.js +0 -1
  621. package/dist/cobalt/p-0bf288cd.entry.js +0 -1
  622. package/dist/cobalt/p-15708d32.entry.js +0 -1
  623. package/dist/cobalt/p-1578b019.entry.js +0 -1
  624. package/dist/cobalt/p-23d48581.entry.js +0 -1
  625. package/dist/cobalt/p-2718ff27.entry.js +0 -1
  626. package/dist/cobalt/p-3190d715.entry.js +0 -1
  627. package/dist/cobalt/p-41228dce.entry.js +0 -1
  628. package/dist/cobalt/p-44672953.entry.js +0 -1
  629. package/dist/cobalt/p-53ce9023.entry.js +0 -1
  630. package/dist/cobalt/p-5d01bd4d.entry.js +0 -1
  631. package/dist/cobalt/p-5e7141aa.entry.js +0 -1
  632. package/dist/cobalt/p-5f905739.entry.js +0 -1
  633. package/dist/cobalt/p-6404bd21.entry.js +0 -1
  634. package/dist/cobalt/p-654bbc2a.entry.js +0 -1
  635. package/dist/cobalt/p-6678ac0a.entry.js +0 -1
  636. package/dist/cobalt/p-66a912dd.entry.js +0 -1
  637. package/dist/cobalt/p-6759ee1c.entry.js +0 -1
  638. package/dist/cobalt/p-69a40bfd.entry.js +0 -1
  639. package/dist/cobalt/p-6a6a62cb.entry.js +0 -1
  640. package/dist/cobalt/p-6d43b6cd.entry.js +0 -1
  641. package/dist/cobalt/p-759c3dd0.entry.js +0 -1
  642. package/dist/cobalt/p-782f729f.entry.js +0 -1
  643. package/dist/cobalt/p-83b89bf8.entry.js +0 -1
  644. package/dist/cobalt/p-88dc561a.entry.js +0 -1
  645. package/dist/cobalt/p-8c27aff7.entry.js +0 -1
  646. package/dist/cobalt/p-95d14878.entry.js +0 -1
  647. package/dist/cobalt/p-996179f7.entry.js +0 -1
  648. package/dist/cobalt/p-9c533830.entry.js +0 -1
  649. package/dist/cobalt/p-9d89bf47.entry.js +0 -1
  650. package/dist/cobalt/p-BKmfyPZK.js +0 -2
  651. package/dist/cobalt/p-BchB6Hdr.js +0 -1
  652. package/dist/cobalt/p-DcK0GGZC.js +0 -2
  653. package/dist/cobalt/p-Qqq8fysz.js +0 -1
  654. package/dist/cobalt/p-aa17c70b.entry.js +0 -1
  655. package/dist/cobalt/p-ad4c1b41.entry.js +0 -1
  656. package/dist/cobalt/p-ae4d3207.entry.js +0 -1
  657. package/dist/cobalt/p-af64da37.entry.js +0 -1
  658. package/dist/cobalt/p-c6a242e4.entry.js +0 -1
  659. package/dist/cobalt/p-cd57e8b4.entry.js +0 -1
  660. package/dist/cobalt/p-ce3a535f.entry.js +0 -1
  661. package/dist/cobalt/p-d17e1444.entry.js +0 -1
  662. package/dist/cobalt/p-d958566a.entry.js +0 -1
  663. package/dist/cobalt/p-dd873bf8.entry.js +0 -1
  664. package/dist/cobalt/p-e4de8865.entry.js +0 -1
  665. package/dist/cobalt/p-eba0bf7f.entry.js +0 -1
  666. package/dist/cobalt/p-f8728b21.entry.js +0 -1
  667. package/dist/cobalt/p-fad3605d.entry.js +0 -1
  668. package/dist/components/p-BXdfh__-.js +0 -1
  669. package/dist/components/p-BchB6Hdr.js +0 -1
  670. package/dist/components/p-BiW0ubLs.js +0 -1
  671. package/dist/components/p-CaMgu2_g.js +0 -1
  672. package/dist/components/p-DBhNS7JD.js +0 -1
  673. package/dist/components/p-DPi_U-Kl.js +0 -1
  674. package/dist/components/p-DcK0GGZC.js +0 -2
  675. package/dist/components/p-MiSJXuBx.js +0 -1
  676. package/dist/components/p-Sgn-2g8m.js +0 -1
  677. package/dist/components/p-jDjfGZJp.js +0 -1
  678. package/dist/components/p-o8hrDIKe.js +0 -1
@@ -1,7 +1,10 @@
1
- import { r as registerInstance, c as createEvent, h, a as getElement } from './index-BKmfyPZK.js';
2
- import { R as RequiredMark } from './requiredMark-DFvtYtkE.js';
1
+ import { r as registerInstance, c as createEvent, h, a as getElement } from './index-Es9IUmmt.js';
2
+ import { R as RichText } from './index-Cyrxk8Qq.js';
3
+ import { g as getRichTextStrings } from './richTextI18n-B-ckjCUA.js';
4
+ import './purify.es-B2QLgWrz.js';
5
+ import './toolbar-config-ChibIpZv.js';
3
6
 
4
- const coRichTextEditorCss = () => `co-rich-text-editor{display:block;font-family:var(--co-font-family-primary);font-size:var(--co-font-size-14);letter-spacing:var(--co-font-letter-spacing-body)}.co-rich-text-editor{display:flex;flex-direction:column;gap:var(--co-spacing-sm2, 6px)}.co-rich-text-editor__labels{display:flex;align-items:center;justify-content:space-between;padding:0 var(--co-spacing-xs);gap:var(--co-spacing-sm2, 6px)}.co-rich-text-editor__label,.co-rich-text-editor__secondary-label{color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-14);font-weight:400;line-height:1}.co-rich-text-editor__box{display:flex;flex-direction:column;background:var(--co-semantic-surface-secondary);border:1px solid var(--co-semantic-border-subtle);border-radius:var(--co-border-radius-xs);transition:border-color 0.15s ease, box-shadow 0.15s ease;overflow:hidden}.co-rich-text-editor--focused .co-rich-text-editor__box{border-color:var(--co-semantic-border-focus, var(--co-color-primary-azul));box-shadow:0 0 0 3px var(--co-semantic-border-focus-ring, rgba(37, 99, 235, 0.15))}.co-rich-text-editor--error .co-rich-text-editor__box{border-color:var(--co-color-status-error)}.co-rich-text-editor--success .co-rich-text-editor__box{border-color:var(--co-color-status-success)}.co-rich-text-editor--disabled .co-rich-text-editor__box,.co-rich-text-editor--readonly .co-rich-text-editor__box{opacity:0.7;cursor:not-allowed}.co-rich-text-editor--loading .co-rte-content{min-height:96px;background:linear-gradient(90deg, var(--co-semantic-surface-secondary) 0%, var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.04)) 50%, var(--co-semantic-surface-secondary) 100%);background-size:200% 100%;animation:co-rte-skeleton 1.2s ease-in-out infinite}@keyframes co-rte-skeleton{0%{background-position:200% 0}100%{background-position:-200% 0}}.co-rte-content{padding:var(--co-spacing-md) var(--co-spacing-md);min-height:96px;color:var(--co-semantic-text-default)}.co-rte-content .ProseMirror{outline:none;min-height:72px;line-height:1.5}.co-rte-content .ProseMirror p{margin:0 0 var(--co-spacing-sm) 0}.co-rte-content .ProseMirror p:last-child{margin-bottom:0}.co-rte-content .ProseMirror h2,.co-rte-content .ProseMirror h3,.co-rte-content .ProseMirror h4{margin:var(--co-spacing-md) 0 var(--co-spacing-sm);font-weight:600;line-height:1.3}.co-rte-content .ProseMirror h2{font-size:var(--co-font-size-20, 20px)}.co-rte-content .ProseMirror h3{font-size:var(--co-font-size-16, 16px)}.co-rte-content .ProseMirror ul,.co-rte-content .ProseMirror ol{padding-left:var(--co-spacing-xl);margin:0 0 var(--co-spacing-sm) 0}.co-rte-content .ProseMirror blockquote{border-left:3px solid var(--co-semantic-border-default, var(--co-semantic-border-subtle));padding-left:var(--co-spacing-md);margin:0 0 var(--co-spacing-sm) 0;color:var(--co-semantic-text-secondary)}.co-rte-content .ProseMirror a{color:var(--co-color-primary-azul);text-decoration:underline}.co-rte-content .ProseMirror img{max-width:100%;height:auto;border-radius:var(--co-border-radius-xs);margin:var(--co-spacing-sm) 0}.co-rte-content .ProseMirror img.ProseMirror-selectednode{outline:2px solid var(--co-semantic-border-focus, var(--co-color-primary-azul))}.co-rte-content .ProseMirror code{font-family:var(--co-font-family-mono);font-size:0.9em;background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06));padding:0.1em 0.3em;border-radius:var(--co-border-radius-xxs)}.co-rte-content .ProseMirror p.is-editor-empty:first-child::before{content:attr(data-placeholder);color:var(--co-semantic-text-muted);float:left;height:0;pointer-events:none}.co-rte-content .co-rte-variable,.co-rte-content .co-rte-mention{display:inline-block;padding:0.05em 0.4em;border-radius:var(--co-border-radius-xxs);background:var(--co-color-primary-azul);color:var(--co-color-base-blanco, #fff);font-size:0.9em;white-space:nowrap}.co-rte-content .co-rte-mention{background:var(--co-color-primary-verde)}.co-rich-text-editor__footer{display:flex;align-items:center;justify-content:space-between;gap:var(--co-spacing-sm);padding:0 var(--co-spacing-xs);min-height:0}.co-rich-text-editor__helper{display:flex;align-items:center;gap:var(--co-spacing-xs);color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-12, 12px)}.co-rich-text-editor__helper--error{color:var(--co-color-status-error)}.co-rich-text-editor__helper--success{color:var(--co-color-status-success)}.co-rich-text-editor__count{margin-left:auto;color:var(--co-semantic-text-muted);font-size:var(--co-font-size-12, 12px)}co-rich-text-editor[layout='horizontal'] .co-rich-text-editor{display:grid;grid-template-columns:var(--co-field-label-width, max-content) 1fr;align-items:start;column-gap:var(--co-spacing-md);row-gap:var(--co-spacing-sm2)}co-rich-text-editor[layout='horizontal'] .co-rich-text-editor__labels{grid-column:1;grid-row:1;padding-top:var(--co-spacing-sm2);min-width:0}co-rich-text-editor[layout='horizontal'] .co-rich-text-editor__label{white-space:normal}co-rich-text-editor[layout='horizontal'] .co-rich-text-editor>:not(.co-rich-text-editor__labels){grid-column:2;min-width:0}.co-field-required{margin-left:2px;color:var(--co-color-status-error)}.co-field-required__caption{margin-left:4px;color:var(--co-semantic-text-muted);font-size:var(--co-font-size-12);font-weight:400}.co-field-required__caption::before{content:var(--co-field-required-text, ' (required)')}`;
7
+ const coRichTextEditorCss = () => `co-rich-text-editor{display:block;font-family:var(--co-font-family-primary);font-size:var(--co-font-size-14);letter-spacing:var(--co-font-letter-spacing-body)}.co-rich-text-editor{display:flex;flex-direction:column;gap:var(--co-spacing-sm2, 6px)}.co-rich-text-editor__labels{display:flex;align-items:center;justify-content:space-between;padding:0 var(--co-spacing-xs);gap:var(--co-spacing-sm2, 6px)}.co-rich-text-editor__label,.co-rich-text-editor__secondary-label{color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-14);font-weight:400;line-height:1}.co-rich-text-editor__frame{display:flex;flex-direction:column;background:var(--co-semantic-surface-secondary);border:1px solid var(--co-semantic-border-subtle);border-radius:var(--co-border-radius-xs);transition:border-color 0.15s ease, box-shadow 0.15s ease;min-height:0;flex:1;position:relative;overflow:visible}.co-rich-text-editor__box{display:flex;flex-direction:column;min-height:0;flex:1;position:relative;overflow-y:auto;overflow-x:hidden}.co-rich-text-editor--focused .co-rich-text-editor__frame{border-color:var(--co-semantic-border-focus, var(--co-color-base-negro, #1a1a1a));box-shadow:0 0 0 3px var(--co-semantic-border-focus-ring, rgba(37, 99, 235, 0.15))}.co-rich-text-editor--error .co-rich-text-editor__frame{border-color:var(--co-color-status-error)}.co-rich-text-editor--success .co-rich-text-editor__frame{border-color:var(--co-color-status-success)}.co-rich-text-editor--disabled .co-rich-text-editor__frame,.co-rich-text-editor--readonly .co-rich-text-editor__frame{opacity:0.7;cursor:not-allowed}.co-rich-text-editor--loading .co-rte-content{min-height:96px;background:linear-gradient(90deg, var(--co-semantic-surface-secondary) 0%, var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.04)) 50%, var(--co-semantic-surface-secondary) 100%);background-size:200% 100%;animation:co-rte-skeleton 1.2s ease-in-out infinite}@keyframes co-rte-skeleton{0%{background-position:200% 0}100%{background-position:-200% 0}}.co-rich-text-editor__toolbar{position:relative;flex-shrink:0;z-index:60}.co-rte-content{min-height:96px;color:var(--co-semantic-text-default);flex:1 0 auto;display:flex;flex-direction:column}.co-rte-content .ProseMirror{outline:none;flex:1 0 auto;line-height:1.5;padding:var(--co-spacing-md);box-sizing:border-box}.co-rte-content .ProseMirror p{margin:0 0 var(--co-spacing-sm) 0}.co-rte-content .ProseMirror p:last-child{margin-bottom:0}.co-rte-content .ProseMirror>p{margin-bottom:var(--co-spacing-sm) !important}.co-rte-content .ProseMirror>p:last-child{margin-bottom:0 !important}.co-rte-content .ProseMirror [style*="text-align: justify"]{text-align-last:left}.co-rte-content .ProseMirror [style*="text-align: center"]{text-align:center}.co-rte-content .ProseMirror [style*="text-align: right"]{text-align:right}.co-rte-content .ProseMirror h1,.co-rte-content .ProseMirror h2,.co-rte-content .ProseMirror h3,.co-rte-content .ProseMirror h4{margin:var(--co-spacing-md) 0 var(--co-spacing-sm);font-weight:600;line-height:1.3}.co-rte-content .ProseMirror h1{font-size:var(--co-font-size-28, 28px)}.co-rte-content .ProseMirror h2{font-size:var(--co-font-size-20, 20px)}.co-rte-content .ProseMirror h3{font-size:var(--co-font-size-16, 16px)}.co-rte-content .ProseMirror ul,.co-rte-content .ProseMirror ol{padding-left:var(--co-spacing-xl);margin:0 0 var(--co-spacing-sm) 0}.co-rte-content .ProseMirror ul[data-type="taskList"]{list-style:none;padding-left:0;margin:0 0 var(--co-spacing-sm) 0}.co-rte-content .ProseMirror ul[data-type="taskList"] li{display:flex;align-items:flex-start;gap:var(--co-spacing-sm, 8px)}.co-rte-content .ProseMirror ul[data-type="taskList"] li>label{flex:0 0 auto;margin-top:0.15em;user-select:none}.co-rte-content .ProseMirror ul[data-type="taskList"] li>div{flex:1 1 auto;min-width:0}.co-rte-content .ProseMirror ul[data-type="taskList"] li>div>p{margin:0}.co-rte-content .ProseMirror ul[data-type="taskList"] input[type="checkbox"]{width:16px;height:16px;cursor:pointer;accent-color:var(--co-color-base-negro, #1a1a1a)}.co-rte-content .ProseMirror ul[data-type="taskList"][data-variant="strike"] li[data-checked="true"]>div{text-decoration:line-through;color:var(--co-semantic-text-muted, #999)}.co-rte-content .ProseMirror ul[data-type="taskList"][data-variant="plain"] li[data-checked="true"]>div{text-decoration:none}.co-rte-content .ProseMirror blockquote{border-left:3px solid var(--co-semantic-border-default, var(--co-semantic-border-subtle));padding-left:var(--co-spacing-md);margin:0 0 var(--co-spacing-sm) 0;color:var(--co-semantic-text-secondary)}.co-rte-content .ProseMirror a{color:var(--co-color-base-negro, #1a1a1a);text-decoration:underline;text-underline-offset:2px}.co-rte-content .ProseMirror img{max-width:100%;height:auto;border-radius:var(--co-border-radius-xs);margin:var(--co-spacing-sm) 0;cursor:default;-webkit-user-drag:none;user-select:none}.co-rte-content .ProseMirror img.ProseMirror-selectednode{outline:2px solid var(--co-color-base-negro, #1a1a1a)}.co-rte-content [data-resize-container].ProseMirror-selectednode{outline:2px solid var(--co-color-base-negro, #1a1a1a);outline-offset:0px;border-radius:0}.co-rte-content [data-resize-container]{position:relative;display:inline-block;width:fit-content;max-width:100%;margin:var(--co-spacing-sm) 0;line-height:0}.co-rte-content [data-resize-container][data-resize-state="true"]{outline:2px solid var(--co-color-base-negro, #1a1a1a);outline-offset:0px;border-radius:0}.co-rte-content [data-resize-wrapper]{position:relative;display:inline-block;line-height:0}.co-rte-content [data-resize-handle]{width:10px;height:10px;background:var(--co-color-base-negro, #1a1a1a);border:1.5px solid #fff;border-radius:50%;box-shadow:0 0 2px rgba(0, 0, 0, 0.3);z-index:5;opacity:0;pointer-events:none}.co-rte-content [data-resize-container][data-resize-state="true"] [data-resize-handle],.co-rte-content [data-resize-container].ProseMirror-selectednode [data-resize-handle]{opacity:1;pointer-events:auto}.co-rte-content [data-resize-handle="top-left"]{cursor:nw-resize}.co-rte-content [data-resize-handle="top-right"]{cursor:ne-resize}.co-rte-content [data-resize-handle="bottom-left"]{cursor:sw-resize}.co-rte-content [data-resize-handle="bottom-right"]{cursor:se-resize}.co-rte-content [data-resize-handle="top"],.co-rte-content [data-resize-handle="bottom"]{width:30px;height:6px;border-radius:3px;left:50% !important;transform:translateX(-50%)}.co-rte-content [data-resize-handle="top"]{cursor:n-resize}.co-rte-content [data-resize-handle="bottom"]{cursor:s-resize}.co-rte-content [data-resize-handle="left"],.co-rte-content [data-resize-handle="right"]{width:6px;height:30px;border-radius:3px;top:50% !important;transform:translateY(-50%)}.co-rte-content [data-resize-handle="left"]{cursor:w-resize}.co-rte-content [data-resize-handle="right"]{cursor:e-resize}.co-rte-content [data-resize-container] img{max-width:100%;display:block;border-radius:0;margin:0}.co-rte-content .ProseMirror hr{border:none;border-top:1px solid var(--co-semantic-border-default, #e0e0e0);margin:var(--co-spacing-lg) 0}.co-rte-content .ProseMirror code{font-family:var(--co-font-family-mono);font-size:0.9em;background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06));padding:0.1em 0.3em;border-radius:var(--co-border-radius-xxs)}.co-rte-content .ProseMirror pre{font-family:var(--co-font-family-mono);font-size:0.9em;background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06));padding:var(--co-spacing-md);border-radius:var(--co-border-radius-xs);overflow-x:auto;margin:var(--co-spacing-sm) 0}.co-rte-content .ProseMirror pre code{background:none;padding:0;border-radius:0}.co-rte-content .ProseMirror p.is-editor-empty:first-child::before{content:attr(data-placeholder);color:var(--co-semantic-text-muted);float:left;height:0;pointer-events:none}.co-rte-content .co-rte-variable,.co-rte-content .co-rte-mention{display:inline-block;padding:0.05em 0.4em;border-radius:var(--co-border-radius-xxs);background:var(--co-color-base-negro, #1a1a1a);color:var(--co-color-base-blanco, #fff);font-size:0.9em;white-space:nowrap}.co-rte-content .co-rte-mention{background:var(--co-color-primary-verde)}.co-rich-text-editor__footer{display:flex;align-items:center;justify-content:space-between;gap:var(--co-spacing-sm);padding:0 var(--co-spacing-xs);min-height:0}.co-rich-text-editor__helper{display:flex;align-items:center;gap:var(--co-spacing-xs);color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-12, 12px)}.co-rich-text-editor__helper--error{color:var(--co-color-status-error)}.co-rich-text-editor__helper--success{color:var(--co-color-status-success)}.co-rich-text-editor__count{margin-left:auto;color:var(--co-semantic-text-muted);font-size:var(--co-font-size-12, 12px)}.co-rte-bubble.co-rte-bubble--suppressed{display:none !important}.co-rte-bubble{position:absolute;z-index:50;display:flex;flex-direction:row;align-items:center;gap:2px;padding:var(--co-spacing-xs, 4px) var(--co-spacing-sm, 8px);background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xs, 8px);box-shadow:0 4px 16px rgba(0, 0, 0, 0.12);user-select:none;white-space:nowrap}.co-rte-bubble__drag-handle{display:flex;align-items:center;justify-content:center;cursor:grab;color:var(--co-semantic-text-muted, #999);width:18px;height:28px;margin:0 2px 0 0;flex-shrink:0}.co-rte-bubble__drag-handle:hover{color:var(--co-semantic-text-secondary, #555)}.co-rte-bubble__drag-handle:active{cursor:grabbing}.co-rte-bubble__row{display:flex;align-items:center;gap:2px;flex-wrap:nowrap}.co-rte-bubble__btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:var(--co-border-radius-xxs, 4px);background:transparent;color:var(--co-semantic-text-default, #333);cursor:pointer}.co-rte-bubble__btn:hover:not(.co-rte-bubble__btn--active){background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06))}.co-rte-bubble__btn--active{background:var(--co-color-base-negro, #1a1a1a);color:var(--co-color-base-blanco, #fff)}.co-rte-bubble__btn--active:hover{background:var(--co-color-base-negro, #333)}.co-rte-bubble__sep{display:inline-block;width:1px;height:18px;margin:0 4px;background:var(--co-semantic-border-default, rgba(0, 0, 0, 0.12));flex-shrink:0}.co-rte-bubble__select{position:relative}.co-rte-bubble__select-trigger{display:flex;align-items:center;gap:2px;height:28px;padding:0 6px;border:1px solid transparent;border-radius:var(--co-border-radius-xxs, 4px);background:transparent;color:var(--co-semantic-text-default, #333);font-family:var(--co-font-family-primary);font-size:11px;cursor:pointer;white-space:nowrap;transition:background 0.12s, border-color 0.12s}.co-rte-bubble__select-trigger:hover{background:var(--co-semantic-surface-hover, #f5f5f5);border-color:var(--co-semantic-border-default, #e0e0e0)}.co-rte-bubble__select-label{max-width:72px;overflow:hidden;text-overflow:ellipsis}.co-rte-bubble__select--font .co-rte-bubble__select-label{max-width:110px}.co-rte-bubble__select-dropdown{position:absolute;bottom:100%;left:0;z-index:120;min-width:100px;max-height:260px;overflow-y:auto;padding:var(--co-spacing-xxs, 2px);background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xxs, 4px);box-shadow:0 4px 16px rgba(0, 0, 0, 0.12);margin-bottom:4px;white-space:normal}.co-rte-bubble__select-dropdown[data-position="above"]{bottom:100%;top:auto;margin-bottom:4px;margin-top:0}.co-rte-bubble__select-dropdown[data-position="below"]{top:100%;bottom:auto;margin-top:4px;margin-bottom:0}.co-rte-bubble__select-option{display:block;width:100%;padding:4px 8px;border:none;border-radius:3px;background:transparent;color:var(--co-semantic-text-default, #333);font-family:var(--co-font-family-primary);font-size:12px;text-align:left;cursor:pointer;white-space:nowrap}.co-rte-bubble__select-option:hover{background:var(--co-semantic-surface-hover, #f5f5f5)}.co-rte-bubble__select-dropdown--font{min-width:200px;max-height:320px;overflow:hidden;overflow-y:auto;display:flex;flex-direction:column;white-space:normal}.co-rte-bubble__font-search{padding:6px 6px 4px;flex-shrink:0}.co-rte-bubble__font-search-input{width:100%;padding:4px 8px;border:1px solid var(--co-semantic-border-default, #ccc);border-radius:4px;background:var(--co-semantic-surface-secondary, #fff);color:var(--co-semantic-text-default, #333);font-family:var(--co-font-family-primary);font-size:12px;outline:none;box-sizing:border-box}.co-rte-bubble__font-search-input:focus{border-color:var(--co-color-base-negro, #1a1a1a)}.co-rte-bubble__font-list{max-height:260px;overflow-y:auto;padding:0 var(--co-spacing-xxs, 2px) var(--co-spacing-xxs, 2px)}.co-rte-bubble__font-section-header{padding:6px 8px 2px;font-size:11px;font-weight:600;color:var(--co-semantic-text-muted, #888);text-transform:uppercase;letter-spacing:0.5px}.co-rte-bubble__font-empty{padding:12px 8px;text-align:center;color:var(--co-semantic-text-muted, #888);font-size:12px}.co-rte-bubble__color{position:relative}.co-rte-bubble__color-dropdown{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);z-index:120;width:224px;padding:var(--co-spacing-sm, 8px);background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xs, 8px);box-shadow:0 4px 16px rgba(0, 0, 0, 0.12);margin-bottom:4px;white-space:normal;max-width:calc(100vw - 16px)}.co-rte-bubble__color-dropdown[data-position="above"]{bottom:100%;top:auto;margin-bottom:4px;margin-top:0}.co-rte-bubble__color-dropdown[data-position="below"]{top:100%;bottom:auto;margin-top:4px;margin-bottom:0}.co-rte-bubble__color-grid{display:grid;grid-template-columns:repeat(10, 1fr);gap:2px}.co-rte-bubble__color-swatch{width:20px;height:20px;padding:0;border:none;border-radius:3px;cursor:pointer;transition:transform 0.1s, box-shadow 0.1s}.co-rte-bubble__color-swatch:hover{transform:scale(1.2);box-shadow:0 0 0 2px var(--co-color-base-negro, #1a1a1a)}.co-rte-bubble__color-hex{display:flex;align-items:center;gap:4px;margin-top:6px}.co-rte-bubble__color-hex-input{width:100%;padding:3px 6px;border:1px solid var(--co-semantic-border-default, #ccc);border-radius:3px;background:var(--co-semantic-surface-secondary, #fff);color:var(--co-semantic-text-default, #333);font-family:var(--co-font-family-mono, monospace);font-size:11px;outline:none}.co-rte-bubble__color-hex-input:focus{border-color:var(--co-color-base-negro, #1a1a1a)}.co-rte-bubble__color-clear{display:flex;align-items:center;gap:4px;width:100%;padding:3px 6px;margin-top:4px;border:none;background:transparent;color:var(--co-semantic-text-secondary, #666);font-family:var(--co-font-family-primary);font-size:11px;cursor:pointer;border-radius:3px}.co-rte-bubble__color-clear:hover{background:var(--co-semantic-surface-hover, #f5f5f5)}.co-rte-bubble__link-form{display:flex;align-items:center;gap:4px;margin-left:4px}.co-rte-bubble__link-input{width:160px;padding:3px 8px;border:1px solid var(--co-semantic-border-default, #ccc);border-radius:4px;background:var(--co-semantic-surface-secondary, #fff);color:var(--co-semantic-text-default, #333);font-family:var(--co-font-family-primary);font-size:12px;outline:none}.co-rte-bubble__link-input::placeholder{color:var(--co-semantic-text-muted, #999)}.co-rte-bubble__link-input:focus{border-color:var(--co-color-base-negro, #1a1a1a);box-shadow:0 0 0 2px rgba(0, 0, 0, 0.1)}.co-rte-bubble__link-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:4px;background:var(--co-color-base-negro, #1a1a1a);color:#fff;cursor:pointer}.co-rte-bubble__link-btn:hover{opacity:0.9}.co-rte-bubble__link-unlink{background:var(--co-semantic-surface-error, #ef4444)}.co-rte-bubble__panel{position:absolute;z-index:140;width:230px;background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xs, 8px);box-shadow:0 4px 16px rgba(0, 0, 0, 0.12);overflow:hidden;user-select:none}.co-rte-bubble__panel-header{display:flex;align-items:center;gap:4px;padding:6px 8px;border-bottom:1px solid var(--co-semantic-border-subtle, #eee)}.co-rte-bubble__panel-drag{cursor:grab;display:flex;align-items:center;justify-content:center;color:var(--co-semantic-text-muted, #999);flex-shrink:0}.co-rte-bubble__panel-drag:active{cursor:grabbing}.co-rte-bubble__panel-title{flex:1;font-size:12px;font-weight:600;color:var(--co-semantic-text-default, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.co-rte-bubble__panel-close{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;border-radius:3px;background:transparent;color:var(--co-semantic-text-muted, #999);cursor:pointer;flex-shrink:0}.co-rte-bubble__panel-close:hover{background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06));color:var(--co-semantic-text-default, #333)}.co-rte-bubble__panel-input-wrap{padding:6px 8px}.co-rte-bubble__panel-input{width:100%;padding:4px 8px;border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:4px;font-size:12px;font-family:inherit;outline:none;box-sizing:border-box;background:var(--co-semantic-surface-secondary, #fff);color:var(--co-semantic-text-default, #333)}.co-rte-bubble__panel-input:focus{border-color:var(--co-color-base-negro, #1a1a1a)}.co-rte-bubble__panel-options{max-height:280px;overflow-y:auto;padding:2px 4px 4px}.co-rte-bubble__panel-option{display:block;width:100%;padding:5px 8px;border:none;border-radius:3px;background:transparent;cursor:pointer;text-align:left;font-family:inherit;color:var(--co-semantic-text-default, #333)}.co-rte-bubble__panel-option:hover{background:var(--co-semantic-surface-hover, #f5f5f5)}.co-rte-bubble__panel-sep{height:1px;background:var(--co-semantic-border-subtle, #eee);margin:4px 8px}.co-rte-bubble__panel-opt-row{display:flex;justify-content:space-between;align-items:center;width:100%}.co-rte-bubble__panel-opt-value{color:var(--co-semantic-text-muted, #999);font-size:11px;font-weight:400 !important;min-width:28px;text-align:right}.co-rte-bubble__panel[data-position="above"]{bottom:100%;top:auto;margin-bottom:4px}.co-rte-bubble__panel[data-position="below"]{top:100%;bottom:auto;margin-top:4px}.co-rte-bubble__overflow{position:relative}.co-rte-bubble__overflow-menu{position:absolute;bottom:100%;right:0;z-index:130;min-width:230px;padding:4px;background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xs, 8px);box-shadow:0 4px 16px rgba(0, 0, 0, 0.12);margin-bottom:4px}.co-rte-bubble__overflow-menu[data-position="below"]{top:100%;bottom:auto;margin-top:4px;margin-bottom:0}.co-rte-bubble__overflow-item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border:none;border-radius:4px;background:transparent;font-family:inherit;font-size:13px;color:var(--co-semantic-text-default, #333);cursor:pointer;text-align:left;white-space:nowrap}.co-rte-bubble__overflow-item:hover{background:var(--co-semantic-surface-hover, #f5f5f5)}.co-rte-bubble__overflow-item--active{background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06));color:var(--co-color-base-negro, #1a1a1a);font-weight:600}.co-rte-bubble__overflow-value{margin-left:auto;color:var(--co-semantic-text-muted, #999);font-size:11px}.co-rte-bubble__overflow-sep{height:1px;background:var(--co-semantic-border-subtle, #eee);margin:3px 8px}.co-rte-bubble__overflow-section-title{padding:6px 8px 2px;font-size:11px;font-weight:600;color:var(--co-semantic-text-muted, #888);letter-spacing:0.5px}.co-rte-bubble__overflow-item--danger{color:var(--co-color-status-error, #aa2e1b)}.co-rte-bubble__overflow-item--danger:hover{background:rgba(170, 46, 27, 0.06)}.co-rte-bubble__color-indicator{display:flex;flex-direction:column;align-items:center;gap:1px;line-height:1}.co-rte-bubble__color-letter{font-family:var(--co-font-family-primary);font-size:14px;font-weight:700;color:var(--co-semantic-text-default, #333);line-height:1}.co-rte-bubble__color-bar{width:14px;height:3px;border-radius:1px}.co-rte-content .callout{display:flex;gap:0.75rem;padding:1rem;border-radius:var(--co-border-radius-xs, 8px);border:2px solid;margin:1rem 0}.co-rte-content .callout--info{background:#eff6ff;border-color:#bfdbfe}.co-rte-content .callout--warning{background:#fffbeb;border-color:#fde68a}.co-rte-content .callout--success{background:#f0fdf4;border-color:#bbf7d0}.co-rte-content .callout--error{background:#fef2f2;border-color:#fecaca}.co-rte-content .callout__icon{flex-shrink:0;font-size:1.2em}.co-rte-content .callout__content{flex:1}.co-rte-content .callout__content p{margin:0}.co-rte-content table{border-collapse:collapse;table-layout:auto;width:100%;margin:1rem 0;overflow:hidden}.co-rte-content .tableWrapper{overflow-x:auto;max-width:100%}.co-rte-content td,.co-rte-content th{min-width:1em;border:1px solid var(--co-semantic-border-default, #e0e0e0);padding:0.5rem;vertical-align:top;box-sizing:border-box;position:relative}.co-rte-content th{font-weight:600;text-align:left;background-color:#e3e3e3;color:var(--co-semantic-text-default, #333)}.co-rte-content .ProseMirror table th{background-color:#e3e3e3}.co-rte-content .selectedCell{background:rgba(0, 0, 0, 0.06)}.co-rte-content .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:var(--co-color-base-negro, #1a1a1a);pointer-events:none}.co-rte-content .ProseMirror.resize-cursor,.co-rte-content .ProseMirror.resize-cursor *{cursor:col-resize}.co-rte-content iframe{border-radius:var(--co-border-radius-xs, 8px);max-width:100%;aspect-ratio:16 / 9;width:100%;height:auto;display:block;margin:0}.co-rte-content .co-rte-embed{position:relative;display:block;max-width:100%;margin:1rem 0;line-height:0}.co-rte-content .co-rte-embed::before{content:'';position:absolute;inset:0;z-index:1}.co-rte-content .co-rte-embed.ProseMirror-selectednode,.co-rte-content .co-rte-embed--selected{outline:2px solid var(--co-color-base-negro, #1a1a1a);outline-offset:2px;border-radius:var(--co-border-radius-xs, 8px)}.co-rte-content .co-rte-embed__handle{position:absolute;width:12px;height:12px;background:var(--co-color-base-negro, #1a1a1a);border:1.5px solid #fff;border-radius:50%;box-shadow:0 0 2px rgba(0, 0, 0, 0.3);z-index:3;opacity:0;pointer-events:none}.co-rte-content .co-rte-embed.ProseMirror-selectednode .co-rte-embed__handle,.co-rte-content .co-rte-embed--selected .co-rte-embed__handle{opacity:1;pointer-events:auto}.co-rte-content .co-rte-embed__handle--bottom-right{right:-6px;bottom:-6px;cursor:nwse-resize}.co-rte-content .co-rte-embed__handle--bottom-left{left:-6px;bottom:-6px;cursor:nesw-resize}.co-rte-content .co-rte-embed--resizing{outline:2px dashed var(--co-color-base-negro, #1a1a1a);outline-offset:2px}.co-rich-text-editor--readonly .co-rte-embed::before,.co-rich-text-editor--disabled .co-rte-embed::before{display:none}.co-rich-text-editor--readonly .co-rte-embed.ProseMirror-selectednode,.co-rich-text-editor--readonly .co-rte-embed--selected,.co-rich-text-editor--disabled .co-rte-embed.ProseMirror-selectednode,.co-rich-text-editor--disabled .co-rte-embed--selected{outline:none !important}.co-rte-img-layout{position:absolute;z-index:50;display:flex;align-items:center;gap:2px;padding:4px;background:var(--co-semantic-surface-secondary, #fff);border:1px solid var(--co-semantic-border-default, #e0e0e0);border-radius:var(--co-border-radius-xs, 8px);box-shadow:0 2px 12px rgba(0, 0, 0, 0.12);pointer-events:auto}.co-rte-img-layout__btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border:1px solid transparent;border-radius:var(--co-border-radius-xxs, 4px);background:transparent;color:var(--co-semantic-text-default, #333);cursor:pointer;transition:background 0.12s, border-color 0.12s}.co-rte-img-layout__btn:hover{background:var(--co-semantic-surface-hover, rgba(0, 0, 0, 0.06))}.co-rte-img-layout__btn--active{background:var(--co-color-base-negro, #1a1a1a);color:var(--co-color-base-blanco, #fff)}.co-rte-img-layout__btn--active:hover{background:var(--co-color-base-negro, #333)}.co-rte-img-layout__btn[data-tooltip]{position:relative}.co-rte-img-layout__btn[data-tooltip]::after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);padding:4px 8px;background:var(--co-color-base-negro, #1a1a1a);color:var(--co-color-base-blanco, #fff);font-family:var(--co-font-family-primary);font-size:11px;font-weight:500;line-height:1.3;white-space:nowrap;border-radius:4px;pointer-events:none;opacity:0;transition:opacity 0.12s ease;z-index:100}.co-rte-img-layout__btn[data-tooltip]:hover::after{opacity:1;transition-delay:0.3s}.co-rte-content [data-resize-container][data-image-layout="wrap-left"]{float:left;max-width:50%;margin:4px 16px 8px 0}.co-rte-content [data-resize-container][data-image-layout="wrap-right"]{float:right;max-width:50%;margin:4px 0 8px 16px}.co-rte-content [data-resize-container][data-image-layout="center"]{display:block;margin:12px auto}.co-rte-content [data-resize-container][data-image-layout="full-width"]{display:block;width:100%;margin:12px 0}.co-rte-content [data-resize-container][data-image-layout="full-width"] [data-resize-wrapper],.co-rte-content [data-resize-container][data-image-layout="full-width"] img{width:100%}@media (max-width: 768px){.co-rte-content [data-resize-container][data-image-layout="wrap-left"],.co-rte-content [data-resize-container][data-image-layout="wrap-right"]{float:none;max-width:100%;display:block;margin:12px 0}}.co-rte-content--site .ProseMirror{width:var(--co-rte-content-width, 80%);max-width:100%;margin:0 auto}@media (max-width: 768px){.co-rte-content--site .ProseMirror{width:100%}}.co-rich-text-editor--readonly [data-resize-handle],.co-rich-text-editor--disabled [data-resize-handle]{display:none !important}.co-rich-text-editor--readonly [data-resize-container].ProseMirror-selectednode,.co-rich-text-editor--disabled [data-resize-container].ProseMirror-selectednode,.co-rich-text-editor--readonly img.ProseMirror-selectednode,.co-rich-text-editor--disabled img.ProseMirror-selectednode{outline:none !important}`;
5
8
 
6
9
  const CoRichTextEditor = class {
7
10
  constructor(hostRef) {
@@ -12,13 +15,13 @@ const CoRichTextEditor = class {
12
15
  this.coBlur = createEvent(this, "coBlur", 7);
13
16
  this.coClear = createEvent(this, "coClear", 7);
14
17
  this.coReady = createEvent(this, "coReady", 7);
18
+ this.coFontPopupShow = createEvent(this, "coFontPopupShow", 7);
19
+ this.coFontPopupHide = createEvent(this, "coFontPopupHide", 7);
15
20
  /** ProseMirror document as a JSON string. `null`/empty = empty editor. */
16
21
  this.value = null;
17
22
  /** Preset controlling allowed nodes/marks, toolbar and sanitization. */
18
23
  this.preset = 'task';
19
24
  this.placeholder = '';
20
- /** Label layout: vertical (label above) or horizontal (label beside) */
21
- this.layout = 'vertical';
22
25
  this.status = 'default';
23
26
  this.disabled = false;
24
27
  this.readonly = false;
@@ -27,42 +30,80 @@ const CoRichTextEditor = class {
27
30
  this.autofocus = false;
28
31
  /** Toolbar layout. `auto` uses the preset default. */
29
32
  this.toolbar = 'auto';
33
+ /** BCP-47 locale for UI strings (e.g. 'en', 'es-CO', 'pt-BR'). Default English. */
34
+ this.locale = 'en';
30
35
  this.ready = false;
31
36
  this.hasFocus = false;
37
+ /** Character count — updated imperatively to avoid re-renders on every keystroke. */
32
38
  this.charCount = 0;
33
- /** Last value we emitted — guards the value Watch against feedback loops. */
34
- this.lastEmitted = null;
39
+ this.bubbleDragged = false;
40
+ this.bubbleDragOffset = { x: 0, y: 0 };
41
+ this.bubbleDragPos = { x: 0, y: 0 };
42
+ /** Position lock — prevents floating-ui from repositioning the bubble during toolbar interactions. */
43
+ this.bubblePositionLocked = false;
44
+ this.bubbleLockPos = { x: 0, y: 0 };
45
+ this.applyingBubbleLock = false;
46
+ /** Account fonts loaded via fontLoader callback. */
47
+ this._loadedAccountFonts = [];
48
+ this._fontLoaderCalled = false;
49
+ this._fontLoaderLoading = false;
50
+ /** Last emitted JSON string — guards the value Watch against feedback loops. */
51
+ this.lastEmittedJson = null;
52
+ /** Last emitted HTML string — parents often send HTML back via value prop. */
53
+ this.lastEmittedHtml = '';
35
54
  /** True while applying an external value (suppresses emit). */
36
55
  this.applyingExternal = false;
37
- /** Set by disconnectedCallback — aborts editor creation if the element was
38
- * removed while the lazy import was still in flight (ProseMirror leak). */
39
- this.destroyed = false;
56
+ this.rt = RichText;
57
+ this.imgLayoutVisible = false;
40
58
  this.handleUpdate = (editor) => {
41
59
  this.refreshCharCount();
42
60
  if (this.applyingExternal)
43
61
  return;
44
62
  const out = this.buildOutput(editor);
45
- const next = out.json ? JSON.stringify(out.json) : null;
46
- this.lastEmitted = next;
47
- this.value = next;
63
+ // Track both JSON and HTML forms to prevent feedback loops.
64
+ // The parent may send back either format via the value prop.
65
+ this.lastEmittedJson = out.json ? JSON.stringify(out.json) : null;
66
+ this.lastEmittedHtml = out.html;
67
+ // Do NOT set this.value here — it triggers unnecessary Stencil re-renders
68
+ // and the Watch cycle. The parent is the source of truth for the value prop.
48
69
  this.coInput.emit(out);
70
+ // In readonly mode there's no blur cycle, so commit immediately
71
+ // (e.g. task-list checkbox toggled by onReadOnlyChecked).
72
+ if (this.readonly)
73
+ this.coChange.emit(out);
49
74
  };
50
75
  this.handleFocus = () => {
51
76
  this.hasFocus = true;
52
77
  this.coFocus.emit();
53
78
  };
54
79
  this.handleBlur = () => {
55
- this.hasFocus = false;
56
- if (this.editor)
57
- this.coChange.emit(this.buildOutput(this.editor));
58
- this.coBlur.emit();
80
+ // Delay blur processing — if the user clicked a toolbar button,
81
+ // chain().focus() will re-focus the editor before this timeout fires.
82
+ clearTimeout(this.blurTimeout);
83
+ this.blurTimeout = setTimeout(() => {
84
+ var _a, _b;
85
+ if ((_a = this.editor) === null || _a === void 0 ? void 0 : _a.isFocused)
86
+ return; // Focus was restored (toolbar click)
87
+ // Don't blur if focus moved to an element inside the bubble (e.g. hex input)
88
+ if ((_b = this.bubbleEl) === null || _b === void 0 ? void 0 : _b.contains(document.activeElement))
89
+ return;
90
+ this.hasFocus = false;
91
+ if (this.editor)
92
+ this.coChange.emit(this.buildOutput(this.editor));
93
+ this.coBlur.emit();
94
+ }, 100);
59
95
  };
60
96
  }
61
97
  async componentDidLoad() {
62
98
  var _a, _b;
63
- this.rt = await import('./index-BjAqSidM.js');
64
- if (this.destroyed || !this.contentEl)
99
+ if (!this.contentEl)
65
100
  return;
101
+ // Create bubble element imperatively so Stencil VDOM cannot interfere
102
+ // with BubbleMenu's DOM management (it calls element.remove/appendChild).
103
+ const showToolbar = this.resolvedToolbar !== 'none' && !this.readonly && !this.disabled;
104
+ if (showToolbar) {
105
+ this.bubbleEl = this.createBubbleElement();
106
+ }
66
107
  this.editor = this.rt.createEditor({
67
108
  preset: this.preset,
68
109
  element: this.contentEl,
@@ -72,40 +113,113 @@ const CoRichTextEditor = class {
72
113
  maxLength: this.maxLength,
73
114
  features: this.parsedFeatures,
74
115
  customExtensions: (_a = this.customExtensions) !== null && _a !== void 0 ? _a : [],
116
+ bubbleMenuElement: this.bubbleEl,
75
117
  imageUpload: this.imageUpload,
76
118
  onUpdate: (editor) => this.handleUpdate(editor),
77
119
  onFocus: () => this.handleFocus(),
78
120
  onBlur: () => this.handleBlur(),
79
121
  });
80
- this.lastEmitted = (_b = this.value) !== null && _b !== void 0 ? _b : null;
122
+ // Document / "site" preset: fluid ~80% content width (see editor.css). Marks
123
+ // both editable and readonly so the reader matches the author's measure.
124
+ if (this.preset === 'document') {
125
+ this.contentEl.classList.add('co-rte-content--site');
126
+ }
127
+ // Image layout toolbar — only when actually editable. The layout itself is
128
+ // CSS-driven (keyed on `data-image-layout`); the bar just lets the author
129
+ // pick a reflow mode (inline / wrap-left / wrap-right / center / full-width).
130
+ if (showToolbar && this.imagesEnabled) {
131
+ this.contentEl.style.position = 'relative'; // offset parent for the bar
132
+ this.imgLayoutEl = this.createImageLayoutBar();
133
+ this.contentEl.appendChild(this.imgLayoutEl);
134
+ }
135
+ // Update bubble active states on every transaction
136
+ this.editor.on('transaction', ({ transaction }) => {
137
+ if (this.bubbleEl) {
138
+ this.updateBubbleActiveStates();
139
+ if ((this.bubbleDragged || this.bubblePositionLocked) && this.bubbleEl) {
140
+ this.applyBubbleFixedPosition();
141
+ }
142
+ }
143
+ // Reapply floating-image positions only when the doc changed (skip pure
144
+ // selection/cursor moves to avoid a full descendants walk on every keystroke).
145
+ if (this.imagesEnabled && transaction.docChanged)
146
+ this.syncImageLayouts();
147
+ this.updateImageLayoutBar();
148
+ });
149
+ // Clicking the toolbar closes bubble popups (link form, panels, etc.)
150
+ if (this.bubbleEl && this.toolbarEl) {
151
+ this.toolbarEl.addEventListener('mousedown', () => {
152
+ this.closeBubbleDropdowns();
153
+ });
154
+ // Hide the selection bubble while a toolbar dropdown/popover is open so
155
+ // the two never overlap in the same space (the bubble lives inside the
156
+ // content area, right where toolbar dropdowns expand into).
157
+ this.toolbarEl.addEventListener('coPopoverChange', (e) => {
158
+ var _a;
159
+ const open = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.open;
160
+ this.suppressBubble(!!open);
161
+ });
162
+ }
163
+ this.lastEmittedJson = (_b = this.value) !== null && _b !== void 0 ? _b : null;
81
164
  this.ready = true;
82
165
  this.refreshCharCount();
83
166
  this.syncToolbar();
84
167
  this.coReady.emit();
85
168
  if (this.autofocus)
86
169
  this.editor.commands.focus();
170
+ // Tag every image container with its layout mode so the CSS rules apply.
171
+ // Runs even without the layout toolbar (readonly/disabled viewers).
172
+ requestAnimationFrame(() => this.syncImageLayouts());
87
173
  }
88
174
  disconnectedCallback() {
89
- var _a;
90
- this.destroyed = true;
91
- (_a = this.editor) === null || _a === void 0 ? void 0 : _a.destroy();
175
+ var _a, _b, _c, _d;
176
+ clearTimeout(this.blurTimeout);
177
+ clearTimeout(this.bubbleLockTimer);
178
+ (_a = this.bubbleStyleObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
179
+ if (this.bubbleDragMoveHandler)
180
+ document.removeEventListener('mousemove', this.bubbleDragMoveHandler);
181
+ if (this.bubbleDragEndHandler)
182
+ document.removeEventListener('mouseup', this.bubbleDragEndHandler);
183
+ if (this.bubbleOutsideClickHandler)
184
+ document.removeEventListener('click', this.bubbleOutsideClickHandler, true);
185
+ (_b = this.editor) === null || _b === void 0 ? void 0 : _b.destroy();
92
186
  this.editor = undefined;
187
+ (_c = this.bubbleEl) === null || _c === void 0 ? void 0 : _c.remove();
188
+ (_d = this.imgLayoutEl) === null || _d === void 0 ? void 0 : _d.remove();
93
189
  }
94
190
  componentDidRender() {
95
191
  this.syncToolbar();
96
192
  }
193
+ onAccountFontsChange() {
194
+ var _a;
195
+ // Re-render the font dropdown list if it's open
196
+ if (this._fontDropdownRenderFn) {
197
+ const filter = ((_a = this._fontDropdownSearchInput) === null || _a === void 0 ? void 0 : _a.value) || '';
198
+ this._fontDropdownRenderFn(filter);
199
+ }
200
+ }
97
201
  onValueChange(next) {
98
202
  if (!this.editor || this.applyingExternal)
99
203
  return;
100
- if ((next !== null && next !== void 0 ? next : null) === this.lastEmitted)
204
+ const incoming = next !== null && next !== void 0 ? next : null;
205
+ // Skip if this value matches what we last emitted (JSON or HTML form).
206
+ // This prevents the destructive feedback loop where the parent sends
207
+ // back our own output and setContent resets the editor on every keystroke.
208
+ if (incoming === this.lastEmittedJson || incoming === this.lastEmittedHtml)
101
209
  return;
102
210
  this.applyingExternal = true;
103
211
  try {
104
- this.editor.commands.setContent(this.parseValue(next), { emitUpdate: false });
212
+ if (incoming === '' || incoming === null) {
213
+ this.editor.commands.clearContent(false);
214
+ }
215
+ else {
216
+ this.editor.commands.setContent(this.parseValue(next), { emitUpdate: false });
217
+ }
105
218
  }
106
219
  finally {
107
220
  this.applyingExternal = false;
108
- this.lastEmitted = next !== null && next !== void 0 ? next : null;
221
+ this.lastEmittedJson = incoming;
222
+ this.lastEmittedHtml = '';
109
223
  this.refreshCharCount();
110
224
  }
111
225
  }
@@ -143,6 +257,12 @@ const CoRichTextEditor = class {
143
257
  return (_a = this.editor) !== null && _a !== void 0 ? _a : null;
144
258
  }
145
259
  /* ── internals ── */
260
+ /** Whether the image node is enabled (mirrors presets.ts `wantImage` logic). */
261
+ get imagesEnabled() {
262
+ var _a;
263
+ const f = this.parsedFeatures;
264
+ return (_a = f === null || f === void 0 ? void 0 : f.image) !== null && _a !== void 0 ? _a : this.preset === 'document';
265
+ }
146
266
  get parsedFeatures() {
147
267
  if (!this.features)
148
268
  return undefined;
@@ -167,9 +287,7 @@ const CoRichTextEditor = class {
167
287
  }
168
288
  }
169
289
  sanitizeHtml(html) {
170
- // Same features as the schema — otherwise feature-enabled nodes (images,
171
- // variables) would survive in `json` but be stripped from `html`.
172
- return this.rt ? this.rt.sanitize(html, this.preset, this.parsedFeatures) : html;
290
+ return this.rt.sanitize(html, this.preset);
173
291
  }
174
292
  buildOutput(editor) {
175
293
  const empty = editor.isEmpty;
@@ -179,21 +297,191 @@ const CoRichTextEditor = class {
179
297
  text: editor.getText(),
180
298
  };
181
299
  }
300
+ /** Lock the bubble position so floating-ui doesn't reposition it. */
301
+ lockBubblePosition(durationMs = 1000) {
302
+ if (!this.bubbleEl)
303
+ return;
304
+ const rect = this.bubbleEl.getBoundingClientRect();
305
+ if (rect.width === 0)
306
+ return; // bubble not visible
307
+ this.bubbleLockPos = { x: rect.left, y: rect.top };
308
+ this.bubblePositionLocked = true;
309
+ clearTimeout(this.bubbleLockTimer);
310
+ this.bubbleLockTimer = setTimeout(() => {
311
+ this.bubblePositionLocked = false;
312
+ }, durationMs);
313
+ }
314
+ /** Apply fixed position to the bubble, overriding floating-ui. */
315
+ applyBubbleFixedPosition() {
316
+ if (!this.bubbleEl)
317
+ return;
318
+ const pos = this.bubbleDragged ? this.bubbleDragPos : this.bubbleLockPos;
319
+ this.applyingBubbleLock = true;
320
+ this.bubbleEl.style.position = 'fixed';
321
+ this.bubbleEl.style.top = `${pos.y}px`;
322
+ this.bubbleEl.style.left = `${pos.x}px`;
323
+ this.bubbleEl.style.transform = 'none';
324
+ this.bubbleEl.style.visibility = 'visible';
325
+ requestAnimationFrame(() => { this.applyingBubbleLock = false; });
326
+ }
327
+ /** Watch for floating-ui style changes and override them when locked/dragged. */
328
+ setupBubbleStyleObserver(bubble) {
329
+ // Use BubbleMenu plugin's onHide/onShow callbacks (dispatched as custom
330
+ // events from create-editor) for reliable drag state management.
331
+ // These fire synchronously inside hide()/show(), avoiding microtask races.
332
+ bubble.addEventListener('co-bubble-hide', () => {
333
+ this.bubbleDragged = false;
334
+ this.bubblePositionLocked = false;
335
+ clearTimeout(this.bubbleLockTimer);
336
+ this.closeBubbleDropdowns();
337
+ bubble.style.position = '';
338
+ bubble.style.top = '';
339
+ bubble.style.left = '';
340
+ bubble.style.transform = '';
341
+ });
342
+ bubble.addEventListener('co-bubble-show', () => {
343
+ this.bubbleDragged = false;
344
+ this.bubblePositionLocked = false;
345
+ });
346
+ // MutationObserver only handles overriding floating-ui position
347
+ // while the bubble is actively dragged or position-locked.
348
+ this.bubbleStyleObserver = new MutationObserver(() => {
349
+ if (this.applyingBubbleLock)
350
+ return;
351
+ if (!this.bubblePositionLocked && !this.bubbleDragged)
352
+ return;
353
+ this.applyBubbleFixedPosition();
354
+ });
355
+ this.bubbleStyleObserver.observe(bubble, {
356
+ attributes: true,
357
+ attributeFilter: ['style'],
358
+ });
359
+ }
360
+ /**
361
+ * Hide/show the selection bubble while a toolbar dropdown is open. Uses a
362
+ * class with `!important` so it wins over the BubbleMenu plugin's inline
363
+ * display/visibility writes. When unsuppressed, the plugin's own state
364
+ * (selection still active) reveals it again on the next update.
365
+ */
366
+ suppressBubble(on) {
367
+ if (!this.bubbleEl)
368
+ return;
369
+ this.bubbleEl.classList.toggle('co-rte-bubble--suppressed', on);
370
+ if (on)
371
+ this.closeBubbleDropdowns();
372
+ }
373
+ /** Close all open sub-dropdowns inside the bubble. */
374
+ closeBubbleDropdowns() {
375
+ if (!this.bubbleEl)
376
+ return;
377
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
378
+ d.style.display = 'none';
379
+ });
380
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
381
+ d.style.display = 'none';
382
+ });
383
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__panel').forEach(d => {
384
+ d.style.display = 'none';
385
+ });
386
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-menu').forEach(d => {
387
+ d.style.display = 'none';
388
+ });
389
+ if (this.bubbleLinkFormEl) {
390
+ this.bubbleLinkFormEl.style.display = 'none';
391
+ }
392
+ }
182
393
  refreshCharCount() {
183
394
  var _a;
184
395
  const storage = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.storage;
185
- if (storage === null || storage === void 0 ? void 0 : storage.characterCount)
396
+ if (storage === null || storage === void 0 ? void 0 : storage.characterCount) {
186
397
  this.charCount = storage.characterCount.characters();
398
+ // Update DOM directly to avoid Stencil re-renders on every keystroke
399
+ if (this.charCountEl) {
400
+ this.charCountEl.textContent = this.maxLength != null
401
+ ? `${this.charCount} / ${this.maxLength}`
402
+ : `${this.charCount}`;
403
+ }
404
+ }
187
405
  }
188
406
  syncToolbar() {
189
407
  if (this.toolbarEl && this.editor && this.toolbarEl.editor !== this.editor) {
190
408
  this.toolbarEl.editor = this.editor;
191
409
  }
410
+ if (this.toolbarEl) {
411
+ this.toolbarEl.imageUpload = this.imageUpload;
412
+ }
192
413
  }
193
414
  get resolvedToolbar() {
194
415
  if (this.toolbar !== 'auto')
195
416
  return this.toolbar;
196
- return this.rt ? this.rt.defaultToolbarForPreset(this.preset) : 'basic';
417
+ return this.rt.defaultToolbarForPreset(this.preset);
418
+ }
419
+ get resolvedFontFamilies() {
420
+ if (!this.fontFamilies)
421
+ return CoRichTextEditor.DEFAULT_FONTS;
422
+ if (typeof this.fontFamilies === 'string') {
423
+ try {
424
+ return JSON.parse(this.fontFamilies);
425
+ }
426
+ catch (_a) {
427
+ return CoRichTextEditor.DEFAULT_FONTS;
428
+ }
429
+ }
430
+ return this.fontFamilies;
431
+ }
432
+ get resolvedAccountFonts() {
433
+ // Prefer prop over loaded fonts
434
+ if (this.accountFonts) {
435
+ if (typeof this.accountFonts === 'string') {
436
+ try {
437
+ return JSON.parse(this.accountFonts);
438
+ }
439
+ catch (_a) {
440
+ return [];
441
+ }
442
+ }
443
+ return this.accountFonts;
444
+ }
445
+ return this._loadedAccountFonts;
446
+ }
447
+ registerFontFace(name, url) {
448
+ if (!url || !name || CoRichTextEditor._registeredFonts.has(name))
449
+ return;
450
+ CoRichTextEditor._registeredFonts.add(name);
451
+ try {
452
+ const face = new FontFace(name, `url("${url}")`);
453
+ face.load().then(() => document.fonts.add(face)).catch(() => { });
454
+ }
455
+ catch ( /* ignore */_a) { /* ignore */ }
456
+ }
457
+ /** Load account fonts via the fontLoader callback (called once). */
458
+ async loadFontsViaCallback() {
459
+ var _a, _b, _c;
460
+ if (this._fontLoaderCalled || !this.fontLoader)
461
+ return;
462
+ this._fontLoaderCalled = true;
463
+ this._fontLoaderLoading = true;
464
+ // Re-render to show loading state
465
+ (_a = this._fontDropdownRenderFn) === null || _a === void 0 ? void 0 : _a.call(this, '');
466
+ try {
467
+ const fonts = await this.fontLoader();
468
+ if (Array.isArray(fonts)) {
469
+ this._loadedAccountFonts = fonts.map(f => {
470
+ if (f.url)
471
+ this.registerFontFace(f.label, f.url);
472
+ return { label: f.label, value: f.value };
473
+ });
474
+ }
475
+ }
476
+ catch (e) {
477
+ console.error('[co-rich-text-editor] fontLoader error', e);
478
+ }
479
+ finally {
480
+ this._fontLoaderLoading = false;
481
+ // Re-render with loaded fonts
482
+ const filter = ((_b = this._fontDropdownSearchInput) === null || _b === void 0 ? void 0 : _b.value) || '';
483
+ (_c = this._fontDropdownRenderFn) === null || _c === void 0 ? void 0 : _c.call(this, filter);
484
+ }
197
485
  }
198
486
  get helperIcon() {
199
487
  switch (this.status) {
@@ -203,20 +491,1546 @@ const CoRichTextEditor = class {
203
491
  default: return 'info';
204
492
  }
205
493
  }
494
+ /* ── Bubble menu (imperative — outside Stencil VDOM) ── */
495
+ /**
496
+ * Create the bubble menu element imperatively. BubbleMenu v3 manages
497
+ * the element via remove()/appendChild(), which conflicts with Stencil's
498
+ * virtual DOM reconciliation. By creating it outside the VDOM, Stencil
499
+ * won't recreate or interfere with the element.
500
+ */
501
+ createBubbleElement() {
502
+ const bubble = document.createElement('div');
503
+ bubble.className = 'co-rte-bubble';
504
+ // Start hidden and absolutely positioned so it never takes document flow space.
505
+ // BubbleMenu's floating-ui will manage position via inline styles when shown.
506
+ bubble.style.visibility = 'hidden';
507
+ bubble.style.position = 'absolute';
508
+ bubble.style.top = '0';
509
+ bubble.style.left = '0';
510
+ // Prevent any bubble click from stealing editor focus
511
+ // and lock bubble position during any toolbar interaction.
512
+ bubble.addEventListener('mousedown', (e) => {
513
+ if (e.target.tagName !== 'INPUT')
514
+ e.preventDefault();
515
+ this.lockBubblePosition();
516
+ });
517
+ // Close dropdowns/panels when clicking outside the bubble
518
+ this.bubbleOutsideClickHandler = (e) => {
519
+ if (!bubble.contains(e.target)) {
520
+ this.closeBubbleDropdowns();
521
+ }
522
+ };
523
+ document.addEventListener('click', this.bubbleOutsideClickHandler, true);
524
+ // Watch for floating-ui style overrides and restore locked position
525
+ this.setupBubbleStyleObserver(bubble);
526
+ const isDocument = this.preset === 'document';
527
+ /* ── Drag handle (document only) ── */
528
+ if (isDocument) {
529
+ const dragHandle = document.createElement('div');
530
+ dragHandle.className = 'co-rte-bubble__drag-handle';
531
+ dragHandle.innerHTML = `<co-icon name="dots-six-vertical" size="14"></co-icon>`;
532
+ dragHandle.addEventListener('mousedown', (e) => {
533
+ e.preventDefault();
534
+ e.stopPropagation();
535
+ const rect = bubble.getBoundingClientRect();
536
+ this.bubbleDragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
537
+ if (!this.bubbleDragged) {
538
+ this.bubbleDragPos = { x: rect.left, y: rect.top };
539
+ }
540
+ this.bubbleDragged = true;
541
+ this.bubbleDragMoveHandler = (ev) => {
542
+ this.bubbleDragPos.x = ev.clientX - this.bubbleDragOffset.x;
543
+ this.bubbleDragPos.y = ev.clientY - this.bubbleDragOffset.y;
544
+ bubble.style.position = 'fixed';
545
+ bubble.style.top = `${this.bubbleDragPos.y}px`;
546
+ bubble.style.left = `${this.bubbleDragPos.x}px`;
547
+ bubble.style.transform = 'none';
548
+ bubble.style.visibility = 'visible';
549
+ };
550
+ this.bubbleDragEndHandler = () => {
551
+ document.removeEventListener('mousemove', this.bubbleDragMoveHandler);
552
+ document.removeEventListener('mouseup', this.bubbleDragEndHandler);
553
+ };
554
+ document.addEventListener('mousemove', this.bubbleDragMoveHandler);
555
+ document.addEventListener('mouseup', this.bubbleDragEndHandler);
556
+ });
557
+ bubble.appendChild(dragHandle);
558
+ } // end isDocument drag handle
559
+ /* ── Single row: all controls ── */
560
+ const row = document.createElement('div');
561
+ row.className = 'co-rte-bubble__row';
562
+ // --- Advanced controls (document preset only) ---
563
+ // Panels will be appended to bubble root (not inside the row) at the end.
564
+ let fontSizePanel = null;
565
+ let fontWeightPanel = null;
566
+ let lineHeightPanelEl = null;
567
+ let letterSpacingPanelEl = null;
568
+ let bgColorPanelEl = null;
569
+ let overflowResult = null;
570
+ if (isDocument) {
571
+ // --- Font Family select (with search) ---
572
+ const fontFamilyWrap = this.createBubbleFontFamilySelect();
573
+ row.appendChild(fontFamilyWrap);
574
+ // --- Font Size panel (draggable with custom input) ---
575
+ fontSizePanel = this.createBubbleFontSizePanel();
576
+ row.appendChild(fontSizePanel.wrap);
577
+ // --- Font Weight panel (draggable, two-column) ---
578
+ fontWeightPanel = this.createBubbleFontWeightPanel();
579
+ row.appendChild(fontWeightPanel.wrap);
580
+ row.appendChild(this.createSep());
581
+ // --- Text color picker ---
582
+ const colorWrap = this.createBubbleColorPicker('textColor', (color) => {
583
+ if (!this.editor)
584
+ return;
585
+ this.editor.chain().focus().setColor(color).run();
586
+ });
587
+ row.appendChild(colorWrap);
588
+ row.appendChild(this.createSep());
589
+ } // end isDocument advanced controls
590
+ // --- B I U (all presets except comment which disables underline) ---
591
+ const _s = getRichTextStrings(this.locale);
592
+ const formatBtns = [
593
+ { action: 'bold', icon: 'text-b', label: _s.bold, check: 'bold' },
594
+ { action: 'italic', icon: 'text-italic', label: _s.italic, check: 'italic' },
595
+ ];
596
+ // Underline is available on task, email, document (not comment)
597
+ if (this.preset !== 'comment') {
598
+ formatBtns.push({ action: 'underline', icon: 'text-underline', label: _s.underline, check: 'underline' });
599
+ }
600
+ formatBtns.forEach(({ action, icon, label, check }) => {
601
+ const btn = this.createBubbleBtn(icon, label, action, check, () => {
602
+ if (!this.editor)
603
+ return;
604
+ const chain = this.editor.chain().focus();
605
+ switch (action) {
606
+ case 'bold':
607
+ chain.toggleBold().run();
608
+ break;
609
+ case 'italic':
610
+ chain.toggleItalic().run();
611
+ break;
612
+ case 'underline':
613
+ chain.toggleUnderline().run();
614
+ break;
615
+ }
616
+ });
617
+ row.appendChild(btn);
618
+ });
619
+ row.appendChild(this.createSep());
620
+ // --- Alignment buttons (document and email only) ---
621
+ if (isDocument || this.preset === 'email') {
622
+ const alignments = [
623
+ { align: 'left', icon: 'text-align-left', label: _s.alignLeft },
624
+ { align: 'center', icon: 'text-align-center', label: _s.center },
625
+ { align: 'right', icon: 'text-align-right', label: _s.alignRight },
626
+ { align: 'justify', icon: 'text-align-justify', label: _s.justify },
627
+ ];
628
+ alignments.forEach(({ align, icon, label }) => {
629
+ const btn = document.createElement('button');
630
+ btn.type = 'button';
631
+ btn.className = 'co-rte-bubble__btn';
632
+ btn.title = label;
633
+ btn.setAttribute('aria-label', label);
634
+ btn.setAttribute('data-action', 'textAlign');
635
+ btn.setAttribute('data-align', align);
636
+ btn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon>`;
637
+ btn.addEventListener('click', () => {
638
+ if (!this.editor)
639
+ return;
640
+ this.editor.chain().focus().setTextAlign(align).run();
641
+ });
642
+ row.appendChild(btn);
643
+ });
644
+ row.appendChild(this.createSep());
645
+ } // end alignment
646
+ // --- Bullet / Ordered list (task, email — not comment, not document) ---
647
+ // For document preset, lists are moved to the overflow menu.
648
+ if (this.preset !== 'comment' && !isDocument) {
649
+ row.appendChild(this.createBubbleBtn('list-bullets', _s.bulletList, 'bulletList', 'bulletList', () => {
650
+ if (!this.editor)
651
+ return;
652
+ this.editor.chain().focus().toggleBulletList().run();
653
+ }));
654
+ row.appendChild(this.createBubbleBtn('list-numbers', _s.orderedList, 'orderedList', 'orderedList', () => {
655
+ if (!this.editor)
656
+ return;
657
+ this.editor.chain().focus().toggleOrderedList().run();
658
+ }));
659
+ row.appendChild(this.createSep());
660
+ } // end lists (non-document)
661
+ // --- Link (all presets) ---
662
+ const linkBtn = this.createBubbleBtn('link', _s.link, 'link', 'link', () => {
663
+ if (!this.editor)
664
+ return;
665
+ this.toggleBubbleLinkForm(true);
666
+ });
667
+ row.appendChild(linkBtn);
668
+ // --- Overflow menu (document only) ---
669
+ // Superscript, subscript, lists, strikethrough, bg color, line height,
670
+ // letter spacing, horizontal rule, clear formatting — all in overflow.
671
+ if (isDocument) {
672
+ row.appendChild(this.createSep());
673
+ lineHeightPanelEl = this.createBubbleLineHeightPanel();
674
+ letterSpacingPanelEl = this.createBubbleLetterSpacingPanel();
675
+ bgColorPanelEl = this.createBubbleBgColorPanel();
676
+ overflowResult = this.createBubbleOverflowMenu({
677
+ lineHeight: lineHeightPanelEl,
678
+ letterSpacing: letterSpacingPanelEl,
679
+ bgColor: bgColorPanelEl,
680
+ });
681
+ row.appendChild(overflowResult.overflowWrap);
682
+ } // end isDocument overflow
683
+ bubble.appendChild(row);
684
+ // Append floating panels to bubble root (outside the row, so they float freely)
685
+ if (isDocument) {
686
+ if (fontSizePanel)
687
+ bubble.appendChild(fontSizePanel.panelEl);
688
+ if (fontWeightPanel)
689
+ bubble.appendChild(fontWeightPanel.panelEl);
690
+ if (lineHeightPanelEl)
691
+ bubble.appendChild(lineHeightPanelEl);
692
+ if (letterSpacingPanelEl)
693
+ bubble.appendChild(letterSpacingPanelEl);
694
+ if (bgColorPanelEl)
695
+ bubble.appendChild(bgColorPanelEl);
696
+ }
697
+ // Link form (hidden by default)
698
+ const linkForm = document.createElement('div');
699
+ linkForm.className = 'co-rte-bubble__link-form';
700
+ linkForm.style.display = 'none';
701
+ this.bubbleLinkFormEl = linkForm;
702
+ const linkInput = document.createElement('input');
703
+ linkInput.type = 'url';
704
+ linkInput.className = 'co-rte-bubble__link-input';
705
+ linkInput.placeholder = 'https://...';
706
+ this.bubbleLinkInputEl = linkInput;
707
+ linkInput.addEventListener('keydown', (e) => {
708
+ if (e.key === 'Enter')
709
+ this.submitBubbleLinkImperative();
710
+ if (e.key === 'Escape')
711
+ this.toggleBubbleLinkForm(false);
712
+ });
713
+ const linkSubmit = document.createElement('button');
714
+ linkSubmit.type = 'button';
715
+ linkSubmit.className = 'co-rte-bubble__link-btn';
716
+ linkSubmit.innerHTML = `<co-icon name="check" size="14"></co-icon>`;
717
+ linkSubmit.addEventListener('click', () => this.submitBubbleLinkImperative());
718
+ const linkUnlink = document.createElement('button');
719
+ linkUnlink.type = 'button';
720
+ linkUnlink.className = 'co-rte-bubble__link-btn co-rte-bubble__link-unlink';
721
+ linkUnlink.title = _s.unlinkLink;
722
+ linkUnlink.innerHTML = `<co-icon name="link-break" size="14"></co-icon>`;
723
+ linkUnlink.addEventListener('click', () => {
724
+ if (!this.editor)
725
+ return;
726
+ this.editor.chain().focus().unsetLink().run();
727
+ this.toggleBubbleLinkForm(false);
728
+ });
729
+ this.bubbleLinkUnlinkEl = linkUnlink;
730
+ linkForm.appendChild(linkInput);
731
+ linkForm.appendChild(linkSubmit);
732
+ linkForm.appendChild(linkUnlink);
733
+ bubble.appendChild(linkForm);
734
+ return bubble;
735
+ }
736
+ /** Helper: create a separator span */
737
+ createSep() {
738
+ const sep = document.createElement('span');
739
+ sep.className = 'co-rte-bubble__sep';
740
+ return sep;
741
+ }
742
+ /**
743
+ * Position a dropdown above or below the trigger depending on available
744
+ * viewport space. Sets `data-position="above"|"below"` so CSS can flip.
745
+ */
746
+ positionDropdown(trigger, dropdown) {
747
+ const triggerRect = trigger.getBoundingClientRect();
748
+ // The dropdown is already display:block when this is called.
749
+ // Remove any previous position so it can be measured at its natural height.
750
+ dropdown.removeAttribute('data-position');
751
+ dropdown.style.removeProperty('left');
752
+ dropdown.style.removeProperty('transform');
753
+ const dropH = dropdown.offsetHeight || 320;
754
+ const dropW = dropdown.offsetWidth || 224;
755
+ const spaceAbove = triggerRect.top;
756
+ const spaceBelow = window.innerHeight - triggerRect.bottom;
757
+ if (spaceBelow >= dropH || spaceBelow > spaceAbove) {
758
+ dropdown.setAttribute('data-position', 'below');
759
+ }
760
+ else {
761
+ dropdown.setAttribute('data-position', 'above');
762
+ }
763
+ // Clamp horizontal position so the dropdown stays within the viewport.
764
+ // The dropdown is positioned relative to its parent (trigger wrapper).
765
+ // Default CSS uses left:50% + translateX(-50%) to center; we override
766
+ // when centering would push the dropdown outside the viewport.
767
+ const isColorDropdown = dropdown.classList.contains('co-rte-bubble__color-dropdown');
768
+ if (isColorDropdown) {
769
+ const parentRect = (trigger.parentElement || trigger).getBoundingClientRect();
770
+ // Desired center-aligned left edge in viewport coords
771
+ const idealLeft = parentRect.left + parentRect.width / 2 - dropW / 2;
772
+ const idealRight = idealLeft + dropW;
773
+ const viewportPad = 8;
774
+ if (idealLeft < viewportPad) {
775
+ // Would overflow left — align to left edge of trigger
776
+ dropdown.style.left = '0';
777
+ dropdown.style.transform = 'none';
778
+ }
779
+ else if (idealRight > window.innerWidth - viewportPad) {
780
+ // Would overflow right — align to right edge of trigger
781
+ dropdown.style.left = 'auto';
782
+ dropdown.style.right = '0';
783
+ dropdown.style.transform = 'none';
784
+ }
785
+ // else: default centering from CSS is fine
786
+ }
787
+ }
788
+ positionPanelNearBubble(panel) {
789
+ if (!this.bubbleEl)
790
+ return;
791
+ const overflowMenu = this.bubbleEl.querySelector('.co-rte-bubble__overflow-menu');
792
+ const anchorRect = overflowMenu && overflowMenu.style.display !== 'none'
793
+ ? overflowMenu.getBoundingClientRect()
794
+ : this.bubbleEl.getBoundingClientRect();
795
+ const panelH = panel.offsetHeight || 320;
796
+ const panelW = panel.offsetWidth || 230;
797
+ const gap = 4;
798
+ const pad = 8;
799
+ let top = anchorRect.top;
800
+ if (top + panelH > window.innerHeight - pad)
801
+ top = window.innerHeight - pad - panelH;
802
+ if (top < pad)
803
+ top = pad;
804
+ let left = anchorRect.left - panelW - gap;
805
+ if (left < pad)
806
+ left = anchorRect.right + gap;
807
+ if (left + panelW > window.innerWidth - pad)
808
+ left = window.innerWidth - pad - panelW;
809
+ panel.style.position = 'fixed';
810
+ panel.style.top = `${top}px`;
811
+ panel.style.left = `${left}px`;
812
+ panel.style.bottom = 'auto';
813
+ panel.style.right = 'auto';
814
+ panel.style.transform = 'none';
815
+ panel.removeAttribute('data-position');
816
+ }
817
+ /** Helper: create a toggle button for the bubble */
818
+ createBubbleBtn(icon, label, action, check, onClick) {
819
+ const btn = document.createElement('button');
820
+ btn.type = 'button';
821
+ btn.className = 'co-rte-bubble__btn';
822
+ btn.title = label;
823
+ btn.setAttribute('aria-label', label);
824
+ btn.setAttribute('data-action', action);
825
+ btn.setAttribute('data-check', check);
826
+ btn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon>`;
827
+ btn.addEventListener('click', onClick);
828
+ return btn;
829
+ }
830
+ /** Creates the font family dropdown with search for the bubble menu. */
831
+ createBubbleFontFamilySelect() {
832
+ const wrap = document.createElement('div');
833
+ wrap.className = 'co-rte-bubble__select co-rte-bubble__select--font';
834
+ wrap.setAttribute('data-select', 'fontFamily');
835
+ const trigger = document.createElement('button');
836
+ trigger.type = 'button';
837
+ trigger.className = 'co-rte-bubble__select-trigger';
838
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">Sans-serif</span><co-icon name="caret-down" size="12"></co-icon>`;
839
+ const dropdown = document.createElement('div');
840
+ dropdown.className = 'co-rte-bubble__select-dropdown co-rte-bubble__select-dropdown--font';
841
+ dropdown.style.display = 'none';
842
+ // Search input
843
+ const searchWrap = document.createElement('div');
844
+ searchWrap.className = 'co-rte-bubble__font-search';
845
+ const searchInput = document.createElement('input');
846
+ searchInput.type = 'text';
847
+ searchInput.className = 'co-rte-bubble__font-search-input';
848
+ searchInput.placeholder = getRichTextStrings(this.locale).searchFont;
849
+ searchWrap.appendChild(searchInput);
850
+ dropdown.appendChild(searchWrap);
851
+ // Font list container
852
+ const listEl = document.createElement('div');
853
+ listEl.className = 'co-rte-bubble__font-list';
854
+ dropdown.appendChild(listEl);
855
+ const createFontOption = (label, value) => {
856
+ const opt = document.createElement('button');
857
+ opt.type = 'button';
858
+ opt.className = 'co-rte-bubble__select-option';
859
+ opt.setAttribute('data-value', value);
860
+ opt.textContent = label;
861
+ opt.style.fontFamily = value.includes(',') ? value : `"${value}", sans-serif`;
862
+ opt.addEventListener('click', () => {
863
+ if (!this.editor)
864
+ return;
865
+ this.editor.chain().focus().setFontFamily(value).run();
866
+ dropdown.style.display = 'none';
867
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
868
+ if (labelEl)
869
+ labelEl.textContent = label;
870
+ searchInput.value = '';
871
+ this.coFontPopupHide.emit();
872
+ });
873
+ return opt;
874
+ };
875
+ const renderFonts = (filter) => {
876
+ listEl.innerHTML = '';
877
+ const term = filter.toLowerCase();
878
+ const accountFonts = this.resolvedAccountFonts;
879
+ const systemFonts = this.resolvedFontFamilies;
880
+ const filteredAccount = term ? accountFonts.filter(f => f.label.toLowerCase().includes(term)) : accountFonts;
881
+ const filteredSystem = term ? systemFonts.filter(f => f.label.toLowerCase().includes(term)) : systemFonts;
882
+ if (!filteredAccount.length && !filteredSystem.length) {
883
+ const empty = document.createElement('div');
884
+ empty.className = 'co-rte-bubble__font-empty';
885
+ empty.textContent = getRichTextStrings(this.locale).noResults;
886
+ listEl.appendChild(empty);
887
+ return;
888
+ }
889
+ // Loading indicator
890
+ if ((this.fontsLoading || this._fontLoaderLoading) && !filteredAccount.length) {
891
+ const loading = document.createElement('div');
892
+ loading.className = 'co-rte-bubble__font-empty';
893
+ loading.textContent = getRichTextStrings(this.locale).loadingFonts;
894
+ listEl.appendChild(loading);
895
+ }
896
+ // Imported fonts section
897
+ if (filteredAccount.length) {
898
+ const header = document.createElement('div');
899
+ header.className = 'co-rte-bubble__font-section-header';
900
+ header.textContent = getRichTextStrings(this.locale).importedFonts;
901
+ listEl.appendChild(header);
902
+ filteredAccount.forEach(({ label, value }) => listEl.appendChild(createFontOption(label, value)));
903
+ }
904
+ // System fonts section
905
+ if (filteredSystem.length) {
906
+ const header = document.createElement('div');
907
+ header.className = 'co-rte-bubble__font-section-header';
908
+ header.textContent = getRichTextStrings(this.locale).systemFonts;
909
+ listEl.appendChild(header);
910
+ filteredSystem.forEach(({ label, value }) => listEl.appendChild(createFontOption(label, value)));
911
+ }
912
+ };
913
+ searchInput.addEventListener('input', () => renderFonts(searchInput.value));
914
+ // Re-render fonts when accountFonts prop changes (MutationObserver on the host)
915
+ this._fontDropdownRenderFn = renderFonts;
916
+ this._fontDropdownSearchInput = searchInput;
917
+ trigger.addEventListener('click', () => {
918
+ const parent = wrap.closest('.co-rte-bubble');
919
+ if (parent) {
920
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
921
+ if (d !== dropdown)
922
+ d.style.display = 'none';
923
+ });
924
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
925
+ d.style.display = 'none';
926
+ });
927
+ }
928
+ const isOpen = dropdown.style.display !== 'none';
929
+ dropdown.style.display = isOpen ? 'none' : 'block';
930
+ if (!isOpen) {
931
+ this.coFontPopupShow.emit();
932
+ this.loadFontsViaCallback();
933
+ this.positionDropdown(trigger, dropdown);
934
+ renderFonts('');
935
+ setTimeout(() => searchInput.focus(), 0);
936
+ }
937
+ else {
938
+ this.coFontPopupHide.emit();
939
+ }
940
+ });
941
+ wrap.appendChild(trigger);
942
+ wrap.appendChild(dropdown);
943
+ return wrap;
944
+ }
945
+ /** Creates a compact dropdown-select for the bubble menu. */
946
+ createBubbleSelect(name, options, defaultLabel, onChange) {
947
+ const wrap = document.createElement('div');
948
+ wrap.className = 'co-rte-bubble__select';
949
+ wrap.setAttribute('data-select', name);
950
+ const trigger = document.createElement('button');
951
+ trigger.type = 'button';
952
+ trigger.className = 'co-rte-bubble__select-trigger';
953
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">${defaultLabel}</span><co-icon name="caret-down" size="12"></co-icon>`;
954
+ const dropdown = document.createElement('div');
955
+ dropdown.className = 'co-rte-bubble__select-dropdown';
956
+ dropdown.style.display = 'none';
957
+ options.forEach(({ label, value }) => {
958
+ const opt = document.createElement('button');
959
+ opt.type = 'button';
960
+ opt.className = 'co-rte-bubble__select-option';
961
+ opt.setAttribute('data-value', value);
962
+ opt.textContent = label;
963
+ // Preview font weight in the option
964
+ if (name === 'fontWeight') {
965
+ opt.style.fontWeight = value;
966
+ }
967
+ opt.addEventListener('click', () => {
968
+ onChange(value);
969
+ dropdown.style.display = 'none';
970
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
971
+ if (labelEl)
972
+ labelEl.textContent = label;
973
+ });
974
+ dropdown.appendChild(opt);
975
+ });
976
+ trigger.addEventListener('click', () => {
977
+ // Close other open dropdowns in the bubble
978
+ const parent = wrap.closest('.co-rte-bubble');
979
+ if (parent) {
980
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
981
+ if (d !== dropdown)
982
+ d.style.display = 'none';
983
+ });
984
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
985
+ d.style.display = 'none';
986
+ });
987
+ }
988
+ const isOpen = dropdown.style.display !== 'none';
989
+ dropdown.style.display = isOpen ? 'none' : 'block';
990
+ if (!isOpen)
991
+ this.positionDropdown(trigger, dropdown);
992
+ });
993
+ wrap.appendChild(trigger);
994
+ wrap.appendChild(dropdown);
995
+ return wrap;
996
+ }
997
+ /** Creates a compact color picker button for the bubble menu. */
998
+ createBubbleColorPicker(name, onChange) {
999
+ const colors = [
1000
+ '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc',
1001
+ '#d9d9d9', '#efefef', '#f3f3f3', '#ffffff',
1002
+ '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff',
1003
+ '#4a86e8', '#0000ff', '#9900ff', '#ff00ff',
1004
+ '#e6b8af', '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3',
1005
+ '#c9daf8', '#cfe2f3', '#d9d2e9', '#ead1dc',
1006
+ ];
1007
+ const wrap = document.createElement('div');
1008
+ wrap.className = 'co-rte-bubble__color';
1009
+ wrap.setAttribute('data-color', name);
1010
+ const iconName = name === 'textColor' ? '' : 'highlighter';
1011
+ const trigger = document.createElement('button');
1012
+ trigger.type = 'button';
1013
+ trigger.className = 'co-rte-bubble__btn';
1014
+ const _cs = getRichTextStrings(this.locale);
1015
+ trigger.title = name === 'textColor' ? _cs.textColor : _cs.backgroundColor;
1016
+ if (name === 'textColor') {
1017
+ trigger.innerHTML = `<span class="co-rte-bubble__color-indicator"><span class="co-rte-bubble__color-letter">A</span><span class="co-rte-bubble__color-bar" style="background:#000000"></span></span>`;
1018
+ }
1019
+ else {
1020
+ trigger.innerHTML = `<co-icon name="${iconName}" size="16"></co-icon>`;
1021
+ }
1022
+ const dropdown = document.createElement('div');
1023
+ dropdown.className = 'co-rte-bubble__color-dropdown';
1024
+ dropdown.style.display = 'none';
1025
+ const colorTitle = name === 'textColor' ? _cs.textColor : _cs.backgroundColor;
1026
+ const { resetDrag: resetColorDrag } = this.addDragHeader(dropdown, colorTitle);
1027
+ // Prevent focus loss
1028
+ dropdown.addEventListener('mousedown', (e) => {
1029
+ if (e.target.tagName !== 'INPUT')
1030
+ e.preventDefault();
1031
+ this.lockBubblePosition();
1032
+ });
1033
+ const grid = document.createElement('div');
1034
+ grid.className = 'co-rte-bubble__color-grid';
1035
+ colors.forEach(color => {
1036
+ const swatch = document.createElement('button');
1037
+ swatch.type = 'button';
1038
+ swatch.className = 'co-rte-bubble__color-swatch';
1039
+ swatch.style.background = color;
1040
+ if (color === '#ffffff') {
1041
+ swatch.style.border = '1px solid #e0e0e0';
1042
+ }
1043
+ swatch.addEventListener('click', () => {
1044
+ onChange(color);
1045
+ dropdown.style.display = 'none';
1046
+ });
1047
+ grid.appendChild(swatch);
1048
+ });
1049
+ // Hex input
1050
+ const hexRow = document.createElement('div');
1051
+ hexRow.className = 'co-rte-bubble__color-hex';
1052
+ const hexInput = document.createElement('input');
1053
+ hexInput.type = 'text';
1054
+ hexInput.className = 'co-rte-bubble__color-hex-input';
1055
+ hexInput.placeholder = '#hex';
1056
+ hexInput.maxLength = 7;
1057
+ hexInput.addEventListener('keydown', (e) => {
1058
+ if (e.key === 'Enter') {
1059
+ const val = hexInput.value.trim();
1060
+ if (/^#[0-9a-fA-F]{3,6}$/.test(val)) {
1061
+ onChange(val);
1062
+ dropdown.style.display = 'none';
1063
+ hexInput.value = '';
1064
+ }
1065
+ }
1066
+ });
1067
+ // Clear color button
1068
+ const clearBtn = document.createElement('button');
1069
+ clearBtn.type = 'button';
1070
+ clearBtn.className = 'co-rte-bubble__color-clear';
1071
+ clearBtn.innerHTML = `<co-icon name="x" size="12"></co-icon> ${_cs.noColor}`;
1072
+ clearBtn.addEventListener('click', () => {
1073
+ if (!this.editor)
1074
+ return;
1075
+ if (name === 'textColor')
1076
+ this.editor.chain().focus().unsetColor().run();
1077
+ else
1078
+ this.editor.chain().focus().unsetHighlight().run();
1079
+ dropdown.style.display = 'none';
1080
+ });
1081
+ dropdown.appendChild(grid);
1082
+ hexRow.appendChild(hexInput);
1083
+ dropdown.appendChild(hexRow);
1084
+ dropdown.appendChild(clearBtn);
1085
+ trigger.addEventListener('click', () => {
1086
+ const parent = wrap.closest('.co-rte-bubble');
1087
+ if (parent) {
1088
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
1089
+ d.style.display = 'none';
1090
+ });
1091
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
1092
+ if (d !== dropdown)
1093
+ d.style.display = 'none';
1094
+ });
1095
+ }
1096
+ const isOpen = dropdown.style.display !== 'none';
1097
+ if (isOpen) {
1098
+ dropdown.style.display = 'none';
1099
+ }
1100
+ else {
1101
+ resetColorDrag();
1102
+ dropdown.style.position = '';
1103
+ dropdown.style.top = '';
1104
+ dropdown.style.left = '';
1105
+ dropdown.style.bottom = '';
1106
+ dropdown.style.right = '';
1107
+ dropdown.style.transform = '';
1108
+ dropdown.style.display = 'block';
1109
+ this.positionDropdown(trigger, dropdown);
1110
+ }
1111
+ });
1112
+ wrap.appendChild(trigger);
1113
+ wrap.appendChild(dropdown);
1114
+ return wrap;
1115
+ }
1116
+ /** Close all bubble popups EXCEPT the given element. */
1117
+ closeAllBubblePopups(...except) {
1118
+ if (!this.bubbleEl)
1119
+ return;
1120
+ const keep = except.filter(Boolean);
1121
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
1122
+ if (!keep.includes(d))
1123
+ d.style.display = 'none';
1124
+ });
1125
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
1126
+ if (!keep.includes(d))
1127
+ d.style.display = 'none';
1128
+ });
1129
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__panel').forEach(d => {
1130
+ if (!keep.includes(d))
1131
+ d.style.display = 'none';
1132
+ });
1133
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-menu').forEach(d => {
1134
+ if (!keep.includes(d))
1135
+ d.style.display = 'none';
1136
+ });
1137
+ if (this.bubbleLinkFormEl && !keep.includes(this.bubbleLinkFormEl)) {
1138
+ this.bubbleLinkFormEl.style.display = 'none';
1139
+ }
1140
+ }
1141
+ addDragHeader(panel, title) {
1142
+ let dragged = false;
1143
+ let dragPos = { x: 0, y: 0 };
1144
+ let dragOffset = { x: 0, y: 0 };
1145
+ const header = document.createElement('div');
1146
+ header.className = 'co-rte-bubble__panel-header';
1147
+ const dragHandle = document.createElement('div');
1148
+ dragHandle.className = 'co-rte-bubble__panel-drag';
1149
+ dragHandle.innerHTML = `<co-icon name="dots-six" size="14"></co-icon>`;
1150
+ const titleEl = document.createElement('span');
1151
+ titleEl.className = 'co-rte-bubble__panel-title';
1152
+ titleEl.textContent = title;
1153
+ const closeBtn = document.createElement('button');
1154
+ closeBtn.type = 'button';
1155
+ closeBtn.className = 'co-rte-bubble__panel-close';
1156
+ closeBtn.innerHTML = `<co-icon name="x" size="14"></co-icon>`;
1157
+ closeBtn.addEventListener('click', () => { panel.style.display = 'none'; });
1158
+ header.appendChild(dragHandle);
1159
+ header.appendChild(titleEl);
1160
+ header.appendChild(closeBtn);
1161
+ dragHandle.addEventListener('mousedown', (e) => {
1162
+ e.preventDefault();
1163
+ e.stopPropagation();
1164
+ const rect = panel.getBoundingClientRect();
1165
+ dragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1166
+ if (!dragged)
1167
+ dragPos = { x: rect.left, y: rect.top };
1168
+ dragged = true;
1169
+ const onMove = (ev) => {
1170
+ dragPos.x = ev.clientX - dragOffset.x;
1171
+ dragPos.y = ev.clientY - dragOffset.y;
1172
+ panel.style.position = 'fixed';
1173
+ panel.style.top = `${dragPos.y}px`;
1174
+ panel.style.left = `${dragPos.x}px`;
1175
+ panel.style.bottom = 'auto';
1176
+ panel.style.right = 'auto';
1177
+ panel.style.transform = 'none';
1178
+ panel.removeAttribute('data-position');
1179
+ };
1180
+ const onUp = () => {
1181
+ document.removeEventListener('mousemove', onMove);
1182
+ document.removeEventListener('mouseup', onUp);
1183
+ };
1184
+ document.addEventListener('mousemove', onMove);
1185
+ document.addEventListener('mouseup', onUp);
1186
+ });
1187
+ const resetDrag = () => { dragged = false; };
1188
+ panel.insertBefore(header, panel.firstChild);
1189
+ return { header, resetDrag };
1190
+ }
1191
+ /** Generic draggable panel factory. */
1192
+ createBubblePanel(config) {
1193
+ const wrap = document.createElement('div');
1194
+ wrap.className = 'co-rte-bubble__select';
1195
+ wrap.setAttribute('data-select', config.name);
1196
+ const trigger = document.createElement('button');
1197
+ trigger.type = 'button';
1198
+ trigger.className = 'co-rte-bubble__select-trigger';
1199
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">${config.triggerLabel}</span><co-icon name="caret-down" size="12"></co-icon>`;
1200
+ const panel = document.createElement('div');
1201
+ panel.className = 'co-rte-bubble__panel';
1202
+ panel.setAttribute('data-panel', config.name);
1203
+ panel.style.display = 'none';
1204
+ // Header
1205
+ const header = document.createElement('div');
1206
+ header.className = 'co-rte-bubble__panel-header';
1207
+ const dragHandle = document.createElement('div');
1208
+ dragHandle.className = 'co-rte-bubble__panel-drag';
1209
+ dragHandle.innerHTML = `<co-icon name="dots-six" size="14"></co-icon>`;
1210
+ const titleEl = document.createElement('span');
1211
+ titleEl.className = 'co-rte-bubble__panel-title';
1212
+ titleEl.textContent = config.title;
1213
+ const closeBtn = document.createElement('button');
1214
+ closeBtn.type = 'button';
1215
+ closeBtn.className = 'co-rte-bubble__panel-close';
1216
+ closeBtn.innerHTML = `<co-icon name="x" size="14"></co-icon>`;
1217
+ closeBtn.addEventListener('click', () => { panel.style.display = 'none'; });
1218
+ header.appendChild(dragHandle);
1219
+ header.appendChild(titleEl);
1220
+ header.appendChild(closeBtn);
1221
+ panel.appendChild(header);
1222
+ // Panel drag
1223
+ let panelDragged = false;
1224
+ let panelDragPos = { x: 0, y: 0 };
1225
+ let panelDragOffset = { x: 0, y: 0 };
1226
+ dragHandle.addEventListener('mousedown', (e) => {
1227
+ e.preventDefault();
1228
+ e.stopPropagation();
1229
+ const rect = panel.getBoundingClientRect();
1230
+ panelDragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1231
+ if (!panelDragged)
1232
+ panelDragPos = { x: rect.left, y: rect.top };
1233
+ panelDragged = true;
1234
+ const onMove = (ev) => {
1235
+ panelDragPos.x = ev.clientX - panelDragOffset.x;
1236
+ panelDragPos.y = ev.clientY - panelDragOffset.y;
1237
+ panel.style.position = 'fixed';
1238
+ panel.style.top = `${panelDragPos.y}px`;
1239
+ panel.style.left = `${panelDragPos.x}px`;
1240
+ panel.style.bottom = 'auto';
1241
+ panel.style.right = 'auto';
1242
+ panel.style.transform = 'none';
1243
+ panel.removeAttribute('data-position');
1244
+ };
1245
+ const onUp = () => {
1246
+ document.removeEventListener('mousemove', onMove);
1247
+ document.removeEventListener('mouseup', onUp);
1248
+ };
1249
+ document.addEventListener('mousemove', onMove);
1250
+ document.addEventListener('mouseup', onUp);
1251
+ });
1252
+ // Custom input
1253
+ if (config.hasCustomInput) {
1254
+ const inputWrap = document.createElement('div');
1255
+ inputWrap.className = 'co-rte-bubble__panel-input-wrap';
1256
+ const input = document.createElement('input');
1257
+ input.type = config.inputType || 'text';
1258
+ input.className = 'co-rte-bubble__panel-input';
1259
+ input.placeholder = config.inputPlaceholder || '';
1260
+ input.addEventListener('mousedown', (e) => e.stopPropagation());
1261
+ input.addEventListener('keydown', (e) => {
1262
+ if (e.key === 'Enter') {
1263
+ const val = input.value.trim();
1264
+ if (val && config.onCustomInput) {
1265
+ config.onCustomInput(val);
1266
+ input.value = '';
1267
+ }
1268
+ }
1269
+ if (e.key === 'Escape') {
1270
+ panel.style.display = 'none';
1271
+ }
1272
+ });
1273
+ inputWrap.appendChild(input);
1274
+ panel.appendChild(inputWrap);
1275
+ }
1276
+ // Options
1277
+ const optionsWrap = document.createElement('div');
1278
+ optionsWrap.className = 'co-rte-bubble__panel-options';
1279
+ config.options.forEach(opt => {
1280
+ const btn = document.createElement('button');
1281
+ btn.type = 'button';
1282
+ btn.className = 'co-rte-bubble__panel-option';
1283
+ btn.setAttribute('data-value', opt.value);
1284
+ if (config.renderOption) {
1285
+ config.renderOption(opt, btn);
1286
+ }
1287
+ else {
1288
+ btn.textContent = opt.label;
1289
+ }
1290
+ btn.addEventListener('click', () => {
1291
+ config.onSelect(opt.value);
1292
+ panel.style.display = 'none';
1293
+ panelDragged = false;
1294
+ });
1295
+ optionsWrap.appendChild(btn);
1296
+ });
1297
+ panel.appendChild(optionsWrap);
1298
+ // Prevent bubble from losing focus
1299
+ panel.addEventListener('mousedown', (e) => {
1300
+ if (e.target.tagName !== 'INPUT')
1301
+ e.preventDefault();
1302
+ this.lockBubblePosition();
1303
+ });
1304
+ // Toggle logic
1305
+ const togglePanel = () => {
1306
+ this.closeAllBubblePopups(panel);
1307
+ const isOpen = panel.style.display !== 'none';
1308
+ if (isOpen) {
1309
+ panel.style.display = 'none';
1310
+ }
1311
+ else {
1312
+ panelDragged = false;
1313
+ panel.style.position = '';
1314
+ panel.style.top = '';
1315
+ panel.style.left = '';
1316
+ panel.style.bottom = '';
1317
+ panel.style.right = '';
1318
+ panel.style.transform = '';
1319
+ panel.style.display = 'block';
1320
+ this.positionDropdown(trigger, panel);
1321
+ }
1322
+ };
1323
+ trigger.addEventListener('click', togglePanel);
1324
+ wrap.appendChild(trigger);
1325
+ const updateLabel = (text) => {
1326
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
1327
+ if (labelEl)
1328
+ labelEl.textContent = text;
1329
+ };
1330
+ return { wrap, panelEl: panel, updateLabel };
1331
+ }
1332
+ /** Font size panel with visual preview and custom input. */
1333
+ createBubbleFontSizePanel() {
1334
+ const _fs = getRichTextStrings(this.locale);
1335
+ const headings = [
1336
+ { label: _fs.title, value: 'h1' },
1337
+ { label: _fs.heading1, value: 'h2' },
1338
+ { label: _fs.heading2, value: 'h3' },
1339
+ ];
1340
+ const sizes = ['8px', '10px', '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px', '64px', '72px'];
1341
+ const allOptions = [
1342
+ ...headings,
1343
+ { label: '---', value: '---' },
1344
+ ...sizes.map(s => ({ label: s, value: s })),
1345
+ ];
1346
+ return this.createBubblePanel({
1347
+ name: 'fontSize',
1348
+ title: _fs.fontSize,
1349
+ triggerLabel: '16px',
1350
+ hasCustomInput: true,
1351
+ inputType: 'number',
1352
+ inputPlaceholder: _fs.writeSize,
1353
+ options: allOptions,
1354
+ renderOption: (opt, btn) => {
1355
+ if (opt.value === '---') {
1356
+ btn.className = 'co-rte-bubble__panel-sep';
1357
+ btn.disabled = true;
1358
+ btn.style.pointerEvents = 'none';
1359
+ return;
1360
+ }
1361
+ if (opt.value === 'h1') {
1362
+ btn.textContent = opt.label;
1363
+ btn.style.fontSize = '24px';
1364
+ btn.style.fontWeight = '700';
1365
+ btn.style.padding = '6px 8px';
1366
+ }
1367
+ else if (opt.value === 'h2') {
1368
+ btn.textContent = opt.label;
1369
+ btn.style.fontSize = '18px';
1370
+ btn.style.fontWeight = '700';
1371
+ btn.style.padding = '5px 8px';
1372
+ }
1373
+ else if (opt.value === 'h3') {
1374
+ btn.textContent = opt.label;
1375
+ btn.style.fontSize = '15px';
1376
+ btn.style.fontWeight = '700';
1377
+ btn.style.padding = '4px 8px';
1378
+ }
1379
+ else {
1380
+ btn.textContent = opt.label;
1381
+ const px = parseInt(opt.value);
1382
+ btn.style.fontSize = `${Math.min(px, 36)}px`;
1383
+ btn.style.lineHeight = '1.3';
1384
+ }
1385
+ },
1386
+ onSelect: (val) => {
1387
+ if (!this.editor || val === '---')
1388
+ return;
1389
+ const chain = this.editor.chain().focus();
1390
+ if (val === 'h1')
1391
+ chain.toggleHeading({ level: 1 }).run();
1392
+ else if (val === 'h2')
1393
+ chain.toggleHeading({ level: 2 }).run();
1394
+ else if (val === 'h3')
1395
+ chain.toggleHeading({ level: 3 }).run();
1396
+ else
1397
+ chain.setFontSize(val).run();
1398
+ },
1399
+ onCustomInput: (val) => {
1400
+ if (!this.editor)
1401
+ return;
1402
+ const num = parseInt(val);
1403
+ if (num > 0)
1404
+ this.editor.chain().focus().setFontSize(`${num}px`).run();
1405
+ },
1406
+ });
1407
+ }
1408
+ /** Font weight panel with two-column layout and visual preview. */
1409
+ createBubbleFontWeightPanel() {
1410
+ const weights = [
1411
+ { label: 'Thin', value: '100' },
1412
+ { label: 'Extra Light', value: '200' },
1413
+ { label: 'Light', value: '300' },
1414
+ { label: 'Regular', value: '400' },
1415
+ { label: 'Medium', value: '500' },
1416
+ { label: 'Semi Bold', value: '600' },
1417
+ { label: 'Bold', value: '700' },
1418
+ { label: 'Extra Bold', value: '800' },
1419
+ { label: 'Black', value: '900' },
1420
+ ];
1421
+ return this.createBubblePanel({
1422
+ name: 'fontWeight',
1423
+ title: getRichTextStrings(this.locale).fontWeight,
1424
+ triggerLabel: 'Regular',
1425
+ hasCustomInput: false,
1426
+ options: weights,
1427
+ renderOption: (opt, btn) => {
1428
+ btn.style.fontWeight = opt.value;
1429
+ btn.innerHTML = `<span class="co-rte-bubble__panel-opt-row"><span>${opt.label}</span><span class="co-rte-bubble__panel-opt-value">${opt.value}</span></span>`;
1430
+ },
1431
+ onSelect: (val) => {
1432
+ if (!this.editor)
1433
+ return;
1434
+ this.editor.chain().focus().setFontWeight(val).run();
1435
+ },
1436
+ });
1437
+ }
1438
+ /** Line height panel with custom input. */
1439
+ createBubbleLineHeightPanel() {
1440
+ const options = [
1441
+ { label: '0.5', value: '0.5' },
1442
+ { label: '1', value: '1' },
1443
+ { label: '1.15', value: '1.15' },
1444
+ { label: '1.5', value: '1.5' },
1445
+ { label: '1.75', value: '1.75' },
1446
+ { label: '2', value: '2' },
1447
+ { label: '2.5', value: '2.5' },
1448
+ { label: '3', value: '3' },
1449
+ { label: '---', value: '---' },
1450
+ { label: '16px', value: '16px' },
1451
+ { label: '20px', value: '20px' },
1452
+ { label: '24px', value: '24px' },
1453
+ { label: '32px', value: '32px' },
1454
+ { label: '---', value: '---2' },
1455
+ { label: '100%', value: '100%' },
1456
+ { label: '150%', value: '150%' },
1457
+ { label: '200%', value: '200%' },
1458
+ ];
1459
+ const { panelEl } = this.createBubblePanel({
1460
+ name: 'lineHeight',
1461
+ title: getRichTextStrings(this.locale).lineSpacing,
1462
+ triggerLabel: '1.5',
1463
+ hasCustomInput: true,
1464
+ inputPlaceholder: '1.5, 20px, 150%...',
1465
+ options,
1466
+ renderOption: (opt, btn) => {
1467
+ if (opt.value.startsWith('---')) {
1468
+ btn.className = 'co-rte-bubble__panel-sep';
1469
+ btn.disabled = true;
1470
+ btn.style.pointerEvents = 'none';
1471
+ return;
1472
+ }
1473
+ btn.textContent = opt.label;
1474
+ },
1475
+ onSelect: (val) => {
1476
+ if (!this.editor || val.startsWith('---'))
1477
+ return;
1478
+ this.editor.chain().focus().setLineHeight(val).run();
1479
+ },
1480
+ onCustomInput: (val) => {
1481
+ if (!this.editor)
1482
+ return;
1483
+ this.editor.chain().focus().setLineHeight(val).run();
1484
+ },
1485
+ });
1486
+ return panelEl;
1487
+ }
1488
+ /** Letter spacing panel with custom input. */
1489
+ createBubbleLetterSpacingPanel() {
1490
+ const options = [
1491
+ { label: '-0.05em', value: '-0.05em' },
1492
+ { label: 'Normal', value: 'normal' },
1493
+ { label: '0.05em', value: '0.05em' },
1494
+ { label: '0.1em', value: '0.1em' },
1495
+ { label: '0.2em', value: '0.2em' },
1496
+ ];
1497
+ const { panelEl } = this.createBubblePanel({
1498
+ name: 'letterSpacing',
1499
+ title: getRichTextStrings(this.locale).letterSpacing,
1500
+ triggerLabel: getRichTextStrings(this.locale).normal,
1501
+ hasCustomInput: true,
1502
+ inputPlaceholder: 'Custom (em)...',
1503
+ options,
1504
+ onSelect: (val) => {
1505
+ if (!this.editor)
1506
+ return;
1507
+ if (val === 'normal')
1508
+ this.editor.chain().focus().unsetLetterSpacing().run();
1509
+ else
1510
+ this.editor.chain().focus().setLetterSpacing(val).run();
1511
+ },
1512
+ onCustomInput: (val) => {
1513
+ if (!this.editor)
1514
+ return;
1515
+ const v = val.includes('em') || val.includes('px') ? val : `${val}em`;
1516
+ this.editor.chain().focus().setLetterSpacing(v).run();
1517
+ },
1518
+ });
1519
+ return panelEl;
1520
+ }
1521
+ /** Background color panel for overflow menu. */
1522
+ createBubbleBgColorPanel() {
1523
+ const bgColorWrap = this.createBubbleColorPicker('bgColor', (color) => {
1524
+ if (!this.editor)
1525
+ return;
1526
+ this.editor.chain().focus().toggleHighlight({ color }).run();
1527
+ });
1528
+ // Hide the trigger button — bg color is only opened from the overflow menu.
1529
+ const triggerBtn = bgColorWrap.querySelector('.co-rte-bubble__btn');
1530
+ if (triggerBtn)
1531
+ triggerBtn.style.display = 'none';
1532
+ return bgColorWrap;
1533
+ }
1534
+ /** Overflow menu (three-dots ⋮) with dynamic table context section. */
1535
+ createBubbleOverflowMenu(panels) {
1536
+ const wrap = document.createElement('div');
1537
+ wrap.className = 'co-rte-bubble__overflow';
1538
+ const btn = document.createElement('button');
1539
+ btn.type = 'button';
1540
+ btn.className = 'co-rte-bubble__btn';
1541
+ const _os = getRichTextStrings(this.locale);
1542
+ btn.title = _os.moreOptions;
1543
+ btn.setAttribute('aria-label', _os.moreOptions);
1544
+ btn.innerHTML = `<co-icon name="dots-three" size="16"></co-icon>`;
1545
+ const menu = document.createElement('div');
1546
+ menu.className = 'co-rte-bubble__overflow-menu';
1547
+ menu.style.display = 'none';
1548
+ const { resetDrag: resetOverflowDrag } = this.addDragHeader(menu, _os.moreOptions);
1549
+ // Prevent focus loss
1550
+ menu.addEventListener('mousedown', (e) => {
1551
+ if (e.target.tagName !== 'INPUT')
1552
+ e.preventDefault();
1553
+ this.lockBubblePosition();
1554
+ });
1555
+ const items = [
1556
+ { icon: 'text-strikethrough', label: _os.strikethrough, action: 'strike', check: 'strike', type: 'toggle' },
1557
+ { icon: 'highlighter', label: _os.backgroundColor, action: 'bgColor', type: 'panel', panel: panels.bgColor },
1558
+ { icon: 'list-bullets', label: _os.bulletList, action: 'bulletList', check: 'bulletList', type: 'toggle' },
1559
+ { icon: 'list-numbers', label: _os.orderedList, action: 'orderedList', check: 'orderedList', type: 'toggle' },
1560
+ { icon: 'text-superscript', label: _os.superscript, action: 'superscript', check: 'superscript', type: 'toggle' },
1561
+ { icon: 'text-subscript', label: _os.subscript, action: 'subscript', check: 'subscript', type: 'toggle' },
1562
+ { icon: 'line-segments', label: _os.lineSpacing, action: 'lineHeight', type: 'panel', panel: panels.lineHeight, valueAttr: 'lineHeight' },
1563
+ { icon: 'text-aa', label: _os.letterSpacing, action: 'letterSpacing', type: 'panel', panel: panels.letterSpacing, valueAttr: 'letterSpacing' },
1564
+ { icon: 'minus', label: _os.horizontalRule, action: 'horizontalRule', type: 'toggle' },
1565
+ { icon: 'eraser', label: _os.clearFormat, action: 'clearFormat', type: 'toggle' },
1566
+ ];
1567
+ items.forEach((item) => {
1568
+ if (item.action === 'lineHeight' || item.action === 'horizontalRule') {
1569
+ const sep = document.createElement('div');
1570
+ sep.className = 'co-rte-bubble__overflow-sep';
1571
+ menu.appendChild(sep);
1572
+ }
1573
+ const itemBtn = document.createElement('button');
1574
+ itemBtn.type = 'button';
1575
+ itemBtn.className = 'co-rte-bubble__overflow-item';
1576
+ itemBtn.setAttribute('data-overflow-item', item.action);
1577
+ if (item.check)
1578
+ itemBtn.setAttribute('data-check', item.check);
1579
+ let valueSpan = '';
1580
+ if (item.valueAttr) {
1581
+ valueSpan = `<span class="co-rte-bubble__overflow-value" data-overflow-value="${item.valueAttr}"></span>`;
1582
+ }
1583
+ itemBtn.innerHTML = `<co-icon name="${item.icon}" size="16"></co-icon><span>${item.label}</span>${valueSpan}`;
1584
+ itemBtn.addEventListener('click', () => {
1585
+ if (!this.editor)
1586
+ return;
1587
+ if (item.type === 'panel' && item.panel) {
1588
+ if (item.action === 'bgColor') {
1589
+ const dd = item.panel.querySelector('.co-rte-bubble__color-dropdown');
1590
+ if (dd) {
1591
+ const isOpen = dd.style.display !== 'none';
1592
+ this.closeAllBubblePopups(menu, isOpen ? undefined : dd);
1593
+ dd.style.display = isOpen ? 'none' : 'block';
1594
+ if (!isOpen)
1595
+ this.positionPanelNearBubble(dd);
1596
+ }
1597
+ }
1598
+ else {
1599
+ const isOpen = item.panel.style.display !== 'none';
1600
+ this.closeAllBubblePopups(menu, isOpen ? undefined : item.panel);
1601
+ item.panel.style.display = isOpen ? 'none' : 'block';
1602
+ if (!isOpen)
1603
+ this.positionPanelNearBubble(item.panel);
1604
+ }
1605
+ return;
1606
+ }
1607
+ const chain = this.editor.chain().focus();
1608
+ switch (item.action) {
1609
+ case 'strike':
1610
+ chain.toggleStrike().run();
1611
+ break;
1612
+ case 'bulletList':
1613
+ chain.toggleBulletList().run();
1614
+ break;
1615
+ case 'orderedList':
1616
+ chain.toggleOrderedList().run();
1617
+ break;
1618
+ case 'superscript':
1619
+ chain.toggleSuperscript().run();
1620
+ break;
1621
+ case 'subscript':
1622
+ chain.toggleSubscript().run();
1623
+ break;
1624
+ case 'horizontalRule':
1625
+ chain.setHorizontalRule().run();
1626
+ menu.style.display = 'none';
1627
+ break;
1628
+ case 'clearFormat':
1629
+ chain.unsetAllMarks().clearNodes().run();
1630
+ menu.style.display = 'none';
1631
+ break;
1632
+ }
1633
+ });
1634
+ menu.appendChild(itemBtn);
1635
+ });
1636
+ // ── Table context section (hidden by default, shown when cursor is in a table) ──
1637
+ const tableSection = document.createElement('div');
1638
+ tableSection.className = 'co-rte-bubble__overflow-table-section';
1639
+ tableSection.style.display = 'none';
1640
+ const tableSep = document.createElement('div');
1641
+ tableSep.className = 'co-rte-bubble__overflow-sep';
1642
+ tableSection.appendChild(tableSep);
1643
+ const tableHeader = document.createElement('div');
1644
+ tableHeader.className = 'co-rte-bubble__overflow-section-title';
1645
+ tableHeader.textContent = _os.tableOptions;
1646
+ tableSection.appendChild(tableHeader);
1647
+ const tableItems = [
1648
+ { action: 'addColumnBefore', icon: 'columns-plus-left', label: _os.addColumnBefore },
1649
+ { action: 'addColumnAfter', icon: 'columns-plus-right', label: _os.addColumnAfter },
1650
+ { action: 'addRowBefore', icon: 'rows-plus-top', label: _os.addRowAbove },
1651
+ { action: 'addRowAfter', icon: 'rows-plus-bottom', label: _os.addRowBelow },
1652
+ { action: 'mergeCells', icon: 'arrows-merge', label: _os.mergeCells },
1653
+ { action: 'splitCell', icon: 'arrows-split', label: _os.splitCell },
1654
+ { action: 'toggleHeaderRow', icon: 'rows', label: _os.headerRow },
1655
+ ];
1656
+ tableItems.forEach(({ action, icon, label }) => {
1657
+ const tBtn = document.createElement('button');
1658
+ tBtn.type = 'button';
1659
+ tBtn.className = 'co-rte-bubble__overflow-item';
1660
+ tBtn.setAttribute('data-overflow-item', action);
1661
+ if (action === 'toggleHeaderRow')
1662
+ tBtn.setAttribute('data-check', 'toggleHeaderRow');
1663
+ tBtn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon><span>${label}</span>`;
1664
+ tBtn.addEventListener('click', () => {
1665
+ if (!this.editor)
1666
+ return;
1667
+ const chain = this.editor.chain().focus();
1668
+ switch (action) {
1669
+ case 'addColumnAfter':
1670
+ chain.addColumnAfter().run();
1671
+ break;
1672
+ case 'addColumnBefore':
1673
+ chain.addColumnBefore().run();
1674
+ break;
1675
+ case 'addRowAfter':
1676
+ chain.addRowAfter().run();
1677
+ break;
1678
+ case 'addRowBefore':
1679
+ chain.addRowBefore().run();
1680
+ break;
1681
+ case 'mergeCells':
1682
+ chain.mergeCells().run();
1683
+ break;
1684
+ case 'splitCell':
1685
+ chain.splitCell().run();
1686
+ break;
1687
+ case 'toggleHeaderRow':
1688
+ chain.toggleHeaderRow().run();
1689
+ break;
1690
+ }
1691
+ });
1692
+ tableSection.appendChild(tBtn);
1693
+ });
1694
+ // Danger items (delete column, row, table)
1695
+ const dangerSep = document.createElement('div');
1696
+ dangerSep.className = 'co-rte-bubble__overflow-sep';
1697
+ tableSection.appendChild(dangerSep);
1698
+ const dangerItems = [
1699
+ { action: 'deleteColumn', icon: 'minus-square', label: _os.deleteColumn },
1700
+ { action: 'deleteRow', icon: 'x-square', label: _os.deleteRow },
1701
+ { action: 'deleteTable', icon: 'trash', label: _os.deleteTable },
1702
+ ];
1703
+ dangerItems.forEach(({ action, icon, label }) => {
1704
+ const dBtn = document.createElement('button');
1705
+ dBtn.type = 'button';
1706
+ dBtn.className = 'co-rte-bubble__overflow-item co-rte-bubble__overflow-item--danger';
1707
+ dBtn.setAttribute('data-overflow-item', action);
1708
+ dBtn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon><span>${label}</span>`;
1709
+ dBtn.addEventListener('click', () => {
1710
+ if (!this.editor)
1711
+ return;
1712
+ const chain = this.editor.chain().focus();
1713
+ switch (action) {
1714
+ case 'deleteColumn':
1715
+ chain.deleteColumn().run();
1716
+ break;
1717
+ case 'deleteRow':
1718
+ chain.deleteRow().run();
1719
+ break;
1720
+ case 'deleteTable':
1721
+ chain.deleteTable().run();
1722
+ menu.style.display = 'none';
1723
+ break;
1724
+ }
1725
+ });
1726
+ tableSection.appendChild(dBtn);
1727
+ });
1728
+ menu.appendChild(tableSection);
1729
+ btn.addEventListener('click', () => {
1730
+ this.closeAllBubblePopups(menu);
1731
+ const isOpen = menu.style.display !== 'none';
1732
+ if (isOpen) {
1733
+ menu.style.display = 'none';
1734
+ }
1735
+ else {
1736
+ resetOverflowDrag();
1737
+ menu.style.position = '';
1738
+ menu.style.top = '';
1739
+ menu.style.left = '';
1740
+ menu.style.bottom = '';
1741
+ menu.style.right = '';
1742
+ menu.style.transform = '';
1743
+ menu.style.display = 'block';
1744
+ this.positionDropdown(btn, menu);
1745
+ }
1746
+ });
1747
+ wrap.appendChild(btn);
1748
+ wrap.appendChild(menu);
1749
+ return { overflowWrap: wrap, overflowMenu: menu };
1750
+ }
1751
+ toggleBubbleLinkForm(show) {
1752
+ var _a, _b;
1753
+ if (!this.bubbleLinkFormEl || !this.bubbleLinkInputEl)
1754
+ return;
1755
+ this.bubbleLinkFormEl.style.display = show ? 'flex' : 'none';
1756
+ if (show) {
1757
+ const existing = ((_a = this.editor) === null || _a === void 0 ? void 0 : _a.isActive('link'))
1758
+ ? ((_b = this.editor.getAttributes('link')) === null || _b === void 0 ? void 0 : _b.href) || ''
1759
+ : '';
1760
+ this.bubbleLinkInputEl.value = existing;
1761
+ if (this.bubbleLinkUnlinkEl) {
1762
+ this.bubbleLinkUnlinkEl.style.display = existing ? 'flex' : 'none';
1763
+ }
1764
+ setTimeout(() => { var _a; return (_a = this.bubbleLinkInputEl) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
1765
+ }
1766
+ }
1767
+ submitBubbleLinkImperative() {
1768
+ if (!this.editor || !this.bubbleLinkInputEl)
1769
+ return;
1770
+ const url = this.bubbleLinkInputEl.value.trim();
1771
+ if (!url) {
1772
+ this.toggleBubbleLinkForm(false);
1773
+ return;
1774
+ }
1775
+ this.editor.chain().focus().setLink({ href: url }).run();
1776
+ this.toggleBubbleLinkForm(false);
1777
+ }
1778
+ updateBubbleActiveStates() {
1779
+ if (!this.editor || !this.bubbleEl)
1780
+ return;
1781
+ // Toggle buttons (bold, italic, etc.)
1782
+ const btns = this.bubbleEl.querySelectorAll('.co-rte-bubble__btn[data-check]');
1783
+ btns.forEach(btn => {
1784
+ const check = btn.getAttribute('data-check');
1785
+ if (check) {
1786
+ btn.classList.toggle('co-rte-bubble__btn--active', this.editor.isActive(check));
1787
+ }
1788
+ });
1789
+ // Alignment buttons
1790
+ const alignBtns = this.bubbleEl.querySelectorAll('.co-rte-bubble__btn[data-align]');
1791
+ alignBtns.forEach(btn => {
1792
+ const align = btn.getAttribute('data-align');
1793
+ if (align) {
1794
+ btn.classList.toggle('co-rte-bubble__btn--active', this.editor.isActive({ textAlign: align }));
1795
+ }
1796
+ });
1797
+ // Font family label
1798
+ const ffLabel = this.bubbleEl.querySelector('[data-select="fontFamily"] .co-rte-bubble__select-label');
1799
+ if (ffLabel) {
1800
+ const attrs = this.editor.getAttributes('textStyle');
1801
+ const family = (attrs === null || attrs === void 0 ? void 0 : attrs.fontFamily) || '';
1802
+ ffLabel.textContent = family ? family.split(',')[0].replace(/['"]/g, '').trim() : 'Sans-serif';
1803
+ }
1804
+ // Font size label (panel trigger)
1805
+ const fsTrigger = this.bubbleEl.querySelector('[data-select="fontSize"] .co-rte-bubble__select-label');
1806
+ if (fsTrigger) {
1807
+ const attrs = this.editor.getAttributes('textStyle');
1808
+ const _us = getRichTextStrings(this.locale);
1809
+ if (this.editor.isActive('heading', { level: 1 }))
1810
+ fsTrigger.textContent = _us.title;
1811
+ else if (this.editor.isActive('heading', { level: 2 }))
1812
+ fsTrigger.textContent = _us.headingAbbr1;
1813
+ else if (this.editor.isActive('heading', { level: 3 }))
1814
+ fsTrigger.textContent = _us.headingAbbr2;
1815
+ else
1816
+ fsTrigger.textContent = (attrs === null || attrs === void 0 ? void 0 : attrs.fontSize) || '16px';
1817
+ }
1818
+ // Font weight label (panel trigger)
1819
+ const fwTrigger = this.bubbleEl.querySelector('[data-select="fontWeight"] .co-rte-bubble__select-label');
1820
+ if (fwTrigger) {
1821
+ const attrs = this.editor.getAttributes('textStyle');
1822
+ const w = (attrs === null || attrs === void 0 ? void 0 : attrs.fontWeight) || '400';
1823
+ const wMap = { '100': 'Thin', '200': 'Extra Light', '300': 'Light', '400': 'Regular', '500': 'Medium', '600': 'Semi-bold', '700': 'Bold', '800': 'Extra-bold', '900': 'Black' };
1824
+ fwTrigger.textContent = wMap[w] || 'Regular';
1825
+ }
1826
+ // Overflow menu items active states
1827
+ const overflowItems = this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-item[data-check]');
1828
+ overflowItems.forEach(item => {
1829
+ const check = item.getAttribute('data-check');
1830
+ if (check) {
1831
+ item.classList.toggle('co-rte-bubble__overflow-item--active', this.editor.isActive(check));
1832
+ }
1833
+ });
1834
+ // Line height value in overflow (lineHeight is a block-level attribute on paragraph/heading)
1835
+ const lhValue = this.bubbleEl.querySelector('[data-overflow-value="lineHeight"]');
1836
+ if (lhValue) {
1837
+ const pAttrs = this.editor.getAttributes('paragraph');
1838
+ const hAttrs = this.editor.getAttributes('heading');
1839
+ lhValue.textContent = (pAttrs === null || pAttrs === void 0 ? void 0 : pAttrs.lineHeight) || (hAttrs === null || hAttrs === void 0 ? void 0 : hAttrs.lineHeight) || '';
1840
+ }
1841
+ // Letter spacing value in overflow
1842
+ const lsValue = this.bubbleEl.querySelector('[data-overflow-value="letterSpacing"]');
1843
+ if (lsValue) {
1844
+ const attrs = this.editor.getAttributes('textStyle');
1845
+ lsValue.textContent = (attrs === null || attrs === void 0 ? void 0 : attrs.letterSpacing) || '';
1846
+ }
1847
+ // Text color indicator bar
1848
+ const colorBar = this.bubbleEl.querySelector('.co-rte-bubble__color-bar');
1849
+ if (colorBar) {
1850
+ const attrs = this.editor.getAttributes('textStyle');
1851
+ colorBar.style.background = (attrs === null || attrs === void 0 ? void 0 : attrs.color) || '#000000';
1852
+ }
1853
+ // Table context section — show/hide based on cursor position
1854
+ const tableSection = this.bubbleEl.querySelector('.co-rte-bubble__overflow-table-section');
1855
+ if (tableSection) {
1856
+ const inTable = this.editor.isActive('table');
1857
+ tableSection.style.display = inTable ? 'block' : 'none';
1858
+ // Toggle header row active state
1859
+ if (inTable) {
1860
+ const headerBtn = tableSection.querySelector('[data-overflow-item="toggleHeaderRow"]');
1861
+ if (headerBtn) {
1862
+ const view = this.editor.view;
1863
+ const { $anchor } = this.editor.state.selection;
1864
+ let d = $anchor.depth;
1865
+ let hasHeader = false;
1866
+ while (d > 0) {
1867
+ if ($anchor.node(d).type.name === 'table') {
1868
+ const domEl = view.nodeDOM($anchor.start(d) - 1);
1869
+ if (domEl) {
1870
+ const tbl = domEl.querySelector('table') || domEl;
1871
+ const firstRow = tbl.querySelector('tr');
1872
+ hasHeader = firstRow ? firstRow.querySelector('th') !== null : false;
1873
+ }
1874
+ break;
1875
+ }
1876
+ d--;
1877
+ }
1878
+ headerBtn.classList.toggle('co-rte-bubble__overflow-item--active', hasHeader);
1879
+ }
1880
+ }
1881
+ }
1882
+ }
1883
+ createImageLayoutBar() {
1884
+ const bar = document.createElement('div');
1885
+ bar.className = 'co-rte-img-layout';
1886
+ bar.style.display = 'none';
1887
+ bar.addEventListener('mousedown', (e) => {
1888
+ e.preventDefault();
1889
+ e.stopPropagation();
1890
+ });
1891
+ const s = getRichTextStrings(this.locale);
1892
+ const labels = {
1893
+ 'inline': s.imageLayoutInline,
1894
+ 'wrap-left': s.imageLayoutWrapLeft,
1895
+ 'wrap-right': s.imageLayoutWrapRight,
1896
+ 'center': s.imageLayoutCenter,
1897
+ 'full-width': s.imageLayoutFullWidth,
1898
+ };
1899
+ const keys = ['inline', 'wrap-left', 'wrap-right', 'center', 'full-width'];
1900
+ keys.forEach(key => {
1901
+ const btn = document.createElement('button');
1902
+ btn.type = 'button';
1903
+ btn.className = 'co-rte-img-layout__btn';
1904
+ btn.setAttribute('data-layout', key);
1905
+ // Fast CSS tooltip (avoids the slow native `title` delay).
1906
+ btn.setAttribute('data-tooltip', labels[key] || key);
1907
+ btn.setAttribute('aria-label', labels[key] || key);
1908
+ btn.innerHTML = `<co-icon name="${CoRichTextEditor.IMG_LAYOUT_ICONS[key]}" size="18"></co-icon>`;
1909
+ btn.addEventListener('click', () => this.setImageLayout(key));
1910
+ bar.appendChild(btn);
1911
+ });
1912
+ return bar;
1913
+ }
1914
+ setImageLayout(layout) {
1915
+ if (!this.editor || !this.contentEl)
1916
+ return;
1917
+ const { state } = this.editor;
1918
+ const sel = state.selection;
1919
+ if (sel.constructor.name !== 'NodeSelection')
1920
+ return;
1921
+ const node = sel.node;
1922
+ if ((node === null || node === void 0 ? void 0 : node.type.name) !== 'image')
1923
+ return;
1924
+ const pos = sel.from;
1925
+ const tr = state.tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { imageLayout: layout }));
1926
+ this.editor.view.dispatch(tr);
1927
+ this.editor.commands.setNodeSelection(pos);
1928
+ requestAnimationFrame(() => {
1929
+ this.syncImageLayouts();
1930
+ this.updateImageLayoutBar();
1931
+ });
1932
+ }
1933
+ getSelectedImageInfo() {
1934
+ var _a;
1935
+ if (!this.editor)
1936
+ return null;
1937
+ const { state } = this.editor;
1938
+ const sel = state.selection;
1939
+ if (sel.constructor.name !== 'NodeSelection')
1940
+ return null;
1941
+ const node = sel.node;
1942
+ if ((node === null || node === void 0 ? void 0 : node.type.name) !== 'image')
1943
+ return null;
1944
+ const pos = sel.from;
1945
+ const domNode = this.editor.view.nodeDOM(pos);
1946
+ if (!domNode)
1947
+ return null;
1948
+ const container = (((_a = domNode.closest) === null || _a === void 0 ? void 0 : _a.call(domNode, '[data-resize-container]')) || domNode);
1949
+ return { node, pos, container };
1950
+ }
1951
+ /**
1952
+ * Tag every image container with its layout mode (`data-image-layout`) so the
1953
+ * stylesheet's responsive rules apply, and clear any stray inline positioning
1954
+ * left over from legacy absolute-positioned content. Layout is CSS-only now
1955
+ * (it reflows and collapses on mobile); we only set the attribute here.
1956
+ *
1957
+ * Runs on every transaction. The resize NodeView's `onUpdate` returns `true`,
1958
+ * so ProseMirror never reflects attribute changes to the DOM — we must read
1959
+ * from state and write the attribute imperatively to the container.
1960
+ */
1961
+ syncImageLayouts() {
1962
+ if (!this.editor)
1963
+ return;
1964
+ const view = this.editor.view;
1965
+ this.editor.state.doc.descendants((node, pos) => {
1966
+ var _a;
1967
+ if (node.type.name !== 'image')
1968
+ return true;
1969
+ const dom = view.nodeDOM(pos);
1970
+ const c = (((_a = dom === null || dom === void 0 ? void 0 : dom.closest) === null || _a === void 0 ? void 0 : _a.call(dom, '[data-resize-container]')) || dom);
1971
+ if (!c)
1972
+ return true;
1973
+ c.dataset.imageLayout = node.attrs.imageLayout || 'inline';
1974
+ // Neutralise any absolute positioning baked by the old fixed-page model.
1975
+ c.style.position = '';
1976
+ c.style.left = '';
1977
+ c.style.top = '';
1978
+ c.style.zIndex = '';
1979
+ return true;
1980
+ });
1981
+ }
1982
+ /** Reposition only the layout bar (used during drag for performance). */
1983
+ updateImageLayoutBarPosition() {
1984
+ if (!this.imgLayoutEl || !this.contentEl)
1985
+ return;
1986
+ const info = this.getSelectedImageInfo();
1987
+ if (!info)
1988
+ return;
1989
+ const containerRect = info.container.getBoundingClientRect();
1990
+ const contentRect = this.contentEl.getBoundingClientRect();
1991
+ const barWidth = this.imgLayoutEl.offsetWidth || 194;
1992
+ let leftPos = (containerRect.left + containerRect.width / 2) - contentRect.left + this.contentEl.scrollLeft - barWidth / 2;
1993
+ leftPos = Math.max(4, Math.min(leftPos, contentRect.width - barWidth - 4));
1994
+ const topPos = containerRect.bottom - contentRect.top + this.contentEl.scrollTop + 8;
1995
+ this.imgLayoutEl.style.left = `${leftPos}px`;
1996
+ this.imgLayoutEl.style.top = `${topPos}px`;
1997
+ }
1998
+ updateImageLayoutBar() {
1999
+ if (!this.imgLayoutEl || !this.editor)
2000
+ return;
2001
+ const info = this.getSelectedImageInfo();
2002
+ if (!info) {
2003
+ if (this.imgLayoutVisible) {
2004
+ this.imgLayoutEl.style.display = 'none';
2005
+ this.imgLayoutVisible = false;
2006
+ }
2007
+ return;
2008
+ }
2009
+ this.imgLayoutEl.style.display = 'flex';
2010
+ this.imgLayoutVisible = true;
2011
+ this.updateImageLayoutBarPosition();
2012
+ const currentLayout = info.node.attrs.imageLayout || 'inline';
2013
+ this.imgLayoutEl.querySelectorAll('.co-rte-img-layout__btn').forEach(btn => {
2014
+ btn.classList.toggle('co-rte-img-layout__btn--active', btn.getAttribute('data-layout') === currentLayout);
2015
+ });
2016
+ }
206
2017
  render() {
207
2018
  const showToolbar = this.resolvedToolbar !== 'none' && !this.readonly && !this.disabled;
208
2019
  const showCount = this.showCharacterCount || this.maxLength != null;
209
- return (h("div", { key: 'c853d865716114025949e33e011394d824e4a961', class: {
2020
+ return (h("div", { key: '1ba222ae8d8e46a45619685771253cdd3d1befd3', class: {
210
2021
  'co-rich-text-editor': true,
211
2022
  'co-rich-text-editor--focused': this.hasFocus,
212
2023
  'co-rich-text-editor--disabled': this.disabled,
213
2024
  'co-rich-text-editor--readonly': this.readonly,
214
2025
  'co-rich-text-editor--loading': !this.ready,
215
2026
  [`co-rich-text-editor--${this.status}`]: this.status !== 'default',
216
- }, part: "wrapper" }, (this.label || this.secondaryLabel) && (h("div", { key: '049a14875b801e745c91f28410474d8139a366e6', class: "co-rich-text-editor__labels" }, this.label && h("label", { key: '4221652dd84a86192d84ba8889eafbd311ac27dd', class: "co-rich-text-editor__label", part: "label" }, this.label, h(RequiredMark, { key: '6576f8bdd8c744f6f4fd2990e3c3b58806a03bd4', required: this.required })), this.secondaryLabel && (h("span", { key: '5c28820cf466f06900ae3981b780f6664a14ca08', class: "co-rich-text-editor__secondary-label" }, this.secondaryLabel)))), h("div", { key: '94557b815f4dd9bfd33f2d4ae613554a54a391ad', class: "co-rich-text-editor__box" }, showToolbar && (h("co-rich-text-toolbar", { key: '7727dc54776263c3ef56f274e09d7d851df245d8', class: "co-rich-text-editor__toolbar", part: "toolbar", variant: this.resolvedToolbar, disabled: this.disabled || this.readonly, ref: (el) => (this.toolbarEl = el) })), h("div", { key: 'd81af8d3887e1f77062eb64efe02cda157f77216', class: "co-rte-content", part: "content", role: "textbox", "aria-multiline": "true", "aria-label": this.label, "aria-required": this.required ? 'true' : undefined, "aria-invalid": this.status === 'error' ? 'true' : undefined, ref: (el) => (this.contentEl = el) })), h("div", { key: 'f747db5469b5a805e88101cb7670432dc114c30f', class: "co-rich-text-editor__footer" }, this.helperText && (h("div", { key: '80c703179448310e86a16e908cc29edfc73260ba', class: `co-rich-text-editor__helper co-rich-text-editor__helper--${this.status}`, part: "helper" }, h("co-icon", { key: '7411c41c32e7c1845983df2608f604f764585230', name: this.helperIcon, size: 14 }), h("span", { key: 'be108ca9544684e2d6d0dbf68eca65d11f3c841b' }, this.helperText))), showCount && (h("span", { key: '5c88aeb55460778024664510a58ca9d331ef10c7', class: "co-rich-text-editor__count" }, this.charCount, this.maxLength != null ? ` / ${this.maxLength}` : '')))));
2027
+ }, part: "wrapper" }, (this.label || this.secondaryLabel) && (h("div", { key: '3bb65d173c680c2b8581aeeacdf9e94045378c43', class: "co-rich-text-editor__labels" }, this.label && h("label", { key: 'a8c743e49b37c486e80fe0227bf1d7954ade234f', class: "co-rich-text-editor__label", part: "label" }, this.label), this.secondaryLabel && (h("span", { key: 'a0d33d71573bd06d4c2b568973144ddd22424362', class: "co-rich-text-editor__secondary-label" }, this.secondaryLabel)))), h("div", { key: '39d4776d45ca2a616b64c9aab1eb15a99ae916ce', class: "co-rich-text-editor__frame" }, showToolbar && (h("co-rich-text-toolbar", { key: '80844f77a0a1aadd7a9b109110e99d218c98542c', class: "co-rich-text-editor__toolbar", part: "toolbar", variant: this.resolvedToolbar, disabled: this.disabled || this.readonly, locale: this.locale, ref: (el) => (this.toolbarEl = el) })), h("div", { key: 'f60519b8253b6070f6ac0f0a292e0402075f401a', class: "co-rich-text-editor__box" }, h("div", { key: '858aaa1ee60e6ed5142c72831d4b5f321b77132e', class: "co-rte-content", part: "content", role: "textbox", "aria-multiline": "true", "aria-label": this.label, "aria-required": this.required ? 'true' : undefined, "aria-invalid": this.status === 'error' ? 'true' : undefined, ref: (el) => (this.contentEl = el) }))), h("div", { key: '320d390eccc2fd2381c26568241e2ebb335a6aa2', class: "co-rich-text-editor__footer" }, this.helperText && (h("div", { key: 'de5d9e8605e3a8edd037e9e49884a55f641b4585', class: `co-rich-text-editor__helper co-rich-text-editor__helper--${this.status}`, part: "helper" }, h("co-icon", { key: 'ef7d3a8894a084e09e692839800bf8f1eb9c9b3f', name: this.helperIcon, size: 14 }), h("span", { key: 'a914b24fce4d891f7a7936051e04fa2f9dae6d62' }, this.helperText))), showCount && (h("span", { key: 'f9d197782e4e983b72f7432dd9b2fb8324f45a0b', class: "co-rich-text-editor__count", ref: (el) => (this.charCountEl = el) }, this.charCount, this.maxLength != null ? ` / ${this.maxLength}` : '')))));
217
2028
  }
218
2029
  get el() { return getElement(this); }
219
2030
  static get watchers() { return {
2031
+ "accountFonts": [{
2032
+ "onAccountFontsChange": 0
2033
+ }],
220
2034
  "value": [{
221
2035
  "onValueChange": 0
222
2036
  }],
@@ -228,6 +2042,38 @@ const CoRichTextEditor = class {
228
2042
  }]
229
2043
  }; }
230
2044
  };
2045
+ CoRichTextEditor.DEFAULT_FONTS = [
2046
+ { label: 'Arial', value: 'Arial, sans-serif' },
2047
+ { label: 'Calibri', value: 'Calibri, sans-serif' },
2048
+ { label: 'Cambria', value: 'Cambria, serif' },
2049
+ { label: 'Comic Sans MS', value: "'Comic Sans MS', cursive" },
2050
+ { label: 'Courier New', value: "'Courier New', monospace" },
2051
+ { label: 'Georgia', value: 'Georgia, serif' },
2052
+ { label: 'Geist', value: "'Geist', sans-serif" },
2053
+ { label: 'Helvetica', value: 'Helvetica, Arial, sans-serif' },
2054
+ { label: 'Impact', value: 'Impact, sans-serif' },
2055
+ { label: 'Inter', value: "'Inter', sans-serif" },
2056
+ { label: 'Lato', value: "'Lato', sans-serif" },
2057
+ { label: 'Montserrat', value: "'Montserrat', sans-serif" },
2058
+ { label: 'Open Sans', value: "'Open Sans', sans-serif" },
2059
+ { label: 'Poppins', value: "'Poppins', sans-serif" },
2060
+ { label: 'Roboto', value: "'Roboto', sans-serif" },
2061
+ { label: 'Segoe UI', value: "'Segoe UI', sans-serif" },
2062
+ { label: 'Tahoma', value: 'Tahoma, sans-serif' },
2063
+ { label: 'Times New Roman', value: "'Times New Roman', serif" },
2064
+ { label: 'Trebuchet MS', value: "'Trebuchet MS', sans-serif" },
2065
+ { label: 'Verdana', value: 'Verdana, sans-serif' },
2066
+ ];
2067
+ /** Register a font via FontFace API so it can be previewed. */
2068
+ CoRichTextEditor._registeredFonts = new Set();
2069
+ /* ── Image layout bar (Google-Docs-style toolbar below selected image) ── */
2070
+ CoRichTextEditor.IMG_LAYOUT_ICONS = {
2071
+ 'inline': 'image-square',
2072
+ 'wrap-left': 'text-align-left',
2073
+ 'wrap-right': 'text-align-right',
2074
+ 'center': 'text-align-center',
2075
+ 'full-width': 'arrows-horizontal',
2076
+ };
231
2077
  CoRichTextEditor.style = coRichTextEditorCss();
232
2078
 
233
2079
  export { CoRichTextEditor as co_rich_text_editor };