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