@prolibu-suite/cobalt-core 0.1.2 → 0.3.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 (682) hide show
  1. package/custom-elements.json +21351 -7087
  2. package/dist/cjs/co-accordion.cjs.entry.js +19 -4
  3. package/dist/cjs/co-app-shell.cjs.entry.js +4 -4
  4. package/dist/cjs/co-autocomplete.cjs.entry.js +54 -6
  5. package/dist/cjs/co-avatar-group.cjs.entry.js +77 -0
  6. package/dist/cjs/co-avatar.cjs.entry.js +42 -7
  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-button-group.cjs.entry.js +3 -3
  10. package/dist/cjs/co-button.cjs.entry.js +12 -7
  11. package/dist/cjs/co-calendar-month.cjs.entry.js +381 -0
  12. package/dist/cjs/co-calendar_3.cjs.entry.js +692 -0
  13. package/dist/cjs/co-card.cjs.entry.js +21 -4
  14. package/dist/cjs/co-checkbox-group.cjs.entry.js +7 -5
  15. package/dist/cjs/co-checkbox.cjs.entry.js +5 -5
  16. package/dist/cjs/co-chip.cjs.entry.js +11 -8
  17. package/dist/cjs/co-color-picker.cjs.entry.js +111 -0
  18. package/dist/cjs/co-column-picker.cjs.entry.js +443 -0
  19. package/dist/cjs/co-combobox.cjs.entry.js +51 -15
  20. package/dist/cjs/co-command-search.cjs.entry.js +159 -13
  21. package/dist/cjs/co-data-table-pagination.cjs.entry.js +5 -5
  22. package/dist/cjs/co-data-table.cjs.entry.js +38 -12
  23. package/dist/cjs/co-date-picker.cjs.entry.js +177 -0
  24. package/dist/cjs/co-date-range-picker.cjs.entry.js +378 -0
  25. package/dist/cjs/co-date-range.cjs.entry.js +13 -259
  26. package/dist/cjs/co-empty-state.cjs.entry.js +2 -2
  27. package/dist/cjs/co-event-calendar.cjs.entry.js +318 -0
  28. package/dist/cjs/co-fab.cjs.entry.js +3 -3
  29. package/dist/cjs/co-file-field.cjs.entry.js +498 -0
  30. package/dist/cjs/co-helper-text.cjs.entry.js +3 -3
  31. package/dist/cjs/co-icon-button.cjs.entry.js +6 -6
  32. package/dist/cjs/co-icon.cjs.entry.js +36 -25
  33. package/dist/cjs/co-input.cjs.entry.js +13 -8
  34. package/dist/cjs/co-json-field.cjs.entry.js +113 -0
  35. package/dist/cjs/co-lightbox.cjs.entry.js +344 -0
  36. package/dist/cjs/co-list-footer.cjs.entry.js +25 -0
  37. package/dist/cjs/co-list-item.cjs.entry.js +70 -4
  38. package/dist/cjs/co-loader_2.cjs.entry.js +293 -0
  39. package/dist/cjs/co-menu-divider.cjs.entry.js +2 -2
  40. package/dist/cjs/co-menu-item.cjs.entry.js +17 -10
  41. package/dist/cjs/co-menu.cjs.entry.js +2 -2
  42. package/dist/cjs/co-modal.cjs.entry.js +25 -3
  43. package/dist/cjs/co-navbar.cjs.entry.js +4 -4
  44. package/dist/cjs/co-number-field.cjs.entry.js +60 -12
  45. package/dist/cjs/co-page-header.cjs.entry.js +2 -2
  46. package/dist/cjs/co-phone-field.cjs.entry.js +378 -0
  47. package/dist/cjs/co-popover.cjs.entry.js +46 -15
  48. package/dist/cjs/co-progress-bar.cjs.entry.js +8 -4
  49. package/dist/cjs/co-progress-circle.cjs.entry.js +38 -0
  50. package/dist/cjs/co-radio-group.cjs.entry.js +7 -5
  51. package/dist/cjs/co-radio.cjs.entry.js +4 -4
  52. package/dist/cjs/co-rating.cjs.entry.js +4 -4
  53. package/dist/cjs/co-ref-field.cjs.entry.js +214 -21
  54. package/dist/cjs/co-rich-text-editor.cjs.entry.js +2081 -0
  55. package/dist/cjs/co-rich-text-toolbar.cjs.entry.js +1108 -0
  56. package/dist/cjs/co-rich-text-viewer.cjs.entry.js +118 -0
  57. package/dist/cjs/co-row.cjs.entry.js +3 -3
  58. package/dist/cjs/co-select.cjs.entry.js +119 -18
  59. package/dist/cjs/co-separator.cjs.entry.js +2 -2
  60. package/dist/cjs/co-sidebar-nav.cjs.entry.js +55 -10
  61. package/dist/cjs/co-sidebar.cjs.entry.js +3 -3
  62. package/dist/cjs/co-skeleton.cjs.entry.js +26 -0
  63. package/dist/cjs/co-slider.cjs.entry.js +3 -3
  64. package/dist/cjs/co-switch.cjs.entry.js +9 -6
  65. package/dist/cjs/co-tab-group.cjs.entry.js +2 -2
  66. package/dist/cjs/co-tab.cjs.entry.js +3 -3
  67. package/dist/cjs/co-tags-field.cjs.entry.js +211 -0
  68. package/dist/cjs/co-textarea.cjs.entry.js +96 -0
  69. package/dist/cjs/co-toast.cjs.entry.js +2 -2
  70. package/dist/cjs/co-toggle-button-group.cjs.entry.js +7 -4
  71. package/dist/cjs/co-toggle-button.cjs.entry.js +4 -4
  72. package/dist/cjs/co-tooltip.cjs.entry.js +56 -15
  73. package/dist/cjs/co-transfer-list.cjs.entry.js +20 -6
  74. package/dist/cjs/co-video.cjs.entry.js +839 -0
  75. package/dist/cjs/cobalt.cjs.js +2 -2
  76. package/dist/cjs/dateI18n-BdiNAl0_.js +106 -0
  77. package/dist/cjs/dates-D8D-aS5d.js +432 -0
  78. package/dist/cjs/fieldChip-CDIMz_Y6.js +7 -0
  79. package/dist/cjs/index-5NdsiFjZ.js +35405 -0
  80. package/dist/cjs/{index-BEovErzl.js → index-BumlM92r.js} +115 -23
  81. package/dist/cjs/loader.cjs.js +2 -2
  82. package/dist/cjs/normalizeText-B-v-XPKf.js +96 -0
  83. package/dist/cjs/overlayAfterClose-BdeXrhVY.js +12 -0
  84. package/dist/cjs/overlayScroll-ifzDNeyb.js +25 -0
  85. package/dist/cjs/overlayscrollbars-BlBHo2Xx.js +2842 -0
  86. package/dist/cjs/{positioning-DozpXyBd.js → positioning-DwHW399W.js} +40 -25
  87. package/dist/cjs/purify.es-DX41ZWS2.js +1776 -0
  88. package/dist/cjs/requiredMark-CqMGt1H1.js +16 -0
  89. package/dist/cjs/richTextI18n-B7ktXg3M.js +382 -0
  90. package/dist/cjs/toolbar-config-3PlT-3zm.js +216 -0
  91. package/dist/cjs/tz-Dgom0W69.js +127 -0
  92. package/dist/cobalt/cobalt.css +1 -1
  93. package/dist/cobalt/cobalt.esm.js +1 -1
  94. package/dist/cobalt/p-0a506c9d.entry.js +1 -0
  95. package/dist/cobalt/p-0bb55163.entry.js +1 -0
  96. package/dist/cobalt/{p-fb047df8.entry.js → p-0e8c0d87.entry.js} +1 -1
  97. package/dist/cobalt/p-12e2c2c4.entry.js +1 -0
  98. package/dist/cobalt/p-136ad468.entry.js +1 -0
  99. package/dist/cobalt/p-14b59277.entry.js +1 -0
  100. package/dist/cobalt/p-1531d3c9.entry.js +1 -0
  101. package/dist/cobalt/p-1774d211.entry.js +1 -0
  102. package/dist/cobalt/{p-c7517f86.entry.js → p-180e1106.entry.js} +1 -1
  103. package/dist/cobalt/p-1a07c23c.entry.js +1 -0
  104. package/dist/cobalt/p-1dc9c49e.entry.js +1 -0
  105. package/dist/cobalt/p-1f747e45.entry.js +1 -0
  106. package/dist/cobalt/{p-d29c77cb.entry.js → p-201eaf35.entry.js} +1 -1
  107. package/dist/cobalt/p-260101ab.entry.js +1 -0
  108. package/dist/cobalt/p-279bf91c.entry.js +1 -0
  109. package/dist/cobalt/p-29be61a9.entry.js +1 -0
  110. package/dist/cobalt/p-2d2ce434.entry.js +1 -0
  111. package/dist/cobalt/{p-416bb5ae.entry.js → p-2f86e1e0.entry.js} +1 -1
  112. package/dist/cobalt/{p-4cf6d1f4.entry.js → p-31ab9a46.entry.js} +1 -1
  113. package/dist/cobalt/{p-319937c3.entry.js → p-37595103.entry.js} +1 -1
  114. package/dist/cobalt/p-377c2ccc.entry.js +1 -0
  115. package/dist/cobalt/p-3863ea91.entry.js +1 -0
  116. package/dist/cobalt/p-3a257cb0.entry.js +1 -0
  117. package/dist/cobalt/p-3e187456.entry.js +1 -0
  118. package/dist/cobalt/p-4431faac.entry.js +1 -0
  119. package/dist/cobalt/{p-4d8ff00a.entry.js → p-4504f7b0.entry.js} +1 -1
  120. package/dist/cobalt/p-456fa86f.entry.js +1 -0
  121. package/dist/cobalt/p-4871690e.entry.js +1 -0
  122. package/dist/cobalt/p-4c01d984.entry.js +1 -0
  123. package/dist/cobalt/p-51a53177.entry.js +1 -0
  124. package/dist/cobalt/p-52de17da.entry.js +1 -0
  125. package/dist/cobalt/p-5890e4d1.entry.js +1 -0
  126. package/dist/cobalt/{p-e50c4c6f.entry.js → p-58a53421.entry.js} +1 -1
  127. package/dist/cobalt/p-62274eba.entry.js +1 -0
  128. package/dist/cobalt/p-635b03d5.entry.js +1 -0
  129. package/dist/cobalt/p-64ddee92.entry.js +1 -0
  130. package/dist/cobalt/p-65af5017.entry.js +1 -0
  131. package/dist/cobalt/p-69d4c0c8.entry.js +1 -0
  132. package/dist/cobalt/p-6c480916.entry.js +1 -0
  133. package/dist/cobalt/p-6d1217c3.entry.js +1 -0
  134. package/dist/cobalt/p-6e808b3a.entry.js +1 -0
  135. package/dist/cobalt/{p-697df797.entry.js → p-70b14b05.entry.js} +1 -1
  136. package/dist/cobalt/{p-1d7da33f.entry.js → p-790d384e.entry.js} +1 -1
  137. package/dist/cobalt/p-8012e152.entry.js +1 -0
  138. package/dist/cobalt/p-80b27203.entry.js +1 -0
  139. package/dist/cobalt/p-867c1465.entry.js +1 -0
  140. package/dist/cobalt/p-86a143d7.entry.js +1 -0
  141. package/dist/cobalt/{p-3b2f7959.entry.js → p-8d59f5ad.entry.js} +1 -1
  142. package/dist/cobalt/p-8d7fdb9d.entry.js +1 -0
  143. package/dist/cobalt/p-8dc1dab8.entry.js +1 -0
  144. package/dist/cobalt/p-8e1dc062.entry.js +1 -0
  145. package/dist/cobalt/p-929e647f.entry.js +1 -0
  146. package/dist/cobalt/p-92bd9b29.entry.js +1 -0
  147. package/dist/cobalt/p-93046365.entry.js +1 -0
  148. package/dist/cobalt/p-98ab5f3f.entry.js +1 -0
  149. package/dist/cobalt/p-9a04ca90.entry.js +1 -0
  150. package/dist/cobalt/{p-ebd1555e.entry.js → p-9a088515.entry.js} +1 -1
  151. package/dist/cobalt/p-9abbd436.entry.js +1 -0
  152. package/dist/cobalt/p-9d69c067.entry.js +1 -0
  153. package/dist/cobalt/p-B-ckjCUA.js +1 -0
  154. package/dist/cobalt/p-B2QLgWrz.js +2 -0
  155. package/dist/cobalt/p-B6JZk8fL.js +1 -0
  156. package/dist/cobalt/p-BZJ7NCm5.js +1 -0
  157. package/dist/cobalt/p-C1DCLOEl.js +1 -0
  158. package/dist/cobalt/p-C2mZ7x_Y.js +1 -0
  159. package/dist/cobalt/p-CQY6Ul7q.js +1 -0
  160. package/dist/cobalt/p-CYsftTKf.js +2 -0
  161. package/dist/cobalt/p-CegCk7FL.js +1 -0
  162. package/dist/cobalt/p-Ch1jfwZ2.js +1 -0
  163. package/dist/cobalt/p-ChibIpZv.js +1 -0
  164. package/dist/cobalt/p-DqyWGweA.js +1 -0
  165. package/dist/cobalt/p-afb7e19e.entry.js +1 -0
  166. package/dist/cobalt/p-b6f20268.entry.js +1 -0
  167. package/dist/cobalt/p-ba90e871.entry.js +1 -0
  168. package/dist/cobalt/p-c10697e1.entry.js +1 -0
  169. package/dist/cobalt/p-c4f59532.entry.js +1 -0
  170. package/dist/cobalt/{p-1b5c723a.entry.js → p-cb235aa7.entry.js} +1 -1
  171. package/dist/cobalt/p-cfb36943.entry.js +1 -0
  172. package/dist/cobalt/p-d809bd44.entry.js +1 -0
  173. package/dist/cobalt/p-e53861e4.entry.js +1 -0
  174. package/dist/cobalt/p-e54dd404.entry.js +1 -0
  175. package/dist/cobalt/{p-1021f612.entry.js → p-eb18fdbf.entry.js} +1 -1
  176. package/dist/cobalt/{p-a7fa4484.entry.js → p-eb73052a.entry.js} +1 -1
  177. package/dist/cobalt/p-ef7d4ae3.entry.js +1 -0
  178. package/dist/cobalt/p-f4063c41.entry.js +1 -0
  179. package/dist/cobalt/p-oImf-7fN.js +1 -0
  180. package/dist/cobalt/p-ox7HzCZn.js +10 -0
  181. package/dist/cobalt/p-tPYikBRJ.js +1 -0
  182. package/dist/collection/collection-manifest.json +27 -4
  183. package/dist/collection/components/co-accordion/co-accordion.css +19 -1
  184. package/dist/collection/components/co-accordion/co-accordion.js +46 -4
  185. package/dist/collection/components/co-app-shell/co-app-shell.css +79 -6
  186. package/dist/collection/components/co-app-shell/co-app-shell.js +2 -2
  187. package/dist/collection/components/co-autocomplete/co-autocomplete.css +753 -8
  188. package/dist/collection/components/co-autocomplete/co-autocomplete.js +111 -4
  189. package/dist/collection/components/co-avatar/co-avatar.css +45 -1
  190. package/dist/collection/components/co-avatar/co-avatar.js +56 -6
  191. package/dist/collection/components/co-avatar-group/co-avatar-group.css +86 -0
  192. package/dist/collection/components/co-avatar-group/co-avatar-group.js +224 -0
  193. package/dist/collection/components/co-badge/co-badge.js +1 -1
  194. package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.css +136 -0
  195. package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.js +507 -0
  196. package/dist/collection/components/co-button/co-button.css +48 -12
  197. package/dist/collection/components/co-button/co-button.js +70 -8
  198. package/dist/collection/components/co-button-group/co-button-group.js +2 -2
  199. package/dist/collection/components/co-calendar/co-calendar.css +236 -0
  200. package/dist/collection/components/co-calendar/co-calendar.js +728 -0
  201. package/dist/collection/components/co-calendar-month/co-calendar-month.css +231 -0
  202. package/dist/collection/components/co-calendar-month/co-calendar-month.js +594 -0
  203. package/dist/collection/components/co-card/co-card.css +28 -5
  204. package/dist/collection/components/co-card/co-card.js +47 -4
  205. package/dist/collection/components/co-checkbox/co-checkbox.css +7 -1
  206. package/dist/collection/components/co-checkbox/co-checkbox.js +3 -3
  207. package/dist/collection/components/co-checkbox-group/co-checkbox-group.css +33 -1
  208. package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +25 -3
  209. package/dist/collection/components/co-chip/co-chip.css +27 -7
  210. package/dist/collection/components/co-chip/co-chip.js +52 -10
  211. package/dist/collection/components/co-color-picker/co-color-picker.css +258 -0
  212. package/dist/collection/components/co-color-picker/co-color-picker.js +355 -0
  213. package/dist/collection/components/co-color-picker/presets.js +19 -0
  214. package/dist/collection/components/co-column-picker/co-column-picker.css +490 -0
  215. package/dist/collection/components/co-column-picker/co-column-picker.js +675 -0
  216. package/dist/collection/components/co-column-picker/column-picker-node.js +34 -0
  217. package/dist/collection/components/co-column-picker/utils/column-picker-tree.js +221 -0
  218. package/dist/collection/components/co-combobox/co-combobox.css +778 -51
  219. package/dist/collection/components/co-combobox/co-combobox.js +130 -15
  220. package/dist/collection/components/co-command-search/co-command-search.css +167 -1
  221. package/dist/collection/components/co-command-search/co-command-search.js +362 -14
  222. package/dist/collection/components/co-command-search/commandSearchGroup.js +17 -0
  223. package/dist/collection/components/co-command-search/commandSearchLogic.js +27 -0
  224. package/dist/collection/components/co-data-table/co-data-table.css +37 -1
  225. package/dist/collection/components/co-data-table/co-data-table.js +38 -12
  226. package/dist/collection/components/co-data-table-pagination/co-data-table-pagination.js +4 -4
  227. package/dist/collection/components/co-date-field/co-date-field.css +245 -0
  228. package/dist/collection/components/co-date-field/co-date-field.js +746 -0
  229. package/dist/collection/components/co-date-picker/co-date-picker.css +112 -0
  230. package/dist/collection/components/co-date-picker/co-date-picker.js +801 -0
  231. package/dist/collection/components/co-date-range/co-date-range.css +3 -254
  232. package/dist/collection/components/co-date-range/co-date-range.js +29 -433
  233. package/dist/collection/components/co-date-range-picker/co-date-range-picker.css +257 -0
  234. package/dist/collection/components/co-date-range-picker/co-date-range-picker.js +1142 -0
  235. package/dist/collection/components/co-drawer/co-drawer.css +20 -0
  236. package/dist/collection/components/co-drawer/co-drawer.js +46 -2
  237. package/dist/collection/components/co-empty-state/co-empty-state.js +1 -1
  238. package/dist/collection/components/co-event-calendar/co-event-calendar.css +146 -0
  239. package/dist/collection/components/co-event-calendar/co-event-calendar.js +620 -0
  240. package/dist/collection/components/co-fab/co-fab.js +2 -2
  241. package/dist/collection/components/co-file-field/co-file-field.css +395 -0
  242. package/dist/collection/components/co-file-field/co-file-field.js +841 -0
  243. package/dist/collection/components/co-file-field/co-file-field.utils.js +47 -0
  244. package/dist/collection/components/co-helper-text/co-helper-text.js +2 -2
  245. package/dist/collection/components/co-icon/co-icon.js +7 -34
  246. package/dist/collection/components/co-icon/iconLoader.js +39 -0
  247. package/dist/collection/components/co-icon-button/co-icon-button.css +27 -6
  248. package/dist/collection/components/co-icon-button/co-icon-button.js +26 -7
  249. package/dist/collection/components/co-input/co-input.css +63 -11
  250. package/dist/collection/components/co-input/co-input.js +34 -9
  251. package/dist/collection/components/co-json-field/co-json-field.css +193 -0
  252. package/dist/collection/components/co-json-field/co-json-field.js +477 -0
  253. package/dist/collection/components/co-lightbox/co-lightbox.css +164 -0
  254. package/dist/collection/components/co-lightbox/co-lightbox.js +451 -0
  255. package/dist/collection/components/co-list-footer/co-list-footer.css +50 -0
  256. package/dist/collection/components/co-list-footer/co-list-footer.js +149 -0
  257. package/dist/collection/components/co-list-item/co-list-item.css +12 -0
  258. package/dist/collection/components/co-list-item/co-list-item.js +75 -2
  259. package/dist/collection/components/co-loader/co-loader.css +9 -0
  260. package/dist/collection/components/co-menu/co-menu.js +1 -1
  261. package/dist/collection/components/co-menu-divider/co-menu-divider.js +1 -1
  262. package/dist/collection/components/co-menu-item/co-menu-item.css +18 -0
  263. package/dist/collection/components/co-menu-item/co-menu-item.js +15 -8
  264. package/dist/collection/components/co-modal/co-modal.css +59 -5
  265. package/dist/collection/components/co-modal/co-modal.js +91 -1
  266. package/dist/collection/components/co-navbar/co-navbar.css +1 -1
  267. package/dist/collection/components/co-navbar/co-navbar.js +2 -2
  268. package/dist/collection/components/co-number-field/co-number-field.css +89 -1
  269. package/dist/collection/components/co-number-field/co-number-field.js +175 -14
  270. package/dist/collection/components/co-overlay/co-overlay.css +15 -1
  271. package/dist/collection/components/co-overlay/co-overlay.js +266 -1
  272. package/dist/collection/components/co-overlay/focusTrap.js +53 -0
  273. package/dist/collection/components/co-overlay/overlayAfterClose.js +8 -0
  274. package/dist/collection/components/co-page-header/co-page-header.js +1 -1
  275. package/dist/collection/components/co-phone-field/co-phone-field.css +293 -0
  276. package/dist/collection/components/co-phone-field/co-phone-field.js +414 -0
  277. package/dist/collection/components/co-phone-field/dial-codes.js +208 -0
  278. package/dist/collection/components/co-popover/co-popover.css +9 -0
  279. package/dist/collection/components/co-popover/co-popover.js +43 -12
  280. package/dist/collection/components/co-progress-bar/co-progress-bar.css +22 -0
  281. package/dist/collection/components/co-progress-bar/co-progress-bar.js +26 -2
  282. package/dist/collection/components/co-progress-circle/co-progress-circle.css +50 -0
  283. package/dist/collection/components/co-progress-circle/co-progress-circle.js +148 -0
  284. package/dist/collection/components/co-radio/co-radio.js +3 -3
  285. package/dist/collection/components/co-radio-group/co-radio-group.css +26 -0
  286. package/dist/collection/components/co-radio-group/co-radio-group.js +25 -3
  287. package/dist/collection/components/co-rating/co-rating.js +3 -3
  288. package/dist/collection/components/co-ref-field/co-ref-field.css +876 -56
  289. package/dist/collection/components/co-ref-field/co-ref-field.js +0 -0
  290. package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.css +1322 -0
  291. package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.js +2823 -0
  292. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.css +837 -0
  293. package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.js +1289 -0
  294. package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.css +156 -0
  295. package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.js +237 -0
  296. package/dist/collection/components/co-row/co-row.js +2 -2
  297. package/dist/collection/components/co-select/co-select.css +852 -8
  298. package/dist/collection/components/co-select/co-select.js +240 -17
  299. package/dist/collection/components/co-separator/co-separator.js +1 -1
  300. package/dist/collection/components/co-sidebar/co-sidebar.js +2 -2
  301. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.css +99 -12
  302. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +54 -9
  303. package/dist/collection/components/co-skeleton/co-skeleton.css +28 -0
  304. package/dist/collection/components/co-skeleton/co-skeleton.js +97 -0
  305. package/dist/collection/components/co-slider/co-slider.js +2 -2
  306. package/dist/collection/components/co-switch/co-switch.css +26 -1
  307. package/dist/collection/components/co-switch/co-switch.js +27 -4
  308. package/dist/collection/components/co-tab/co-tab.js +2 -2
  309. package/dist/collection/components/co-tab-group/co-tab-group.js +1 -1
  310. package/dist/collection/components/co-tags-field/co-tags-field.css +310 -0
  311. package/dist/collection/components/co-tags-field/co-tags-field.js +616 -0
  312. package/dist/collection/components/co-textarea/co-textarea.css +286 -0
  313. package/dist/collection/components/co-textarea/co-textarea.js +508 -0
  314. package/dist/collection/components/co-toast/co-toast.js +1 -1
  315. package/dist/collection/components/co-toggle-button/co-toggle-button.css +30 -6
  316. package/dist/collection/components/co-toggle-button/co-toggle-button.js +3 -3
  317. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.css +32 -12
  318. package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.js +25 -2
  319. package/dist/collection/components/co-tooltip/co-tooltip.css +24 -0
  320. package/dist/collection/components/co-tooltip/co-tooltip.js +73 -12
  321. package/dist/collection/components/co-transfer-list/co-transfer-list.css +683 -7
  322. package/dist/collection/components/co-transfer-list/co-transfer-list.js +17 -4
  323. package/dist/collection/components/co-video/co-video.css +497 -0
  324. package/dist/collection/components/co-video/co-video.js +1772 -0
  325. package/dist/collection/utils/dateI18n.js +101 -0
  326. package/dist/collection/utils/fieldChip.js +2 -0
  327. package/dist/collection/utils/fileI18n.js +76 -0
  328. package/dist/collection/utils/icon-config.js +34 -0
  329. package/dist/collection/utils/lightboxI18n.js +42 -0
  330. package/dist/collection/utils/normalizeText.js +94 -0
  331. package/dist/collection/utils/overlayScroll.js +20 -0
  332. package/dist/collection/utils/positioning.js +40 -25
  333. package/dist/collection/utils/requiredMark.js +11 -0
  334. package/dist/collection/utils/richTextI18n.js +378 -0
  335. package/dist/collection/utils/sheetGesture.js +53 -0
  336. package/dist/components/co-accordion.js +1 -1
  337. package/dist/components/co-app-shell.js +1 -1
  338. package/dist/components/co-autocomplete.js +1 -1
  339. package/dist/components/co-avatar-group.d.ts +11 -0
  340. package/dist/components/co-avatar-group.js +1 -0
  341. package/dist/components/co-avatar.js +1 -1
  342. package/dist/components/co-badge.js +1 -1
  343. package/dist/components/co-bottom-sheet.d.ts +11 -0
  344. package/dist/components/co-bottom-sheet.js +1 -0
  345. package/dist/components/co-button-group.js +1 -1
  346. package/dist/components/co-button.js +1 -1
  347. package/dist/components/co-calendar-month.d.ts +11 -0
  348. package/dist/components/co-calendar-month.js +1 -0
  349. package/dist/components/co-calendar.d.ts +11 -0
  350. package/dist/components/co-calendar.js +1 -0
  351. package/dist/components/co-card.js +1 -1
  352. package/dist/components/co-checkbox-group.js +1 -1
  353. package/dist/components/co-checkbox.js +1 -1
  354. package/dist/components/co-chip.js +1 -1
  355. package/dist/components/co-color-picker.d.ts +11 -0
  356. package/dist/components/co-color-picker.js +1 -0
  357. package/dist/components/co-column-picker.d.ts +11 -0
  358. package/dist/components/co-column-picker.js +1 -0
  359. package/dist/components/co-combobox.js +1 -1
  360. package/dist/components/co-command-search.js +1 -1
  361. package/dist/components/co-data-table-pagination.js +1 -1
  362. package/dist/components/co-data-table.js +1 -1
  363. package/dist/components/co-date-field.d.ts +11 -0
  364. package/dist/components/co-date-field.js +1 -0
  365. package/dist/components/co-date-picker.d.ts +11 -0
  366. package/dist/components/co-date-picker.js +1 -0
  367. package/dist/components/co-date-range-picker.d.ts +11 -0
  368. package/dist/components/co-date-range-picker.js +1 -0
  369. package/dist/components/co-date-range.js +1 -1
  370. package/dist/components/co-drawer.js +1 -1
  371. package/dist/components/co-empty-state.js +1 -1
  372. package/dist/components/co-event-calendar.d.ts +11 -0
  373. package/dist/components/co-event-calendar.js +1 -0
  374. package/dist/components/co-fab.js +1 -1
  375. package/dist/components/co-file-field.d.ts +11 -0
  376. package/dist/components/co-file-field.js +1 -0
  377. package/dist/components/co-helper-text.js +1 -1
  378. package/dist/components/co-icon-button.js +1 -1
  379. package/dist/components/co-icon.js +1 -1
  380. package/dist/components/co-input.js +1 -1
  381. package/dist/components/co-json-field.d.ts +11 -0
  382. package/dist/components/co-json-field.js +1 -0
  383. package/dist/components/co-lightbox.d.ts +11 -0
  384. package/dist/components/co-lightbox.js +1 -0
  385. package/dist/components/co-list-footer.d.ts +11 -0
  386. package/dist/components/co-list-footer.js +1 -0
  387. package/dist/components/co-list-item.js +1 -1
  388. package/dist/components/co-loader.js +1 -1
  389. package/dist/components/co-menu-divider.js +1 -1
  390. package/dist/components/co-menu-item.js +1 -1
  391. package/dist/components/co-menu.js +1 -1
  392. package/dist/components/co-modal.js +1 -1
  393. package/dist/components/co-navbar.js +1 -1
  394. package/dist/components/co-number-field.js +1 -1
  395. package/dist/components/co-overlay.js +1 -1
  396. package/dist/components/co-page-header.js +1 -1
  397. package/dist/components/co-phone-field.d.ts +11 -0
  398. package/dist/components/co-phone-field.js +1 -0
  399. package/dist/components/co-popover.js +1 -1
  400. package/dist/components/co-progress-bar.js +1 -1
  401. package/dist/components/co-progress-circle.d.ts +11 -0
  402. package/dist/components/co-progress-circle.js +1 -0
  403. package/dist/components/co-radio-group.js +1 -1
  404. package/dist/components/co-radio.js +1 -1
  405. package/dist/components/co-rating.js +1 -1
  406. package/dist/components/co-ref-field.js +1 -1
  407. package/dist/components/co-rich-text-editor.d.ts +11 -0
  408. package/dist/components/co-rich-text-editor.js +1 -0
  409. package/dist/components/co-rich-text-toolbar.d.ts +11 -0
  410. package/dist/components/co-rich-text-toolbar.js +1 -0
  411. package/dist/components/co-rich-text-viewer.d.ts +11 -0
  412. package/dist/components/co-rich-text-viewer.js +1 -0
  413. package/dist/components/co-row.js +1 -1
  414. package/dist/components/co-select.js +1 -1
  415. package/dist/components/co-separator.js +1 -1
  416. package/dist/components/co-sidebar-nav.js +1 -1
  417. package/dist/components/co-sidebar.js +1 -1
  418. package/dist/components/co-skeleton.d.ts +11 -0
  419. package/dist/components/co-skeleton.js +1 -0
  420. package/dist/components/co-slider.js +1 -1
  421. package/dist/components/co-switch.js +1 -1
  422. package/dist/components/co-tab-group.js +1 -1
  423. package/dist/components/co-tab.js +1 -1
  424. package/dist/components/co-tags-field.d.ts +11 -0
  425. package/dist/components/co-tags-field.js +1 -0
  426. package/dist/components/co-textarea.d.ts +11 -0
  427. package/dist/components/co-textarea.js +1 -0
  428. package/dist/components/co-toast.js +1 -1
  429. package/dist/components/co-toggle-button-group.js +1 -1
  430. package/dist/components/co-toggle-button.js +1 -1
  431. package/dist/components/co-tooltip.js +1 -1
  432. package/dist/components/co-transfer-list.js +1 -1
  433. package/dist/components/co-video.d.ts +11 -0
  434. package/dist/components/co-video.js +1 -0
  435. package/dist/components/index.js +1 -1
  436. package/dist/components/p-B2QLgWrz.js +2 -0
  437. package/dist/components/p-B7vGYFbO.js +1 -0
  438. package/dist/components/p-BB2OaYKF.js +1 -0
  439. package/dist/components/p-BFeE_fiq.js +1 -0
  440. package/dist/components/p-BNKz39GA.js +1 -0
  441. package/dist/components/p-Ba4v1NXo.js +1 -0
  442. package/dist/components/p-C1DCLOEl.js +1 -0
  443. package/dist/components/p-C2mZ7x_Y.js +1 -0
  444. package/dist/components/p-CQY6Ul7q.js +1 -0
  445. package/dist/components/p-CWneqh4n.js +1 -0
  446. package/dist/components/p-C_ULDaks.js +1 -0
  447. package/dist/components/p-CegCk7FL.js +1 -0
  448. package/dist/components/p-ChibIpZv.js +1 -0
  449. package/dist/components/p-CyYF8IJE.js +1 -0
  450. package/dist/components/p-D3Y_ti3Q.js +1 -0
  451. package/dist/components/p-DKh8ZK4U.js +1 -0
  452. package/dist/components/p-DeZxp9vb.js +1 -0
  453. package/dist/components/p-DqyWGweA.js +1 -0
  454. package/dist/components/p-DvhR3H61.js +1 -0
  455. package/dist/components/p-DxCFMMfY.js +1 -0
  456. package/dist/components/{p-OGpfa9Yd.js → p-DzoNGEDU.js} +1 -1
  457. package/dist/components/p-EPZfLt5l.js +1 -0
  458. package/dist/components/p-FMnqPWcM.js +1 -0
  459. package/dist/components/p-Hzh9U2cM.js +1 -0
  460. package/dist/components/p-WZ06pT2Y.js +1 -0
  461. package/dist/components/p-ox7HzCZn.js +10 -0
  462. package/dist/components/p-tloAgDin.js +1 -0
  463. package/dist/esm/co-accordion.entry.js +19 -4
  464. package/dist/esm/co-app-shell.entry.js +4 -4
  465. package/dist/esm/co-autocomplete.entry.js +54 -6
  466. package/dist/esm/co-avatar-group.entry.js +75 -0
  467. package/dist/esm/co-avatar.entry.js +41 -6
  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-button-group.entry.js +3 -3
  471. package/dist/esm/co-button.entry.js +12 -7
  472. package/dist/esm/co-calendar-month.entry.js +379 -0
  473. package/dist/esm/co-calendar_3.entry.js +688 -0
  474. package/dist/esm/co-card.entry.js +21 -4
  475. package/dist/esm/co-checkbox-group.entry.js +7 -5
  476. package/dist/esm/co-checkbox.entry.js +5 -5
  477. package/dist/esm/co-chip.entry.js +11 -8
  478. package/dist/esm/co-color-picker.entry.js +109 -0
  479. package/dist/esm/co-column-picker.entry.js +441 -0
  480. package/dist/esm/co-combobox.entry.js +51 -15
  481. package/dist/esm/co-command-search.entry.js +159 -13
  482. package/dist/esm/co-data-table-pagination.entry.js +5 -5
  483. package/dist/esm/co-data-table.entry.js +38 -12
  484. package/dist/esm/co-date-picker.entry.js +175 -0
  485. package/dist/esm/co-date-range-picker.entry.js +376 -0
  486. package/dist/esm/co-date-range.entry.js +13 -259
  487. package/dist/esm/co-empty-state.entry.js +2 -2
  488. package/dist/esm/co-event-calendar.entry.js +316 -0
  489. package/dist/esm/co-fab.entry.js +3 -3
  490. package/dist/esm/co-file-field.entry.js +496 -0
  491. package/dist/esm/co-helper-text.entry.js +3 -3
  492. package/dist/esm/co-icon-button.entry.js +6 -6
  493. package/dist/esm/co-icon.entry.js +36 -25
  494. package/dist/esm/co-input.entry.js +13 -8
  495. package/dist/esm/co-json-field.entry.js +111 -0
  496. package/dist/esm/co-lightbox.entry.js +342 -0
  497. package/dist/esm/co-list-footer.entry.js +23 -0
  498. package/dist/esm/co-list-item.entry.js +70 -4
  499. package/dist/esm/co-loader_2.entry.js +290 -0
  500. package/dist/esm/co-menu-divider.entry.js +2 -2
  501. package/dist/esm/co-menu-item.entry.js +17 -10
  502. package/dist/esm/co-menu.entry.js +2 -2
  503. package/dist/esm/co-modal.entry.js +25 -3
  504. package/dist/esm/co-navbar.entry.js +4 -4
  505. package/dist/esm/co-number-field.entry.js +60 -12
  506. package/dist/esm/co-page-header.entry.js +2 -2
  507. package/dist/esm/co-phone-field.entry.js +376 -0
  508. package/dist/esm/co-popover.entry.js +46 -15
  509. package/dist/esm/co-progress-bar.entry.js +8 -4
  510. package/dist/esm/co-progress-circle.entry.js +36 -0
  511. package/dist/esm/co-radio-group.entry.js +7 -5
  512. package/dist/esm/co-radio.entry.js +4 -4
  513. package/dist/esm/co-rating.entry.js +4 -4
  514. package/dist/esm/co-ref-field.entry.js +214 -21
  515. package/dist/esm/co-rich-text-editor.entry.js +2079 -0
  516. package/dist/esm/co-rich-text-toolbar.entry.js +1106 -0
  517. package/dist/esm/co-rich-text-viewer.entry.js +116 -0
  518. package/dist/esm/co-row.entry.js +3 -3
  519. package/dist/esm/co-select.entry.js +119 -18
  520. package/dist/esm/co-separator.entry.js +2 -2
  521. package/dist/esm/co-sidebar-nav.entry.js +55 -10
  522. package/dist/esm/co-sidebar.entry.js +3 -3
  523. package/dist/esm/co-skeleton.entry.js +24 -0
  524. package/dist/esm/co-slider.entry.js +3 -3
  525. package/dist/esm/co-switch.entry.js +9 -6
  526. package/dist/esm/co-tab-group.entry.js +2 -2
  527. package/dist/esm/co-tab.entry.js +3 -3
  528. package/dist/esm/co-tags-field.entry.js +209 -0
  529. package/dist/esm/co-textarea.entry.js +94 -0
  530. package/dist/esm/co-toast.entry.js +2 -2
  531. package/dist/esm/co-toggle-button-group.entry.js +7 -4
  532. package/dist/esm/co-toggle-button.entry.js +4 -4
  533. package/dist/esm/co-tooltip.entry.js +56 -15
  534. package/dist/esm/co-transfer-list.entry.js +20 -6
  535. package/dist/esm/co-video.entry.js +837 -0
  536. package/dist/esm/cobalt.js +3 -3
  537. package/dist/esm/dateI18n-C1DCLOEl.js +103 -0
  538. package/dist/esm/dates-tPYikBRJ.js +416 -0
  539. package/dist/esm/fieldChip-GPikjpYw.js +5 -0
  540. package/dist/esm/{index-B0lqrhFo.js → index-CYsftTKf.js} +115 -23
  541. package/dist/esm/index-w_Wxgclf.js +35403 -0
  542. package/dist/esm/loader.js +3 -3
  543. package/dist/esm/normalizeText-CQY6Ul7q.js +92 -0
  544. package/dist/esm/overlayAfterClose-Ch1jfwZ2.js +10 -0
  545. package/dist/esm/overlayScroll-Bpv882_z.js +23 -0
  546. package/dist/esm/overlayscrollbars-ox7HzCZn.js +2840 -0
  547. package/dist/esm/{positioning-Am-OlB8h.js → positioning-C2mZ7x_Y.js} +40 -25
  548. package/dist/esm/purify.es-B2QLgWrz.js +1774 -0
  549. package/dist/esm/requiredMark-CEbXKHcU.js +14 -0
  550. package/dist/esm/richTextI18n-B-ckjCUA.js +380 -0
  551. package/dist/esm/toolbar-config-ChibIpZv.js +212 -0
  552. package/dist/esm/tz-B6JZk8fL.js +119 -0
  553. package/dist/types/components/co-accordion/co-accordion.d.ts +12 -2
  554. package/dist/types/components/co-autocomplete/co-autocomplete.d.ts +13 -0
  555. package/dist/types/components/co-avatar/co-avatar.d.ts +8 -2
  556. package/dist/types/components/co-avatar-group/co-avatar-group.d.ts +33 -0
  557. package/dist/types/components/co-bottom-sheet/co-bottom-sheet.d.ts +81 -0
  558. package/dist/types/components/co-button/co-button.d.ts +7 -1
  559. package/dist/types/components/co-calendar/co-calendar.d.ts +108 -0
  560. package/dist/types/components/co-calendar-month/co-calendar-month.d.ts +83 -0
  561. package/dist/types/components/co-card/co-card.d.ts +10 -2
  562. package/dist/types/components/co-checkbox-group/co-checkbox-group.d.ts +2 -0
  563. package/dist/types/components/co-chip/co-chip.d.ts +7 -2
  564. package/dist/types/components/co-color-picker/co-color-picker.d.ts +50 -0
  565. package/dist/types/components/co-color-picker/presets.d.ts +10 -0
  566. package/dist/types/components/co-column-picker/co-column-picker.d.ts +60 -0
  567. package/dist/types/components/co-column-picker/column-picker-node.d.ts +18 -0
  568. package/dist/types/components/co-column-picker/utils/column-picker-tree.d.ts +37 -0
  569. package/dist/types/components/co-combobox/co-combobox.d.ts +14 -1
  570. package/dist/types/components/co-command-search/co-command-search.d.ts +41 -6
  571. package/dist/types/components/co-command-search/commandSearchGroup.d.ts +20 -0
  572. package/dist/types/components/co-command-search/commandSearchLogic.d.ts +17 -0
  573. package/dist/types/components/co-data-table/co-data-table.d.ts +3 -1
  574. package/dist/types/components/co-date-field/co-date-field.d.ts +96 -0
  575. package/dist/types/components/co-date-picker/co-date-picker.d.ts +92 -0
  576. package/dist/types/components/co-date-range/co-date-range.d.ts +12 -50
  577. package/dist/types/components/co-date-range-picker/co-date-range-picker.d.ts +112 -0
  578. package/dist/types/components/co-drawer/co-drawer.d.ts +4 -0
  579. package/dist/types/components/co-event-calendar/co-event-calendar.d.ts +110 -0
  580. package/dist/types/components/co-file-field/co-file-field.d.ts +146 -0
  581. package/dist/types/components/co-file-field/co-file-field.utils.d.ts +18 -0
  582. package/dist/types/components/co-icon/co-icon.d.ts +1 -1
  583. package/dist/types/components/co-icon/iconLoader.d.ts +6 -0
  584. package/dist/types/components/co-icon-button/co-icon-button.d.ts +3 -1
  585. package/dist/types/components/co-input/co-input.d.ts +4 -1
  586. package/dist/types/components/co-json-field/co-json-field.d.ts +69 -0
  587. package/dist/types/components/co-lightbox/co-lightbox.d.ts +95 -0
  588. package/dist/types/components/co-list-footer/co-list-footer.d.ts +26 -0
  589. package/dist/types/components/co-list-item/co-list-item.d.ts +12 -0
  590. package/dist/types/components/co-modal/co-modal.d.ts +10 -0
  591. package/dist/types/components/co-number-field/co-number-field.d.ts +29 -2
  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 +58 -0
  596. package/dist/types/components/co-phone-field/dial-codes.d.ts +14 -0
  597. package/dist/types/components/co-popover/co-popover.d.ts +9 -0
  598. package/dist/types/components/co-progress-bar/co-progress-bar.d.ts +2 -0
  599. package/dist/types/components/co-progress-circle/co-progress-circle.d.ts +16 -0
  600. package/dist/types/components/co-radio-group/co-radio-group.d.ts +2 -0
  601. package/dist/types/components/co-ref-field/co-ref-field.d.ts +69 -1
  602. package/dist/types/components/co-rich-text-editor/co-rich-text-editor.d.ts +246 -0
  603. package/dist/types/components/co-rich-text-toolbar/co-rich-text-toolbar.d.ts +148 -0
  604. package/dist/types/components/co-rich-text-viewer/co-rich-text-viewer.d.ts +19 -0
  605. package/dist/types/components/co-select/co-select.d.ts +31 -1
  606. package/dist/types/components/co-skeleton/co-skeleton.d.ts +13 -0
  607. package/dist/types/components/co-switch/co-switch.d.ts +2 -0
  608. package/dist/types/components/co-tags-field/co-tags-field.d.ts +84 -0
  609. package/dist/types/components/co-textarea/co-textarea.d.ts +68 -0
  610. package/dist/types/components/co-toggle-button-group/co-toggle-button-group.d.ts +2 -0
  611. package/dist/types/components/co-tooltip/co-tooltip.d.ts +12 -0
  612. package/dist/types/components/co-transfer-list/co-transfer-list.d.ts +4 -0
  613. package/dist/types/components/co-video/co-video.d.ts +203 -0
  614. package/dist/types/components.d.ts +5422 -391
  615. package/dist/types/utils/dateI18n.d.ts +39 -0
  616. package/dist/types/utils/fieldChip.d.ts +37 -0
  617. package/dist/types/utils/fileI18n.d.ts +34 -0
  618. package/dist/types/utils/icon-config.d.ts +31 -0
  619. package/dist/types/utils/lightboxI18n.d.ts +12 -0
  620. package/dist/types/utils/normalizeText.d.ts +41 -0
  621. package/dist/types/utils/overlayScroll.d.ts +17 -0
  622. package/dist/types/utils/positioning.d.ts +7 -14
  623. package/dist/types/utils/requiredMark.d.ts +13 -0
  624. package/dist/types/utils/richTextI18n.d.ts +130 -0
  625. package/dist/types/utils/sheetGesture.d.ts +31 -0
  626. package/package.json +10 -1
  627. package/dist/cjs/co-drawer.cjs.entry.js +0 -75
  628. package/dist/cjs/co-loader.cjs.entry.js +0 -34
  629. package/dist/cjs/co-overlay.cjs.entry.js +0 -23
  630. package/dist/cjs/color-YhUkm10t.js +0 -32
  631. package/dist/cobalt/p-08afdc51.entry.js +0 -1
  632. package/dist/cobalt/p-1b7d6808.entry.js +0 -1
  633. package/dist/cobalt/p-1d3338b6.entry.js +0 -1
  634. package/dist/cobalt/p-1d91ec93.entry.js +0 -1
  635. package/dist/cobalt/p-230a23f3.entry.js +0 -1
  636. package/dist/cobalt/p-31bc842d.entry.js +0 -1
  637. package/dist/cobalt/p-37c1f700.entry.js +0 -1
  638. package/dist/cobalt/p-4905b51d.entry.js +0 -1
  639. package/dist/cobalt/p-4dd7499c.entry.js +0 -1
  640. package/dist/cobalt/p-4e7ce8ee.entry.js +0 -1
  641. package/dist/cobalt/p-4ffba5a3.entry.js +0 -1
  642. package/dist/cobalt/p-5a13e3a0.entry.js +0 -1
  643. package/dist/cobalt/p-6793c51e.entry.js +0 -1
  644. package/dist/cobalt/p-689e38b3.entry.js +0 -1
  645. package/dist/cobalt/p-7028880b.entry.js +0 -1
  646. package/dist/cobalt/p-72113ec2.entry.js +0 -1
  647. package/dist/cobalt/p-8e54e74d.entry.js +0 -1
  648. package/dist/cobalt/p-92c39eed.entry.js +0 -1
  649. package/dist/cobalt/p-9887b828.entry.js +0 -1
  650. package/dist/cobalt/p-9a5c6600.entry.js +0 -1
  651. package/dist/cobalt/p-Am-OlB8h.js +0 -1
  652. package/dist/cobalt/p-B0lqrhFo.js +0 -2
  653. package/dist/cobalt/p-BG4WRR22.js +0 -1
  654. package/dist/cobalt/p-a1b248ad.entry.js +0 -1
  655. package/dist/cobalt/p-a470b764.entry.js +0 -1
  656. package/dist/cobalt/p-a4d55b1a.entry.js +0 -1
  657. package/dist/cobalt/p-b6840df4.entry.js +0 -1
  658. package/dist/cobalt/p-b89d54d9.entry.js +0 -1
  659. package/dist/cobalt/p-ba84631a.entry.js +0 -1
  660. package/dist/cobalt/p-c9b0e73f.entry.js +0 -1
  661. package/dist/cobalt/p-ca41eec2.entry.js +0 -1
  662. package/dist/cobalt/p-cc93ab05.entry.js +0 -1
  663. package/dist/cobalt/p-d9d8b10e.entry.js +0 -1
  664. package/dist/cobalt/p-da55678f.entry.js +0 -1
  665. package/dist/cobalt/p-dc5598d1.entry.js +0 -1
  666. package/dist/cobalt/p-e2c9cb00.entry.js +0 -1
  667. package/dist/cobalt/p-e808916c.entry.js +0 -1
  668. package/dist/cobalt/p-ebd68f56.entry.js +0 -1
  669. package/dist/cobalt/p-f051f44d.entry.js +0 -1
  670. package/dist/cobalt/p-fe1447a3.entry.js +0 -1
  671. package/dist/cobalt/p-ff6a647c.entry.js +0 -1
  672. package/dist/components/p-Am-OlB8h.js +0 -1
  673. package/dist/components/p-B18FTYLq.js +0 -1
  674. package/dist/components/p-BG4WRR22.js +0 -1
  675. package/dist/components/p-Cr8Yc0zj.js +0 -1
  676. package/dist/components/p-FBICWTuN.js +0 -1
  677. package/dist/components/p-cpdUXBiS.js +0 -1
  678. package/dist/components/p-wwWquAtm.js +0 -1
  679. package/dist/esm/co-drawer.entry.js +0 -73
  680. package/dist/esm/co-loader.entry.js +0 -32
  681. package/dist/esm/co-overlay.entry.js +0 -21
  682. package/dist/esm/color-BG4WRR22.js +0 -30
@@ -0,0 +1,2823 @@
1
+ import { h } from "@stencil/core";
2
+ import * as RichText from "@prolibu-suite/cobalt-rich-text";
3
+ import { getRichTextStrings } from "../../utils/richTextI18n";
4
+ /**
5
+ * Rich text editor backed by Tiptap v3.
6
+ *
7
+ * Uses `shadow: false, scoped: false` (the co-data-table pattern) because
8
+ * ProseMirror builds its editable DOM imperatively — Stencil's scoped CSS would
9
+ * never reach it. All styles live in light DOM via BEM + `--co-*` tokens.
10
+ *
11
+ * @part wrapper - Outer container
12
+ * @part toolbar - Formatting toolbar
13
+ * @part content - Editable ProseMirror surface
14
+ * @part label - Field label
15
+ * @part helper - Helper text row
16
+ */
17
+ export class CoRichTextEditor {
18
+ constructor() {
19
+ /** ProseMirror document as a JSON string. `null`/empty = empty editor. */
20
+ this.value = null;
21
+ /** Preset controlling allowed nodes/marks, toolbar and sanitization. */
22
+ this.preset = 'task';
23
+ this.placeholder = '';
24
+ this.status = 'default';
25
+ this.disabled = false;
26
+ this.readonly = false;
27
+ this.required = false;
28
+ this.showCharacterCount = false;
29
+ this.autofocus = false;
30
+ /** Toolbar layout. `auto` uses the preset default. */
31
+ this.toolbar = 'auto';
32
+ /** BCP-47 locale for UI strings (e.g. 'en', 'es-CO', 'pt-BR'). Default English. */
33
+ this.locale = 'en';
34
+ this.ready = false;
35
+ this.hasFocus = false;
36
+ /** Character count — updated imperatively to avoid re-renders on every keystroke. */
37
+ this.charCount = 0;
38
+ this.bubbleDragged = false;
39
+ this.bubbleDragOffset = { x: 0, y: 0 };
40
+ this.bubbleDragPos = { x: 0, y: 0 };
41
+ /** Position lock — prevents floating-ui from repositioning the bubble during toolbar interactions. */
42
+ this.bubblePositionLocked = false;
43
+ this.bubbleLockPos = { x: 0, y: 0 };
44
+ this.applyingBubbleLock = false;
45
+ /** Account fonts loaded via fontLoader callback. */
46
+ this._loadedAccountFonts = [];
47
+ this._fontLoaderCalled = false;
48
+ this._fontLoaderLoading = false;
49
+ /** Last emitted JSON string — guards the value Watch against feedback loops. */
50
+ this.lastEmittedJson = null;
51
+ /** Last emitted HTML string — parents often send HTML back via value prop. */
52
+ this.lastEmittedHtml = '';
53
+ /** True while applying an external value (suppresses emit). */
54
+ this.applyingExternal = false;
55
+ this.rt = RichText;
56
+ this.imgLayoutVisible = false;
57
+ this.handleUpdate = (editor) => {
58
+ this.refreshCharCount();
59
+ if (this.applyingExternal)
60
+ return;
61
+ const out = this.buildOutput(editor);
62
+ // Track both JSON and HTML forms to prevent feedback loops.
63
+ // The parent may send back either format via the value prop.
64
+ this.lastEmittedJson = out.json ? JSON.stringify(out.json) : null;
65
+ this.lastEmittedHtml = out.html;
66
+ // Do NOT set this.value here — it triggers unnecessary Stencil re-renders
67
+ // and the Watch cycle. The parent is the source of truth for the value prop.
68
+ this.coInput.emit(out);
69
+ // In readonly mode there's no blur cycle, so commit immediately
70
+ // (e.g. task-list checkbox toggled by onReadOnlyChecked).
71
+ if (this.readonly)
72
+ this.coChange.emit(out);
73
+ };
74
+ this.handleFocus = () => {
75
+ this.hasFocus = true;
76
+ this.coFocus.emit();
77
+ };
78
+ this.handleBlur = () => {
79
+ // Delay blur processing — if the user clicked a toolbar button,
80
+ // chain().focus() will re-focus the editor before this timeout fires.
81
+ clearTimeout(this.blurTimeout);
82
+ this.blurTimeout = setTimeout(() => {
83
+ var _a, _b;
84
+ if ((_a = this.editor) === null || _a === void 0 ? void 0 : _a.isFocused)
85
+ return; // Focus was restored (toolbar click)
86
+ // Don't blur if focus moved to an element inside the bubble (e.g. hex input)
87
+ if ((_b = this.bubbleEl) === null || _b === void 0 ? void 0 : _b.contains(document.activeElement))
88
+ return;
89
+ this.hasFocus = false;
90
+ if (this.editor)
91
+ this.coChange.emit(this.buildOutput(this.editor));
92
+ this.coBlur.emit();
93
+ }, 100);
94
+ };
95
+ }
96
+ async componentDidLoad() {
97
+ var _a, _b;
98
+ if (!this.contentEl)
99
+ return;
100
+ // Create bubble element imperatively so Stencil VDOM cannot interfere
101
+ // with BubbleMenu's DOM management (it calls element.remove/appendChild).
102
+ const showToolbar = this.resolvedToolbar !== 'none' && !this.readonly && !this.disabled;
103
+ if (showToolbar) {
104
+ this.bubbleEl = this.createBubbleElement();
105
+ }
106
+ this.editor = this.rt.createEditor({
107
+ preset: this.preset,
108
+ element: this.contentEl,
109
+ content: this.parseValue(this.value),
110
+ editable: !this.disabled && !this.readonly,
111
+ placeholder: this.placeholder,
112
+ maxLength: this.maxLength,
113
+ features: this.parsedFeatures,
114
+ customExtensions: (_a = this.customExtensions) !== null && _a !== void 0 ? _a : [],
115
+ bubbleMenuElement: this.bubbleEl,
116
+ imageUpload: this.imageUpload,
117
+ onUpdate: (editor) => this.handleUpdate(editor),
118
+ onFocus: () => this.handleFocus(),
119
+ onBlur: () => this.handleBlur(),
120
+ });
121
+ // Document / "site" preset: fluid ~80% content width (see editor.css). Marks
122
+ // both editable and readonly so the reader matches the author's measure.
123
+ if (this.preset === 'document') {
124
+ this.contentEl.classList.add('co-rte-content--site');
125
+ }
126
+ // Image layout toolbar — only when actually editable. The layout itself is
127
+ // CSS-driven (keyed on `data-image-layout`); the bar just lets the author
128
+ // pick a reflow mode (inline / wrap-left / wrap-right / center / full-width).
129
+ if (showToolbar && this.imagesEnabled) {
130
+ this.contentEl.style.position = 'relative'; // offset parent for the bar
131
+ this.imgLayoutEl = this.createImageLayoutBar();
132
+ this.contentEl.appendChild(this.imgLayoutEl);
133
+ }
134
+ // Update bubble active states on every transaction
135
+ this.editor.on('transaction', ({ transaction }) => {
136
+ if (this.bubbleEl) {
137
+ this.updateBubbleActiveStates();
138
+ if ((this.bubbleDragged || this.bubblePositionLocked) && this.bubbleEl) {
139
+ this.applyBubbleFixedPosition();
140
+ }
141
+ }
142
+ // Reapply floating-image positions only when the doc changed (skip pure
143
+ // selection/cursor moves to avoid a full descendants walk on every keystroke).
144
+ if (this.imagesEnabled && transaction.docChanged)
145
+ this.syncImageLayouts();
146
+ this.updateImageLayoutBar();
147
+ });
148
+ // Clicking the toolbar closes bubble popups (link form, panels, etc.)
149
+ if (this.bubbleEl && this.toolbarEl) {
150
+ this.toolbarEl.addEventListener('mousedown', () => {
151
+ this.closeBubbleDropdowns();
152
+ });
153
+ // Hide the selection bubble while a toolbar dropdown/popover is open so
154
+ // the two never overlap in the same space (the bubble lives inside the
155
+ // content area, right where toolbar dropdowns expand into).
156
+ this.toolbarEl.addEventListener('coPopoverChange', (e) => {
157
+ var _a;
158
+ const open = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.open;
159
+ this.suppressBubble(!!open);
160
+ });
161
+ }
162
+ this.lastEmittedJson = (_b = this.value) !== null && _b !== void 0 ? _b : null;
163
+ this.ready = true;
164
+ this.refreshCharCount();
165
+ this.syncToolbar();
166
+ this.coReady.emit();
167
+ if (this.autofocus)
168
+ this.editor.commands.focus();
169
+ // Tag every image container with its layout mode so the CSS rules apply.
170
+ // Runs even without the layout toolbar (readonly/disabled viewers).
171
+ requestAnimationFrame(() => this.syncImageLayouts());
172
+ }
173
+ disconnectedCallback() {
174
+ var _a, _b, _c, _d;
175
+ clearTimeout(this.blurTimeout);
176
+ clearTimeout(this.bubbleLockTimer);
177
+ (_a = this.bubbleStyleObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
178
+ if (this.bubbleDragMoveHandler)
179
+ document.removeEventListener('mousemove', this.bubbleDragMoveHandler);
180
+ if (this.bubbleDragEndHandler)
181
+ document.removeEventListener('mouseup', this.bubbleDragEndHandler);
182
+ if (this.bubbleOutsideClickHandler)
183
+ document.removeEventListener('click', this.bubbleOutsideClickHandler, true);
184
+ (_b = this.editor) === null || _b === void 0 ? void 0 : _b.destroy();
185
+ this.editor = undefined;
186
+ (_c = this.bubbleEl) === null || _c === void 0 ? void 0 : _c.remove();
187
+ (_d = this.imgLayoutEl) === null || _d === void 0 ? void 0 : _d.remove();
188
+ }
189
+ componentDidRender() {
190
+ this.syncToolbar();
191
+ }
192
+ onAccountFontsChange() {
193
+ var _a;
194
+ // Re-render the font dropdown list if it's open
195
+ if (this._fontDropdownRenderFn) {
196
+ const filter = ((_a = this._fontDropdownSearchInput) === null || _a === void 0 ? void 0 : _a.value) || '';
197
+ this._fontDropdownRenderFn(filter);
198
+ }
199
+ }
200
+ onValueChange(next) {
201
+ if (!this.editor || this.applyingExternal)
202
+ return;
203
+ const incoming = next !== null && next !== void 0 ? next : null;
204
+ // Skip if this value matches what we last emitted (JSON or HTML form).
205
+ // This prevents the destructive feedback loop where the parent sends
206
+ // back our own output and setContent resets the editor on every keystroke.
207
+ if (incoming === this.lastEmittedJson || incoming === this.lastEmittedHtml)
208
+ return;
209
+ this.applyingExternal = true;
210
+ try {
211
+ if (incoming === '' || incoming === null) {
212
+ this.editor.commands.clearContent(false);
213
+ }
214
+ else {
215
+ this.editor.commands.setContent(this.parseValue(next), { emitUpdate: false });
216
+ }
217
+ }
218
+ finally {
219
+ this.applyingExternal = false;
220
+ this.lastEmittedJson = incoming;
221
+ this.lastEmittedHtml = '';
222
+ this.refreshCharCount();
223
+ }
224
+ }
225
+ onEditableChange() {
226
+ var _a;
227
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.setEditable(!this.disabled && !this.readonly);
228
+ }
229
+ /* ── Public methods (escape hatches + imperative control) ── */
230
+ async getJSON() {
231
+ return this.editor && !this.editor.isEmpty ? this.editor.getJSON() : null;
232
+ }
233
+ async getHtml() {
234
+ return this.editor ? this.sanitizeHtml(this.editor.getHTML()) : '';
235
+ }
236
+ async getText() {
237
+ var _a, _b;
238
+ return (_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getText()) !== null && _b !== void 0 ? _b : '';
239
+ }
240
+ async clear() {
241
+ if (!this.editor)
242
+ return;
243
+ this.editor.commands.clearContent(true);
244
+ this.coClear.emit();
245
+ }
246
+ async focusEditor() {
247
+ var _a;
248
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.commands.focus();
249
+ }
250
+ async setContent(content) {
251
+ var _a;
252
+ (_a = this.editor) === null || _a === void 0 ? void 0 : _a.commands.setContent(content);
253
+ }
254
+ async getEditorInstance() {
255
+ var _a;
256
+ return (_a = this.editor) !== null && _a !== void 0 ? _a : null;
257
+ }
258
+ /* ── internals ── */
259
+ /** Whether the image node is enabled (mirrors presets.ts `wantImage` logic). */
260
+ get imagesEnabled() {
261
+ var _a;
262
+ const f = this.parsedFeatures;
263
+ return (_a = f === null || f === void 0 ? void 0 : f.image) !== null && _a !== void 0 ? _a : this.preset === 'document';
264
+ }
265
+ get parsedFeatures() {
266
+ if (!this.features)
267
+ return undefined;
268
+ if (typeof this.features === 'string') {
269
+ try {
270
+ return JSON.parse(this.features);
271
+ }
272
+ catch (_a) {
273
+ return undefined;
274
+ }
275
+ }
276
+ return this.features;
277
+ }
278
+ parseValue(v) {
279
+ if (!v)
280
+ return '';
281
+ try {
282
+ return JSON.parse(v);
283
+ }
284
+ catch (_a) {
285
+ return v; // tolerate an HTML string
286
+ }
287
+ }
288
+ sanitizeHtml(html) {
289
+ return this.rt.sanitize(html, this.preset);
290
+ }
291
+ buildOutput(editor) {
292
+ const empty = editor.isEmpty;
293
+ return {
294
+ json: empty ? null : editor.getJSON(),
295
+ html: empty ? '' : this.sanitizeHtml(editor.getHTML()),
296
+ text: editor.getText(),
297
+ };
298
+ }
299
+ /** Lock the bubble position so floating-ui doesn't reposition it. */
300
+ lockBubblePosition(durationMs = 1000) {
301
+ if (!this.bubbleEl)
302
+ return;
303
+ const rect = this.bubbleEl.getBoundingClientRect();
304
+ if (rect.width === 0)
305
+ return; // bubble not visible
306
+ this.bubbleLockPos = { x: rect.left, y: rect.top };
307
+ this.bubblePositionLocked = true;
308
+ clearTimeout(this.bubbleLockTimer);
309
+ this.bubbleLockTimer = setTimeout(() => {
310
+ this.bubblePositionLocked = false;
311
+ }, durationMs);
312
+ }
313
+ /** Apply fixed position to the bubble, overriding floating-ui. */
314
+ applyBubbleFixedPosition() {
315
+ if (!this.bubbleEl)
316
+ return;
317
+ const pos = this.bubbleDragged ? this.bubbleDragPos : this.bubbleLockPos;
318
+ this.applyingBubbleLock = true;
319
+ this.bubbleEl.style.position = 'fixed';
320
+ this.bubbleEl.style.top = `${pos.y}px`;
321
+ this.bubbleEl.style.left = `${pos.x}px`;
322
+ this.bubbleEl.style.transform = 'none';
323
+ this.bubbleEl.style.visibility = 'visible';
324
+ requestAnimationFrame(() => { this.applyingBubbleLock = false; });
325
+ }
326
+ /** Watch for floating-ui style changes and override them when locked/dragged. */
327
+ setupBubbleStyleObserver(bubble) {
328
+ // Use BubbleMenu plugin's onHide/onShow callbacks (dispatched as custom
329
+ // events from create-editor) for reliable drag state management.
330
+ // These fire synchronously inside hide()/show(), avoiding microtask races.
331
+ bubble.addEventListener('co-bubble-hide', () => {
332
+ this.bubbleDragged = false;
333
+ this.bubblePositionLocked = false;
334
+ clearTimeout(this.bubbleLockTimer);
335
+ this.closeBubbleDropdowns();
336
+ bubble.style.position = '';
337
+ bubble.style.top = '';
338
+ bubble.style.left = '';
339
+ bubble.style.transform = '';
340
+ });
341
+ bubble.addEventListener('co-bubble-show', () => {
342
+ this.bubbleDragged = false;
343
+ this.bubblePositionLocked = false;
344
+ });
345
+ // MutationObserver only handles overriding floating-ui position
346
+ // while the bubble is actively dragged or position-locked.
347
+ this.bubbleStyleObserver = new MutationObserver(() => {
348
+ if (this.applyingBubbleLock)
349
+ return;
350
+ if (!this.bubblePositionLocked && !this.bubbleDragged)
351
+ return;
352
+ this.applyBubbleFixedPosition();
353
+ });
354
+ this.bubbleStyleObserver.observe(bubble, {
355
+ attributes: true,
356
+ attributeFilter: ['style'],
357
+ });
358
+ }
359
+ /**
360
+ * Hide/show the selection bubble while a toolbar dropdown is open. Uses a
361
+ * class with `!important` so it wins over the BubbleMenu plugin's inline
362
+ * display/visibility writes. When unsuppressed, the plugin's own state
363
+ * (selection still active) reveals it again on the next update.
364
+ */
365
+ suppressBubble(on) {
366
+ if (!this.bubbleEl)
367
+ return;
368
+ this.bubbleEl.classList.toggle('co-rte-bubble--suppressed', on);
369
+ if (on)
370
+ this.closeBubbleDropdowns();
371
+ }
372
+ /** Close all open sub-dropdowns inside the bubble. */
373
+ closeBubbleDropdowns() {
374
+ if (!this.bubbleEl)
375
+ return;
376
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
377
+ d.style.display = 'none';
378
+ });
379
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
380
+ d.style.display = 'none';
381
+ });
382
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__panel').forEach(d => {
383
+ d.style.display = 'none';
384
+ });
385
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-menu').forEach(d => {
386
+ d.style.display = 'none';
387
+ });
388
+ if (this.bubbleLinkFormEl) {
389
+ this.bubbleLinkFormEl.style.display = 'none';
390
+ }
391
+ }
392
+ refreshCharCount() {
393
+ var _a;
394
+ const storage = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.storage;
395
+ if (storage === null || storage === void 0 ? void 0 : storage.characterCount) {
396
+ this.charCount = storage.characterCount.characters();
397
+ // Update DOM directly to avoid Stencil re-renders on every keystroke
398
+ if (this.charCountEl) {
399
+ this.charCountEl.textContent = this.maxLength != null
400
+ ? `${this.charCount} / ${this.maxLength}`
401
+ : `${this.charCount}`;
402
+ }
403
+ }
404
+ }
405
+ syncToolbar() {
406
+ if (this.toolbarEl && this.editor && this.toolbarEl.editor !== this.editor) {
407
+ this.toolbarEl.editor = this.editor;
408
+ }
409
+ if (this.toolbarEl) {
410
+ this.toolbarEl.imageUpload = this.imageUpload;
411
+ }
412
+ }
413
+ get resolvedToolbar() {
414
+ if (this.toolbar !== 'auto')
415
+ return this.toolbar;
416
+ return this.rt.defaultToolbarForPreset(this.preset);
417
+ }
418
+ get resolvedFontFamilies() {
419
+ if (!this.fontFamilies)
420
+ return CoRichTextEditor.DEFAULT_FONTS;
421
+ if (typeof this.fontFamilies === 'string') {
422
+ try {
423
+ return JSON.parse(this.fontFamilies);
424
+ }
425
+ catch (_a) {
426
+ return CoRichTextEditor.DEFAULT_FONTS;
427
+ }
428
+ }
429
+ return this.fontFamilies;
430
+ }
431
+ get resolvedAccountFonts() {
432
+ // Prefer prop over loaded fonts
433
+ if (this.accountFonts) {
434
+ if (typeof this.accountFonts === 'string') {
435
+ try {
436
+ return JSON.parse(this.accountFonts);
437
+ }
438
+ catch (_a) {
439
+ return [];
440
+ }
441
+ }
442
+ return this.accountFonts;
443
+ }
444
+ return this._loadedAccountFonts;
445
+ }
446
+ registerFontFace(name, url) {
447
+ if (!url || !name || CoRichTextEditor._registeredFonts.has(name))
448
+ return;
449
+ CoRichTextEditor._registeredFonts.add(name);
450
+ try {
451
+ const face = new FontFace(name, `url("${url}")`);
452
+ face.load().then(() => document.fonts.add(face)).catch(() => { });
453
+ }
454
+ catch ( /* ignore */_a) { /* ignore */ }
455
+ }
456
+ /** Load account fonts via the fontLoader callback (called once). */
457
+ async loadFontsViaCallback() {
458
+ var _a, _b, _c;
459
+ if (this._fontLoaderCalled || !this.fontLoader)
460
+ return;
461
+ this._fontLoaderCalled = true;
462
+ this._fontLoaderLoading = true;
463
+ // Re-render to show loading state
464
+ (_a = this._fontDropdownRenderFn) === null || _a === void 0 ? void 0 : _a.call(this, '');
465
+ try {
466
+ const fonts = await this.fontLoader();
467
+ if (Array.isArray(fonts)) {
468
+ this._loadedAccountFonts = fonts.map(f => {
469
+ if (f.url)
470
+ this.registerFontFace(f.label, f.url);
471
+ return { label: f.label, value: f.value };
472
+ });
473
+ }
474
+ }
475
+ catch (e) {
476
+ console.error('[co-rich-text-editor] fontLoader error', e);
477
+ }
478
+ finally {
479
+ this._fontLoaderLoading = false;
480
+ // Re-render with loaded fonts
481
+ const filter = ((_b = this._fontDropdownSearchInput) === null || _b === void 0 ? void 0 : _b.value) || '';
482
+ (_c = this._fontDropdownRenderFn) === null || _c === void 0 ? void 0 : _c.call(this, filter);
483
+ }
484
+ }
485
+ get helperIcon() {
486
+ switch (this.status) {
487
+ case 'error': return 'warning-circle';
488
+ case 'success': return 'check-circle';
489
+ case 'warning': return 'warning-circle';
490
+ default: return 'info';
491
+ }
492
+ }
493
+ /* ── Bubble menu (imperative — outside Stencil VDOM) ── */
494
+ /**
495
+ * Create the bubble menu element imperatively. BubbleMenu v3 manages
496
+ * the element via remove()/appendChild(), which conflicts with Stencil's
497
+ * virtual DOM reconciliation. By creating it outside the VDOM, Stencil
498
+ * won't recreate or interfere with the element.
499
+ */
500
+ createBubbleElement() {
501
+ const bubble = document.createElement('div');
502
+ bubble.className = 'co-rte-bubble';
503
+ // Start hidden and absolutely positioned so it never takes document flow space.
504
+ // BubbleMenu's floating-ui will manage position via inline styles when shown.
505
+ bubble.style.visibility = 'hidden';
506
+ bubble.style.position = 'absolute';
507
+ bubble.style.top = '0';
508
+ bubble.style.left = '0';
509
+ // Prevent any bubble click from stealing editor focus
510
+ // and lock bubble position during any toolbar interaction.
511
+ bubble.addEventListener('mousedown', (e) => {
512
+ if (e.target.tagName !== 'INPUT')
513
+ e.preventDefault();
514
+ this.lockBubblePosition();
515
+ });
516
+ // Close dropdowns/panels when clicking outside the bubble
517
+ this.bubbleOutsideClickHandler = (e) => {
518
+ if (!bubble.contains(e.target)) {
519
+ this.closeBubbleDropdowns();
520
+ }
521
+ };
522
+ document.addEventListener('click', this.bubbleOutsideClickHandler, true);
523
+ // Watch for floating-ui style overrides and restore locked position
524
+ this.setupBubbleStyleObserver(bubble);
525
+ const isDocument = this.preset === 'document';
526
+ /* ── Drag handle (document only) ── */
527
+ if (isDocument) {
528
+ const dragHandle = document.createElement('div');
529
+ dragHandle.className = 'co-rte-bubble__drag-handle';
530
+ dragHandle.innerHTML = `<co-icon name="dots-six-vertical" size="14"></co-icon>`;
531
+ dragHandle.addEventListener('mousedown', (e) => {
532
+ e.preventDefault();
533
+ e.stopPropagation();
534
+ const rect = bubble.getBoundingClientRect();
535
+ this.bubbleDragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
536
+ if (!this.bubbleDragged) {
537
+ this.bubbleDragPos = { x: rect.left, y: rect.top };
538
+ }
539
+ this.bubbleDragged = true;
540
+ this.bubbleDragMoveHandler = (ev) => {
541
+ this.bubbleDragPos.x = ev.clientX - this.bubbleDragOffset.x;
542
+ this.bubbleDragPos.y = ev.clientY - this.bubbleDragOffset.y;
543
+ bubble.style.position = 'fixed';
544
+ bubble.style.top = `${this.bubbleDragPos.y}px`;
545
+ bubble.style.left = `${this.bubbleDragPos.x}px`;
546
+ bubble.style.transform = 'none';
547
+ bubble.style.visibility = 'visible';
548
+ };
549
+ this.bubbleDragEndHandler = () => {
550
+ document.removeEventListener('mousemove', this.bubbleDragMoveHandler);
551
+ document.removeEventListener('mouseup', this.bubbleDragEndHandler);
552
+ };
553
+ document.addEventListener('mousemove', this.bubbleDragMoveHandler);
554
+ document.addEventListener('mouseup', this.bubbleDragEndHandler);
555
+ });
556
+ bubble.appendChild(dragHandle);
557
+ } // end isDocument drag handle
558
+ /* ── Single row: all controls ── */
559
+ const row = document.createElement('div');
560
+ row.className = 'co-rte-bubble__row';
561
+ // --- Advanced controls (document preset only) ---
562
+ // Panels will be appended to bubble root (not inside the row) at the end.
563
+ let fontSizePanel = null;
564
+ let fontWeightPanel = null;
565
+ let lineHeightPanelEl = null;
566
+ let letterSpacingPanelEl = null;
567
+ let bgColorPanelEl = null;
568
+ let overflowResult = null;
569
+ if (isDocument) {
570
+ // --- Font Family select (with search) ---
571
+ const fontFamilyWrap = this.createBubbleFontFamilySelect();
572
+ row.appendChild(fontFamilyWrap);
573
+ // --- Font Size panel (draggable with custom input) ---
574
+ fontSizePanel = this.createBubbleFontSizePanel();
575
+ row.appendChild(fontSizePanel.wrap);
576
+ // --- Font Weight panel (draggable, two-column) ---
577
+ fontWeightPanel = this.createBubbleFontWeightPanel();
578
+ row.appendChild(fontWeightPanel.wrap);
579
+ row.appendChild(this.createSep());
580
+ // --- Text color picker ---
581
+ const colorWrap = this.createBubbleColorPicker('textColor', (color) => {
582
+ if (!this.editor)
583
+ return;
584
+ this.editor.chain().focus().setColor(color).run();
585
+ });
586
+ row.appendChild(colorWrap);
587
+ row.appendChild(this.createSep());
588
+ } // end isDocument advanced controls
589
+ // --- B I U (all presets except comment which disables underline) ---
590
+ const _s = getRichTextStrings(this.locale);
591
+ const formatBtns = [
592
+ { action: 'bold', icon: 'text-b', label: _s.bold, check: 'bold' },
593
+ { action: 'italic', icon: 'text-italic', label: _s.italic, check: 'italic' },
594
+ ];
595
+ // Underline is available on task, email, document (not comment)
596
+ if (this.preset !== 'comment') {
597
+ formatBtns.push({ action: 'underline', icon: 'text-underline', label: _s.underline, check: 'underline' });
598
+ }
599
+ formatBtns.forEach(({ action, icon, label, check }) => {
600
+ const btn = this.createBubbleBtn(icon, label, action, check, () => {
601
+ if (!this.editor)
602
+ return;
603
+ const chain = this.editor.chain().focus();
604
+ switch (action) {
605
+ case 'bold':
606
+ chain.toggleBold().run();
607
+ break;
608
+ case 'italic':
609
+ chain.toggleItalic().run();
610
+ break;
611
+ case 'underline':
612
+ chain.toggleUnderline().run();
613
+ break;
614
+ }
615
+ });
616
+ row.appendChild(btn);
617
+ });
618
+ row.appendChild(this.createSep());
619
+ // --- Alignment buttons (document and email only) ---
620
+ if (isDocument || this.preset === 'email') {
621
+ const alignments = [
622
+ { align: 'left', icon: 'text-align-left', label: _s.alignLeft },
623
+ { align: 'center', icon: 'text-align-center', label: _s.center },
624
+ { align: 'right', icon: 'text-align-right', label: _s.alignRight },
625
+ { align: 'justify', icon: 'text-align-justify', label: _s.justify },
626
+ ];
627
+ alignments.forEach(({ align, icon, label }) => {
628
+ const btn = document.createElement('button');
629
+ btn.type = 'button';
630
+ btn.className = 'co-rte-bubble__btn';
631
+ btn.title = label;
632
+ btn.setAttribute('aria-label', label);
633
+ btn.setAttribute('data-action', 'textAlign');
634
+ btn.setAttribute('data-align', align);
635
+ btn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon>`;
636
+ btn.addEventListener('click', () => {
637
+ if (!this.editor)
638
+ return;
639
+ this.editor.chain().focus().setTextAlign(align).run();
640
+ });
641
+ row.appendChild(btn);
642
+ });
643
+ row.appendChild(this.createSep());
644
+ } // end alignment
645
+ // --- Bullet / Ordered list (task, email — not comment, not document) ---
646
+ // For document preset, lists are moved to the overflow menu.
647
+ if (this.preset !== 'comment' && !isDocument) {
648
+ row.appendChild(this.createBubbleBtn('list-bullets', _s.bulletList, 'bulletList', 'bulletList', () => {
649
+ if (!this.editor)
650
+ return;
651
+ this.editor.chain().focus().toggleBulletList().run();
652
+ }));
653
+ row.appendChild(this.createBubbleBtn('list-numbers', _s.orderedList, 'orderedList', 'orderedList', () => {
654
+ if (!this.editor)
655
+ return;
656
+ this.editor.chain().focus().toggleOrderedList().run();
657
+ }));
658
+ row.appendChild(this.createSep());
659
+ } // end lists (non-document)
660
+ // --- Link (all presets) ---
661
+ const linkBtn = this.createBubbleBtn('link', _s.link, 'link', 'link', () => {
662
+ if (!this.editor)
663
+ return;
664
+ this.toggleBubbleLinkForm(true);
665
+ });
666
+ row.appendChild(linkBtn);
667
+ // --- Overflow menu (document only) ---
668
+ // Superscript, subscript, lists, strikethrough, bg color, line height,
669
+ // letter spacing, horizontal rule, clear formatting — all in overflow.
670
+ if (isDocument) {
671
+ row.appendChild(this.createSep());
672
+ lineHeightPanelEl = this.createBubbleLineHeightPanel();
673
+ letterSpacingPanelEl = this.createBubbleLetterSpacingPanel();
674
+ bgColorPanelEl = this.createBubbleBgColorPanel();
675
+ overflowResult = this.createBubbleOverflowMenu({
676
+ lineHeight: lineHeightPanelEl,
677
+ letterSpacing: letterSpacingPanelEl,
678
+ bgColor: bgColorPanelEl,
679
+ });
680
+ row.appendChild(overflowResult.overflowWrap);
681
+ } // end isDocument overflow
682
+ bubble.appendChild(row);
683
+ // Append floating panels to bubble root (outside the row, so they float freely)
684
+ if (isDocument) {
685
+ if (fontSizePanel)
686
+ bubble.appendChild(fontSizePanel.panelEl);
687
+ if (fontWeightPanel)
688
+ bubble.appendChild(fontWeightPanel.panelEl);
689
+ if (lineHeightPanelEl)
690
+ bubble.appendChild(lineHeightPanelEl);
691
+ if (letterSpacingPanelEl)
692
+ bubble.appendChild(letterSpacingPanelEl);
693
+ if (bgColorPanelEl)
694
+ bubble.appendChild(bgColorPanelEl);
695
+ }
696
+ // Link form (hidden by default)
697
+ const linkForm = document.createElement('div');
698
+ linkForm.className = 'co-rte-bubble__link-form';
699
+ linkForm.style.display = 'none';
700
+ this.bubbleLinkFormEl = linkForm;
701
+ const linkInput = document.createElement('input');
702
+ linkInput.type = 'url';
703
+ linkInput.className = 'co-rte-bubble__link-input';
704
+ linkInput.placeholder = 'https://...';
705
+ this.bubbleLinkInputEl = linkInput;
706
+ linkInput.addEventListener('keydown', (e) => {
707
+ if (e.key === 'Enter')
708
+ this.submitBubbleLinkImperative();
709
+ if (e.key === 'Escape')
710
+ this.toggleBubbleLinkForm(false);
711
+ });
712
+ const linkSubmit = document.createElement('button');
713
+ linkSubmit.type = 'button';
714
+ linkSubmit.className = 'co-rte-bubble__link-btn';
715
+ linkSubmit.innerHTML = `<co-icon name="check" size="14"></co-icon>`;
716
+ linkSubmit.addEventListener('click', () => this.submitBubbleLinkImperative());
717
+ const linkUnlink = document.createElement('button');
718
+ linkUnlink.type = 'button';
719
+ linkUnlink.className = 'co-rte-bubble__link-btn co-rte-bubble__link-unlink';
720
+ linkUnlink.title = _s.unlinkLink;
721
+ linkUnlink.innerHTML = `<co-icon name="link-break" size="14"></co-icon>`;
722
+ linkUnlink.addEventListener('click', () => {
723
+ if (!this.editor)
724
+ return;
725
+ this.editor.chain().focus().unsetLink().run();
726
+ this.toggleBubbleLinkForm(false);
727
+ });
728
+ this.bubbleLinkUnlinkEl = linkUnlink;
729
+ linkForm.appendChild(linkInput);
730
+ linkForm.appendChild(linkSubmit);
731
+ linkForm.appendChild(linkUnlink);
732
+ bubble.appendChild(linkForm);
733
+ return bubble;
734
+ }
735
+ /** Helper: create a separator span */
736
+ createSep() {
737
+ const sep = document.createElement('span');
738
+ sep.className = 'co-rte-bubble__sep';
739
+ return sep;
740
+ }
741
+ /**
742
+ * Position a dropdown above or below the trigger depending on available
743
+ * viewport space. Sets `data-position="above"|"below"` so CSS can flip.
744
+ */
745
+ positionDropdown(trigger, dropdown) {
746
+ const triggerRect = trigger.getBoundingClientRect();
747
+ // The dropdown is already display:block when this is called.
748
+ // Remove any previous position so it can be measured at its natural height.
749
+ dropdown.removeAttribute('data-position');
750
+ dropdown.style.removeProperty('left');
751
+ dropdown.style.removeProperty('transform');
752
+ // Force layout so offsetHeight is accurate
753
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
754
+ dropdown.offsetHeight;
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
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
798
+ panel.offsetHeight;
799
+ const panelH = panel.offsetHeight || 320;
800
+ const panelW = panel.offsetWidth || 230;
801
+ const gap = 4;
802
+ const pad = 8;
803
+ let top = anchorRect.top;
804
+ if (top + panelH > window.innerHeight - pad)
805
+ top = window.innerHeight - pad - panelH;
806
+ if (top < pad)
807
+ top = pad;
808
+ let left = anchorRect.left - panelW - gap;
809
+ if (left < pad)
810
+ left = anchorRect.right + gap;
811
+ if (left + panelW > window.innerWidth - pad)
812
+ left = window.innerWidth - pad - panelW;
813
+ panel.style.position = 'fixed';
814
+ panel.style.top = `${top}px`;
815
+ panel.style.left = `${left}px`;
816
+ panel.style.bottom = 'auto';
817
+ panel.style.right = 'auto';
818
+ panel.style.transform = 'none';
819
+ panel.removeAttribute('data-position');
820
+ }
821
+ /** Helper: create a toggle button for the bubble */
822
+ createBubbleBtn(icon, label, action, check, onClick) {
823
+ const btn = document.createElement('button');
824
+ btn.type = 'button';
825
+ btn.className = 'co-rte-bubble__btn';
826
+ btn.title = label;
827
+ btn.setAttribute('aria-label', label);
828
+ btn.setAttribute('data-action', action);
829
+ btn.setAttribute('data-check', check);
830
+ btn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon>`;
831
+ btn.addEventListener('click', onClick);
832
+ return btn;
833
+ }
834
+ /** Creates the font family dropdown with search for the bubble menu. */
835
+ createBubbleFontFamilySelect() {
836
+ const wrap = document.createElement('div');
837
+ wrap.className = 'co-rte-bubble__select co-rte-bubble__select--font';
838
+ wrap.setAttribute('data-select', 'fontFamily');
839
+ const trigger = document.createElement('button');
840
+ trigger.type = 'button';
841
+ trigger.className = 'co-rte-bubble__select-trigger';
842
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">Sans-serif</span><co-icon name="caret-down" size="12"></co-icon>`;
843
+ const dropdown = document.createElement('div');
844
+ dropdown.className = 'co-rte-bubble__select-dropdown co-rte-bubble__select-dropdown--font';
845
+ dropdown.style.display = 'none';
846
+ // Search input
847
+ const searchWrap = document.createElement('div');
848
+ searchWrap.className = 'co-rte-bubble__font-search';
849
+ const searchInput = document.createElement('input');
850
+ searchInput.type = 'text';
851
+ searchInput.className = 'co-rte-bubble__font-search-input';
852
+ searchInput.placeholder = getRichTextStrings(this.locale).searchFont;
853
+ searchWrap.appendChild(searchInput);
854
+ dropdown.appendChild(searchWrap);
855
+ // Font list container
856
+ const listEl = document.createElement('div');
857
+ listEl.className = 'co-rte-bubble__font-list';
858
+ dropdown.appendChild(listEl);
859
+ const createFontOption = (label, value) => {
860
+ const opt = document.createElement('button');
861
+ opt.type = 'button';
862
+ opt.className = 'co-rte-bubble__select-option';
863
+ opt.setAttribute('data-value', value);
864
+ opt.textContent = label;
865
+ opt.style.fontFamily = value.includes(',') ? value : `"${value}", sans-serif`;
866
+ opt.addEventListener('click', () => {
867
+ if (!this.editor)
868
+ return;
869
+ this.editor.chain().focus().setFontFamily(value).run();
870
+ dropdown.style.display = 'none';
871
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
872
+ if (labelEl)
873
+ labelEl.textContent = label;
874
+ searchInput.value = '';
875
+ this.coFontPopupHide.emit();
876
+ });
877
+ return opt;
878
+ };
879
+ const renderFonts = (filter) => {
880
+ listEl.innerHTML = '';
881
+ const term = filter.toLowerCase();
882
+ const accountFonts = this.resolvedAccountFonts;
883
+ const systemFonts = this.resolvedFontFamilies;
884
+ const filteredAccount = term ? accountFonts.filter(f => f.label.toLowerCase().includes(term)) : accountFonts;
885
+ const filteredSystem = term ? systemFonts.filter(f => f.label.toLowerCase().includes(term)) : systemFonts;
886
+ if (!filteredAccount.length && !filteredSystem.length) {
887
+ const empty = document.createElement('div');
888
+ empty.className = 'co-rte-bubble__font-empty';
889
+ empty.textContent = getRichTextStrings(this.locale).noResults;
890
+ listEl.appendChild(empty);
891
+ return;
892
+ }
893
+ // Loading indicator
894
+ if ((this.fontsLoading || this._fontLoaderLoading) && !filteredAccount.length) {
895
+ const loading = document.createElement('div');
896
+ loading.className = 'co-rte-bubble__font-empty';
897
+ loading.textContent = getRichTextStrings(this.locale).loadingFonts;
898
+ listEl.appendChild(loading);
899
+ }
900
+ // Imported fonts section
901
+ if (filteredAccount.length) {
902
+ const header = document.createElement('div');
903
+ header.className = 'co-rte-bubble__font-section-header';
904
+ header.textContent = getRichTextStrings(this.locale).importedFonts;
905
+ listEl.appendChild(header);
906
+ filteredAccount.forEach(({ label, value }) => listEl.appendChild(createFontOption(label, value)));
907
+ }
908
+ // System fonts section
909
+ if (filteredSystem.length) {
910
+ const header = document.createElement('div');
911
+ header.className = 'co-rte-bubble__font-section-header';
912
+ header.textContent = getRichTextStrings(this.locale).systemFonts;
913
+ listEl.appendChild(header);
914
+ filteredSystem.forEach(({ label, value }) => listEl.appendChild(createFontOption(label, value)));
915
+ }
916
+ };
917
+ searchInput.addEventListener('input', () => renderFonts(searchInput.value));
918
+ // Re-render fonts when accountFonts prop changes (MutationObserver on the host)
919
+ this._fontDropdownRenderFn = renderFonts;
920
+ this._fontDropdownSearchInput = searchInput;
921
+ trigger.addEventListener('click', () => {
922
+ const parent = wrap.closest('.co-rte-bubble');
923
+ if (parent) {
924
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
925
+ if (d !== dropdown)
926
+ d.style.display = 'none';
927
+ });
928
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
929
+ d.style.display = 'none';
930
+ });
931
+ }
932
+ const isOpen = dropdown.style.display !== 'none';
933
+ dropdown.style.display = isOpen ? 'none' : 'block';
934
+ if (!isOpen) {
935
+ this.coFontPopupShow.emit();
936
+ this.loadFontsViaCallback();
937
+ this.positionDropdown(trigger, dropdown);
938
+ renderFonts('');
939
+ setTimeout(() => searchInput.focus(), 0);
940
+ }
941
+ else {
942
+ this.coFontPopupHide.emit();
943
+ }
944
+ });
945
+ wrap.appendChild(trigger);
946
+ wrap.appendChild(dropdown);
947
+ return wrap;
948
+ }
949
+ /** Creates a compact dropdown-select for the bubble menu. */
950
+ createBubbleSelect(name, options, defaultLabel, onChange) {
951
+ const wrap = document.createElement('div');
952
+ wrap.className = 'co-rte-bubble__select';
953
+ wrap.setAttribute('data-select', name);
954
+ const trigger = document.createElement('button');
955
+ trigger.type = 'button';
956
+ trigger.className = 'co-rte-bubble__select-trigger';
957
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">${defaultLabel}</span><co-icon name="caret-down" size="12"></co-icon>`;
958
+ const dropdown = document.createElement('div');
959
+ dropdown.className = 'co-rte-bubble__select-dropdown';
960
+ dropdown.style.display = 'none';
961
+ options.forEach(({ label, value }) => {
962
+ const opt = document.createElement('button');
963
+ opt.type = 'button';
964
+ opt.className = 'co-rte-bubble__select-option';
965
+ opt.setAttribute('data-value', value);
966
+ opt.textContent = label;
967
+ // Preview font weight in the option
968
+ if (name === 'fontWeight') {
969
+ opt.style.fontWeight = value;
970
+ }
971
+ opt.addEventListener('click', () => {
972
+ onChange(value);
973
+ dropdown.style.display = 'none';
974
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
975
+ if (labelEl)
976
+ labelEl.textContent = label;
977
+ });
978
+ dropdown.appendChild(opt);
979
+ });
980
+ trigger.addEventListener('click', () => {
981
+ // Close other open dropdowns in the bubble
982
+ const parent = wrap.closest('.co-rte-bubble');
983
+ if (parent) {
984
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
985
+ if (d !== dropdown)
986
+ d.style.display = 'none';
987
+ });
988
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
989
+ d.style.display = 'none';
990
+ });
991
+ }
992
+ const isOpen = dropdown.style.display !== 'none';
993
+ dropdown.style.display = isOpen ? 'none' : 'block';
994
+ if (!isOpen)
995
+ this.positionDropdown(trigger, dropdown);
996
+ });
997
+ wrap.appendChild(trigger);
998
+ wrap.appendChild(dropdown);
999
+ return wrap;
1000
+ }
1001
+ /** Creates a compact color picker button for the bubble menu. */
1002
+ createBubbleColorPicker(name, onChange) {
1003
+ const colors = [
1004
+ '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc',
1005
+ '#d9d9d9', '#efefef', '#f3f3f3', '#ffffff',
1006
+ '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff',
1007
+ '#4a86e8', '#0000ff', '#9900ff', '#ff00ff',
1008
+ '#e6b8af', '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3',
1009
+ '#c9daf8', '#cfe2f3', '#d9d2e9', '#ead1dc',
1010
+ ];
1011
+ const wrap = document.createElement('div');
1012
+ wrap.className = 'co-rte-bubble__color';
1013
+ wrap.setAttribute('data-color', name);
1014
+ const iconName = name === 'textColor' ? '' : 'highlighter';
1015
+ const trigger = document.createElement('button');
1016
+ trigger.type = 'button';
1017
+ trigger.className = 'co-rte-bubble__btn';
1018
+ const _cs = getRichTextStrings(this.locale);
1019
+ trigger.title = name === 'textColor' ? _cs.textColor : _cs.backgroundColor;
1020
+ if (name === 'textColor') {
1021
+ 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>`;
1022
+ }
1023
+ else {
1024
+ trigger.innerHTML = `<co-icon name="${iconName}" size="16"></co-icon>`;
1025
+ }
1026
+ const dropdown = document.createElement('div');
1027
+ dropdown.className = 'co-rte-bubble__color-dropdown';
1028
+ dropdown.style.display = 'none';
1029
+ const colorTitle = name === 'textColor' ? _cs.textColor : _cs.backgroundColor;
1030
+ const { resetDrag: resetColorDrag } = this.addDragHeader(dropdown, colorTitle);
1031
+ // Prevent focus loss
1032
+ dropdown.addEventListener('mousedown', (e) => {
1033
+ if (e.target.tagName !== 'INPUT')
1034
+ e.preventDefault();
1035
+ this.lockBubblePosition();
1036
+ });
1037
+ const grid = document.createElement('div');
1038
+ grid.className = 'co-rte-bubble__color-grid';
1039
+ colors.forEach(color => {
1040
+ const swatch = document.createElement('button');
1041
+ swatch.type = 'button';
1042
+ swatch.className = 'co-rte-bubble__color-swatch';
1043
+ swatch.style.background = color;
1044
+ if (color === '#ffffff') {
1045
+ swatch.style.border = '1px solid #e0e0e0';
1046
+ }
1047
+ swatch.addEventListener('click', () => {
1048
+ onChange(color);
1049
+ dropdown.style.display = 'none';
1050
+ });
1051
+ grid.appendChild(swatch);
1052
+ });
1053
+ // Hex input
1054
+ const hexRow = document.createElement('div');
1055
+ hexRow.className = 'co-rte-bubble__color-hex';
1056
+ const hexInput = document.createElement('input');
1057
+ hexInput.type = 'text';
1058
+ hexInput.className = 'co-rte-bubble__color-hex-input';
1059
+ hexInput.placeholder = '#hex';
1060
+ hexInput.maxLength = 7;
1061
+ hexInput.addEventListener('keydown', (e) => {
1062
+ if (e.key === 'Enter') {
1063
+ const val = hexInput.value.trim();
1064
+ if (/^#[0-9a-fA-F]{3,6}$/.test(val)) {
1065
+ onChange(val);
1066
+ dropdown.style.display = 'none';
1067
+ hexInput.value = '';
1068
+ }
1069
+ }
1070
+ });
1071
+ // Clear color button
1072
+ const clearBtn = document.createElement('button');
1073
+ clearBtn.type = 'button';
1074
+ clearBtn.className = 'co-rte-bubble__color-clear';
1075
+ clearBtn.innerHTML = `<co-icon name="x" size="12"></co-icon> ${_cs.noColor}`;
1076
+ clearBtn.addEventListener('click', () => {
1077
+ if (!this.editor)
1078
+ return;
1079
+ if (name === 'textColor')
1080
+ this.editor.chain().focus().unsetColor().run();
1081
+ else
1082
+ this.editor.chain().focus().unsetHighlight().run();
1083
+ dropdown.style.display = 'none';
1084
+ });
1085
+ dropdown.appendChild(grid);
1086
+ hexRow.appendChild(hexInput);
1087
+ dropdown.appendChild(hexRow);
1088
+ dropdown.appendChild(clearBtn);
1089
+ trigger.addEventListener('click', () => {
1090
+ const parent = wrap.closest('.co-rte-bubble');
1091
+ if (parent) {
1092
+ parent.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
1093
+ d.style.display = 'none';
1094
+ });
1095
+ parent.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
1096
+ if (d !== dropdown)
1097
+ d.style.display = 'none';
1098
+ });
1099
+ }
1100
+ const isOpen = dropdown.style.display !== 'none';
1101
+ if (isOpen) {
1102
+ dropdown.style.display = 'none';
1103
+ }
1104
+ else {
1105
+ resetColorDrag();
1106
+ dropdown.style.position = '';
1107
+ dropdown.style.top = '';
1108
+ dropdown.style.left = '';
1109
+ dropdown.style.bottom = '';
1110
+ dropdown.style.right = '';
1111
+ dropdown.style.transform = '';
1112
+ dropdown.style.display = 'block';
1113
+ this.positionDropdown(trigger, dropdown);
1114
+ }
1115
+ });
1116
+ wrap.appendChild(trigger);
1117
+ wrap.appendChild(dropdown);
1118
+ return wrap;
1119
+ }
1120
+ /** Close all bubble popups EXCEPT the given element. */
1121
+ closeAllBubblePopups(...except) {
1122
+ if (!this.bubbleEl)
1123
+ return;
1124
+ const keep = except.filter(Boolean);
1125
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__select-dropdown').forEach(d => {
1126
+ if (!keep.includes(d))
1127
+ d.style.display = 'none';
1128
+ });
1129
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__color-dropdown').forEach(d => {
1130
+ if (!keep.includes(d))
1131
+ d.style.display = 'none';
1132
+ });
1133
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__panel').forEach(d => {
1134
+ if (!keep.includes(d))
1135
+ d.style.display = 'none';
1136
+ });
1137
+ this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-menu').forEach(d => {
1138
+ if (!keep.includes(d))
1139
+ d.style.display = 'none';
1140
+ });
1141
+ if (this.bubbleLinkFormEl && !keep.includes(this.bubbleLinkFormEl)) {
1142
+ this.bubbleLinkFormEl.style.display = 'none';
1143
+ }
1144
+ }
1145
+ addDragHeader(panel, title) {
1146
+ let dragged = false;
1147
+ let dragPos = { x: 0, y: 0 };
1148
+ let dragOffset = { x: 0, y: 0 };
1149
+ const header = document.createElement('div');
1150
+ header.className = 'co-rte-bubble__panel-header';
1151
+ const dragHandle = document.createElement('div');
1152
+ dragHandle.className = 'co-rte-bubble__panel-drag';
1153
+ dragHandle.innerHTML = `<co-icon name="dots-six" size="14"></co-icon>`;
1154
+ const titleEl = document.createElement('span');
1155
+ titleEl.className = 'co-rte-bubble__panel-title';
1156
+ titleEl.textContent = title;
1157
+ const closeBtn = document.createElement('button');
1158
+ closeBtn.type = 'button';
1159
+ closeBtn.className = 'co-rte-bubble__panel-close';
1160
+ closeBtn.innerHTML = `<co-icon name="x" size="14"></co-icon>`;
1161
+ closeBtn.addEventListener('click', () => { panel.style.display = 'none'; });
1162
+ header.appendChild(dragHandle);
1163
+ header.appendChild(titleEl);
1164
+ header.appendChild(closeBtn);
1165
+ dragHandle.addEventListener('mousedown', (e) => {
1166
+ e.preventDefault();
1167
+ e.stopPropagation();
1168
+ const rect = panel.getBoundingClientRect();
1169
+ dragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1170
+ if (!dragged)
1171
+ dragPos = { x: rect.left, y: rect.top };
1172
+ dragged = true;
1173
+ const onMove = (ev) => {
1174
+ dragPos.x = ev.clientX - dragOffset.x;
1175
+ dragPos.y = ev.clientY - dragOffset.y;
1176
+ panel.style.position = 'fixed';
1177
+ panel.style.top = `${dragPos.y}px`;
1178
+ panel.style.left = `${dragPos.x}px`;
1179
+ panel.style.bottom = 'auto';
1180
+ panel.style.right = 'auto';
1181
+ panel.style.transform = 'none';
1182
+ panel.removeAttribute('data-position');
1183
+ };
1184
+ const onUp = () => {
1185
+ document.removeEventListener('mousemove', onMove);
1186
+ document.removeEventListener('mouseup', onUp);
1187
+ };
1188
+ document.addEventListener('mousemove', onMove);
1189
+ document.addEventListener('mouseup', onUp);
1190
+ });
1191
+ const resetDrag = () => { dragged = false; };
1192
+ panel.insertBefore(header, panel.firstChild);
1193
+ return { header, resetDrag };
1194
+ }
1195
+ /** Generic draggable panel factory. */
1196
+ createBubblePanel(config) {
1197
+ const wrap = document.createElement('div');
1198
+ wrap.className = 'co-rte-bubble__select';
1199
+ wrap.setAttribute('data-select', config.name);
1200
+ const trigger = document.createElement('button');
1201
+ trigger.type = 'button';
1202
+ trigger.className = 'co-rte-bubble__select-trigger';
1203
+ trigger.innerHTML = `<span class="co-rte-bubble__select-label">${config.triggerLabel}</span><co-icon name="caret-down" size="12"></co-icon>`;
1204
+ const panel = document.createElement('div');
1205
+ panel.className = 'co-rte-bubble__panel';
1206
+ panel.setAttribute('data-panel', config.name);
1207
+ panel.style.display = 'none';
1208
+ // Header
1209
+ const header = document.createElement('div');
1210
+ header.className = 'co-rte-bubble__panel-header';
1211
+ const dragHandle = document.createElement('div');
1212
+ dragHandle.className = 'co-rte-bubble__panel-drag';
1213
+ dragHandle.innerHTML = `<co-icon name="dots-six" size="14"></co-icon>`;
1214
+ const titleEl = document.createElement('span');
1215
+ titleEl.className = 'co-rte-bubble__panel-title';
1216
+ titleEl.textContent = config.title;
1217
+ const closeBtn = document.createElement('button');
1218
+ closeBtn.type = 'button';
1219
+ closeBtn.className = 'co-rte-bubble__panel-close';
1220
+ closeBtn.innerHTML = `<co-icon name="x" size="14"></co-icon>`;
1221
+ closeBtn.addEventListener('click', () => { panel.style.display = 'none'; });
1222
+ header.appendChild(dragHandle);
1223
+ header.appendChild(titleEl);
1224
+ header.appendChild(closeBtn);
1225
+ panel.appendChild(header);
1226
+ // Panel drag
1227
+ let panelDragged = false;
1228
+ let panelDragPos = { x: 0, y: 0 };
1229
+ let panelDragOffset = { x: 0, y: 0 };
1230
+ dragHandle.addEventListener('mousedown', (e) => {
1231
+ e.preventDefault();
1232
+ e.stopPropagation();
1233
+ const rect = panel.getBoundingClientRect();
1234
+ panelDragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1235
+ if (!panelDragged)
1236
+ panelDragPos = { x: rect.left, y: rect.top };
1237
+ panelDragged = true;
1238
+ const onMove = (ev) => {
1239
+ panelDragPos.x = ev.clientX - panelDragOffset.x;
1240
+ panelDragPos.y = ev.clientY - panelDragOffset.y;
1241
+ panel.style.position = 'fixed';
1242
+ panel.style.top = `${panelDragPos.y}px`;
1243
+ panel.style.left = `${panelDragPos.x}px`;
1244
+ panel.style.bottom = 'auto';
1245
+ panel.style.right = 'auto';
1246
+ panel.style.transform = 'none';
1247
+ panel.removeAttribute('data-position');
1248
+ };
1249
+ const onUp = () => {
1250
+ document.removeEventListener('mousemove', onMove);
1251
+ document.removeEventListener('mouseup', onUp);
1252
+ };
1253
+ document.addEventListener('mousemove', onMove);
1254
+ document.addEventListener('mouseup', onUp);
1255
+ });
1256
+ // Custom input
1257
+ if (config.hasCustomInput) {
1258
+ const inputWrap = document.createElement('div');
1259
+ inputWrap.className = 'co-rte-bubble__panel-input-wrap';
1260
+ const input = document.createElement('input');
1261
+ input.type = config.inputType || 'text';
1262
+ input.className = 'co-rte-bubble__panel-input';
1263
+ input.placeholder = config.inputPlaceholder || '';
1264
+ input.addEventListener('mousedown', (e) => e.stopPropagation());
1265
+ input.addEventListener('keydown', (e) => {
1266
+ if (e.key === 'Enter') {
1267
+ const val = input.value.trim();
1268
+ if (val && config.onCustomInput) {
1269
+ config.onCustomInput(val);
1270
+ input.value = '';
1271
+ }
1272
+ }
1273
+ if (e.key === 'Escape') {
1274
+ panel.style.display = 'none';
1275
+ }
1276
+ });
1277
+ inputWrap.appendChild(input);
1278
+ panel.appendChild(inputWrap);
1279
+ }
1280
+ // Options
1281
+ const optionsWrap = document.createElement('div');
1282
+ optionsWrap.className = 'co-rte-bubble__panel-options';
1283
+ config.options.forEach(opt => {
1284
+ const btn = document.createElement('button');
1285
+ btn.type = 'button';
1286
+ btn.className = 'co-rte-bubble__panel-option';
1287
+ btn.setAttribute('data-value', opt.value);
1288
+ if (config.renderOption) {
1289
+ config.renderOption(opt, btn);
1290
+ }
1291
+ else {
1292
+ btn.textContent = opt.label;
1293
+ }
1294
+ btn.addEventListener('click', () => {
1295
+ config.onSelect(opt.value);
1296
+ panel.style.display = 'none';
1297
+ panelDragged = false;
1298
+ });
1299
+ optionsWrap.appendChild(btn);
1300
+ });
1301
+ panel.appendChild(optionsWrap);
1302
+ // Prevent bubble from losing focus
1303
+ panel.addEventListener('mousedown', (e) => {
1304
+ if (e.target.tagName !== 'INPUT')
1305
+ e.preventDefault();
1306
+ this.lockBubblePosition();
1307
+ });
1308
+ // Toggle logic
1309
+ const togglePanel = () => {
1310
+ this.closeAllBubblePopups(panel);
1311
+ const isOpen = panel.style.display !== 'none';
1312
+ if (isOpen) {
1313
+ panel.style.display = 'none';
1314
+ }
1315
+ else {
1316
+ panelDragged = false;
1317
+ panel.style.position = '';
1318
+ panel.style.top = '';
1319
+ panel.style.left = '';
1320
+ panel.style.bottom = '';
1321
+ panel.style.right = '';
1322
+ panel.style.transform = '';
1323
+ panel.style.display = 'block';
1324
+ this.positionDropdown(trigger, panel);
1325
+ }
1326
+ };
1327
+ trigger.addEventListener('click', togglePanel);
1328
+ wrap.appendChild(trigger);
1329
+ const updateLabel = (text) => {
1330
+ const labelEl = trigger.querySelector('.co-rte-bubble__select-label');
1331
+ if (labelEl)
1332
+ labelEl.textContent = text;
1333
+ };
1334
+ return { wrap, panelEl: panel, updateLabel };
1335
+ }
1336
+ /** Font size panel with visual preview and custom input. */
1337
+ createBubbleFontSizePanel() {
1338
+ const _fs = getRichTextStrings(this.locale);
1339
+ const headings = [
1340
+ { label: _fs.title, value: 'h1' },
1341
+ { label: _fs.heading1, value: 'h2' },
1342
+ { label: _fs.heading2, value: 'h3' },
1343
+ ];
1344
+ const sizes = ['8px', '10px', '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px', '64px', '72px'];
1345
+ const allOptions = [
1346
+ ...headings,
1347
+ { label: '---', value: '---' },
1348
+ ...sizes.map(s => ({ label: s, value: s })),
1349
+ ];
1350
+ return this.createBubblePanel({
1351
+ name: 'fontSize',
1352
+ title: _fs.fontSize,
1353
+ triggerLabel: '16px',
1354
+ hasCustomInput: true,
1355
+ inputType: 'number',
1356
+ inputPlaceholder: _fs.writeSize,
1357
+ options: allOptions,
1358
+ renderOption: (opt, btn) => {
1359
+ if (opt.value === '---') {
1360
+ btn.className = 'co-rte-bubble__panel-sep';
1361
+ btn.disabled = true;
1362
+ btn.style.pointerEvents = 'none';
1363
+ return;
1364
+ }
1365
+ if (opt.value === 'h1') {
1366
+ btn.textContent = opt.label;
1367
+ btn.style.fontSize = '24px';
1368
+ btn.style.fontWeight = '700';
1369
+ btn.style.padding = '6px 8px';
1370
+ }
1371
+ else if (opt.value === 'h2') {
1372
+ btn.textContent = opt.label;
1373
+ btn.style.fontSize = '18px';
1374
+ btn.style.fontWeight = '700';
1375
+ btn.style.padding = '5px 8px';
1376
+ }
1377
+ else if (opt.value === 'h3') {
1378
+ btn.textContent = opt.label;
1379
+ btn.style.fontSize = '15px';
1380
+ btn.style.fontWeight = '700';
1381
+ btn.style.padding = '4px 8px';
1382
+ }
1383
+ else {
1384
+ btn.textContent = opt.label;
1385
+ const px = parseInt(opt.value);
1386
+ btn.style.fontSize = `${Math.min(px, 36)}px`;
1387
+ btn.style.lineHeight = '1.3';
1388
+ }
1389
+ },
1390
+ onSelect: (val) => {
1391
+ if (!this.editor || val === '---')
1392
+ return;
1393
+ const chain = this.editor.chain().focus();
1394
+ if (val === 'h1')
1395
+ chain.toggleHeading({ level: 1 }).run();
1396
+ else if (val === 'h2')
1397
+ chain.toggleHeading({ level: 2 }).run();
1398
+ else if (val === 'h3')
1399
+ chain.toggleHeading({ level: 3 }).run();
1400
+ else
1401
+ chain.setFontSize(val).run();
1402
+ },
1403
+ onCustomInput: (val) => {
1404
+ if (!this.editor)
1405
+ return;
1406
+ const num = parseInt(val);
1407
+ if (num > 0)
1408
+ this.editor.chain().focus().setFontSize(`${num}px`).run();
1409
+ },
1410
+ });
1411
+ }
1412
+ /** Font weight panel with two-column layout and visual preview. */
1413
+ createBubbleFontWeightPanel() {
1414
+ const weights = [
1415
+ { label: 'Thin', value: '100' },
1416
+ { label: 'Extra Light', value: '200' },
1417
+ { label: 'Light', value: '300' },
1418
+ { label: 'Regular', value: '400' },
1419
+ { label: 'Medium', value: '500' },
1420
+ { label: 'Semi Bold', value: '600' },
1421
+ { label: 'Bold', value: '700' },
1422
+ { label: 'Extra Bold', value: '800' },
1423
+ { label: 'Black', value: '900' },
1424
+ ];
1425
+ return this.createBubblePanel({
1426
+ name: 'fontWeight',
1427
+ title: getRichTextStrings(this.locale).fontWeight,
1428
+ triggerLabel: 'Regular',
1429
+ hasCustomInput: false,
1430
+ options: weights,
1431
+ renderOption: (opt, btn) => {
1432
+ btn.style.fontWeight = opt.value;
1433
+ 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>`;
1434
+ },
1435
+ onSelect: (val) => {
1436
+ if (!this.editor)
1437
+ return;
1438
+ this.editor.chain().focus().setFontWeight(val).run();
1439
+ },
1440
+ });
1441
+ }
1442
+ /** Line height panel with custom input. */
1443
+ createBubbleLineHeightPanel() {
1444
+ const options = [
1445
+ { label: '0.5', value: '0.5' },
1446
+ { label: '1', value: '1' },
1447
+ { label: '1.15', value: '1.15' },
1448
+ { label: '1.5', value: '1.5' },
1449
+ { label: '1.75', value: '1.75' },
1450
+ { label: '2', value: '2' },
1451
+ { label: '2.5', value: '2.5' },
1452
+ { label: '3', value: '3' },
1453
+ { label: '---', value: '---' },
1454
+ { label: '16px', value: '16px' },
1455
+ { label: '20px', value: '20px' },
1456
+ { label: '24px', value: '24px' },
1457
+ { label: '32px', value: '32px' },
1458
+ { label: '---', value: '---2' },
1459
+ { label: '100%', value: '100%' },
1460
+ { label: '150%', value: '150%' },
1461
+ { label: '200%', value: '200%' },
1462
+ ];
1463
+ const { panelEl } = this.createBubblePanel({
1464
+ name: 'lineHeight',
1465
+ title: getRichTextStrings(this.locale).lineSpacing,
1466
+ triggerLabel: '1.5',
1467
+ hasCustomInput: true,
1468
+ inputPlaceholder: '1.5, 20px, 150%...',
1469
+ options,
1470
+ renderOption: (opt, btn) => {
1471
+ if (opt.value.startsWith('---')) {
1472
+ btn.className = 'co-rte-bubble__panel-sep';
1473
+ btn.disabled = true;
1474
+ btn.style.pointerEvents = 'none';
1475
+ return;
1476
+ }
1477
+ btn.textContent = opt.label;
1478
+ },
1479
+ onSelect: (val) => {
1480
+ if (!this.editor || val.startsWith('---'))
1481
+ return;
1482
+ this.editor.chain().focus().setLineHeight(val).run();
1483
+ },
1484
+ onCustomInput: (val) => {
1485
+ if (!this.editor)
1486
+ return;
1487
+ this.editor.chain().focus().setLineHeight(val).run();
1488
+ },
1489
+ });
1490
+ return panelEl;
1491
+ }
1492
+ /** Letter spacing panel with custom input. */
1493
+ createBubbleLetterSpacingPanel() {
1494
+ const options = [
1495
+ { label: '-0.05em', value: '-0.05em' },
1496
+ { label: 'Normal', value: 'normal' },
1497
+ { label: '0.05em', value: '0.05em' },
1498
+ { label: '0.1em', value: '0.1em' },
1499
+ { label: '0.2em', value: '0.2em' },
1500
+ ];
1501
+ const { panelEl } = this.createBubblePanel({
1502
+ name: 'letterSpacing',
1503
+ title: getRichTextStrings(this.locale).letterSpacing,
1504
+ triggerLabel: getRichTextStrings(this.locale).normal,
1505
+ hasCustomInput: true,
1506
+ inputPlaceholder: 'Custom (em)...',
1507
+ options,
1508
+ onSelect: (val) => {
1509
+ if (!this.editor)
1510
+ return;
1511
+ if (val === 'normal')
1512
+ this.editor.chain().focus().unsetLetterSpacing().run();
1513
+ else
1514
+ this.editor.chain().focus().setLetterSpacing(val).run();
1515
+ },
1516
+ onCustomInput: (val) => {
1517
+ if (!this.editor)
1518
+ return;
1519
+ const v = val.includes('em') || val.includes('px') ? val : `${val}em`;
1520
+ this.editor.chain().focus().setLetterSpacing(v).run();
1521
+ },
1522
+ });
1523
+ return panelEl;
1524
+ }
1525
+ /** Background color panel for overflow menu. */
1526
+ createBubbleBgColorPanel() {
1527
+ const bgColorWrap = this.createBubbleColorPicker('bgColor', (color) => {
1528
+ if (!this.editor)
1529
+ return;
1530
+ this.editor.chain().focus().toggleHighlight({ color }).run();
1531
+ });
1532
+ // Hide the trigger button — bg color is only opened from the overflow menu.
1533
+ const triggerBtn = bgColorWrap.querySelector('.co-rte-bubble__btn');
1534
+ if (triggerBtn)
1535
+ triggerBtn.style.display = 'none';
1536
+ return bgColorWrap;
1537
+ }
1538
+ /** Overflow menu (three-dots ⋮) with dynamic table context section. */
1539
+ createBubbleOverflowMenu(panels) {
1540
+ const wrap = document.createElement('div');
1541
+ wrap.className = 'co-rte-bubble__overflow';
1542
+ const btn = document.createElement('button');
1543
+ btn.type = 'button';
1544
+ btn.className = 'co-rte-bubble__btn';
1545
+ const _os = getRichTextStrings(this.locale);
1546
+ btn.title = _os.moreOptions;
1547
+ btn.setAttribute('aria-label', _os.moreOptions);
1548
+ btn.innerHTML = `<co-icon name="dots-three" size="16"></co-icon>`;
1549
+ const menu = document.createElement('div');
1550
+ menu.className = 'co-rte-bubble__overflow-menu';
1551
+ menu.style.display = 'none';
1552
+ const { resetDrag: resetOverflowDrag } = this.addDragHeader(menu, _os.moreOptions);
1553
+ // Prevent focus loss
1554
+ menu.addEventListener('mousedown', (e) => {
1555
+ if (e.target.tagName !== 'INPUT')
1556
+ e.preventDefault();
1557
+ this.lockBubblePosition();
1558
+ });
1559
+ const items = [
1560
+ { icon: 'text-strikethrough', label: _os.strikethrough, action: 'strike', check: 'strike', type: 'toggle' },
1561
+ { icon: 'highlighter', label: _os.backgroundColor, action: 'bgColor', type: 'panel', panel: panels.bgColor },
1562
+ { icon: 'list-bullets', label: _os.bulletList, action: 'bulletList', check: 'bulletList', type: 'toggle' },
1563
+ { icon: 'list-numbers', label: _os.orderedList, action: 'orderedList', check: 'orderedList', type: 'toggle' },
1564
+ { icon: 'text-superscript', label: _os.superscript, action: 'superscript', check: 'superscript', type: 'toggle' },
1565
+ { icon: 'text-subscript', label: _os.subscript, action: 'subscript', check: 'subscript', type: 'toggle' },
1566
+ { icon: 'line-segments', label: _os.lineSpacing, action: 'lineHeight', type: 'panel', panel: panels.lineHeight, valueAttr: 'lineHeight' },
1567
+ { icon: 'text-aa', label: _os.letterSpacing, action: 'letterSpacing', type: 'panel', panel: panels.letterSpacing, valueAttr: 'letterSpacing' },
1568
+ { icon: 'minus', label: _os.horizontalRule, action: 'horizontalRule', type: 'toggle' },
1569
+ { icon: 'eraser', label: _os.clearFormat, action: 'clearFormat', type: 'toggle' },
1570
+ ];
1571
+ items.forEach((item) => {
1572
+ if (item.action === 'lineHeight' || item.action === 'horizontalRule') {
1573
+ const sep = document.createElement('div');
1574
+ sep.className = 'co-rte-bubble__overflow-sep';
1575
+ menu.appendChild(sep);
1576
+ }
1577
+ const itemBtn = document.createElement('button');
1578
+ itemBtn.type = 'button';
1579
+ itemBtn.className = 'co-rte-bubble__overflow-item';
1580
+ itemBtn.setAttribute('data-overflow-item', item.action);
1581
+ if (item.check)
1582
+ itemBtn.setAttribute('data-check', item.check);
1583
+ let valueSpan = '';
1584
+ if (item.valueAttr) {
1585
+ valueSpan = `<span class="co-rte-bubble__overflow-value" data-overflow-value="${item.valueAttr}"></span>`;
1586
+ }
1587
+ itemBtn.innerHTML = `<co-icon name="${item.icon}" size="16"></co-icon><span>${item.label}</span>${valueSpan}`;
1588
+ itemBtn.addEventListener('click', () => {
1589
+ if (!this.editor)
1590
+ return;
1591
+ if (item.type === 'panel' && item.panel) {
1592
+ if (item.action === 'bgColor') {
1593
+ const dd = item.panel.querySelector('.co-rte-bubble__color-dropdown');
1594
+ if (dd) {
1595
+ const isOpen = dd.style.display !== 'none';
1596
+ this.closeAllBubblePopups(menu, isOpen ? undefined : dd);
1597
+ dd.style.display = isOpen ? 'none' : 'block';
1598
+ if (!isOpen)
1599
+ this.positionPanelNearBubble(dd);
1600
+ }
1601
+ }
1602
+ else {
1603
+ const isOpen = item.panel.style.display !== 'none';
1604
+ this.closeAllBubblePopups(menu, isOpen ? undefined : item.panel);
1605
+ item.panel.style.display = isOpen ? 'none' : 'block';
1606
+ if (!isOpen)
1607
+ this.positionPanelNearBubble(item.panel);
1608
+ }
1609
+ return;
1610
+ }
1611
+ const chain = this.editor.chain().focus();
1612
+ switch (item.action) {
1613
+ case 'strike':
1614
+ chain.toggleStrike().run();
1615
+ break;
1616
+ case 'bulletList':
1617
+ chain.toggleBulletList().run();
1618
+ break;
1619
+ case 'orderedList':
1620
+ chain.toggleOrderedList().run();
1621
+ break;
1622
+ case 'superscript':
1623
+ chain.toggleSuperscript().run();
1624
+ break;
1625
+ case 'subscript':
1626
+ chain.toggleSubscript().run();
1627
+ break;
1628
+ case 'horizontalRule':
1629
+ chain.setHorizontalRule().run();
1630
+ menu.style.display = 'none';
1631
+ break;
1632
+ case 'clearFormat':
1633
+ chain.unsetAllMarks().clearNodes().run();
1634
+ menu.style.display = 'none';
1635
+ break;
1636
+ }
1637
+ });
1638
+ menu.appendChild(itemBtn);
1639
+ });
1640
+ // ── Table context section (hidden by default, shown when cursor is in a table) ──
1641
+ const tableSection = document.createElement('div');
1642
+ tableSection.className = 'co-rte-bubble__overflow-table-section';
1643
+ tableSection.style.display = 'none';
1644
+ const tableSep = document.createElement('div');
1645
+ tableSep.className = 'co-rte-bubble__overflow-sep';
1646
+ tableSection.appendChild(tableSep);
1647
+ const tableHeader = document.createElement('div');
1648
+ tableHeader.className = 'co-rte-bubble__overflow-section-title';
1649
+ tableHeader.textContent = _os.tableOptions;
1650
+ tableSection.appendChild(tableHeader);
1651
+ const tableItems = [
1652
+ { action: 'addColumnBefore', icon: 'columns-plus-left', label: _os.addColumnBefore },
1653
+ { action: 'addColumnAfter', icon: 'columns-plus-right', label: _os.addColumnAfter },
1654
+ { action: 'addRowBefore', icon: 'rows-plus-top', label: _os.addRowAbove },
1655
+ { action: 'addRowAfter', icon: 'rows-plus-bottom', label: _os.addRowBelow },
1656
+ { action: 'mergeCells', icon: 'arrows-merge', label: _os.mergeCells },
1657
+ { action: 'splitCell', icon: 'arrows-split', label: _os.splitCell },
1658
+ { action: 'toggleHeaderRow', icon: 'rows', label: _os.headerRow },
1659
+ ];
1660
+ tableItems.forEach(({ action, icon, label }) => {
1661
+ const tBtn = document.createElement('button');
1662
+ tBtn.type = 'button';
1663
+ tBtn.className = 'co-rte-bubble__overflow-item';
1664
+ tBtn.setAttribute('data-overflow-item', action);
1665
+ if (action === 'toggleHeaderRow')
1666
+ tBtn.setAttribute('data-check', 'toggleHeaderRow');
1667
+ tBtn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon><span>${label}</span>`;
1668
+ tBtn.addEventListener('click', () => {
1669
+ if (!this.editor)
1670
+ return;
1671
+ const chain = this.editor.chain().focus();
1672
+ switch (action) {
1673
+ case 'addColumnAfter':
1674
+ chain.addColumnAfter().run();
1675
+ break;
1676
+ case 'addColumnBefore':
1677
+ chain.addColumnBefore().run();
1678
+ break;
1679
+ case 'addRowAfter':
1680
+ chain.addRowAfter().run();
1681
+ break;
1682
+ case 'addRowBefore':
1683
+ chain.addRowBefore().run();
1684
+ break;
1685
+ case 'mergeCells':
1686
+ chain.mergeCells().run();
1687
+ break;
1688
+ case 'splitCell':
1689
+ chain.splitCell().run();
1690
+ break;
1691
+ case 'toggleHeaderRow':
1692
+ chain.toggleHeaderRow().run();
1693
+ break;
1694
+ }
1695
+ });
1696
+ tableSection.appendChild(tBtn);
1697
+ });
1698
+ // Danger items (delete column, row, table)
1699
+ const dangerSep = document.createElement('div');
1700
+ dangerSep.className = 'co-rte-bubble__overflow-sep';
1701
+ tableSection.appendChild(dangerSep);
1702
+ const dangerItems = [
1703
+ { action: 'deleteColumn', icon: 'minus-square', label: _os.deleteColumn },
1704
+ { action: 'deleteRow', icon: 'x-square', label: _os.deleteRow },
1705
+ { action: 'deleteTable', icon: 'trash', label: _os.deleteTable },
1706
+ ];
1707
+ dangerItems.forEach(({ action, icon, label }) => {
1708
+ const dBtn = document.createElement('button');
1709
+ dBtn.type = 'button';
1710
+ dBtn.className = 'co-rte-bubble__overflow-item co-rte-bubble__overflow-item--danger';
1711
+ dBtn.setAttribute('data-overflow-item', action);
1712
+ dBtn.innerHTML = `<co-icon name="${icon}" size="16"></co-icon><span>${label}</span>`;
1713
+ dBtn.addEventListener('click', () => {
1714
+ if (!this.editor)
1715
+ return;
1716
+ const chain = this.editor.chain().focus();
1717
+ switch (action) {
1718
+ case 'deleteColumn':
1719
+ chain.deleteColumn().run();
1720
+ break;
1721
+ case 'deleteRow':
1722
+ chain.deleteRow().run();
1723
+ break;
1724
+ case 'deleteTable':
1725
+ chain.deleteTable().run();
1726
+ menu.style.display = 'none';
1727
+ break;
1728
+ }
1729
+ });
1730
+ tableSection.appendChild(dBtn);
1731
+ });
1732
+ menu.appendChild(tableSection);
1733
+ btn.addEventListener('click', () => {
1734
+ this.closeAllBubblePopups(menu);
1735
+ const isOpen = menu.style.display !== 'none';
1736
+ if (isOpen) {
1737
+ menu.style.display = 'none';
1738
+ }
1739
+ else {
1740
+ resetOverflowDrag();
1741
+ menu.style.position = '';
1742
+ menu.style.top = '';
1743
+ menu.style.left = '';
1744
+ menu.style.bottom = '';
1745
+ menu.style.right = '';
1746
+ menu.style.transform = '';
1747
+ menu.style.display = 'block';
1748
+ this.positionDropdown(btn, menu);
1749
+ }
1750
+ });
1751
+ wrap.appendChild(btn);
1752
+ wrap.appendChild(menu);
1753
+ return { overflowWrap: wrap, overflowMenu: menu };
1754
+ }
1755
+ toggleBubbleLinkForm(show) {
1756
+ var _a, _b;
1757
+ if (!this.bubbleLinkFormEl || !this.bubbleLinkInputEl)
1758
+ return;
1759
+ this.bubbleLinkFormEl.style.display = show ? 'flex' : 'none';
1760
+ if (show) {
1761
+ const existing = ((_a = this.editor) === null || _a === void 0 ? void 0 : _a.isActive('link'))
1762
+ ? ((_b = this.editor.getAttributes('link')) === null || _b === void 0 ? void 0 : _b.href) || ''
1763
+ : '';
1764
+ this.bubbleLinkInputEl.value = existing;
1765
+ if (this.bubbleLinkUnlinkEl) {
1766
+ this.bubbleLinkUnlinkEl.style.display = existing ? 'flex' : 'none';
1767
+ }
1768
+ setTimeout(() => { var _a; return (_a = this.bubbleLinkInputEl) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
1769
+ }
1770
+ }
1771
+ submitBubbleLinkImperative() {
1772
+ if (!this.editor || !this.bubbleLinkInputEl)
1773
+ return;
1774
+ const url = this.bubbleLinkInputEl.value.trim();
1775
+ if (!url) {
1776
+ this.toggleBubbleLinkForm(false);
1777
+ return;
1778
+ }
1779
+ this.editor.chain().focus().setLink({ href: url }).run();
1780
+ this.toggleBubbleLinkForm(false);
1781
+ }
1782
+ updateBubbleActiveStates() {
1783
+ if (!this.editor || !this.bubbleEl)
1784
+ return;
1785
+ // Toggle buttons (bold, italic, etc.)
1786
+ const btns = this.bubbleEl.querySelectorAll('.co-rte-bubble__btn[data-check]');
1787
+ btns.forEach(btn => {
1788
+ const check = btn.getAttribute('data-check');
1789
+ if (check) {
1790
+ btn.classList.toggle('co-rte-bubble__btn--active', this.editor.isActive(check));
1791
+ }
1792
+ });
1793
+ // Alignment buttons
1794
+ const alignBtns = this.bubbleEl.querySelectorAll('.co-rte-bubble__btn[data-align]');
1795
+ alignBtns.forEach(btn => {
1796
+ const align = btn.getAttribute('data-align');
1797
+ if (align) {
1798
+ btn.classList.toggle('co-rte-bubble__btn--active', this.editor.isActive({ textAlign: align }));
1799
+ }
1800
+ });
1801
+ // Font family label
1802
+ const ffLabel = this.bubbleEl.querySelector('[data-select="fontFamily"] .co-rte-bubble__select-label');
1803
+ if (ffLabel) {
1804
+ const attrs = this.editor.getAttributes('textStyle');
1805
+ const family = (attrs === null || attrs === void 0 ? void 0 : attrs.fontFamily) || '';
1806
+ ffLabel.textContent = family ? family.split(',')[0].replace(/['"]/g, '').trim() : 'Sans-serif';
1807
+ }
1808
+ // Font size label (panel trigger)
1809
+ const fsTrigger = this.bubbleEl.querySelector('[data-select="fontSize"] .co-rte-bubble__select-label');
1810
+ if (fsTrigger) {
1811
+ const attrs = this.editor.getAttributes('textStyle');
1812
+ const _us = getRichTextStrings(this.locale);
1813
+ if (this.editor.isActive('heading', { level: 1 }))
1814
+ fsTrigger.textContent = _us.title;
1815
+ else if (this.editor.isActive('heading', { level: 2 }))
1816
+ fsTrigger.textContent = _us.headingAbbr1;
1817
+ else if (this.editor.isActive('heading', { level: 3 }))
1818
+ fsTrigger.textContent = _us.headingAbbr2;
1819
+ else
1820
+ fsTrigger.textContent = (attrs === null || attrs === void 0 ? void 0 : attrs.fontSize) || '16px';
1821
+ }
1822
+ // Font weight label (panel trigger)
1823
+ const fwTrigger = this.bubbleEl.querySelector('[data-select="fontWeight"] .co-rte-bubble__select-label');
1824
+ if (fwTrigger) {
1825
+ const attrs = this.editor.getAttributes('textStyle');
1826
+ const w = (attrs === null || attrs === void 0 ? void 0 : attrs.fontWeight) || '400';
1827
+ const wMap = { '100': 'Thin', '200': 'Extra Light', '300': 'Light', '400': 'Regular', '500': 'Medium', '600': 'Semi-bold', '700': 'Bold', '800': 'Extra-bold', '900': 'Black' };
1828
+ fwTrigger.textContent = wMap[w] || 'Regular';
1829
+ }
1830
+ // Overflow menu items active states
1831
+ const overflowItems = this.bubbleEl.querySelectorAll('.co-rte-bubble__overflow-item[data-check]');
1832
+ overflowItems.forEach(item => {
1833
+ const check = item.getAttribute('data-check');
1834
+ if (check) {
1835
+ item.classList.toggle('co-rte-bubble__overflow-item--active', this.editor.isActive(check));
1836
+ }
1837
+ });
1838
+ // Line height value in overflow (lineHeight is a block-level attribute on paragraph/heading)
1839
+ const lhValue = this.bubbleEl.querySelector('[data-overflow-value="lineHeight"]');
1840
+ if (lhValue) {
1841
+ const pAttrs = this.editor.getAttributes('paragraph');
1842
+ const hAttrs = this.editor.getAttributes('heading');
1843
+ lhValue.textContent = (pAttrs === null || pAttrs === void 0 ? void 0 : pAttrs.lineHeight) || (hAttrs === null || hAttrs === void 0 ? void 0 : hAttrs.lineHeight) || '';
1844
+ }
1845
+ // Letter spacing value in overflow
1846
+ const lsValue = this.bubbleEl.querySelector('[data-overflow-value="letterSpacing"]');
1847
+ if (lsValue) {
1848
+ const attrs = this.editor.getAttributes('textStyle');
1849
+ lsValue.textContent = (attrs === null || attrs === void 0 ? void 0 : attrs.letterSpacing) || '';
1850
+ }
1851
+ // Text color indicator bar
1852
+ const colorBar = this.bubbleEl.querySelector('.co-rte-bubble__color-bar');
1853
+ if (colorBar) {
1854
+ const attrs = this.editor.getAttributes('textStyle');
1855
+ colorBar.style.background = (attrs === null || attrs === void 0 ? void 0 : attrs.color) || '#000000';
1856
+ }
1857
+ // Table context section — show/hide based on cursor position
1858
+ const tableSection = this.bubbleEl.querySelector('.co-rte-bubble__overflow-table-section');
1859
+ if (tableSection) {
1860
+ const inTable = this.editor.isActive('table');
1861
+ tableSection.style.display = inTable ? 'block' : 'none';
1862
+ // Toggle header row active state
1863
+ if (inTable) {
1864
+ const headerBtn = tableSection.querySelector('[data-overflow-item="toggleHeaderRow"]');
1865
+ if (headerBtn) {
1866
+ const view = this.editor.view;
1867
+ const { $anchor } = this.editor.state.selection;
1868
+ let d = $anchor.depth;
1869
+ let hasHeader = false;
1870
+ while (d > 0) {
1871
+ if ($anchor.node(d).type.name === 'table') {
1872
+ const domEl = view.nodeDOM($anchor.start(d) - 1);
1873
+ if (domEl) {
1874
+ const tbl = domEl.querySelector('table') || domEl;
1875
+ const firstRow = tbl.querySelector('tr');
1876
+ hasHeader = firstRow ? firstRow.querySelector('th') !== null : false;
1877
+ }
1878
+ break;
1879
+ }
1880
+ d--;
1881
+ }
1882
+ headerBtn.classList.toggle('co-rte-bubble__overflow-item--active', hasHeader);
1883
+ }
1884
+ }
1885
+ }
1886
+ }
1887
+ createImageLayoutBar() {
1888
+ const bar = document.createElement('div');
1889
+ bar.className = 'co-rte-img-layout';
1890
+ bar.style.display = 'none';
1891
+ bar.addEventListener('mousedown', (e) => {
1892
+ e.preventDefault();
1893
+ e.stopPropagation();
1894
+ });
1895
+ const s = getRichTextStrings(this.locale);
1896
+ const labels = {
1897
+ 'inline': s.imageLayoutInline,
1898
+ 'wrap-left': s.imageLayoutWrapLeft,
1899
+ 'wrap-right': s.imageLayoutWrapRight,
1900
+ 'center': s.imageLayoutCenter,
1901
+ 'full-width': s.imageLayoutFullWidth,
1902
+ };
1903
+ const keys = ['inline', 'wrap-left', 'wrap-right', 'center', 'full-width'];
1904
+ keys.forEach(key => {
1905
+ const btn = document.createElement('button');
1906
+ btn.type = 'button';
1907
+ btn.className = 'co-rte-img-layout__btn';
1908
+ btn.setAttribute('data-layout', key);
1909
+ // Fast CSS tooltip (avoids the slow native `title` delay).
1910
+ btn.setAttribute('data-tooltip', labels[key] || key);
1911
+ btn.setAttribute('aria-label', labels[key] || key);
1912
+ btn.innerHTML = `<co-icon name="${CoRichTextEditor.IMG_LAYOUT_ICONS[key]}" size="18"></co-icon>`;
1913
+ btn.addEventListener('click', () => this.setImageLayout(key));
1914
+ bar.appendChild(btn);
1915
+ });
1916
+ return bar;
1917
+ }
1918
+ setImageLayout(layout) {
1919
+ if (!this.editor || !this.contentEl)
1920
+ return;
1921
+ const { state } = this.editor;
1922
+ const sel = state.selection;
1923
+ if (sel.constructor.name !== 'NodeSelection')
1924
+ return;
1925
+ const node = sel.node;
1926
+ if ((node === null || node === void 0 ? void 0 : node.type.name) !== 'image')
1927
+ return;
1928
+ const pos = sel.from;
1929
+ const tr = state.tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { imageLayout: layout }));
1930
+ this.editor.view.dispatch(tr);
1931
+ this.editor.commands.setNodeSelection(pos);
1932
+ requestAnimationFrame(() => {
1933
+ this.syncImageLayouts();
1934
+ this.updateImageLayoutBar();
1935
+ });
1936
+ }
1937
+ getSelectedImageInfo() {
1938
+ var _a;
1939
+ if (!this.editor)
1940
+ return null;
1941
+ const { state } = this.editor;
1942
+ const sel = state.selection;
1943
+ if (sel.constructor.name !== 'NodeSelection')
1944
+ return null;
1945
+ const node = sel.node;
1946
+ if ((node === null || node === void 0 ? void 0 : node.type.name) !== 'image')
1947
+ return null;
1948
+ const pos = sel.from;
1949
+ const domNode = this.editor.view.nodeDOM(pos);
1950
+ if (!domNode)
1951
+ return null;
1952
+ const container = (((_a = domNode.closest) === null || _a === void 0 ? void 0 : _a.call(domNode, '[data-resize-container]')) || domNode);
1953
+ return { node, pos, container };
1954
+ }
1955
+ /**
1956
+ * Tag every image container with its layout mode (`data-image-layout`) so the
1957
+ * stylesheet's responsive rules apply, and clear any stray inline positioning
1958
+ * left over from legacy absolute-positioned content. Layout is CSS-only now
1959
+ * (it reflows and collapses on mobile); we only set the attribute here.
1960
+ *
1961
+ * Runs on every transaction. The resize NodeView's `onUpdate` returns `true`,
1962
+ * so ProseMirror never reflects attribute changes to the DOM — we must read
1963
+ * from state and write the attribute imperatively to the container.
1964
+ */
1965
+ syncImageLayouts() {
1966
+ if (!this.editor)
1967
+ return;
1968
+ const view = this.editor.view;
1969
+ this.editor.state.doc.descendants((node, pos) => {
1970
+ var _a;
1971
+ if (node.type.name !== 'image')
1972
+ return true;
1973
+ const dom = view.nodeDOM(pos);
1974
+ 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);
1975
+ if (!c)
1976
+ return true;
1977
+ c.dataset.imageLayout = node.attrs.imageLayout || 'inline';
1978
+ // Neutralise any absolute positioning baked by the old fixed-page model.
1979
+ c.style.position = '';
1980
+ c.style.left = '';
1981
+ c.style.top = '';
1982
+ c.style.zIndex = '';
1983
+ return true;
1984
+ });
1985
+ }
1986
+ /** Reposition only the layout bar (used during drag for performance). */
1987
+ updateImageLayoutBarPosition() {
1988
+ if (!this.imgLayoutEl || !this.contentEl)
1989
+ return;
1990
+ const info = this.getSelectedImageInfo();
1991
+ if (!info)
1992
+ return;
1993
+ const containerRect = info.container.getBoundingClientRect();
1994
+ const contentRect = this.contentEl.getBoundingClientRect();
1995
+ const barWidth = this.imgLayoutEl.offsetWidth || 194;
1996
+ let leftPos = (containerRect.left + containerRect.width / 2) - contentRect.left + this.contentEl.scrollLeft - barWidth / 2;
1997
+ leftPos = Math.max(4, Math.min(leftPos, contentRect.width - barWidth - 4));
1998
+ const topPos = containerRect.bottom - contentRect.top + this.contentEl.scrollTop + 8;
1999
+ this.imgLayoutEl.style.left = `${leftPos}px`;
2000
+ this.imgLayoutEl.style.top = `${topPos}px`;
2001
+ }
2002
+ updateImageLayoutBar() {
2003
+ if (!this.imgLayoutEl || !this.editor)
2004
+ return;
2005
+ const info = this.getSelectedImageInfo();
2006
+ if (!info) {
2007
+ if (this.imgLayoutVisible) {
2008
+ this.imgLayoutEl.style.display = 'none';
2009
+ this.imgLayoutVisible = false;
2010
+ }
2011
+ return;
2012
+ }
2013
+ this.imgLayoutEl.style.display = 'flex';
2014
+ this.imgLayoutVisible = true;
2015
+ this.updateImageLayoutBarPosition();
2016
+ const currentLayout = info.node.attrs.imageLayout || 'inline';
2017
+ this.imgLayoutEl.querySelectorAll('.co-rte-img-layout__btn').forEach(btn => {
2018
+ btn.classList.toggle('co-rte-img-layout__btn--active', btn.getAttribute('data-layout') === currentLayout);
2019
+ });
2020
+ }
2021
+ render() {
2022
+ const showToolbar = this.resolvedToolbar !== 'none' && !this.readonly && !this.disabled;
2023
+ const showCount = this.showCharacterCount || this.maxLength != null;
2024
+ return (h("div", { key: 'd24b8e5db1151bcd983790ea15f68aaf4838ff43', class: {
2025
+ 'co-rich-text-editor': true,
2026
+ 'co-rich-text-editor--focused': this.hasFocus,
2027
+ 'co-rich-text-editor--disabled': this.disabled,
2028
+ 'co-rich-text-editor--readonly': this.readonly,
2029
+ 'co-rich-text-editor--loading': !this.ready,
2030
+ [`co-rich-text-editor--${this.status}`]: this.status !== 'default',
2031
+ }, part: "wrapper" }, (this.label || this.secondaryLabel) && (h("div", { key: '1622079a94d8ebb190642f91463b715f3456fcf4', class: "co-rich-text-editor__labels" }, this.label && h("label", { key: 'bb5c0754a63d46d45ce8f211ae0f0e8c4ddbc478', class: "co-rich-text-editor__label", part: "label" }, this.label), this.secondaryLabel && (h("span", { key: '1af0a217a38746c3a78693c552be44df6d03b276', class: "co-rich-text-editor__secondary-label" }, this.secondaryLabel)))), h("div", { key: 'e5ad90dd90061be3e40136eece0f485e5cfb89a1', class: "co-rich-text-editor__frame" }, showToolbar && (h("co-rich-text-toolbar", { key: '56f3da29e9259cd37fdf6e7511dc54efb30085ca', class: "co-rich-text-editor__toolbar", part: "toolbar", variant: this.resolvedToolbar, disabled: this.disabled || this.readonly, locale: this.locale, ref: (el) => (this.toolbarEl = el) })), h("div", { key: 'bb0dc27e8625171284cae02b5cae28dcbe638991', class: "co-rich-text-editor__box" }, h("div", { key: '647563e73112023ec546418787dbf61acb58853d', class: "co-rte-content", part: "content", role: "textbox", "aria-multiline": "true", "aria-label": this.label, "aria-required": this.required ? 'true' : undefined, "aria-invalid": this.status === 'error' ? 'true' : undefined, ref: (el) => (this.contentEl = el) }))), h("div", { key: '460dad69fd1781f11d751565d0ca09015013e8ce', class: "co-rich-text-editor__footer" }, this.helperText && (h("div", { key: '69d8fb55797eb8f35885fa10e86cf08e4d0e45ec', class: `co-rich-text-editor__helper co-rich-text-editor__helper--${this.status}`, part: "helper" }, h("co-icon", { key: 'd1c3cc4f06284b865c889dac7492305a4b7d8dfd', name: this.helperIcon, size: 14 }), h("span", { key: '361940f354fcee5a309cd2ef5cff84b73689650e' }, this.helperText))), showCount && (h("span", { key: '2b5a1b6e04ba3d428346034d092bf83978de0124', class: "co-rich-text-editor__count", ref: (el) => (this.charCountEl = el) }, this.charCount, this.maxLength != null ? ` / ${this.maxLength}` : '')))));
2032
+ }
2033
+ static get is() { return "co-rich-text-editor"; }
2034
+ static get originalStyleUrls() {
2035
+ return {
2036
+ "$": ["co-rich-text-editor.css"]
2037
+ };
2038
+ }
2039
+ static get styleUrls() {
2040
+ return {
2041
+ "$": ["co-rich-text-editor.css"]
2042
+ };
2043
+ }
2044
+ static get properties() {
2045
+ return {
2046
+ "value": {
2047
+ "type": "string",
2048
+ "mutable": true,
2049
+ "complexType": {
2050
+ "original": "string | null",
2051
+ "resolved": "null | string",
2052
+ "references": {}
2053
+ },
2054
+ "required": false,
2055
+ "optional": false,
2056
+ "docs": {
2057
+ "tags": [],
2058
+ "text": "ProseMirror document as a JSON string. `null`/empty = empty editor."
2059
+ },
2060
+ "getter": false,
2061
+ "setter": false,
2062
+ "reflect": false,
2063
+ "attribute": "value",
2064
+ "defaultValue": "null"
2065
+ },
2066
+ "preset": {
2067
+ "type": "string",
2068
+ "mutable": false,
2069
+ "complexType": {
2070
+ "original": "RichTextPreset",
2071
+ "resolved": "\"comment\" | \"document\" | \"email\" | \"task\"",
2072
+ "references": {
2073
+ "RichTextPreset": {
2074
+ "location": "import",
2075
+ "path": "@prolibu-suite/cobalt-rich-text",
2076
+ "id": "../rich-text/dist/index.d.ts::RichTextPreset",
2077
+ "referenceLocation": "RichTextPreset"
2078
+ }
2079
+ }
2080
+ },
2081
+ "required": false,
2082
+ "optional": false,
2083
+ "docs": {
2084
+ "tags": [],
2085
+ "text": "Preset controlling allowed nodes/marks, toolbar and sanitization."
2086
+ },
2087
+ "getter": false,
2088
+ "setter": false,
2089
+ "reflect": false,
2090
+ "attribute": "preset",
2091
+ "defaultValue": "'task'"
2092
+ },
2093
+ "placeholder": {
2094
+ "type": "string",
2095
+ "mutable": false,
2096
+ "complexType": {
2097
+ "original": "string",
2098
+ "resolved": "string",
2099
+ "references": {}
2100
+ },
2101
+ "required": false,
2102
+ "optional": false,
2103
+ "docs": {
2104
+ "tags": [],
2105
+ "text": ""
2106
+ },
2107
+ "getter": false,
2108
+ "setter": false,
2109
+ "reflect": false,
2110
+ "attribute": "placeholder",
2111
+ "defaultValue": "''"
2112
+ },
2113
+ "label": {
2114
+ "type": "string",
2115
+ "mutable": false,
2116
+ "complexType": {
2117
+ "original": "string",
2118
+ "resolved": "string | undefined",
2119
+ "references": {}
2120
+ },
2121
+ "required": false,
2122
+ "optional": true,
2123
+ "docs": {
2124
+ "tags": [],
2125
+ "text": ""
2126
+ },
2127
+ "getter": false,
2128
+ "setter": false,
2129
+ "reflect": false,
2130
+ "attribute": "label"
2131
+ },
2132
+ "secondaryLabel": {
2133
+ "type": "string",
2134
+ "mutable": false,
2135
+ "complexType": {
2136
+ "original": "string",
2137
+ "resolved": "string | undefined",
2138
+ "references": {}
2139
+ },
2140
+ "required": false,
2141
+ "optional": true,
2142
+ "docs": {
2143
+ "tags": [],
2144
+ "text": ""
2145
+ },
2146
+ "getter": false,
2147
+ "setter": false,
2148
+ "reflect": false,
2149
+ "attribute": "secondary-label"
2150
+ },
2151
+ "helperText": {
2152
+ "type": "string",
2153
+ "mutable": false,
2154
+ "complexType": {
2155
+ "original": "string",
2156
+ "resolved": "string | undefined",
2157
+ "references": {}
2158
+ },
2159
+ "required": false,
2160
+ "optional": true,
2161
+ "docs": {
2162
+ "tags": [],
2163
+ "text": ""
2164
+ },
2165
+ "getter": false,
2166
+ "setter": false,
2167
+ "reflect": false,
2168
+ "attribute": "helper-text"
2169
+ },
2170
+ "status": {
2171
+ "type": "string",
2172
+ "mutable": false,
2173
+ "complexType": {
2174
+ "original": "'default' | 'error' | 'success' | 'warning' | 'info'",
2175
+ "resolved": "\"default\" | \"error\" | \"info\" | \"success\" | \"warning\"",
2176
+ "references": {}
2177
+ },
2178
+ "required": false,
2179
+ "optional": false,
2180
+ "docs": {
2181
+ "tags": [],
2182
+ "text": ""
2183
+ },
2184
+ "getter": false,
2185
+ "setter": false,
2186
+ "reflect": false,
2187
+ "attribute": "status",
2188
+ "defaultValue": "'default'"
2189
+ },
2190
+ "disabled": {
2191
+ "type": "boolean",
2192
+ "mutable": false,
2193
+ "complexType": {
2194
+ "original": "boolean",
2195
+ "resolved": "boolean",
2196
+ "references": {}
2197
+ },
2198
+ "required": false,
2199
+ "optional": false,
2200
+ "docs": {
2201
+ "tags": [],
2202
+ "text": ""
2203
+ },
2204
+ "getter": false,
2205
+ "setter": false,
2206
+ "reflect": false,
2207
+ "attribute": "disabled",
2208
+ "defaultValue": "false"
2209
+ },
2210
+ "readonly": {
2211
+ "type": "boolean",
2212
+ "mutable": false,
2213
+ "complexType": {
2214
+ "original": "boolean",
2215
+ "resolved": "boolean",
2216
+ "references": {}
2217
+ },
2218
+ "required": false,
2219
+ "optional": false,
2220
+ "docs": {
2221
+ "tags": [],
2222
+ "text": ""
2223
+ },
2224
+ "getter": false,
2225
+ "setter": false,
2226
+ "reflect": false,
2227
+ "attribute": "readonly",
2228
+ "defaultValue": "false"
2229
+ },
2230
+ "required": {
2231
+ "type": "boolean",
2232
+ "mutable": false,
2233
+ "complexType": {
2234
+ "original": "boolean",
2235
+ "resolved": "boolean",
2236
+ "references": {}
2237
+ },
2238
+ "required": false,
2239
+ "optional": false,
2240
+ "docs": {
2241
+ "tags": [],
2242
+ "text": ""
2243
+ },
2244
+ "getter": false,
2245
+ "setter": false,
2246
+ "reflect": false,
2247
+ "attribute": "required",
2248
+ "defaultValue": "false"
2249
+ },
2250
+ "maxLength": {
2251
+ "type": "number",
2252
+ "mutable": false,
2253
+ "complexType": {
2254
+ "original": "number",
2255
+ "resolved": "number | undefined",
2256
+ "references": {}
2257
+ },
2258
+ "required": false,
2259
+ "optional": true,
2260
+ "docs": {
2261
+ "tags": [],
2262
+ "text": ""
2263
+ },
2264
+ "getter": false,
2265
+ "setter": false,
2266
+ "reflect": false,
2267
+ "attribute": "max-length"
2268
+ },
2269
+ "showCharacterCount": {
2270
+ "type": "boolean",
2271
+ "mutable": false,
2272
+ "complexType": {
2273
+ "original": "boolean",
2274
+ "resolved": "boolean",
2275
+ "references": {}
2276
+ },
2277
+ "required": false,
2278
+ "optional": false,
2279
+ "docs": {
2280
+ "tags": [],
2281
+ "text": ""
2282
+ },
2283
+ "getter": false,
2284
+ "setter": false,
2285
+ "reflect": false,
2286
+ "attribute": "show-character-count",
2287
+ "defaultValue": "false"
2288
+ },
2289
+ "autofocus": {
2290
+ "type": "boolean",
2291
+ "mutable": false,
2292
+ "complexType": {
2293
+ "original": "boolean",
2294
+ "resolved": "boolean",
2295
+ "references": {}
2296
+ },
2297
+ "required": false,
2298
+ "optional": false,
2299
+ "docs": {
2300
+ "tags": [],
2301
+ "text": ""
2302
+ },
2303
+ "getter": false,
2304
+ "setter": false,
2305
+ "reflect": false,
2306
+ "attribute": "autofocus",
2307
+ "defaultValue": "false"
2308
+ },
2309
+ "toolbar": {
2310
+ "type": "string",
2311
+ "mutable": false,
2312
+ "complexType": {
2313
+ "original": "ToolbarVariant",
2314
+ "resolved": "\"auto\" | \"basic\" | \"compact\" | \"full\" | \"none\"",
2315
+ "references": {
2316
+ "ToolbarVariant": {
2317
+ "location": "import",
2318
+ "path": "@prolibu-suite/cobalt-rich-text",
2319
+ "id": "../rich-text/dist/index.d.ts::ToolbarVariant",
2320
+ "referenceLocation": "ToolbarVariant"
2321
+ }
2322
+ }
2323
+ },
2324
+ "required": false,
2325
+ "optional": false,
2326
+ "docs": {
2327
+ "tags": [],
2328
+ "text": "Toolbar layout. `auto` uses the preset default."
2329
+ },
2330
+ "getter": false,
2331
+ "setter": false,
2332
+ "reflect": false,
2333
+ "attribute": "toolbar",
2334
+ "defaultValue": "'auto'"
2335
+ },
2336
+ "features": {
2337
+ "type": "string",
2338
+ "mutable": false,
2339
+ "complexType": {
2340
+ "original": "string | object",
2341
+ "resolved": "object | string | undefined",
2342
+ "references": {}
2343
+ },
2344
+ "required": false,
2345
+ "optional": true,
2346
+ "docs": {
2347
+ "tags": [],
2348
+ "text": "Feature overrides (JSON string for HTML attr, or object via JS property)."
2349
+ },
2350
+ "getter": false,
2351
+ "setter": false,
2352
+ "reflect": false,
2353
+ "attribute": "features"
2354
+ },
2355
+ "customExtensions": {
2356
+ "type": "unknown",
2357
+ "mutable": false,
2358
+ "complexType": {
2359
+ "original": "object[]",
2360
+ "resolved": "object[] | undefined",
2361
+ "references": {}
2362
+ },
2363
+ "required": false,
2364
+ "optional": true,
2365
+ "docs": {
2366
+ "tags": [],
2367
+ "text": "Extra Tiptap extensions appended to the preset (JS property only).\nRegistered at editor creation \u2014 required for new schema nodes (images,\ntables, embeds, \u2026) that `getEditorInstance()` cannot add afterwards."
2368
+ },
2369
+ "getter": false,
2370
+ "setter": false
2371
+ },
2372
+ "imageUpload": {
2373
+ "type": "unknown",
2374
+ "mutable": false,
2375
+ "complexType": {
2376
+ "original": "(file: File) => Promise<string>",
2377
+ "resolved": "((file: File) => Promise<string>) | undefined",
2378
+ "references": {
2379
+ "File": {
2380
+ "location": "global",
2381
+ "id": "global::File"
2382
+ },
2383
+ "Promise": {
2384
+ "location": "global",
2385
+ "id": "global::Promise"
2386
+ }
2387
+ }
2388
+ },
2389
+ "required": false,
2390
+ "optional": true,
2391
+ "docs": {
2392
+ "tags": [],
2393
+ "text": "Host image upload handler (JS property): `(file) => Promise<url>`."
2394
+ },
2395
+ "getter": false,
2396
+ "setter": false
2397
+ },
2398
+ "fontFamilies": {
2399
+ "type": "string",
2400
+ "mutable": false,
2401
+ "complexType": {
2402
+ "original": "string | { label: string; value: string }[]",
2403
+ "resolved": "string | undefined | { label: string; value: string; }[]",
2404
+ "references": {}
2405
+ },
2406
+ "required": false,
2407
+ "optional": true,
2408
+ "docs": {
2409
+ "tags": [],
2410
+ "text": "Font families available in the bubble menu font selector.\nJS property: `Array<{ label: string; value: string }>`.\nHTML attribute: JSON string of the same array.\nIf not provided, a default list of system fonts is used."
2411
+ },
2412
+ "getter": false,
2413
+ "setter": false,
2414
+ "reflect": false,
2415
+ "attribute": "font-families"
2416
+ },
2417
+ "accountFonts": {
2418
+ "type": "string",
2419
+ "mutable": false,
2420
+ "complexType": {
2421
+ "original": "string | { label: string; value: string }[]",
2422
+ "resolved": "string | undefined | { label: string; value: string; }[]",
2423
+ "references": {}
2424
+ },
2425
+ "required": false,
2426
+ "optional": true,
2427
+ "docs": {
2428
+ "tags": [],
2429
+ "text": "Account/imported fonts shown in a separate \"Imported fonts\" section.\nJS property: `Array<{ label: string; value: string }>`.\nHTML attribute: JSON string of the same array."
2430
+ },
2431
+ "getter": false,
2432
+ "setter": false,
2433
+ "reflect": false,
2434
+ "attribute": "account-fonts"
2435
+ },
2436
+ "fontsLoading": {
2437
+ "type": "boolean",
2438
+ "mutable": false,
2439
+ "complexType": {
2440
+ "original": "boolean",
2441
+ "resolved": "boolean | undefined",
2442
+ "references": {}
2443
+ },
2444
+ "required": false,
2445
+ "optional": true,
2446
+ "docs": {
2447
+ "tags": [],
2448
+ "text": "Whether account fonts are currently loading."
2449
+ },
2450
+ "getter": false,
2451
+ "setter": false,
2452
+ "reflect": false,
2453
+ "attribute": "fonts-loading"
2454
+ },
2455
+ "fontLoader": {
2456
+ "type": "unknown",
2457
+ "mutable": false,
2458
+ "complexType": {
2459
+ "original": "() => Promise<{ label: string; value: string; url?: string }[]>",
2460
+ "resolved": "(() => Promise<{ label: string; value: string; url?: string | undefined; }[]>) | undefined",
2461
+ "references": {
2462
+ "Promise": {
2463
+ "location": "global",
2464
+ "id": "global::Promise"
2465
+ }
2466
+ }
2467
+ },
2468
+ "required": false,
2469
+ "optional": true,
2470
+ "docs": {
2471
+ "tags": [],
2472
+ "text": "Async callback that loads account/imported fonts.\nCalled once when the font dropdown opens for the first time.\nMust return `Array<{ label: string; value: string; url?: string }>`.\nIf `url` is provided, the font is registered via FontFace API.\nJS property only \u2014 cannot be set via HTML attribute."
2473
+ },
2474
+ "getter": false,
2475
+ "setter": false
2476
+ },
2477
+ "locale": {
2478
+ "type": "string",
2479
+ "mutable": false,
2480
+ "complexType": {
2481
+ "original": "string",
2482
+ "resolved": "string",
2483
+ "references": {}
2484
+ },
2485
+ "required": false,
2486
+ "optional": false,
2487
+ "docs": {
2488
+ "tags": [],
2489
+ "text": "BCP-47 locale for UI strings (e.g. 'en', 'es-CO', 'pt-BR'). Default English."
2490
+ },
2491
+ "getter": false,
2492
+ "setter": false,
2493
+ "reflect": false,
2494
+ "attribute": "locale",
2495
+ "defaultValue": "'en'"
2496
+ }
2497
+ };
2498
+ }
2499
+ static get states() {
2500
+ return {
2501
+ "ready": {},
2502
+ "hasFocus": {}
2503
+ };
2504
+ }
2505
+ static get events() {
2506
+ return [{
2507
+ "method": "coInput",
2508
+ "name": "coInput",
2509
+ "bubbles": true,
2510
+ "cancelable": true,
2511
+ "composed": true,
2512
+ "docs": {
2513
+ "tags": [],
2514
+ "text": "Emitted on every keystroke."
2515
+ },
2516
+ "complexType": {
2517
+ "original": "RichTextOutput",
2518
+ "resolved": "RichTextOutput",
2519
+ "references": {
2520
+ "RichTextOutput": {
2521
+ "location": "import",
2522
+ "path": "@prolibu-suite/cobalt-rich-text",
2523
+ "id": "../rich-text/dist/index.d.ts::RichTextOutput",
2524
+ "referenceLocation": "RichTextOutput"
2525
+ }
2526
+ }
2527
+ }
2528
+ }, {
2529
+ "method": "coChange",
2530
+ "name": "coChange",
2531
+ "bubbles": true,
2532
+ "cancelable": true,
2533
+ "composed": true,
2534
+ "docs": {
2535
+ "tags": [],
2536
+ "text": "Emitted on blur (committed value)."
2537
+ },
2538
+ "complexType": {
2539
+ "original": "RichTextOutput",
2540
+ "resolved": "RichTextOutput",
2541
+ "references": {
2542
+ "RichTextOutput": {
2543
+ "location": "import",
2544
+ "path": "@prolibu-suite/cobalt-rich-text",
2545
+ "id": "../rich-text/dist/index.d.ts::RichTextOutput",
2546
+ "referenceLocation": "RichTextOutput"
2547
+ }
2548
+ }
2549
+ }
2550
+ }, {
2551
+ "method": "coFocus",
2552
+ "name": "coFocus",
2553
+ "bubbles": true,
2554
+ "cancelable": true,
2555
+ "composed": true,
2556
+ "docs": {
2557
+ "tags": [],
2558
+ "text": ""
2559
+ },
2560
+ "complexType": {
2561
+ "original": "void",
2562
+ "resolved": "void",
2563
+ "references": {}
2564
+ }
2565
+ }, {
2566
+ "method": "coBlur",
2567
+ "name": "coBlur",
2568
+ "bubbles": true,
2569
+ "cancelable": true,
2570
+ "composed": true,
2571
+ "docs": {
2572
+ "tags": [],
2573
+ "text": ""
2574
+ },
2575
+ "complexType": {
2576
+ "original": "void",
2577
+ "resolved": "void",
2578
+ "references": {}
2579
+ }
2580
+ }, {
2581
+ "method": "coClear",
2582
+ "name": "coClear",
2583
+ "bubbles": true,
2584
+ "cancelable": true,
2585
+ "composed": true,
2586
+ "docs": {
2587
+ "tags": [],
2588
+ "text": ""
2589
+ },
2590
+ "complexType": {
2591
+ "original": "void",
2592
+ "resolved": "void",
2593
+ "references": {}
2594
+ }
2595
+ }, {
2596
+ "method": "coReady",
2597
+ "name": "coReady",
2598
+ "bubbles": true,
2599
+ "cancelable": true,
2600
+ "composed": true,
2601
+ "docs": {
2602
+ "tags": [],
2603
+ "text": "Emitted once the editor is mounted and ready."
2604
+ },
2605
+ "complexType": {
2606
+ "original": "void",
2607
+ "resolved": "void",
2608
+ "references": {}
2609
+ }
2610
+ }, {
2611
+ "method": "coFontPopupShow",
2612
+ "name": "coFontPopupShow",
2613
+ "bubbles": true,
2614
+ "cancelable": true,
2615
+ "composed": true,
2616
+ "docs": {
2617
+ "tags": [],
2618
+ "text": "Emitted when the font dropdown opens \u2014 host should load account fonts."
2619
+ },
2620
+ "complexType": {
2621
+ "original": "void",
2622
+ "resolved": "void",
2623
+ "references": {}
2624
+ }
2625
+ }, {
2626
+ "method": "coFontPopupHide",
2627
+ "name": "coFontPopupHide",
2628
+ "bubbles": true,
2629
+ "cancelable": true,
2630
+ "composed": true,
2631
+ "docs": {
2632
+ "tags": [],
2633
+ "text": "Emitted when the font dropdown closes."
2634
+ },
2635
+ "complexType": {
2636
+ "original": "void",
2637
+ "resolved": "void",
2638
+ "references": {}
2639
+ }
2640
+ }];
2641
+ }
2642
+ static get methods() {
2643
+ return {
2644
+ "getJSON": {
2645
+ "complexType": {
2646
+ "signature": "() => Promise<object | null>",
2647
+ "parameters": [],
2648
+ "references": {
2649
+ "Promise": {
2650
+ "location": "global",
2651
+ "id": "global::Promise"
2652
+ }
2653
+ },
2654
+ "return": "Promise<object | null>"
2655
+ },
2656
+ "docs": {
2657
+ "text": "",
2658
+ "tags": []
2659
+ }
2660
+ },
2661
+ "getHtml": {
2662
+ "complexType": {
2663
+ "signature": "() => Promise<string>",
2664
+ "parameters": [],
2665
+ "references": {
2666
+ "Promise": {
2667
+ "location": "global",
2668
+ "id": "global::Promise"
2669
+ }
2670
+ },
2671
+ "return": "Promise<string>"
2672
+ },
2673
+ "docs": {
2674
+ "text": "",
2675
+ "tags": []
2676
+ }
2677
+ },
2678
+ "getText": {
2679
+ "complexType": {
2680
+ "signature": "() => Promise<string>",
2681
+ "parameters": [],
2682
+ "references": {
2683
+ "Promise": {
2684
+ "location": "global",
2685
+ "id": "global::Promise"
2686
+ }
2687
+ },
2688
+ "return": "Promise<string>"
2689
+ },
2690
+ "docs": {
2691
+ "text": "",
2692
+ "tags": []
2693
+ }
2694
+ },
2695
+ "clear": {
2696
+ "complexType": {
2697
+ "signature": "() => Promise<void>",
2698
+ "parameters": [],
2699
+ "references": {
2700
+ "Promise": {
2701
+ "location": "global",
2702
+ "id": "global::Promise"
2703
+ }
2704
+ },
2705
+ "return": "Promise<void>"
2706
+ },
2707
+ "docs": {
2708
+ "text": "",
2709
+ "tags": []
2710
+ }
2711
+ },
2712
+ "focusEditor": {
2713
+ "complexType": {
2714
+ "signature": "() => Promise<void>",
2715
+ "parameters": [],
2716
+ "references": {
2717
+ "Promise": {
2718
+ "location": "global",
2719
+ "id": "global::Promise"
2720
+ }
2721
+ },
2722
+ "return": "Promise<void>"
2723
+ },
2724
+ "docs": {
2725
+ "text": "",
2726
+ "tags": []
2727
+ }
2728
+ },
2729
+ "setContent": {
2730
+ "complexType": {
2731
+ "signature": "(content: string | object) => Promise<void>",
2732
+ "parameters": [{
2733
+ "name": "content",
2734
+ "type": "string | object",
2735
+ "docs": ""
2736
+ }],
2737
+ "references": {
2738
+ "Promise": {
2739
+ "location": "global",
2740
+ "id": "global::Promise"
2741
+ }
2742
+ },
2743
+ "return": "Promise<void>"
2744
+ },
2745
+ "docs": {
2746
+ "text": "",
2747
+ "tags": []
2748
+ }
2749
+ },
2750
+ "getEditorInstance": {
2751
+ "complexType": {
2752
+ "signature": "() => Promise<Editor | null>",
2753
+ "parameters": [],
2754
+ "references": {
2755
+ "Promise": {
2756
+ "location": "global",
2757
+ "id": "global::Promise"
2758
+ },
2759
+ "Editor": {
2760
+ "location": "import",
2761
+ "path": "@prolibu-suite/cobalt-rich-text",
2762
+ "id": "../rich-text/dist/index.d.ts::Editor",
2763
+ "referenceLocation": "Editor"
2764
+ }
2765
+ },
2766
+ "return": "Promise<Editor | null>"
2767
+ },
2768
+ "docs": {
2769
+ "text": "",
2770
+ "tags": []
2771
+ }
2772
+ }
2773
+ };
2774
+ }
2775
+ static get elementRef() { return "el"; }
2776
+ static get watchers() {
2777
+ return [{
2778
+ "propName": "accountFonts",
2779
+ "methodName": "onAccountFontsChange"
2780
+ }, {
2781
+ "propName": "value",
2782
+ "methodName": "onValueChange"
2783
+ }, {
2784
+ "propName": "disabled",
2785
+ "methodName": "onEditableChange"
2786
+ }, {
2787
+ "propName": "readonly",
2788
+ "methodName": "onEditableChange"
2789
+ }];
2790
+ }
2791
+ }
2792
+ CoRichTextEditor.DEFAULT_FONTS = [
2793
+ { label: 'Arial', value: 'Arial, sans-serif' },
2794
+ { label: 'Calibri', value: 'Calibri, sans-serif' },
2795
+ { label: 'Cambria', value: 'Cambria, serif' },
2796
+ { label: 'Comic Sans MS', value: "'Comic Sans MS', cursive" },
2797
+ { label: 'Courier New', value: "'Courier New', monospace" },
2798
+ { label: 'Georgia', value: 'Georgia, serif' },
2799
+ { label: 'Geist', value: "'Geist', sans-serif" },
2800
+ { label: 'Helvetica', value: 'Helvetica, Arial, sans-serif' },
2801
+ { label: 'Impact', value: 'Impact, sans-serif' },
2802
+ { label: 'Inter', value: "'Inter', sans-serif" },
2803
+ { label: 'Lato', value: "'Lato', sans-serif" },
2804
+ { label: 'Montserrat', value: "'Montserrat', sans-serif" },
2805
+ { label: 'Open Sans', value: "'Open Sans', sans-serif" },
2806
+ { label: 'Poppins', value: "'Poppins', sans-serif" },
2807
+ { label: 'Roboto', value: "'Roboto', sans-serif" },
2808
+ { label: 'Segoe UI', value: "'Segoe UI', sans-serif" },
2809
+ { label: 'Tahoma', value: 'Tahoma, sans-serif' },
2810
+ { label: 'Times New Roman', value: "'Times New Roman', serif" },
2811
+ { label: 'Trebuchet MS', value: "'Trebuchet MS', sans-serif" },
2812
+ { label: 'Verdana', value: 'Verdana, sans-serif' },
2813
+ ];
2814
+ /** Register a font via FontFace API so it can be previewed. */
2815
+ CoRichTextEditor._registeredFonts = new Set();
2816
+ /* ── Image layout bar (Google-Docs-style toolbar below selected image) ── */
2817
+ CoRichTextEditor.IMG_LAYOUT_ICONS = {
2818
+ 'inline': 'image-square',
2819
+ 'wrap-left': 'text-align-left',
2820
+ 'wrap-right': 'text-align-right',
2821
+ 'center': 'text-align-center',
2822
+ 'full-width': 'arrows-horizontal',
2823
+ };